Back to home page

OSCL-LXR

 
 

    


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