0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define DSS_SUBSYS_NAME "VENC"
0012
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include <linux/clk.h>
0016 #include <linux/err.h>
0017 #include <linux/io.h>
0018 #include <linux/mutex.h>
0019 #include <linux/completion.h>
0020 #include <linux/delay.h>
0021 #include <linux/string.h>
0022 #include <linux/seq_file.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/regulator/consumer.h>
0025 #include <linux/pm_runtime.h>
0026 #include <linux/of.h>
0027 #include <linux/component.h>
0028
0029 #include <video/omapfb_dss.h>
0030
0031 #include "dss.h"
0032 #include "dss_features.h"
0033
0034
0035 #define VENC_REV_ID 0x00
0036 #define VENC_STATUS 0x04
0037 #define VENC_F_CONTROL 0x08
0038 #define VENC_VIDOUT_CTRL 0x10
0039 #define VENC_SYNC_CTRL 0x14
0040 #define VENC_LLEN 0x1C
0041 #define VENC_FLENS 0x20
0042 #define VENC_HFLTR_CTRL 0x24
0043 #define VENC_CC_CARR_WSS_CARR 0x28
0044 #define VENC_C_PHASE 0x2C
0045 #define VENC_GAIN_U 0x30
0046 #define VENC_GAIN_V 0x34
0047 #define VENC_GAIN_Y 0x38
0048 #define VENC_BLACK_LEVEL 0x3C
0049 #define VENC_BLANK_LEVEL 0x40
0050 #define VENC_X_COLOR 0x44
0051 #define VENC_M_CONTROL 0x48
0052 #define VENC_BSTAMP_WSS_DATA 0x4C
0053 #define VENC_S_CARR 0x50
0054 #define VENC_LINE21 0x54
0055 #define VENC_LN_SEL 0x58
0056 #define VENC_L21__WC_CTL 0x5C
0057 #define VENC_HTRIGGER_VTRIGGER 0x60
0058 #define VENC_SAVID__EAVID 0x64
0059 #define VENC_FLEN__FAL 0x68
0060 #define VENC_LAL__PHASE_RESET 0x6C
0061 #define VENC_HS_INT_START_STOP_X 0x70
0062 #define VENC_HS_EXT_START_STOP_X 0x74
0063 #define VENC_VS_INT_START_X 0x78
0064 #define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C
0065 #define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80
0066 #define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84
0067 #define VENC_VS_EXT_STOP_Y 0x88
0068 #define VENC_AVID_START_STOP_X 0x90
0069 #define VENC_AVID_START_STOP_Y 0x94
0070 #define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0
0071 #define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4
0072 #define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8
0073 #define VENC_TVDETGP_INT_START_STOP_X 0xB0
0074 #define VENC_TVDETGP_INT_START_STOP_Y 0xB4
0075 #define VENC_GEN_CTRL 0xB8
0076 #define VENC_OUTPUT_CONTROL 0xC4
0077 #define VENC_OUTPUT_TEST 0xC8
0078 #define VENC_DAC_B__DAC_C 0xC8
0079
0080 struct venc_config {
0081 u32 f_control;
0082 u32 vidout_ctrl;
0083 u32 sync_ctrl;
0084 u32 llen;
0085 u32 flens;
0086 u32 hfltr_ctrl;
0087 u32 cc_carr_wss_carr;
0088 u32 c_phase;
0089 u32 gain_u;
0090 u32 gain_v;
0091 u32 gain_y;
0092 u32 black_level;
0093 u32 blank_level;
0094 u32 x_color;
0095 u32 m_control;
0096 u32 bstamp_wss_data;
0097 u32 s_carr;
0098 u32 line21;
0099 u32 ln_sel;
0100 u32 l21__wc_ctl;
0101 u32 htrigger_vtrigger;
0102 u32 savid__eavid;
0103 u32 flen__fal;
0104 u32 lal__phase_reset;
0105 u32 hs_int_start_stop_x;
0106 u32 hs_ext_start_stop_x;
0107 u32 vs_int_start_x;
0108 u32 vs_int_stop_x__vs_int_start_y;
0109 u32 vs_int_stop_y__vs_ext_start_x;
0110 u32 vs_ext_stop_x__vs_ext_start_y;
0111 u32 vs_ext_stop_y;
0112 u32 avid_start_stop_x;
0113 u32 avid_start_stop_y;
0114 u32 fid_int_start_x__fid_int_start_y;
0115 u32 fid_int_offset_y__fid_ext_start_x;
0116 u32 fid_ext_start_y__fid_ext_offset_y;
0117 u32 tvdetgp_int_start_stop_x;
0118 u32 tvdetgp_int_start_stop_y;
0119 u32 gen_ctrl;
0120 };
0121
0122
0123 static const struct venc_config venc_config_pal_trm = {
0124 .f_control = 0,
0125 .vidout_ctrl = 1,
0126 .sync_ctrl = 0x40,
0127 .llen = 0x35F,
0128 .flens = 0x270,
0129 .hfltr_ctrl = 0,
0130 .cc_carr_wss_carr = 0x2F7225ED,
0131 .c_phase = 0,
0132 .gain_u = 0x111,
0133 .gain_v = 0x181,
0134 .gain_y = 0x140,
0135 .black_level = 0x3B,
0136 .blank_level = 0x3B,
0137 .x_color = 0x7,
0138 .m_control = 0x2,
0139 .bstamp_wss_data = 0x3F,
0140 .s_carr = 0x2A098ACB,
0141 .line21 = 0,
0142 .ln_sel = 0x01290015,
0143 .l21__wc_ctl = 0x0000F603,
0144 .htrigger_vtrigger = 0,
0145
0146 .savid__eavid = 0x06A70108,
0147 .flen__fal = 0x00180270,
0148 .lal__phase_reset = 0x00040135,
0149 .hs_int_start_stop_x = 0x00880358,
0150 .hs_ext_start_stop_x = 0x000F035F,
0151 .vs_int_start_x = 0x01A70000,
0152 .vs_int_stop_x__vs_int_start_y = 0x000001A7,
0153 .vs_int_stop_y__vs_ext_start_x = 0x01AF0000,
0154 .vs_ext_stop_x__vs_ext_start_y = 0x000101AF,
0155 .vs_ext_stop_y = 0x00000025,
0156 .avid_start_stop_x = 0x03530083,
0157 .avid_start_stop_y = 0x026C002E,
0158 .fid_int_start_x__fid_int_start_y = 0x0001008A,
0159 .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
0160 .fid_ext_start_y__fid_ext_offset_y = 0x01380001,
0161
0162 .tvdetgp_int_start_stop_x = 0x00140001,
0163 .tvdetgp_int_start_stop_y = 0x00010001,
0164 .gen_ctrl = 0x00FF0000,
0165 };
0166
0167
0168 static const struct venc_config venc_config_ntsc_trm = {
0169 .f_control = 0,
0170 .vidout_ctrl = 1,
0171 .sync_ctrl = 0x8040,
0172 .llen = 0x359,
0173 .flens = 0x20C,
0174 .hfltr_ctrl = 0,
0175 .cc_carr_wss_carr = 0x043F2631,
0176 .c_phase = 0,
0177 .gain_u = 0x102,
0178 .gain_v = 0x16C,
0179 .gain_y = 0x12F,
0180 .black_level = 0x43,
0181 .blank_level = 0x38,
0182 .x_color = 0x7,
0183 .m_control = 0x1,
0184 .bstamp_wss_data = 0x38,
0185 .s_carr = 0x21F07C1F,
0186 .line21 = 0,
0187 .ln_sel = 0x01310011,
0188 .l21__wc_ctl = 0x0000F003,
0189 .htrigger_vtrigger = 0,
0190
0191 .savid__eavid = 0x069300F4,
0192 .flen__fal = 0x0016020C,
0193 .lal__phase_reset = 0x00060107,
0194 .hs_int_start_stop_x = 0x008E0350,
0195 .hs_ext_start_stop_x = 0x000F0359,
0196 .vs_int_start_x = 0x01A00000,
0197 .vs_int_stop_x__vs_int_start_y = 0x020701A0,
0198 .vs_int_stop_y__vs_ext_start_x = 0x01AC0024,
0199 .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC,
0200 .vs_ext_stop_y = 0x00000006,
0201 .avid_start_stop_x = 0x03480078,
0202 .avid_start_stop_y = 0x02060024,
0203 .fid_int_start_x__fid_int_start_y = 0x0001008A,
0204 .fid_int_offset_y__fid_ext_start_x = 0x01AC0106,
0205 .fid_ext_start_y__fid_ext_offset_y = 0x01060006,
0206
0207 .tvdetgp_int_start_stop_x = 0x00140001,
0208 .tvdetgp_int_start_stop_y = 0x00010001,
0209 .gen_ctrl = 0x00F90000,
0210 };
0211
0212 const struct omap_video_timings omap_dss_pal_timings = {
0213 .x_res = 720,
0214 .y_res = 574,
0215 .pixelclock = 13500000,
0216 .hsw = 64,
0217 .hfp = 12,
0218 .hbp = 68,
0219 .vsw = 5,
0220 .vfp = 5,
0221 .vbp = 41,
0222
0223 .interlace = true,
0224 };
0225 EXPORT_SYMBOL(omap_dss_pal_timings);
0226
0227 const struct omap_video_timings omap_dss_ntsc_timings = {
0228 .x_res = 720,
0229 .y_res = 482,
0230 .pixelclock = 13500000,
0231 .hsw = 64,
0232 .hfp = 16,
0233 .hbp = 58,
0234 .vsw = 6,
0235 .vfp = 6,
0236 .vbp = 31,
0237
0238 .interlace = true,
0239 };
0240 EXPORT_SYMBOL(omap_dss_ntsc_timings);
0241
0242 static struct {
0243 struct platform_device *pdev;
0244 void __iomem *base;
0245 struct mutex venc_lock;
0246 u32 wss_data;
0247 struct regulator *vdda_dac_reg;
0248
0249 struct clk *tv_dac_clk;
0250
0251 struct omap_video_timings timings;
0252 enum omap_dss_venc_type type;
0253 bool invert_polarity;
0254
0255 struct omap_dss_device output;
0256 } venc;
0257
0258 static inline void venc_write_reg(int idx, u32 val)
0259 {
0260 __raw_writel(val, venc.base + idx);
0261 }
0262
0263 static inline u32 venc_read_reg(int idx)
0264 {
0265 u32 l = __raw_readl(venc.base + idx);
0266 return l;
0267 }
0268
0269 static void venc_write_config(const struct venc_config *config)
0270 {
0271 DSSDBG("write venc conf\n");
0272
0273 venc_write_reg(VENC_LLEN, config->llen);
0274 venc_write_reg(VENC_FLENS, config->flens);
0275 venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
0276 venc_write_reg(VENC_C_PHASE, config->c_phase);
0277 venc_write_reg(VENC_GAIN_U, config->gain_u);
0278 venc_write_reg(VENC_GAIN_V, config->gain_v);
0279 venc_write_reg(VENC_GAIN_Y, config->gain_y);
0280 venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
0281 venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
0282 venc_write_reg(VENC_M_CONTROL, config->m_control);
0283 venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
0284 venc.wss_data);
0285 venc_write_reg(VENC_S_CARR, config->s_carr);
0286 venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
0287 venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
0288 venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
0289 venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
0290 venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
0291 venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
0292 venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
0293 venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
0294 config->vs_int_stop_x__vs_int_start_y);
0295 venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
0296 config->vs_int_stop_y__vs_ext_start_x);
0297 venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
0298 config->vs_ext_stop_x__vs_ext_start_y);
0299 venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
0300 venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
0301 venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
0302 venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
0303 config->fid_int_start_x__fid_int_start_y);
0304 venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
0305 config->fid_int_offset_y__fid_ext_start_x);
0306 venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
0307 config->fid_ext_start_y__fid_ext_offset_y);
0308
0309 venc_write_reg(VENC_DAC_B__DAC_C, venc_read_reg(VENC_DAC_B__DAC_C));
0310 venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
0311 venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
0312 venc_write_reg(VENC_X_COLOR, config->x_color);
0313 venc_write_reg(VENC_LINE21, config->line21);
0314 venc_write_reg(VENC_LN_SEL, config->ln_sel);
0315 venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
0316 venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
0317 config->tvdetgp_int_start_stop_x);
0318 venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
0319 config->tvdetgp_int_start_stop_y);
0320 venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
0321 venc_write_reg(VENC_F_CONTROL, config->f_control);
0322 venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
0323 }
0324
0325 static void venc_reset(void)
0326 {
0327 int t = 1000;
0328
0329 venc_write_reg(VENC_F_CONTROL, 1<<8);
0330 while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
0331 if (--t == 0) {
0332 DSSERR("Failed to reset venc\n");
0333 return;
0334 }
0335 }
0336
0337 #ifdef CONFIG_FB_OMAP2_DSS_SLEEP_AFTER_VENC_RESET
0338
0339
0340 msleep(20);
0341 #endif
0342 }
0343
0344 static int venc_runtime_get(void)
0345 {
0346 int r;
0347
0348 DSSDBG("venc_runtime_get\n");
0349
0350 r = pm_runtime_get_sync(&venc.pdev->dev);
0351 if (WARN_ON(r < 0)) {
0352 pm_runtime_put_sync(&venc.pdev->dev);
0353 return r;
0354 }
0355 return 0;
0356 }
0357
0358 static void venc_runtime_put(void)
0359 {
0360 int r;
0361
0362 DSSDBG("venc_runtime_put\n");
0363
0364 r = pm_runtime_put_sync(&venc.pdev->dev);
0365 WARN_ON(r < 0 && r != -ENOSYS);
0366 }
0367
0368 static const struct venc_config *venc_timings_to_config(
0369 struct omap_video_timings *timings)
0370 {
0371 if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
0372 return &venc_config_pal_trm;
0373
0374 if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
0375 return &venc_config_ntsc_trm;
0376
0377 BUG();
0378 return NULL;
0379 }
0380
0381 static int venc_power_on(struct omap_dss_device *dssdev)
0382 {
0383 struct omap_overlay_manager *mgr = venc.output.manager;
0384 u32 l;
0385 int r;
0386
0387 r = venc_runtime_get();
0388 if (r)
0389 goto err0;
0390
0391 venc_reset();
0392 venc_write_config(venc_timings_to_config(&venc.timings));
0393
0394 dss_set_venc_output(venc.type);
0395 dss_set_dac_pwrdn_bgz(1);
0396
0397 l = 0;
0398
0399 if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
0400 l |= 1 << 1;
0401 else
0402 l |= (1 << 0) | (1 << 2);
0403
0404 if (venc.invert_polarity == false)
0405 l |= 1 << 3;
0406
0407 venc_write_reg(VENC_OUTPUT_CONTROL, l);
0408
0409 dss_mgr_set_timings(mgr, &venc.timings);
0410
0411 r = regulator_enable(venc.vdda_dac_reg);
0412 if (r)
0413 goto err1;
0414
0415 r = dss_mgr_enable(mgr);
0416 if (r)
0417 goto err2;
0418
0419 return 0;
0420
0421 err2:
0422 regulator_disable(venc.vdda_dac_reg);
0423 err1:
0424 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
0425 dss_set_dac_pwrdn_bgz(0);
0426
0427 venc_runtime_put();
0428 err0:
0429 return r;
0430 }
0431
0432 static void venc_power_off(struct omap_dss_device *dssdev)
0433 {
0434 struct omap_overlay_manager *mgr = venc.output.manager;
0435
0436 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
0437 dss_set_dac_pwrdn_bgz(0);
0438
0439 dss_mgr_disable(mgr);
0440
0441 regulator_disable(venc.vdda_dac_reg);
0442
0443 venc_runtime_put();
0444 }
0445
0446 static int venc_display_enable(struct omap_dss_device *dssdev)
0447 {
0448 struct omap_dss_device *out = &venc.output;
0449 int r;
0450
0451 DSSDBG("venc_display_enable\n");
0452
0453 mutex_lock(&venc.venc_lock);
0454
0455 if (out->manager == NULL) {
0456 DSSERR("Failed to enable display: no output/manager\n");
0457 r = -ENODEV;
0458 goto err0;
0459 }
0460
0461 r = venc_power_on(dssdev);
0462 if (r)
0463 goto err0;
0464
0465 venc.wss_data = 0;
0466
0467 mutex_unlock(&venc.venc_lock);
0468
0469 return 0;
0470 err0:
0471 mutex_unlock(&venc.venc_lock);
0472 return r;
0473 }
0474
0475 static void venc_display_disable(struct omap_dss_device *dssdev)
0476 {
0477 DSSDBG("venc_display_disable\n");
0478
0479 mutex_lock(&venc.venc_lock);
0480
0481 venc_power_off(dssdev);
0482
0483 mutex_unlock(&venc.venc_lock);
0484 }
0485
0486 static void venc_set_timings(struct omap_dss_device *dssdev,
0487 struct omap_video_timings *timings)
0488 {
0489 DSSDBG("venc_set_timings\n");
0490
0491 mutex_lock(&venc.venc_lock);
0492
0493
0494 if (memcmp(&venc.timings, timings, sizeof(*timings)))
0495 venc.wss_data = 0;
0496
0497 venc.timings = *timings;
0498
0499 dispc_set_tv_pclk(13500000);
0500
0501 mutex_unlock(&venc.venc_lock);
0502 }
0503
0504 static int venc_check_timings(struct omap_dss_device *dssdev,
0505 struct omap_video_timings *timings)
0506 {
0507 DSSDBG("venc_check_timings\n");
0508
0509 if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
0510 return 0;
0511
0512 if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
0513 return 0;
0514
0515 return -EINVAL;
0516 }
0517
0518 static void venc_get_timings(struct omap_dss_device *dssdev,
0519 struct omap_video_timings *timings)
0520 {
0521 mutex_lock(&venc.venc_lock);
0522
0523 *timings = venc.timings;
0524
0525 mutex_unlock(&venc.venc_lock);
0526 }
0527
0528 static u32 venc_get_wss(struct omap_dss_device *dssdev)
0529 {
0530
0531 return (venc.wss_data >> 8) ^ 0xfffff;
0532 }
0533
0534 static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
0535 {
0536 const struct venc_config *config;
0537 int r;
0538
0539 DSSDBG("venc_set_wss\n");
0540
0541 mutex_lock(&venc.venc_lock);
0542
0543 config = venc_timings_to_config(&venc.timings);
0544
0545
0546 venc.wss_data = (wss ^ 0xfffff) << 8;
0547
0548 r = venc_runtime_get();
0549 if (r)
0550 goto err;
0551
0552 venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
0553 venc.wss_data);
0554
0555 venc_runtime_put();
0556
0557 err:
0558 mutex_unlock(&venc.venc_lock);
0559
0560 return r;
0561 }
0562
0563 static void venc_set_type(struct omap_dss_device *dssdev,
0564 enum omap_dss_venc_type type)
0565 {
0566 mutex_lock(&venc.venc_lock);
0567
0568 venc.type = type;
0569
0570 mutex_unlock(&venc.venc_lock);
0571 }
0572
0573 static void venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
0574 bool invert_polarity)
0575 {
0576 mutex_lock(&venc.venc_lock);
0577
0578 venc.invert_polarity = invert_polarity;
0579
0580 mutex_unlock(&venc.venc_lock);
0581 }
0582
0583 static int venc_init_regulator(void)
0584 {
0585 struct regulator *vdda_dac;
0586
0587 if (venc.vdda_dac_reg != NULL)
0588 return 0;
0589
0590 if (venc.pdev->dev.of_node)
0591 vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda");
0592 else
0593 vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda_dac");
0594
0595 if (IS_ERR(vdda_dac)) {
0596 if (PTR_ERR(vdda_dac) != -EPROBE_DEFER)
0597 DSSERR("can't get VDDA_DAC regulator\n");
0598 return PTR_ERR(vdda_dac);
0599 }
0600
0601 venc.vdda_dac_reg = vdda_dac;
0602
0603 return 0;
0604 }
0605
0606 static void venc_dump_regs(struct seq_file *s)
0607 {
0608 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
0609
0610 if (venc_runtime_get())
0611 return;
0612
0613 DUMPREG(VENC_F_CONTROL);
0614 DUMPREG(VENC_VIDOUT_CTRL);
0615 DUMPREG(VENC_SYNC_CTRL);
0616 DUMPREG(VENC_LLEN);
0617 DUMPREG(VENC_FLENS);
0618 DUMPREG(VENC_HFLTR_CTRL);
0619 DUMPREG(VENC_CC_CARR_WSS_CARR);
0620 DUMPREG(VENC_C_PHASE);
0621 DUMPREG(VENC_GAIN_U);
0622 DUMPREG(VENC_GAIN_V);
0623 DUMPREG(VENC_GAIN_Y);
0624 DUMPREG(VENC_BLACK_LEVEL);
0625 DUMPREG(VENC_BLANK_LEVEL);
0626 DUMPREG(VENC_X_COLOR);
0627 DUMPREG(VENC_M_CONTROL);
0628 DUMPREG(VENC_BSTAMP_WSS_DATA);
0629 DUMPREG(VENC_S_CARR);
0630 DUMPREG(VENC_LINE21);
0631 DUMPREG(VENC_LN_SEL);
0632 DUMPREG(VENC_L21__WC_CTL);
0633 DUMPREG(VENC_HTRIGGER_VTRIGGER);
0634 DUMPREG(VENC_SAVID__EAVID);
0635 DUMPREG(VENC_FLEN__FAL);
0636 DUMPREG(VENC_LAL__PHASE_RESET);
0637 DUMPREG(VENC_HS_INT_START_STOP_X);
0638 DUMPREG(VENC_HS_EXT_START_STOP_X);
0639 DUMPREG(VENC_VS_INT_START_X);
0640 DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y);
0641 DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X);
0642 DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y);
0643 DUMPREG(VENC_VS_EXT_STOP_Y);
0644 DUMPREG(VENC_AVID_START_STOP_X);
0645 DUMPREG(VENC_AVID_START_STOP_Y);
0646 DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y);
0647 DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X);
0648 DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y);
0649 DUMPREG(VENC_TVDETGP_INT_START_STOP_X);
0650 DUMPREG(VENC_TVDETGP_INT_START_STOP_Y);
0651 DUMPREG(VENC_GEN_CTRL);
0652 DUMPREG(VENC_OUTPUT_CONTROL);
0653 DUMPREG(VENC_OUTPUT_TEST);
0654
0655 venc_runtime_put();
0656
0657 #undef DUMPREG
0658 }
0659
0660 static int venc_get_clocks(struct platform_device *pdev)
0661 {
0662 struct clk *clk;
0663
0664 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
0665 clk = devm_clk_get(&pdev->dev, "tv_dac_clk");
0666 if (IS_ERR(clk)) {
0667 DSSERR("can't get tv_dac_clk\n");
0668 return PTR_ERR(clk);
0669 }
0670 } else {
0671 clk = NULL;
0672 }
0673
0674 venc.tv_dac_clk = clk;
0675
0676 return 0;
0677 }
0678
0679 static int venc_connect(struct omap_dss_device *dssdev,
0680 struct omap_dss_device *dst)
0681 {
0682 struct omap_overlay_manager *mgr;
0683 int r;
0684
0685 r = venc_init_regulator();
0686 if (r)
0687 return r;
0688
0689 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
0690 if (!mgr)
0691 return -ENODEV;
0692
0693 r = dss_mgr_connect(mgr, dssdev);
0694 if (r)
0695 return r;
0696
0697 r = omapdss_output_set_device(dssdev, dst);
0698 if (r) {
0699 DSSERR("failed to connect output to new device: %s\n",
0700 dst->name);
0701 dss_mgr_disconnect(mgr, dssdev);
0702 return r;
0703 }
0704
0705 return 0;
0706 }
0707
0708 static void venc_disconnect(struct omap_dss_device *dssdev,
0709 struct omap_dss_device *dst)
0710 {
0711 WARN_ON(dst != dssdev->dst);
0712
0713 if (dst != dssdev->dst)
0714 return;
0715
0716 omapdss_output_unset_device(dssdev);
0717
0718 if (dssdev->manager)
0719 dss_mgr_disconnect(dssdev->manager, dssdev);
0720 }
0721
0722 static const struct omapdss_atv_ops venc_ops = {
0723 .connect = venc_connect,
0724 .disconnect = venc_disconnect,
0725
0726 .enable = venc_display_enable,
0727 .disable = venc_display_disable,
0728
0729 .check_timings = venc_check_timings,
0730 .set_timings = venc_set_timings,
0731 .get_timings = venc_get_timings,
0732
0733 .set_type = venc_set_type,
0734 .invert_vid_out_polarity = venc_invert_vid_out_polarity,
0735
0736 .set_wss = venc_set_wss,
0737 .get_wss = venc_get_wss,
0738 };
0739
0740 static void venc_init_output(struct platform_device *pdev)
0741 {
0742 struct omap_dss_device *out = &venc.output;
0743
0744 out->dev = &pdev->dev;
0745 out->id = OMAP_DSS_OUTPUT_VENC;
0746 out->output_type = OMAP_DISPLAY_TYPE_VENC;
0747 out->name = "venc.0";
0748 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
0749 out->ops.atv = &venc_ops;
0750 out->owner = THIS_MODULE;
0751
0752 omapdss_register_output(out);
0753 }
0754
0755 static void venc_uninit_output(struct platform_device *pdev)
0756 {
0757 struct omap_dss_device *out = &venc.output;
0758
0759 omapdss_unregister_output(out);
0760 }
0761
0762 static int venc_probe_of(struct platform_device *pdev)
0763 {
0764 struct device_node *node = pdev->dev.of_node;
0765 struct device_node *ep;
0766 u32 channels;
0767 int r;
0768
0769 ep = omapdss_of_get_first_endpoint(node);
0770 if (!ep)
0771 return 0;
0772
0773 venc.invert_polarity = of_property_read_bool(ep, "ti,invert-polarity");
0774
0775 r = of_property_read_u32(ep, "ti,channels", &channels);
0776 if (r) {
0777 dev_err(&pdev->dev,
0778 "failed to read property 'ti,channels': %d\n", r);
0779 goto err;
0780 }
0781
0782 switch (channels) {
0783 case 1:
0784 venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE;
0785 break;
0786 case 2:
0787 venc.type = OMAP_DSS_VENC_TYPE_SVIDEO;
0788 break;
0789 default:
0790 dev_err(&pdev->dev, "bad channel property '%d'\n", channels);
0791 r = -EINVAL;
0792 goto err;
0793 }
0794
0795 of_node_put(ep);
0796
0797 return 0;
0798 err:
0799 of_node_put(ep);
0800
0801 return 0;
0802 }
0803
0804
0805 static int venc_bind(struct device *dev, struct device *master, void *data)
0806 {
0807 struct platform_device *pdev = to_platform_device(dev);
0808 u8 rev_id;
0809 struct resource *venc_mem;
0810 int r;
0811
0812 venc.pdev = pdev;
0813
0814 mutex_init(&venc.venc_lock);
0815
0816 venc.wss_data = 0;
0817
0818 venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
0819 if (!venc_mem) {
0820 DSSERR("can't get IORESOURCE_MEM VENC\n");
0821 return -EINVAL;
0822 }
0823
0824 venc.base = devm_ioremap(&pdev->dev, venc_mem->start,
0825 resource_size(venc_mem));
0826 if (!venc.base) {
0827 DSSERR("can't ioremap VENC\n");
0828 return -ENOMEM;
0829 }
0830
0831 r = venc_get_clocks(pdev);
0832 if (r)
0833 return r;
0834
0835 pm_runtime_enable(&pdev->dev);
0836
0837 r = venc_runtime_get();
0838 if (r)
0839 goto err_runtime_get;
0840
0841 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
0842 dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
0843
0844 venc_runtime_put();
0845
0846 if (pdev->dev.of_node) {
0847 r = venc_probe_of(pdev);
0848 if (r) {
0849 DSSERR("Invalid DT data\n");
0850 goto err_probe_of;
0851 }
0852 }
0853
0854 dss_debugfs_create_file("venc", venc_dump_regs);
0855
0856 venc_init_output(pdev);
0857
0858 return 0;
0859
0860 err_probe_of:
0861 err_runtime_get:
0862 pm_runtime_disable(&pdev->dev);
0863 return r;
0864 }
0865
0866 static void venc_unbind(struct device *dev, struct device *master, void *data)
0867 {
0868 struct platform_device *pdev = to_platform_device(dev);
0869
0870 venc_uninit_output(pdev);
0871
0872 pm_runtime_disable(&pdev->dev);
0873 }
0874
0875 static const struct component_ops venc_component_ops = {
0876 .bind = venc_bind,
0877 .unbind = venc_unbind,
0878 };
0879
0880 static int venc_probe(struct platform_device *pdev)
0881 {
0882 return component_add(&pdev->dev, &venc_component_ops);
0883 }
0884
0885 static int venc_remove(struct platform_device *pdev)
0886 {
0887 component_del(&pdev->dev, &venc_component_ops);
0888 return 0;
0889 }
0890
0891 static int venc_runtime_suspend(struct device *dev)
0892 {
0893 clk_disable_unprepare(venc.tv_dac_clk);
0894
0895 dispc_runtime_put();
0896
0897 return 0;
0898 }
0899
0900 static int venc_runtime_resume(struct device *dev)
0901 {
0902 int r;
0903
0904 r = dispc_runtime_get();
0905 if (r < 0)
0906 return r;
0907
0908 clk_prepare_enable(venc.tv_dac_clk);
0909
0910 return 0;
0911 }
0912
0913 static const struct dev_pm_ops venc_pm_ops = {
0914 .runtime_suspend = venc_runtime_suspend,
0915 .runtime_resume = venc_runtime_resume,
0916 };
0917
0918 static const struct of_device_id venc_of_match[] = {
0919 { .compatible = "ti,omap2-venc", },
0920 { .compatible = "ti,omap3-venc", },
0921 { .compatible = "ti,omap4-venc", },
0922 {},
0923 };
0924
0925 static struct platform_driver omap_venchw_driver = {
0926 .probe = venc_probe,
0927 .remove = venc_remove,
0928 .driver = {
0929 .name = "omapdss_venc",
0930 .pm = &venc_pm_ops,
0931 .of_match_table = venc_of_match,
0932 .suppress_bind_attrs = true,
0933 },
0934 };
0935
0936 int __init venc_init_platform_driver(void)
0937 {
0938 return platform_driver_register(&omap_venchw_driver);
0939 }
0940
0941 void venc_uninit_platform_driver(void)
0942 {
0943 platform_driver_unregister(&omap_venchw_driver);
0944 }