| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2009 Nokia Corporation |
|---|
| 3 | 4 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> |
|---|
| 4 | 5 | * |
|---|
| 5 | 6 | * VENC settings from TI's DSS driver |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 8 | | - * under the terms of the GNU General Public License version 2 as published by |
|---|
| 9 | | - * the Free Software Foundation. |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
|---|
| 12 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 13 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 14 | | - * more details. |
|---|
| 15 | | - * |
|---|
| 16 | | - * You should have received a copy of the GNU General Public License along with |
|---|
| 17 | | - * this program. If not, see <http://www.gnu.org/licenses/>. |
|---|
| 18 | 7 | */ |
|---|
| 19 | 8 | |
|---|
| 20 | 9 | #define DSS_SUBSYS_NAME "VENC" |
|---|
| .. | .. |
|---|
| 24 | 13 | #include <linux/clk.h> |
|---|
| 25 | 14 | #include <linux/err.h> |
|---|
| 26 | 15 | #include <linux/io.h> |
|---|
| 27 | | -#include <linux/mutex.h> |
|---|
| 28 | 16 | #include <linux/completion.h> |
|---|
| 29 | 17 | #include <linux/delay.h> |
|---|
| 30 | 18 | #include <linux/string.h> |
|---|
| .. | .. |
|---|
| 36 | 24 | #include <linux/of_graph.h> |
|---|
| 37 | 25 | #include <linux/component.h> |
|---|
| 38 | 26 | #include <linux/sys_soc.h> |
|---|
| 27 | + |
|---|
| 28 | +#include <drm/drm_bridge.h> |
|---|
| 39 | 29 | |
|---|
| 40 | 30 | #include "omapdss.h" |
|---|
| 41 | 31 | #include "dss.h" |
|---|
| .. | .. |
|---|
| 218 | 208 | .gen_ctrl = 0x00F90000, |
|---|
| 219 | 209 | }; |
|---|
| 220 | 210 | |
|---|
| 221 | | -static const struct venc_config venc_config_pal_bdghi = { |
|---|
| 222 | | - .f_control = 0, |
|---|
| 223 | | - .vidout_ctrl = 0, |
|---|
| 224 | | - .sync_ctrl = 0, |
|---|
| 225 | | - .hfltr_ctrl = 0, |
|---|
| 226 | | - .x_color = 0, |
|---|
| 227 | | - .line21 = 0, |
|---|
| 228 | | - .ln_sel = 21, |
|---|
| 229 | | - .htrigger_vtrigger = 0, |
|---|
| 230 | | - .tvdetgp_int_start_stop_x = 0x00140001, |
|---|
| 231 | | - .tvdetgp_int_start_stop_y = 0x00010001, |
|---|
| 232 | | - .gen_ctrl = 0x00FB0000, |
|---|
| 233 | | - |
|---|
| 234 | | - .llen = 864-1, |
|---|
| 235 | | - .flens = 625-1, |
|---|
| 236 | | - .cc_carr_wss_carr = 0x2F7625ED, |
|---|
| 237 | | - .c_phase = 0xDF, |
|---|
| 238 | | - .gain_u = 0x111, |
|---|
| 239 | | - .gain_v = 0x181, |
|---|
| 240 | | - .gain_y = 0x140, |
|---|
| 241 | | - .black_level = 0x3e, |
|---|
| 242 | | - .blank_level = 0x3e, |
|---|
| 243 | | - .m_control = 0<<2 | 1<<1, |
|---|
| 244 | | - .bstamp_wss_data = 0x42, |
|---|
| 245 | | - .s_carr = 0x2a098acb, |
|---|
| 246 | | - .l21__wc_ctl = 0<<13 | 0x16<<8 | 0<<0, |
|---|
| 247 | | - .savid__eavid = 0x06A70108, |
|---|
| 248 | | - .flen__fal = 23<<16 | 624<<0, |
|---|
| 249 | | - .lal__phase_reset = 2<<17 | 310<<0, |
|---|
| 250 | | - .hs_int_start_stop_x = 0x00920358, |
|---|
| 251 | | - .hs_ext_start_stop_x = 0x000F035F, |
|---|
| 252 | | - .vs_int_start_x = 0x1a7<<16, |
|---|
| 253 | | - .vs_int_stop_x__vs_int_start_y = 0x000601A7, |
|---|
| 254 | | - .vs_int_stop_y__vs_ext_start_x = 0x01AF0036, |
|---|
| 255 | | - .vs_ext_stop_x__vs_ext_start_y = 0x27101af, |
|---|
| 256 | | - .vs_ext_stop_y = 0x05, |
|---|
| 257 | | - .avid_start_stop_x = 0x03530082, |
|---|
| 258 | | - .avid_start_stop_y = 0x0270002E, |
|---|
| 259 | | - .fid_int_start_x__fid_int_start_y = 0x0005008A, |
|---|
| 260 | | - .fid_int_offset_y__fid_ext_start_x = 0x002E0138, |
|---|
| 261 | | - .fid_ext_start_y__fid_ext_offset_y = 0x01380005, |
|---|
| 262 | | -}; |
|---|
| 263 | | - |
|---|
| 264 | 211 | enum venc_videomode { |
|---|
| 265 | 212 | VENC_MODE_UNKNOWN, |
|---|
| 266 | 213 | VENC_MODE_PAL, |
|---|
| 267 | 214 | VENC_MODE_NTSC, |
|---|
| 268 | 215 | }; |
|---|
| 269 | 216 | |
|---|
| 270 | | -static const struct videomode omap_dss_pal_vm = { |
|---|
| 271 | | - .hactive = 720, |
|---|
| 272 | | - .vactive = 574, |
|---|
| 273 | | - .pixelclock = 13500000, |
|---|
| 274 | | - .hsync_len = 64, |
|---|
| 275 | | - .hfront_porch = 12, |
|---|
| 276 | | - .hback_porch = 68, |
|---|
| 277 | | - .vsync_len = 5, |
|---|
| 278 | | - .vfront_porch = 5, |
|---|
| 279 | | - .vback_porch = 41, |
|---|
| 217 | +static const struct drm_display_mode omap_dss_pal_mode = { |
|---|
| 218 | + .hdisplay = 720, |
|---|
| 219 | + .hsync_start = 732, |
|---|
| 220 | + .hsync_end = 796, |
|---|
| 221 | + .htotal = 864, |
|---|
| 222 | + .vdisplay = 574, |
|---|
| 223 | + .vsync_start = 579, |
|---|
| 224 | + .vsync_end = 584, |
|---|
| 225 | + .vtotal = 625, |
|---|
| 226 | + .clock = 13500, |
|---|
| 280 | 227 | |
|---|
| 281 | | - .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW | |
|---|
| 282 | | - DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH | |
|---|
| 283 | | - DISPLAY_FLAGS_PIXDATA_POSEDGE | |
|---|
| 284 | | - DISPLAY_FLAGS_SYNC_NEGEDGE, |
|---|
| 228 | + .flags = DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_NHSYNC | |
|---|
| 229 | + DRM_MODE_FLAG_NVSYNC, |
|---|
| 285 | 230 | }; |
|---|
| 286 | 231 | |
|---|
| 287 | | -static const struct videomode omap_dss_ntsc_vm = { |
|---|
| 288 | | - .hactive = 720, |
|---|
| 289 | | - .vactive = 482, |
|---|
| 290 | | - .pixelclock = 13500000, |
|---|
| 291 | | - .hsync_len = 64, |
|---|
| 292 | | - .hfront_porch = 16, |
|---|
| 293 | | - .hback_porch = 58, |
|---|
| 294 | | - .vsync_len = 6, |
|---|
| 295 | | - .vfront_porch = 6, |
|---|
| 296 | | - .vback_porch = 31, |
|---|
| 232 | +static const struct drm_display_mode omap_dss_ntsc_mode = { |
|---|
| 233 | + .hdisplay = 720, |
|---|
| 234 | + .hsync_start = 736, |
|---|
| 235 | + .hsync_end = 800, |
|---|
| 236 | + .htotal = 858, |
|---|
| 237 | + .vdisplay = 482, |
|---|
| 238 | + .vsync_start = 488, |
|---|
| 239 | + .vsync_end = 494, |
|---|
| 240 | + .vtotal = 525, |
|---|
| 241 | + .clock = 13500, |
|---|
| 297 | 242 | |
|---|
| 298 | | - .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW | |
|---|
| 299 | | - DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH | |
|---|
| 300 | | - DISPLAY_FLAGS_PIXDATA_POSEDGE | |
|---|
| 301 | | - DISPLAY_FLAGS_SYNC_NEGEDGE, |
|---|
| 243 | + .flags = DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_NHSYNC | |
|---|
| 244 | + DRM_MODE_FLAG_NVSYNC, |
|---|
| 302 | 245 | }; |
|---|
| 303 | | - |
|---|
| 304 | | -static enum venc_videomode venc_get_videomode(const struct videomode *vm) |
|---|
| 305 | | -{ |
|---|
| 306 | | - if (!(vm->flags & DISPLAY_FLAGS_INTERLACED)) |
|---|
| 307 | | - return VENC_MODE_UNKNOWN; |
|---|
| 308 | | - |
|---|
| 309 | | - if (vm->pixelclock == omap_dss_pal_vm.pixelclock && |
|---|
| 310 | | - vm->hactive == omap_dss_pal_vm.hactive && |
|---|
| 311 | | - vm->vactive == omap_dss_pal_vm.vactive) |
|---|
| 312 | | - return VENC_MODE_PAL; |
|---|
| 313 | | - |
|---|
| 314 | | - if (vm->pixelclock == omap_dss_ntsc_vm.pixelclock && |
|---|
| 315 | | - vm->hactive == omap_dss_ntsc_vm.hactive && |
|---|
| 316 | | - vm->vactive == omap_dss_ntsc_vm.vactive) |
|---|
| 317 | | - return VENC_MODE_NTSC; |
|---|
| 318 | | - |
|---|
| 319 | | - return VENC_MODE_UNKNOWN; |
|---|
| 320 | | -} |
|---|
| 321 | 246 | |
|---|
| 322 | 247 | struct venc_device { |
|---|
| 323 | 248 | struct platform_device *pdev; |
|---|
| 324 | 249 | void __iomem *base; |
|---|
| 325 | | - struct mutex venc_lock; |
|---|
| 326 | | - u32 wss_data; |
|---|
| 327 | 250 | struct regulator *vdda_dac_reg; |
|---|
| 328 | 251 | struct dss_device *dss; |
|---|
| 329 | 252 | |
|---|
| .. | .. |
|---|
| 331 | 254 | |
|---|
| 332 | 255 | struct clk *tv_dac_clk; |
|---|
| 333 | 256 | |
|---|
| 334 | | - struct videomode vm; |
|---|
| 257 | + const struct venc_config *config; |
|---|
| 335 | 258 | enum omap_dss_venc_type type; |
|---|
| 336 | 259 | bool invert_polarity; |
|---|
| 337 | 260 | bool requires_tv_dac_clk; |
|---|
| 338 | 261 | |
|---|
| 339 | 262 | struct omap_dss_device output; |
|---|
| 263 | + struct drm_bridge bridge; |
|---|
| 340 | 264 | }; |
|---|
| 341 | 265 | |
|---|
| 342 | | -#define dssdev_to_venc(dssdev) container_of(dssdev, struct venc_device, output) |
|---|
| 266 | +#define drm_bridge_to_venc(b) container_of(b, struct venc_device, bridge) |
|---|
| 343 | 267 | |
|---|
| 344 | 268 | static inline void venc_write_reg(struct venc_device *venc, int idx, u32 val) |
|---|
| 345 | 269 | { |
|---|
| .. | .. |
|---|
| 367 | 291 | venc_write_reg(venc, VENC_BLACK_LEVEL, config->black_level); |
|---|
| 368 | 292 | venc_write_reg(venc, VENC_BLANK_LEVEL, config->blank_level); |
|---|
| 369 | 293 | venc_write_reg(venc, VENC_M_CONTROL, config->m_control); |
|---|
| 370 | | - venc_write_reg(venc, VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | |
|---|
| 371 | | - venc->wss_data); |
|---|
| 294 | + venc_write_reg(venc, VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data); |
|---|
| 372 | 295 | venc_write_reg(venc, VENC_S_CARR, config->s_carr); |
|---|
| 373 | 296 | venc_write_reg(venc, VENC_L21__WC_CTL, config->l21__wc_ctl); |
|---|
| 374 | 297 | venc_write_reg(venc, VENC_SAVID__EAVID, config->savid__eavid); |
|---|
| .. | .. |
|---|
| 452 | 375 | WARN_ON(r < 0 && r != -ENOSYS); |
|---|
| 453 | 376 | } |
|---|
| 454 | 377 | |
|---|
| 455 | | -static const struct venc_config *venc_timings_to_config(struct videomode *vm) |
|---|
| 456 | | -{ |
|---|
| 457 | | - switch (venc_get_videomode(vm)) { |
|---|
| 458 | | - default: |
|---|
| 459 | | - WARN_ON_ONCE(1); |
|---|
| 460 | | - case VENC_MODE_PAL: |
|---|
| 461 | | - return &venc_config_pal_trm; |
|---|
| 462 | | - case VENC_MODE_NTSC: |
|---|
| 463 | | - return &venc_config_ntsc_trm; |
|---|
| 464 | | - } |
|---|
| 465 | | -} |
|---|
| 466 | | - |
|---|
| 467 | 378 | static int venc_power_on(struct venc_device *venc) |
|---|
| 468 | 379 | { |
|---|
| 469 | 380 | u32 l; |
|---|
| .. | .. |
|---|
| 474 | 385 | goto err0; |
|---|
| 475 | 386 | |
|---|
| 476 | 387 | venc_reset(venc); |
|---|
| 477 | | - venc_write_config(venc, venc_timings_to_config(&venc->vm)); |
|---|
| 388 | + venc_write_config(venc, venc->config); |
|---|
| 478 | 389 | |
|---|
| 479 | 390 | dss_set_venc_output(venc->dss, venc->type); |
|---|
| 480 | 391 | dss_set_dac_pwrdn_bgz(venc->dss, 1); |
|---|
| .. | .. |
|---|
| 490 | 401 | l |= 1 << 3; |
|---|
| 491 | 402 | |
|---|
| 492 | 403 | venc_write_reg(venc, VENC_OUTPUT_CONTROL, l); |
|---|
| 493 | | - |
|---|
| 494 | | - dss_mgr_set_timings(&venc->output, &venc->vm); |
|---|
| 495 | 404 | |
|---|
| 496 | 405 | r = regulator_enable(venc->vdda_dac_reg); |
|---|
| 497 | 406 | if (r) |
|---|
| .. | .. |
|---|
| 526 | 435 | venc_runtime_put(venc); |
|---|
| 527 | 436 | } |
|---|
| 528 | 437 | |
|---|
| 529 | | -static int venc_display_enable(struct omap_dss_device *dssdev) |
|---|
| 438 | +static enum venc_videomode venc_get_videomode(const struct drm_display_mode *mode) |
|---|
| 530 | 439 | { |
|---|
| 531 | | - struct venc_device *venc = dssdev_to_venc(dssdev); |
|---|
| 532 | | - int r; |
|---|
| 440 | + if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) |
|---|
| 441 | + return VENC_MODE_UNKNOWN; |
|---|
| 533 | 442 | |
|---|
| 534 | | - DSSDBG("venc_display_enable\n"); |
|---|
| 443 | + if (mode->clock == omap_dss_pal_mode.clock && |
|---|
| 444 | + mode->hdisplay == omap_dss_pal_mode.hdisplay && |
|---|
| 445 | + mode->vdisplay == omap_dss_pal_mode.vdisplay) |
|---|
| 446 | + return VENC_MODE_PAL; |
|---|
| 535 | 447 | |
|---|
| 536 | | - mutex_lock(&venc->venc_lock); |
|---|
| 448 | + if (mode->clock == omap_dss_ntsc_mode.clock && |
|---|
| 449 | + mode->hdisplay == omap_dss_ntsc_mode.hdisplay && |
|---|
| 450 | + mode->vdisplay == omap_dss_ntsc_mode.vdisplay) |
|---|
| 451 | + return VENC_MODE_NTSC; |
|---|
| 537 | 452 | |
|---|
| 538 | | - if (!dssdev->dispc_channel_connected) { |
|---|
| 539 | | - DSSERR("Failed to enable display: no output/manager\n"); |
|---|
| 540 | | - r = -ENODEV; |
|---|
| 541 | | - goto err0; |
|---|
| 542 | | - } |
|---|
| 543 | | - |
|---|
| 544 | | - r = venc_power_on(venc); |
|---|
| 545 | | - if (r) |
|---|
| 546 | | - goto err0; |
|---|
| 547 | | - |
|---|
| 548 | | - venc->wss_data = 0; |
|---|
| 549 | | - |
|---|
| 550 | | - mutex_unlock(&venc->venc_lock); |
|---|
| 551 | | - |
|---|
| 552 | | - return 0; |
|---|
| 553 | | -err0: |
|---|
| 554 | | - mutex_unlock(&venc->venc_lock); |
|---|
| 555 | | - return r; |
|---|
| 556 | | -} |
|---|
| 557 | | - |
|---|
| 558 | | -static void venc_display_disable(struct omap_dss_device *dssdev) |
|---|
| 559 | | -{ |
|---|
| 560 | | - struct venc_device *venc = dssdev_to_venc(dssdev); |
|---|
| 561 | | - |
|---|
| 562 | | - DSSDBG("venc_display_disable\n"); |
|---|
| 563 | | - |
|---|
| 564 | | - mutex_lock(&venc->venc_lock); |
|---|
| 565 | | - |
|---|
| 566 | | - venc_power_off(venc); |
|---|
| 567 | | - |
|---|
| 568 | | - mutex_unlock(&venc->venc_lock); |
|---|
| 569 | | -} |
|---|
| 570 | | - |
|---|
| 571 | | -static void venc_set_timings(struct omap_dss_device *dssdev, |
|---|
| 572 | | - struct videomode *vm) |
|---|
| 573 | | -{ |
|---|
| 574 | | - struct venc_device *venc = dssdev_to_venc(dssdev); |
|---|
| 575 | | - struct videomode actual_vm; |
|---|
| 576 | | - |
|---|
| 577 | | - DSSDBG("venc_set_timings\n"); |
|---|
| 578 | | - |
|---|
| 579 | | - mutex_lock(&venc->venc_lock); |
|---|
| 580 | | - |
|---|
| 581 | | - switch (venc_get_videomode(vm)) { |
|---|
| 582 | | - default: |
|---|
| 583 | | - WARN_ON_ONCE(1); |
|---|
| 584 | | - case VENC_MODE_PAL: |
|---|
| 585 | | - actual_vm = omap_dss_pal_vm; |
|---|
| 586 | | - break; |
|---|
| 587 | | - case VENC_MODE_NTSC: |
|---|
| 588 | | - actual_vm = omap_dss_ntsc_vm; |
|---|
| 589 | | - break; |
|---|
| 590 | | - } |
|---|
| 591 | | - |
|---|
| 592 | | - /* Reset WSS data when the TV standard changes. */ |
|---|
| 593 | | - if (memcmp(&venc->vm, &actual_vm, sizeof(actual_vm))) |
|---|
| 594 | | - venc->wss_data = 0; |
|---|
| 595 | | - |
|---|
| 596 | | - venc->vm = actual_vm; |
|---|
| 597 | | - |
|---|
| 598 | | - dispc_set_tv_pclk(venc->dss->dispc, 13500000); |
|---|
| 599 | | - |
|---|
| 600 | | - mutex_unlock(&venc->venc_lock); |
|---|
| 601 | | -} |
|---|
| 602 | | - |
|---|
| 603 | | -static int venc_check_timings(struct omap_dss_device *dssdev, |
|---|
| 604 | | - struct videomode *vm) |
|---|
| 605 | | -{ |
|---|
| 606 | | - DSSDBG("venc_check_timings\n"); |
|---|
| 607 | | - |
|---|
| 608 | | - switch (venc_get_videomode(vm)) { |
|---|
| 609 | | - case VENC_MODE_PAL: |
|---|
| 610 | | - case VENC_MODE_NTSC: |
|---|
| 611 | | - return 0; |
|---|
| 612 | | - default: |
|---|
| 613 | | - return -EINVAL; |
|---|
| 614 | | - } |
|---|
| 615 | | -} |
|---|
| 616 | | - |
|---|
| 617 | | -static void venc_get_timings(struct omap_dss_device *dssdev, |
|---|
| 618 | | - struct videomode *vm) |
|---|
| 619 | | -{ |
|---|
| 620 | | - struct venc_device *venc = dssdev_to_venc(dssdev); |
|---|
| 621 | | - |
|---|
| 622 | | - mutex_lock(&venc->venc_lock); |
|---|
| 623 | | - |
|---|
| 624 | | - *vm = venc->vm; |
|---|
| 625 | | - |
|---|
| 626 | | - mutex_unlock(&venc->venc_lock); |
|---|
| 627 | | -} |
|---|
| 628 | | - |
|---|
| 629 | | -static u32 venc_get_wss(struct omap_dss_device *dssdev) |
|---|
| 630 | | -{ |
|---|
| 631 | | - struct venc_device *venc = dssdev_to_venc(dssdev); |
|---|
| 632 | | - |
|---|
| 633 | | - /* Invert due to VENC_L21_WC_CTL:INV=1 */ |
|---|
| 634 | | - return (venc->wss_data >> 8) ^ 0xfffff; |
|---|
| 635 | | -} |
|---|
| 636 | | - |
|---|
| 637 | | -static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) |
|---|
| 638 | | -{ |
|---|
| 639 | | - struct venc_device *venc = dssdev_to_venc(dssdev); |
|---|
| 640 | | - const struct venc_config *config; |
|---|
| 641 | | - int r; |
|---|
| 642 | | - |
|---|
| 643 | | - DSSDBG("venc_set_wss\n"); |
|---|
| 644 | | - |
|---|
| 645 | | - mutex_lock(&venc->venc_lock); |
|---|
| 646 | | - |
|---|
| 647 | | - config = venc_timings_to_config(&venc->vm); |
|---|
| 648 | | - |
|---|
| 649 | | - /* Invert due to VENC_L21_WC_CTL:INV=1 */ |
|---|
| 650 | | - venc->wss_data = (wss ^ 0xfffff) << 8; |
|---|
| 651 | | - |
|---|
| 652 | | - r = venc_runtime_get(venc); |
|---|
| 653 | | - if (r) |
|---|
| 654 | | - goto err; |
|---|
| 655 | | - |
|---|
| 656 | | - venc_write_reg(venc, VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | |
|---|
| 657 | | - venc->wss_data); |
|---|
| 658 | | - |
|---|
| 659 | | - venc_runtime_put(venc); |
|---|
| 660 | | - |
|---|
| 661 | | -err: |
|---|
| 662 | | - mutex_unlock(&venc->venc_lock); |
|---|
| 663 | | - |
|---|
| 664 | | - return r; |
|---|
| 665 | | -} |
|---|
| 666 | | - |
|---|
| 667 | | -static int venc_init_regulator(struct venc_device *venc) |
|---|
| 668 | | -{ |
|---|
| 669 | | - struct regulator *vdda_dac; |
|---|
| 670 | | - |
|---|
| 671 | | - if (venc->vdda_dac_reg != NULL) |
|---|
| 672 | | - return 0; |
|---|
| 673 | | - |
|---|
| 674 | | - vdda_dac = devm_regulator_get(&venc->pdev->dev, "vdda"); |
|---|
| 675 | | - if (IS_ERR(vdda_dac)) { |
|---|
| 676 | | - if (PTR_ERR(vdda_dac) != -EPROBE_DEFER) |
|---|
| 677 | | - DSSERR("can't get VDDA_DAC regulator\n"); |
|---|
| 678 | | - return PTR_ERR(vdda_dac); |
|---|
| 679 | | - } |
|---|
| 680 | | - |
|---|
| 681 | | - venc->vdda_dac_reg = vdda_dac; |
|---|
| 682 | | - |
|---|
| 683 | | - return 0; |
|---|
| 453 | + return VENC_MODE_UNKNOWN; |
|---|
| 684 | 454 | } |
|---|
| 685 | 455 | |
|---|
| 686 | 456 | static int venc_dump_regs(struct seq_file *s, void *p) |
|---|
| .. | .. |
|---|
| 760 | 530 | return 0; |
|---|
| 761 | 531 | } |
|---|
| 762 | 532 | |
|---|
| 763 | | -static int venc_connect(struct omap_dss_device *dssdev, |
|---|
| 764 | | - struct omap_dss_device *dst) |
|---|
| 533 | +/* ----------------------------------------------------------------------------- |
|---|
| 534 | + * DRM Bridge Operations |
|---|
| 535 | + */ |
|---|
| 536 | + |
|---|
| 537 | +static int venc_bridge_attach(struct drm_bridge *bridge, |
|---|
| 538 | + enum drm_bridge_attach_flags flags) |
|---|
| 765 | 539 | { |
|---|
| 766 | | - struct venc_device *venc = dssdev_to_venc(dssdev); |
|---|
| 540 | + struct venc_device *venc = drm_bridge_to_venc(bridge); |
|---|
| 541 | + |
|---|
| 542 | + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) |
|---|
| 543 | + return -EINVAL; |
|---|
| 544 | + |
|---|
| 545 | + return drm_bridge_attach(bridge->encoder, venc->output.next_bridge, |
|---|
| 546 | + bridge, flags); |
|---|
| 547 | +} |
|---|
| 548 | + |
|---|
| 549 | +static enum drm_mode_status |
|---|
| 550 | +venc_bridge_mode_valid(struct drm_bridge *bridge, |
|---|
| 551 | + const struct drm_display_info *info, |
|---|
| 552 | + const struct drm_display_mode *mode) |
|---|
| 553 | +{ |
|---|
| 554 | + switch (venc_get_videomode(mode)) { |
|---|
| 555 | + case VENC_MODE_PAL: |
|---|
| 556 | + case VENC_MODE_NTSC: |
|---|
| 557 | + return MODE_OK; |
|---|
| 558 | + |
|---|
| 559 | + default: |
|---|
| 560 | + return MODE_BAD; |
|---|
| 561 | + } |
|---|
| 562 | +} |
|---|
| 563 | + |
|---|
| 564 | +static bool venc_bridge_mode_fixup(struct drm_bridge *bridge, |
|---|
| 565 | + const struct drm_display_mode *mode, |
|---|
| 566 | + struct drm_display_mode *adjusted_mode) |
|---|
| 567 | +{ |
|---|
| 568 | + const struct drm_display_mode *venc_mode; |
|---|
| 569 | + |
|---|
| 570 | + switch (venc_get_videomode(adjusted_mode)) { |
|---|
| 571 | + case VENC_MODE_PAL: |
|---|
| 572 | + venc_mode = &omap_dss_pal_mode; |
|---|
| 573 | + break; |
|---|
| 574 | + |
|---|
| 575 | + case VENC_MODE_NTSC: |
|---|
| 576 | + venc_mode = &omap_dss_ntsc_mode; |
|---|
| 577 | + break; |
|---|
| 578 | + |
|---|
| 579 | + default: |
|---|
| 580 | + return false; |
|---|
| 581 | + } |
|---|
| 582 | + |
|---|
| 583 | + drm_mode_copy(adjusted_mode, venc_mode); |
|---|
| 584 | + drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); |
|---|
| 585 | + drm_mode_set_name(adjusted_mode); |
|---|
| 586 | + |
|---|
| 587 | + return true; |
|---|
| 588 | +} |
|---|
| 589 | + |
|---|
| 590 | +static void venc_bridge_mode_set(struct drm_bridge *bridge, |
|---|
| 591 | + const struct drm_display_mode *mode, |
|---|
| 592 | + const struct drm_display_mode *adjusted_mode) |
|---|
| 593 | +{ |
|---|
| 594 | + struct venc_device *venc = drm_bridge_to_venc(bridge); |
|---|
| 595 | + enum venc_videomode venc_mode = venc_get_videomode(adjusted_mode); |
|---|
| 596 | + |
|---|
| 597 | + switch (venc_mode) { |
|---|
| 598 | + default: |
|---|
| 599 | + WARN_ON_ONCE(1); |
|---|
| 600 | + fallthrough; |
|---|
| 601 | + case VENC_MODE_PAL: |
|---|
| 602 | + venc->config = &venc_config_pal_trm; |
|---|
| 603 | + break; |
|---|
| 604 | + |
|---|
| 605 | + case VENC_MODE_NTSC: |
|---|
| 606 | + venc->config = &venc_config_ntsc_trm; |
|---|
| 607 | + break; |
|---|
| 608 | + } |
|---|
| 609 | + |
|---|
| 610 | + dispc_set_tv_pclk(venc->dss->dispc, 13500000); |
|---|
| 611 | +} |
|---|
| 612 | + |
|---|
| 613 | +static void venc_bridge_enable(struct drm_bridge *bridge) |
|---|
| 614 | +{ |
|---|
| 615 | + struct venc_device *venc = drm_bridge_to_venc(bridge); |
|---|
| 616 | + |
|---|
| 617 | + venc_power_on(venc); |
|---|
| 618 | +} |
|---|
| 619 | + |
|---|
| 620 | +static void venc_bridge_disable(struct drm_bridge *bridge) |
|---|
| 621 | +{ |
|---|
| 622 | + struct venc_device *venc = drm_bridge_to_venc(bridge); |
|---|
| 623 | + |
|---|
| 624 | + venc_power_off(venc); |
|---|
| 625 | +} |
|---|
| 626 | + |
|---|
| 627 | +static int venc_bridge_get_modes(struct drm_bridge *bridge, |
|---|
| 628 | + struct drm_connector *connector) |
|---|
| 629 | +{ |
|---|
| 630 | + static const struct drm_display_mode *modes[] = { |
|---|
| 631 | + &omap_dss_pal_mode, |
|---|
| 632 | + &omap_dss_ntsc_mode, |
|---|
| 633 | + }; |
|---|
| 634 | + unsigned int i; |
|---|
| 635 | + |
|---|
| 636 | + for (i = 0; i < ARRAY_SIZE(modes); ++i) { |
|---|
| 637 | + struct drm_display_mode *mode; |
|---|
| 638 | + |
|---|
| 639 | + mode = drm_mode_duplicate(connector->dev, modes[i]); |
|---|
| 640 | + if (!mode) |
|---|
| 641 | + return i; |
|---|
| 642 | + |
|---|
| 643 | + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; |
|---|
| 644 | + drm_mode_set_name(mode); |
|---|
| 645 | + drm_mode_probed_add(connector, mode); |
|---|
| 646 | + } |
|---|
| 647 | + |
|---|
| 648 | + return ARRAY_SIZE(modes); |
|---|
| 649 | +} |
|---|
| 650 | + |
|---|
| 651 | +static const struct drm_bridge_funcs venc_bridge_funcs = { |
|---|
| 652 | + .attach = venc_bridge_attach, |
|---|
| 653 | + .mode_valid = venc_bridge_mode_valid, |
|---|
| 654 | + .mode_fixup = venc_bridge_mode_fixup, |
|---|
| 655 | + .mode_set = venc_bridge_mode_set, |
|---|
| 656 | + .enable = venc_bridge_enable, |
|---|
| 657 | + .disable = venc_bridge_disable, |
|---|
| 658 | + .get_modes = venc_bridge_get_modes, |
|---|
| 659 | +}; |
|---|
| 660 | + |
|---|
| 661 | +static void venc_bridge_init(struct venc_device *venc) |
|---|
| 662 | +{ |
|---|
| 663 | + venc->bridge.funcs = &venc_bridge_funcs; |
|---|
| 664 | + venc->bridge.of_node = venc->pdev->dev.of_node; |
|---|
| 665 | + venc->bridge.ops = DRM_BRIDGE_OP_MODES; |
|---|
| 666 | + venc->bridge.type = DRM_MODE_CONNECTOR_SVIDEO; |
|---|
| 667 | + venc->bridge.interlace_allowed = true; |
|---|
| 668 | + |
|---|
| 669 | + drm_bridge_add(&venc->bridge); |
|---|
| 670 | +} |
|---|
| 671 | + |
|---|
| 672 | +static void venc_bridge_cleanup(struct venc_device *venc) |
|---|
| 673 | +{ |
|---|
| 674 | + drm_bridge_remove(&venc->bridge); |
|---|
| 675 | +} |
|---|
| 676 | + |
|---|
| 677 | +/* ----------------------------------------------------------------------------- |
|---|
| 678 | + * Component Bind & Unbind |
|---|
| 679 | + */ |
|---|
| 680 | + |
|---|
| 681 | +static int venc_bind(struct device *dev, struct device *master, void *data) |
|---|
| 682 | +{ |
|---|
| 683 | + struct dss_device *dss = dss_get_device(master); |
|---|
| 684 | + struct venc_device *venc = dev_get_drvdata(dev); |
|---|
| 685 | + u8 rev_id; |
|---|
| 767 | 686 | int r; |
|---|
| 768 | 687 | |
|---|
| 769 | | - r = venc_init_regulator(venc); |
|---|
| 688 | + venc->dss = dss; |
|---|
| 689 | + |
|---|
| 690 | + r = venc_runtime_get(venc); |
|---|
| 770 | 691 | if (r) |
|---|
| 771 | 692 | return r; |
|---|
| 772 | 693 | |
|---|
| 773 | | - r = dss_mgr_connect(&venc->output, dssdev); |
|---|
| 774 | | - if (r) |
|---|
| 775 | | - return r; |
|---|
| 694 | + rev_id = (u8)(venc_read_reg(venc, VENC_REV_ID) & 0xff); |
|---|
| 695 | + dev_dbg(dev, "OMAP VENC rev %d\n", rev_id); |
|---|
| 776 | 696 | |
|---|
| 777 | | - r = omapdss_output_set_device(dssdev, dst); |
|---|
| 778 | | - if (r) { |
|---|
| 779 | | - DSSERR("failed to connect output to new device: %s\n", |
|---|
| 780 | | - dst->name); |
|---|
| 781 | | - dss_mgr_disconnect(&venc->output, dssdev); |
|---|
| 782 | | - return r; |
|---|
| 783 | | - } |
|---|
| 697 | + venc_runtime_put(venc); |
|---|
| 698 | + |
|---|
| 699 | + venc->debugfs = dss_debugfs_create_file(dss, "venc", venc_dump_regs, |
|---|
| 700 | + venc); |
|---|
| 784 | 701 | |
|---|
| 785 | 702 | return 0; |
|---|
| 786 | 703 | } |
|---|
| 787 | 704 | |
|---|
| 788 | | -static void venc_disconnect(struct omap_dss_device *dssdev, |
|---|
| 789 | | - struct omap_dss_device *dst) |
|---|
| 705 | +static void venc_unbind(struct device *dev, struct device *master, void *data) |
|---|
| 790 | 706 | { |
|---|
| 791 | | - struct venc_device *venc = dssdev_to_venc(dssdev); |
|---|
| 707 | + struct venc_device *venc = dev_get_drvdata(dev); |
|---|
| 792 | 708 | |
|---|
| 793 | | - WARN_ON(dst != dssdev->dst); |
|---|
| 794 | | - |
|---|
| 795 | | - if (dst != dssdev->dst) |
|---|
| 796 | | - return; |
|---|
| 797 | | - |
|---|
| 798 | | - omapdss_output_unset_device(dssdev); |
|---|
| 799 | | - |
|---|
| 800 | | - dss_mgr_disconnect(&venc->output, dssdev); |
|---|
| 709 | + dss_debugfs_remove_file(venc->debugfs); |
|---|
| 801 | 710 | } |
|---|
| 802 | 711 | |
|---|
| 803 | | -static const struct omapdss_atv_ops venc_ops = { |
|---|
| 804 | | - .connect = venc_connect, |
|---|
| 805 | | - .disconnect = venc_disconnect, |
|---|
| 806 | | - |
|---|
| 807 | | - .enable = venc_display_enable, |
|---|
| 808 | | - .disable = venc_display_disable, |
|---|
| 809 | | - |
|---|
| 810 | | - .check_timings = venc_check_timings, |
|---|
| 811 | | - .set_timings = venc_set_timings, |
|---|
| 812 | | - .get_timings = venc_get_timings, |
|---|
| 813 | | - |
|---|
| 814 | | - .set_wss = venc_set_wss, |
|---|
| 815 | | - .get_wss = venc_get_wss, |
|---|
| 712 | +static const struct component_ops venc_component_ops = { |
|---|
| 713 | + .bind = venc_bind, |
|---|
| 714 | + .unbind = venc_unbind, |
|---|
| 816 | 715 | }; |
|---|
| 817 | 716 | |
|---|
| 818 | | -static void venc_init_output(struct venc_device *venc) |
|---|
| 717 | +/* ----------------------------------------------------------------------------- |
|---|
| 718 | + * Probe & Remove, Suspend & Resume |
|---|
| 719 | + */ |
|---|
| 720 | + |
|---|
| 721 | +static int venc_init_output(struct venc_device *venc) |
|---|
| 819 | 722 | { |
|---|
| 820 | 723 | struct omap_dss_device *out = &venc->output; |
|---|
| 724 | + int r; |
|---|
| 725 | + |
|---|
| 726 | + venc_bridge_init(venc); |
|---|
| 821 | 727 | |
|---|
| 822 | 728 | out->dev = &venc->pdev->dev; |
|---|
| 823 | 729 | out->id = OMAP_DSS_OUTPUT_VENC; |
|---|
| 824 | | - out->output_type = OMAP_DISPLAY_TYPE_VENC; |
|---|
| 730 | + out->type = OMAP_DISPLAY_TYPE_VENC; |
|---|
| 825 | 731 | out->name = "venc.0"; |
|---|
| 826 | 732 | out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; |
|---|
| 827 | | - out->ops.atv = &venc_ops; |
|---|
| 828 | 733 | out->owner = THIS_MODULE; |
|---|
| 734 | + out->of_port = 0; |
|---|
| 735 | + out->ops_flags = OMAP_DSS_DEVICE_OP_MODES; |
|---|
| 829 | 736 | |
|---|
| 830 | | - omapdss_register_output(out); |
|---|
| 737 | + r = omapdss_device_init_output(out, &venc->bridge); |
|---|
| 738 | + if (r < 0) { |
|---|
| 739 | + venc_bridge_cleanup(venc); |
|---|
| 740 | + return r; |
|---|
| 741 | + } |
|---|
| 742 | + |
|---|
| 743 | + omapdss_device_register(out); |
|---|
| 744 | + |
|---|
| 745 | + return 0; |
|---|
| 831 | 746 | } |
|---|
| 832 | 747 | |
|---|
| 833 | 748 | static void venc_uninit_output(struct venc_device *venc) |
|---|
| 834 | 749 | { |
|---|
| 835 | | - omapdss_unregister_output(&venc->output); |
|---|
| 750 | + omapdss_device_unregister(&venc->output); |
|---|
| 751 | + omapdss_device_cleanup_output(&venc->output); |
|---|
| 752 | + |
|---|
| 753 | + venc_bridge_cleanup(venc); |
|---|
| 836 | 754 | } |
|---|
| 837 | 755 | |
|---|
| 838 | 756 | static int venc_probe_of(struct venc_device *venc) |
|---|
| .. | .. |
|---|
| 863 | 781 | venc->type = OMAP_DSS_VENC_TYPE_SVIDEO; |
|---|
| 864 | 782 | break; |
|---|
| 865 | 783 | default: |
|---|
| 866 | | - dev_err(&venc->pdev->dev, "bad channel propert '%d'\n", |
|---|
| 784 | + dev_err(&venc->pdev->dev, "bad channel property '%d'\n", |
|---|
| 867 | 785 | channels); |
|---|
| 868 | 786 | r = -EINVAL; |
|---|
| 869 | 787 | goto err; |
|---|
| .. | .. |
|---|
| 878 | 796 | return r; |
|---|
| 879 | 797 | } |
|---|
| 880 | 798 | |
|---|
| 881 | | -/* VENC HW IP initialisation */ |
|---|
| 882 | 799 | static const struct soc_device_attribute venc_soc_devices[] = { |
|---|
| 883 | 800 | { .machine = "OMAP3[45]*" }, |
|---|
| 884 | 801 | { .machine = "AM35*" }, |
|---|
| 885 | 802 | { /* sentinel */ } |
|---|
| 886 | 803 | }; |
|---|
| 887 | 804 | |
|---|
| 888 | | -static int venc_bind(struct device *dev, struct device *master, void *data) |
|---|
| 805 | +static int venc_probe(struct platform_device *pdev) |
|---|
| 889 | 806 | { |
|---|
| 890 | | - struct platform_device *pdev = to_platform_device(dev); |
|---|
| 891 | | - struct dss_device *dss = dss_get_device(master); |
|---|
| 892 | 807 | struct venc_device *venc; |
|---|
| 893 | | - u8 rev_id; |
|---|
| 894 | 808 | struct resource *venc_mem; |
|---|
| 895 | 809 | int r; |
|---|
| 896 | 810 | |
|---|
| .. | .. |
|---|
| 899 | 813 | return -ENOMEM; |
|---|
| 900 | 814 | |
|---|
| 901 | 815 | venc->pdev = pdev; |
|---|
| 902 | | - venc->dss = dss; |
|---|
| 903 | | - dev_set_drvdata(dev, venc); |
|---|
| 816 | + |
|---|
| 817 | + platform_set_drvdata(pdev, venc); |
|---|
| 904 | 818 | |
|---|
| 905 | 819 | /* The OMAP34xx, OMAP35xx and AM35xx VENC require the TV DAC clock. */ |
|---|
| 906 | 820 | if (soc_device_match(venc_soc_devices)) |
|---|
| 907 | 821 | venc->requires_tv_dac_clk = true; |
|---|
| 908 | 822 | |
|---|
| 909 | | - mutex_init(&venc->venc_lock); |
|---|
| 910 | | - |
|---|
| 911 | | - venc->wss_data = 0; |
|---|
| 823 | + venc->config = &venc_config_pal_trm; |
|---|
| 912 | 824 | |
|---|
| 913 | 825 | venc_mem = platform_get_resource(venc->pdev, IORESOURCE_MEM, 0); |
|---|
| 914 | 826 | venc->base = devm_ioremap_resource(&pdev->dev, venc_mem); |
|---|
| .. | .. |
|---|
| 917 | 829 | goto err_free; |
|---|
| 918 | 830 | } |
|---|
| 919 | 831 | |
|---|
| 832 | + venc->vdda_dac_reg = devm_regulator_get(&pdev->dev, "vdda"); |
|---|
| 833 | + if (IS_ERR(venc->vdda_dac_reg)) { |
|---|
| 834 | + r = PTR_ERR(venc->vdda_dac_reg); |
|---|
| 835 | + if (r != -EPROBE_DEFER) |
|---|
| 836 | + DSSERR("can't get VDDA_DAC regulator\n"); |
|---|
| 837 | + goto err_free; |
|---|
| 838 | + } |
|---|
| 839 | + |
|---|
| 920 | 840 | r = venc_get_clocks(venc); |
|---|
| 841 | + if (r) |
|---|
| 842 | + goto err_free; |
|---|
| 843 | + |
|---|
| 844 | + r = venc_probe_of(venc); |
|---|
| 921 | 845 | if (r) |
|---|
| 922 | 846 | goto err_free; |
|---|
| 923 | 847 | |
|---|
| 924 | 848 | pm_runtime_enable(&pdev->dev); |
|---|
| 925 | 849 | |
|---|
| 926 | | - r = venc_runtime_get(venc); |
|---|
| 850 | + r = venc_init_output(venc); |
|---|
| 927 | 851 | if (r) |
|---|
| 928 | | - goto err_runtime_get; |
|---|
| 852 | + goto err_pm_disable; |
|---|
| 929 | 853 | |
|---|
| 930 | | - rev_id = (u8)(venc_read_reg(venc, VENC_REV_ID) & 0xff); |
|---|
| 931 | | - dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); |
|---|
| 932 | | - |
|---|
| 933 | | - venc_runtime_put(venc); |
|---|
| 934 | | - |
|---|
| 935 | | - r = venc_probe_of(venc); |
|---|
| 936 | | - if (r) { |
|---|
| 937 | | - DSSERR("Invalid DT data\n"); |
|---|
| 938 | | - goto err_probe_of; |
|---|
| 939 | | - } |
|---|
| 940 | | - |
|---|
| 941 | | - venc->debugfs = dss_debugfs_create_file(dss, "venc", venc_dump_regs, |
|---|
| 942 | | - venc); |
|---|
| 943 | | - |
|---|
| 944 | | - venc_init_output(venc); |
|---|
| 854 | + r = component_add(&pdev->dev, &venc_component_ops); |
|---|
| 855 | + if (r) |
|---|
| 856 | + goto err_uninit_output; |
|---|
| 945 | 857 | |
|---|
| 946 | 858 | return 0; |
|---|
| 947 | 859 | |
|---|
| 948 | | -err_probe_of: |
|---|
| 949 | | -err_runtime_get: |
|---|
| 860 | +err_uninit_output: |
|---|
| 861 | + venc_uninit_output(venc); |
|---|
| 862 | +err_pm_disable: |
|---|
| 950 | 863 | pm_runtime_disable(&pdev->dev); |
|---|
| 951 | 864 | err_free: |
|---|
| 952 | 865 | kfree(venc); |
|---|
| 953 | 866 | return r; |
|---|
| 954 | 867 | } |
|---|
| 955 | 868 | |
|---|
| 956 | | -static void venc_unbind(struct device *dev, struct device *master, void *data) |
|---|
| 869 | +static int venc_remove(struct platform_device *pdev) |
|---|
| 957 | 870 | { |
|---|
| 958 | | - struct venc_device *venc = dev_get_drvdata(dev); |
|---|
| 871 | + struct venc_device *venc = platform_get_drvdata(pdev); |
|---|
| 959 | 872 | |
|---|
| 960 | | - dss_debugfs_remove_file(venc->debugfs); |
|---|
| 873 | + component_del(&pdev->dev, &venc_component_ops); |
|---|
| 961 | 874 | |
|---|
| 962 | 875 | venc_uninit_output(venc); |
|---|
| 963 | 876 | |
|---|
| 964 | | - pm_runtime_disable(dev); |
|---|
| 877 | + pm_runtime_disable(&pdev->dev); |
|---|
| 965 | 878 | |
|---|
| 966 | 879 | kfree(venc); |
|---|
| 967 | | -} |
|---|
| 968 | | - |
|---|
| 969 | | -static const struct component_ops venc_component_ops = { |
|---|
| 970 | | - .bind = venc_bind, |
|---|
| 971 | | - .unbind = venc_unbind, |
|---|
| 972 | | -}; |
|---|
| 973 | | - |
|---|
| 974 | | -static int venc_probe(struct platform_device *pdev) |
|---|
| 975 | | -{ |
|---|
| 976 | | - return component_add(&pdev->dev, &venc_component_ops); |
|---|
| 977 | | -} |
|---|
| 978 | | - |
|---|
| 979 | | -static int venc_remove(struct platform_device *pdev) |
|---|
| 980 | | -{ |
|---|
| 981 | | - component_del(&pdev->dev, &venc_component_ops); |
|---|
| 982 | 880 | return 0; |
|---|
| 983 | 881 | } |
|---|
| 984 | 882 | |
|---|
| .. | .. |
|---|
| 989 | 887 | if (venc->tv_dac_clk) |
|---|
| 990 | 888 | clk_disable_unprepare(venc->tv_dac_clk); |
|---|
| 991 | 889 | |
|---|
| 992 | | - dispc_runtime_put(venc->dss->dispc); |
|---|
| 993 | | - |
|---|
| 994 | 890 | return 0; |
|---|
| 995 | 891 | } |
|---|
| 996 | 892 | |
|---|
| 997 | 893 | static int venc_runtime_resume(struct device *dev) |
|---|
| 998 | 894 | { |
|---|
| 999 | 895 | struct venc_device *venc = dev_get_drvdata(dev); |
|---|
| 1000 | | - int r; |
|---|
| 1001 | | - |
|---|
| 1002 | | - r = dispc_runtime_get(venc->dss->dispc); |
|---|
| 1003 | | - if (r < 0) |
|---|
| 1004 | | - return r; |
|---|
| 1005 | 896 | |
|---|
| 1006 | 897 | if (venc->tv_dac_clk) |
|---|
| 1007 | 898 | clk_prepare_enable(venc->tv_dac_clk); |
|---|
| .. | .. |
|---|
| 1012 | 903 | static const struct dev_pm_ops venc_pm_ops = { |
|---|
| 1013 | 904 | .runtime_suspend = venc_runtime_suspend, |
|---|
| 1014 | 905 | .runtime_resume = venc_runtime_resume, |
|---|
| 906 | + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) |
|---|
| 1015 | 907 | }; |
|---|
| 1016 | 908 | |
|---|
| 1017 | 909 | static const struct of_device_id venc_of_match[] = { |
|---|