Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * linux/drivers/video/omap2/dss/venc.c
0004  *
0005  * Copyright (C) 2009 Nokia Corporation
0006  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
0007  *
0008  * VENC settings from TI's DSS driver
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 /* Venc registers */
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 /* from TRM */
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, /* 863 */
0128     .flens                  = 0x270, /* 624 */
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 /* from TRM */
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     /* the magical sleep that makes things work */
0339     /* XXX more info? What bug this circumvents? */
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 /* S-Video */
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     /* Reset WSS data when the TV standard changes. */
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     /* Invert due to VENC_L21_WC_CTL:INV=1 */
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     /* Invert due to VENC_L21_WC_CTL:INV=1 */
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 /* VENC HW IP initialisation */
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 }