1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2009 Nokia Corporation 4 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> 5 * 6 * VENC settings from TI's DSS driver 7 */ 8 9 #define DSS_SUBSYS_NAME "VENC" 10 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/clk.h> 14 #include <linux/err.h> 15 #include <linux/io.h> 16 #include <linux/completion.h> 17 #include <linux/delay.h> 18 #include <linux/string.h> 19 #include <linux/seq_file.h> 20 #include <linux/platform_device.h> 21 #include <linux/regulator/consumer.h> 22 #include <linux/pm_runtime.h> 23 #include <linux/of.h> 24 #include <linux/of_graph.h> 25 #include <linux/component.h> 26 #include <linux/sys_soc.h> 27 28 #include <drm/drm_atomic_state_helper.h> 29 #include <drm/drm_bridge.h> 30 31 #include "omapdss.h" 32 #include "dss.h" 33 34 /* Venc registers */ 35 #define VENC_REV_ID 0x00 36 #define VENC_STATUS 0x04 37 #define VENC_F_CONTROL 0x08 38 #define VENC_VIDOUT_CTRL 0x10 39 #define VENC_SYNC_CTRL 0x14 40 #define VENC_LLEN 0x1C 41 #define VENC_FLENS 0x20 42 #define VENC_HFLTR_CTRL 0x24 43 #define VENC_CC_CARR_WSS_CARR 0x28 44 #define VENC_C_PHASE 0x2C 45 #define VENC_GAIN_U 0x30 46 #define VENC_GAIN_V 0x34 47 #define VENC_GAIN_Y 0x38 48 #define VENC_BLACK_LEVEL 0x3C 49 #define VENC_BLANK_LEVEL 0x40 50 #define VENC_X_COLOR 0x44 51 #define VENC_M_CONTROL 0x48 52 #define VENC_BSTAMP_WSS_DATA 0x4C 53 #define VENC_S_CARR 0x50 54 #define VENC_LINE21 0x54 55 #define VENC_LN_SEL 0x58 56 #define VENC_L21__WC_CTL 0x5C 57 #define VENC_HTRIGGER_VTRIGGER 0x60 58 #define VENC_SAVID__EAVID 0x64 59 #define VENC_FLEN__FAL 0x68 60 #define VENC_LAL__PHASE_RESET 0x6C 61 #define VENC_HS_INT_START_STOP_X 0x70 62 #define VENC_HS_EXT_START_STOP_X 0x74 63 #define VENC_VS_INT_START_X 0x78 64 #define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C 65 #define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80 66 #define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84 67 #define VENC_VS_EXT_STOP_Y 0x88 68 #define VENC_AVID_START_STOP_X 0x90 69 #define VENC_AVID_START_STOP_Y 0x94 70 #define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0 71 #define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4 72 #define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8 73 #define VENC_TVDETGP_INT_START_STOP_X 0xB0 74 #define VENC_TVDETGP_INT_START_STOP_Y 0xB4 75 #define VENC_GEN_CTRL 0xB8 76 #define VENC_OUTPUT_CONTROL 0xC4 77 #define VENC_OUTPUT_TEST 0xC8 78 #define VENC_DAC_B__DAC_C 0xC8 79 80 struct venc_config { 81 u32 f_control; 82 u32 vidout_ctrl; 83 u32 sync_ctrl; 84 u32 llen; 85 u32 flens; 86 u32 hfltr_ctrl; 87 u32 cc_carr_wss_carr; 88 u32 c_phase; 89 u32 gain_u; 90 u32 gain_v; 91 u32 gain_y; 92 u32 black_level; 93 u32 blank_level; 94 u32 x_color; 95 u32 m_control; 96 u32 bstamp_wss_data; 97 u32 s_carr; 98 u32 line21; 99 u32 ln_sel; 100 u32 l21__wc_ctl; 101 u32 htrigger_vtrigger; 102 u32 savid__eavid; 103 u32 flen__fal; 104 u32 lal__phase_reset; 105 u32 hs_int_start_stop_x; 106 u32 hs_ext_start_stop_x; 107 u32 vs_int_start_x; 108 u32 vs_int_stop_x__vs_int_start_y; 109 u32 vs_int_stop_y__vs_ext_start_x; 110 u32 vs_ext_stop_x__vs_ext_start_y; 111 u32 vs_ext_stop_y; 112 u32 avid_start_stop_x; 113 u32 avid_start_stop_y; 114 u32 fid_int_start_x__fid_int_start_y; 115 u32 fid_int_offset_y__fid_ext_start_x; 116 u32 fid_ext_start_y__fid_ext_offset_y; 117 u32 tvdetgp_int_start_stop_x; 118 u32 tvdetgp_int_start_stop_y; 119 u32 gen_ctrl; 120 }; 121 122 /* from TRM */ 123 static const struct venc_config venc_config_pal_trm = { 124 .f_control = 0, 125 .vidout_ctrl = 1, 126 .sync_ctrl = 0x40, 127 .llen = 0x35F, /* 863 */ 128 .flens = 0x270, /* 624 */ 129 .hfltr_ctrl = 0, 130 .cc_carr_wss_carr = 0x2F7225ED, 131 .c_phase = 0, 132 .gain_u = 0x111, 133 .gain_v = 0x181, 134 .gain_y = 0x140, 135 .black_level = 0x3B, 136 .blank_level = 0x3B, 137 .x_color = 0x7, 138 .m_control = 0x2, 139 .bstamp_wss_data = 0x3F, 140 .s_carr = 0x2A098ACB, 141 .line21 = 0, 142 .ln_sel = 0x01290015, 143 .l21__wc_ctl = 0x0000F603, 144 .htrigger_vtrigger = 0, 145 146 .savid__eavid = 0x06A70108, 147 .flen__fal = 0x00180270, 148 .lal__phase_reset = 0x00040135, 149 .hs_int_start_stop_x = 0x00880358, 150 .hs_ext_start_stop_x = 0x000F035F, 151 .vs_int_start_x = 0x01A70000, 152 .vs_int_stop_x__vs_int_start_y = 0x000001A7, 153 .vs_int_stop_y__vs_ext_start_x = 0x01AF0000, 154 .vs_ext_stop_x__vs_ext_start_y = 0x000101AF, 155 .vs_ext_stop_y = 0x00000025, 156 .avid_start_stop_x = 0x03530083, 157 .avid_start_stop_y = 0x026C002E, 158 .fid_int_start_x__fid_int_start_y = 0x0001008A, 159 .fid_int_offset_y__fid_ext_start_x = 0x002E0138, 160 .fid_ext_start_y__fid_ext_offset_y = 0x01380001, 161 162 .tvdetgp_int_start_stop_x = 0x00140001, 163 .tvdetgp_int_start_stop_y = 0x00010001, 164 .gen_ctrl = 0x00FF0000, 165 }; 166 167 /* from TRM */ 168 static const struct venc_config venc_config_ntsc_trm = { 169 .f_control = 0, 170 .vidout_ctrl = 1, 171 .sync_ctrl = 0x8040, 172 .llen = 0x359, 173 .flens = 0x20C, 174 .hfltr_ctrl = 0, 175 .cc_carr_wss_carr = 0x043F2631, 176 .c_phase = 0, 177 .gain_u = 0x102, 178 .gain_v = 0x16C, 179 .gain_y = 0x12F, 180 .black_level = 0x43, 181 .blank_level = 0x38, 182 .x_color = 0x7, 183 .m_control = 0x1, 184 .bstamp_wss_data = 0x38, 185 .s_carr = 0x21F07C1F, 186 .line21 = 0, 187 .ln_sel = 0x01310011, 188 .l21__wc_ctl = 0x0000F003, 189 .htrigger_vtrigger = 0, 190 191 .savid__eavid = 0x069300F4, 192 .flen__fal = 0x0016020C, 193 .lal__phase_reset = 0x00060107, 194 .hs_int_start_stop_x = 0x008E0350, 195 .hs_ext_start_stop_x = 0x000F0359, 196 .vs_int_start_x = 0x01A00000, 197 .vs_int_stop_x__vs_int_start_y = 0x020701A0, 198 .vs_int_stop_y__vs_ext_start_x = 0x01AC0024, 199 .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC, 200 .vs_ext_stop_y = 0x00000006, 201 .avid_start_stop_x = 0x03480078, 202 .avid_start_stop_y = 0x02060024, 203 .fid_int_start_x__fid_int_start_y = 0x0001008A, 204 .fid_int_offset_y__fid_ext_start_x = 0x01AC0106, 205 .fid_ext_start_y__fid_ext_offset_y = 0x01060006, 206 207 .tvdetgp_int_start_stop_x = 0x00140001, 208 .tvdetgp_int_start_stop_y = 0x00010001, 209 .gen_ctrl = 0x00F90000, 210 }; 211 212 enum venc_videomode { 213 VENC_MODE_UNKNOWN, 214 VENC_MODE_PAL, 215 VENC_MODE_NTSC, 216 }; 217 218 static const struct drm_display_mode omap_dss_pal_mode = { 219 .hdisplay = 720, 220 .hsync_start = 732, 221 .hsync_end = 796, 222 .htotal = 864, 223 .vdisplay = 574, 224 .vsync_start = 579, 225 .vsync_end = 584, 226 .vtotal = 625, 227 .clock = 13500, 228 229 .flags = DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_NHSYNC | 230 DRM_MODE_FLAG_NVSYNC, 231 }; 232 233 static const struct drm_display_mode omap_dss_ntsc_mode = { 234 .hdisplay = 720, 235 .hsync_start = 736, 236 .hsync_end = 800, 237 .htotal = 858, 238 .vdisplay = 482, 239 .vsync_start = 488, 240 .vsync_end = 494, 241 .vtotal = 525, 242 .clock = 13500, 243 244 .flags = DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_NHSYNC | 245 DRM_MODE_FLAG_NVSYNC, 246 }; 247 248 struct venc_device { 249 struct platform_device *pdev; 250 void __iomem *base; 251 struct regulator *vdda_dac_reg; 252 struct dss_device *dss; 253 254 struct dss_debugfs_entry *debugfs; 255 256 struct clk *tv_dac_clk; 257 258 const struct venc_config *config; 259 enum omap_dss_venc_type type; 260 bool invert_polarity; 261 bool requires_tv_dac_clk; 262 263 struct omap_dss_device output; 264 struct drm_bridge bridge; 265 }; 266 267 #define drm_bridge_to_venc(b) container_of(b, struct venc_device, bridge) 268 269 static inline void venc_write_reg(struct venc_device *venc, int idx, u32 val) 270 { 271 __raw_writel(val, venc->base + idx); 272 } 273 274 static inline u32 venc_read_reg(struct venc_device *venc, int idx) 275 { 276 u32 l = __raw_readl(venc->base + idx); 277 return l; 278 } 279 280 static void venc_write_config(struct venc_device *venc, 281 const struct venc_config *config) 282 { 283 DSSDBG("write venc conf\n"); 284 285 venc_write_reg(venc, VENC_LLEN, config->llen); 286 venc_write_reg(venc, VENC_FLENS, config->flens); 287 venc_write_reg(venc, VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr); 288 venc_write_reg(venc, VENC_C_PHASE, config->c_phase); 289 venc_write_reg(venc, VENC_GAIN_U, config->gain_u); 290 venc_write_reg(venc, VENC_GAIN_V, config->gain_v); 291 venc_write_reg(venc, VENC_GAIN_Y, config->gain_y); 292 venc_write_reg(venc, VENC_BLACK_LEVEL, config->black_level); 293 venc_write_reg(venc, VENC_BLANK_LEVEL, config->blank_level); 294 venc_write_reg(venc, VENC_M_CONTROL, config->m_control); 295 venc_write_reg(venc, VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data); 296 venc_write_reg(venc, VENC_S_CARR, config->s_carr); 297 venc_write_reg(venc, VENC_L21__WC_CTL, config->l21__wc_ctl); 298 venc_write_reg(venc, VENC_SAVID__EAVID, config->savid__eavid); 299 venc_write_reg(venc, VENC_FLEN__FAL, config->flen__fal); 300 venc_write_reg(venc, VENC_LAL__PHASE_RESET, config->lal__phase_reset); 301 venc_write_reg(venc, VENC_HS_INT_START_STOP_X, 302 config->hs_int_start_stop_x); 303 venc_write_reg(venc, VENC_HS_EXT_START_STOP_X, 304 config->hs_ext_start_stop_x); 305 venc_write_reg(venc, VENC_VS_INT_START_X, config->vs_int_start_x); 306 venc_write_reg(venc, VENC_VS_INT_STOP_X__VS_INT_START_Y, 307 config->vs_int_stop_x__vs_int_start_y); 308 venc_write_reg(venc, VENC_VS_INT_STOP_Y__VS_EXT_START_X, 309 config->vs_int_stop_y__vs_ext_start_x); 310 venc_write_reg(venc, VENC_VS_EXT_STOP_X__VS_EXT_START_Y, 311 config->vs_ext_stop_x__vs_ext_start_y); 312 venc_write_reg(venc, VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y); 313 venc_write_reg(venc, VENC_AVID_START_STOP_X, config->avid_start_stop_x); 314 venc_write_reg(venc, VENC_AVID_START_STOP_Y, config->avid_start_stop_y); 315 venc_write_reg(venc, VENC_FID_INT_START_X__FID_INT_START_Y, 316 config->fid_int_start_x__fid_int_start_y); 317 venc_write_reg(venc, VENC_FID_INT_OFFSET_Y__FID_EXT_START_X, 318 config->fid_int_offset_y__fid_ext_start_x); 319 venc_write_reg(venc, VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y, 320 config->fid_ext_start_y__fid_ext_offset_y); 321 322 venc_write_reg(venc, VENC_DAC_B__DAC_C, 323 venc_read_reg(venc, VENC_DAC_B__DAC_C)); 324 venc_write_reg(venc, VENC_VIDOUT_CTRL, config->vidout_ctrl); 325 venc_write_reg(venc, VENC_HFLTR_CTRL, config->hfltr_ctrl); 326 venc_write_reg(venc, VENC_X_COLOR, config->x_color); 327 venc_write_reg(venc, VENC_LINE21, config->line21); 328 venc_write_reg(venc, VENC_LN_SEL, config->ln_sel); 329 venc_write_reg(venc, VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger); 330 venc_write_reg(venc, VENC_TVDETGP_INT_START_STOP_X, 331 config->tvdetgp_int_start_stop_x); 332 venc_write_reg(venc, VENC_TVDETGP_INT_START_STOP_Y, 333 config->tvdetgp_int_start_stop_y); 334 venc_write_reg(venc, VENC_GEN_CTRL, config->gen_ctrl); 335 venc_write_reg(venc, VENC_F_CONTROL, config->f_control); 336 venc_write_reg(venc, VENC_SYNC_CTRL, config->sync_ctrl); 337 } 338 339 static void venc_reset(struct venc_device *venc) 340 { 341 int t = 1000; 342 343 venc_write_reg(venc, VENC_F_CONTROL, 1<<8); 344 while (venc_read_reg(venc, VENC_F_CONTROL) & (1<<8)) { 345 if (--t == 0) { 346 DSSERR("Failed to reset venc\n"); 347 return; 348 } 349 } 350 351 #ifdef CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET 352 /* the magical sleep that makes things work */ 353 /* XXX more info? What bug this circumvents? */ 354 msleep(20); 355 #endif 356 } 357 358 static int venc_runtime_get(struct venc_device *venc) 359 { 360 int r; 361 362 DSSDBG("venc_runtime_get\n"); 363 364 r = pm_runtime_get_sync(&venc->pdev->dev); 365 if (WARN_ON(r < 0)) { 366 pm_runtime_put_noidle(&venc->pdev->dev); 367 return r; 368 } 369 return 0; 370 } 371 372 static void venc_runtime_put(struct venc_device *venc) 373 { 374 int r; 375 376 DSSDBG("venc_runtime_put\n"); 377 378 r = pm_runtime_put_sync(&venc->pdev->dev); 379 WARN_ON(r < 0 && r != -ENOSYS); 380 } 381 382 static int venc_power_on(struct venc_device *venc) 383 { 384 u32 l; 385 int r; 386 387 r = venc_runtime_get(venc); 388 if (r) 389 goto err0; 390 391 venc_reset(venc); 392 venc_write_config(venc, venc->config); 393 394 dss_set_venc_output(venc->dss, venc->type); 395 dss_set_dac_pwrdn_bgz(venc->dss, 1); 396 397 l = 0; 398 399 if (venc->type == OMAP_DSS_VENC_TYPE_COMPOSITE) 400 l |= 1 << 1; 401 else /* S-Video */ 402 l |= (1 << 0) | (1 << 2); 403 404 if (venc->invert_polarity == false) 405 l |= 1 << 3; 406 407 venc_write_reg(venc, VENC_OUTPUT_CONTROL, l); 408 409 r = regulator_enable(venc->vdda_dac_reg); 410 if (r) 411 goto err1; 412 413 r = dss_mgr_enable(&venc->output); 414 if (r) 415 goto err2; 416 417 return 0; 418 419 err2: 420 regulator_disable(venc->vdda_dac_reg); 421 err1: 422 venc_write_reg(venc, VENC_OUTPUT_CONTROL, 0); 423 dss_set_dac_pwrdn_bgz(venc->dss, 0); 424 425 venc_runtime_put(venc); 426 err0: 427 return r; 428 } 429 430 static void venc_power_off(struct venc_device *venc) 431 { 432 venc_write_reg(venc, VENC_OUTPUT_CONTROL, 0); 433 dss_set_dac_pwrdn_bgz(venc->dss, 0); 434 435 dss_mgr_disable(&venc->output); 436 437 regulator_disable(venc->vdda_dac_reg); 438 439 venc_runtime_put(venc); 440 } 441 442 static enum venc_videomode venc_get_videomode(const struct drm_display_mode *mode) 443 { 444 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) 445 return VENC_MODE_UNKNOWN; 446 447 if (mode->clock == omap_dss_pal_mode.clock && 448 mode->hdisplay == omap_dss_pal_mode.hdisplay && 449 mode->vdisplay == omap_dss_pal_mode.vdisplay) 450 return VENC_MODE_PAL; 451 452 if (mode->clock == omap_dss_ntsc_mode.clock && 453 mode->hdisplay == omap_dss_ntsc_mode.hdisplay && 454 mode->vdisplay == omap_dss_ntsc_mode.vdisplay) 455 return VENC_MODE_NTSC; 456 457 return VENC_MODE_UNKNOWN; 458 } 459 460 static int venc_dump_regs(struct seq_file *s, void *p) 461 { 462 struct venc_device *venc = s->private; 463 464 #define DUMPREG(venc, r) \ 465 seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(venc, r)) 466 467 if (venc_runtime_get(venc)) 468 return 0; 469 470 DUMPREG(venc, VENC_F_CONTROL); 471 DUMPREG(venc, VENC_VIDOUT_CTRL); 472 DUMPREG(venc, VENC_SYNC_CTRL); 473 DUMPREG(venc, VENC_LLEN); 474 DUMPREG(venc, VENC_FLENS); 475 DUMPREG(venc, VENC_HFLTR_CTRL); 476 DUMPREG(venc, VENC_CC_CARR_WSS_CARR); 477 DUMPREG(venc, VENC_C_PHASE); 478 DUMPREG(venc, VENC_GAIN_U); 479 DUMPREG(venc, VENC_GAIN_V); 480 DUMPREG(venc, VENC_GAIN_Y); 481 DUMPREG(venc, VENC_BLACK_LEVEL); 482 DUMPREG(venc, VENC_BLANK_LEVEL); 483 DUMPREG(venc, VENC_X_COLOR); 484 DUMPREG(venc, VENC_M_CONTROL); 485 DUMPREG(venc, VENC_BSTAMP_WSS_DATA); 486 DUMPREG(venc, VENC_S_CARR); 487 DUMPREG(venc, VENC_LINE21); 488 DUMPREG(venc, VENC_LN_SEL); 489 DUMPREG(venc, VENC_L21__WC_CTL); 490 DUMPREG(venc, VENC_HTRIGGER_VTRIGGER); 491 DUMPREG(venc, VENC_SAVID__EAVID); 492 DUMPREG(venc, VENC_FLEN__FAL); 493 DUMPREG(venc, VENC_LAL__PHASE_RESET); 494 DUMPREG(venc, VENC_HS_INT_START_STOP_X); 495 DUMPREG(venc, VENC_HS_EXT_START_STOP_X); 496 DUMPREG(venc, VENC_VS_INT_START_X); 497 DUMPREG(venc, VENC_VS_INT_STOP_X__VS_INT_START_Y); 498 DUMPREG(venc, VENC_VS_INT_STOP_Y__VS_EXT_START_X); 499 DUMPREG(venc, VENC_VS_EXT_STOP_X__VS_EXT_START_Y); 500 DUMPREG(venc, VENC_VS_EXT_STOP_Y); 501 DUMPREG(venc, VENC_AVID_START_STOP_X); 502 DUMPREG(venc, VENC_AVID_START_STOP_Y); 503 DUMPREG(venc, VENC_FID_INT_START_X__FID_INT_START_Y); 504 DUMPREG(venc, VENC_FID_INT_OFFSET_Y__FID_EXT_START_X); 505 DUMPREG(venc, VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y); 506 DUMPREG(venc, VENC_TVDETGP_INT_START_STOP_X); 507 DUMPREG(venc, VENC_TVDETGP_INT_START_STOP_Y); 508 DUMPREG(venc, VENC_GEN_CTRL); 509 DUMPREG(venc, VENC_OUTPUT_CONTROL); 510 DUMPREG(venc, VENC_OUTPUT_TEST); 511 512 venc_runtime_put(venc); 513 514 #undef DUMPREG 515 return 0; 516 } 517 518 static int venc_get_clocks(struct venc_device *venc) 519 { 520 struct clk *clk; 521 522 if (venc->requires_tv_dac_clk) { 523 clk = devm_clk_get(&venc->pdev->dev, "tv_dac_clk"); 524 if (IS_ERR(clk)) { 525 DSSERR("can't get tv_dac_clk\n"); 526 return PTR_ERR(clk); 527 } 528 } else { 529 clk = NULL; 530 } 531 532 venc->tv_dac_clk = clk; 533 534 return 0; 535 } 536 537 /* ----------------------------------------------------------------------------- 538 * DRM Bridge Operations 539 */ 540 541 static int venc_bridge_attach(struct drm_bridge *bridge, 542 struct drm_encoder *encoder, 543 enum drm_bridge_attach_flags flags) 544 { 545 struct venc_device *venc = drm_bridge_to_venc(bridge); 546 547 if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) 548 return -EINVAL; 549 550 return drm_bridge_attach(encoder, venc->output.next_bridge, 551 bridge, flags); 552 } 553 554 static enum drm_mode_status 555 venc_bridge_mode_valid(struct drm_bridge *bridge, 556 const struct drm_display_info *info, 557 const struct drm_display_mode *mode) 558 { 559 switch (venc_get_videomode(mode)) { 560 case VENC_MODE_PAL: 561 case VENC_MODE_NTSC: 562 return MODE_OK; 563 564 default: 565 return MODE_BAD; 566 } 567 } 568 569 static bool venc_bridge_mode_fixup(struct drm_bridge *bridge, 570 const struct drm_display_mode *mode, 571 struct drm_display_mode *adjusted_mode) 572 { 573 const struct drm_display_mode *venc_mode; 574 575 switch (venc_get_videomode(adjusted_mode)) { 576 case VENC_MODE_PAL: 577 venc_mode = &omap_dss_pal_mode; 578 break; 579 580 case VENC_MODE_NTSC: 581 venc_mode = &omap_dss_ntsc_mode; 582 break; 583 584 default: 585 return false; 586 } 587 588 drm_mode_copy(adjusted_mode, venc_mode); 589 drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); 590 drm_mode_set_name(adjusted_mode); 591 592 return true; 593 } 594 595 static void venc_bridge_mode_set(struct drm_bridge *bridge, 596 const struct drm_display_mode *mode, 597 const struct drm_display_mode *adjusted_mode) 598 { 599 struct venc_device *venc = drm_bridge_to_venc(bridge); 600 enum venc_videomode venc_mode = venc_get_videomode(adjusted_mode); 601 602 switch (venc_mode) { 603 default: 604 WARN_ON_ONCE(1); 605 fallthrough; 606 case VENC_MODE_PAL: 607 venc->config = &venc_config_pal_trm; 608 break; 609 610 case VENC_MODE_NTSC: 611 venc->config = &venc_config_ntsc_trm; 612 break; 613 } 614 615 dispc_set_tv_pclk(venc->dss->dispc, 13500000); 616 } 617 618 static void venc_bridge_enable(struct drm_bridge *bridge, 619 struct drm_atomic_commit *commit) 620 { 621 struct venc_device *venc = drm_bridge_to_venc(bridge); 622 623 venc_power_on(venc); 624 } 625 626 static void venc_bridge_disable(struct drm_bridge *bridge, 627 struct drm_atomic_commit *commit) 628 { 629 struct venc_device *venc = drm_bridge_to_venc(bridge); 630 631 venc_power_off(venc); 632 } 633 634 static int venc_bridge_get_modes(struct drm_bridge *bridge, 635 struct drm_connector *connector) 636 { 637 static const struct drm_display_mode *modes[] = { 638 &omap_dss_pal_mode, 639 &omap_dss_ntsc_mode, 640 }; 641 unsigned int i; 642 643 for (i = 0; i < ARRAY_SIZE(modes); ++i) { 644 struct drm_display_mode *mode; 645 646 mode = drm_mode_duplicate(connector->dev, modes[i]); 647 if (!mode) 648 return i; 649 650 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 651 drm_mode_set_name(mode); 652 drm_mode_probed_add(connector, mode); 653 } 654 655 return ARRAY_SIZE(modes); 656 } 657 658 static const struct drm_bridge_funcs venc_bridge_funcs = { 659 .atomic_create_state = drm_atomic_helper_bridge_create_state, 660 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, 661 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, 662 .attach = venc_bridge_attach, 663 .mode_valid = venc_bridge_mode_valid, 664 .mode_fixup = venc_bridge_mode_fixup, 665 .mode_set = venc_bridge_mode_set, 666 .atomic_enable = venc_bridge_enable, 667 .atomic_disable = venc_bridge_disable, 668 .get_modes = venc_bridge_get_modes, 669 }; 670 671 static void venc_bridge_init(struct venc_device *venc) 672 { 673 venc->bridge.of_node = venc->pdev->dev.of_node; 674 venc->bridge.ops = DRM_BRIDGE_OP_MODES; 675 venc->bridge.type = DRM_MODE_CONNECTOR_SVIDEO; 676 venc->bridge.interlace_allowed = true; 677 678 drm_bridge_add(&venc->bridge); 679 } 680 681 static void venc_bridge_cleanup(struct venc_device *venc) 682 { 683 drm_bridge_remove(&venc->bridge); 684 } 685 686 /* ----------------------------------------------------------------------------- 687 * Component Bind & Unbind 688 */ 689 690 static int venc_bind(struct device *dev, struct device *master, void *data) 691 { 692 struct dss_device *dss = dss_get_device(master); 693 struct venc_device *venc = dev_get_drvdata(dev); 694 u8 rev_id; 695 int r; 696 697 venc->dss = dss; 698 699 r = venc_runtime_get(venc); 700 if (r) 701 return r; 702 703 rev_id = (u8)(venc_read_reg(venc, VENC_REV_ID) & 0xff); 704 dev_dbg(dev, "OMAP VENC rev %d\n", rev_id); 705 706 venc_runtime_put(venc); 707 708 venc->debugfs = dss_debugfs_create_file(dss, "venc", venc_dump_regs, 709 venc); 710 711 return 0; 712 } 713 714 static void venc_unbind(struct device *dev, struct device *master, void *data) 715 { 716 struct venc_device *venc = dev_get_drvdata(dev); 717 718 dss_debugfs_remove_file(venc->debugfs); 719 } 720 721 static const struct component_ops venc_component_ops = { 722 .bind = venc_bind, 723 .unbind = venc_unbind, 724 }; 725 726 /* ----------------------------------------------------------------------------- 727 * Probe & Remove, Suspend & Resume 728 */ 729 730 static int venc_init_output(struct venc_device *venc) 731 { 732 struct omap_dss_device *out = &venc->output; 733 int r; 734 735 venc_bridge_init(venc); 736 737 out->dev = &venc->pdev->dev; 738 out->id = OMAP_DSS_OUTPUT_VENC; 739 out->type = OMAP_DISPLAY_TYPE_VENC; 740 out->name = "venc.0"; 741 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; 742 out->of_port = 0; 743 744 r = omapdss_device_init_output(out, &venc->bridge); 745 if (r < 0) { 746 venc_bridge_cleanup(venc); 747 return r; 748 } 749 750 omapdss_device_register(out); 751 752 return 0; 753 } 754 755 static void venc_uninit_output(struct venc_device *venc) 756 { 757 omapdss_device_unregister(&venc->output); 758 omapdss_device_cleanup_output(&venc->output); 759 760 venc_bridge_cleanup(venc); 761 } 762 763 static int venc_probe_of(struct venc_device *venc) 764 { 765 struct device_node *node = venc->pdev->dev.of_node; 766 struct device_node *ep; 767 u32 channels; 768 int r; 769 770 ep = of_graph_get_endpoint_by_regs(node, 0, 0); 771 if (!ep) 772 return 0; 773 774 venc->invert_polarity = of_property_read_bool(ep, "ti,invert-polarity"); 775 776 r = of_property_read_u32(ep, "ti,channels", &channels); 777 if (r) { 778 dev_err(&venc->pdev->dev, 779 "failed to read property 'ti,channels': %d\n", r); 780 goto err; 781 } 782 783 switch (channels) { 784 case 1: 785 venc->type = OMAP_DSS_VENC_TYPE_COMPOSITE; 786 break; 787 case 2: 788 venc->type = OMAP_DSS_VENC_TYPE_SVIDEO; 789 break; 790 default: 791 dev_err(&venc->pdev->dev, "bad channel property '%d'\n", 792 channels); 793 r = -EINVAL; 794 goto err; 795 } 796 797 of_node_put(ep); 798 799 return 0; 800 801 err: 802 of_node_put(ep); 803 return r; 804 } 805 806 static const struct soc_device_attribute venc_soc_devices[] = { 807 { .machine = "OMAP3[45]*" }, 808 { .machine = "AM35*" }, 809 { /* sentinel */ } 810 }; 811 812 static int venc_probe(struct platform_device *pdev) 813 { 814 struct venc_device *venc; 815 int r; 816 817 venc = devm_drm_bridge_alloc(&pdev->dev, struct venc_device, bridge, &venc_bridge_funcs); 818 if (IS_ERR(venc)) 819 return PTR_ERR(venc); 820 821 venc->pdev = pdev; 822 823 platform_set_drvdata(pdev, venc); 824 825 /* The OMAP34xx, OMAP35xx and AM35xx VENC require the TV DAC clock. */ 826 if (soc_device_match(venc_soc_devices)) 827 venc->requires_tv_dac_clk = true; 828 829 venc->config = &venc_config_pal_trm; 830 831 venc->base = devm_platform_ioremap_resource(pdev, 0); 832 if (IS_ERR(venc->base)) 833 return PTR_ERR(venc->base); 834 835 venc->vdda_dac_reg = devm_regulator_get(&pdev->dev, "vdda"); 836 if (IS_ERR(venc->vdda_dac_reg)) { 837 r = PTR_ERR(venc->vdda_dac_reg); 838 if (r != -EPROBE_DEFER) 839 DSSERR("can't get VDDA_DAC regulator\n"); 840 return r; 841 } 842 843 r = venc_get_clocks(venc); 844 if (r) 845 return r; 846 847 r = venc_probe_of(venc); 848 if (r) 849 return r; 850 851 pm_runtime_enable(&pdev->dev); 852 853 r = venc_init_output(venc); 854 if (r) 855 goto err_pm_disable; 856 857 r = component_add(&pdev->dev, &venc_component_ops); 858 if (r) 859 goto err_uninit_output; 860 861 return 0; 862 863 err_uninit_output: 864 venc_uninit_output(venc); 865 err_pm_disable: 866 pm_runtime_disable(&pdev->dev); 867 return r; 868 } 869 870 static void venc_remove(struct platform_device *pdev) 871 { 872 struct venc_device *venc = platform_get_drvdata(pdev); 873 874 component_del(&pdev->dev, &venc_component_ops); 875 876 venc_uninit_output(venc); 877 878 pm_runtime_disable(&pdev->dev); 879 } 880 881 static __maybe_unused int venc_runtime_suspend(struct device *dev) 882 { 883 struct venc_device *venc = dev_get_drvdata(dev); 884 885 if (venc->tv_dac_clk) 886 clk_disable_unprepare(venc->tv_dac_clk); 887 888 return 0; 889 } 890 891 static __maybe_unused int venc_runtime_resume(struct device *dev) 892 { 893 struct venc_device *venc = dev_get_drvdata(dev); 894 895 if (venc->tv_dac_clk) 896 clk_prepare_enable(venc->tv_dac_clk); 897 898 return 0; 899 } 900 901 static const struct dev_pm_ops venc_pm_ops = { 902 SET_RUNTIME_PM_OPS(venc_runtime_suspend, venc_runtime_resume, NULL) 903 SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) 904 }; 905 906 static const struct of_device_id venc_of_match[] = { 907 { .compatible = "ti,omap2-venc", }, 908 { .compatible = "ti,omap3-venc", }, 909 { .compatible = "ti,omap4-venc", }, 910 {}, 911 }; 912 913 struct platform_driver omap_venchw_driver = { 914 .probe = venc_probe, 915 .remove = venc_remove, 916 .driver = { 917 .name = "omapdss_venc", 918 .pm = &venc_pm_ops, 919 .of_match_table = venc_of_match, 920 .suppress_bind_attrs = true, 921 }, 922 }; 923