Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2016 Broadcom
0004  */
0005 
0006 /**
0007  * DOC: VC4 SDTV module
0008  *
0009  * The VEC encoder generates PAL or NTSC composite video output.
0010  *
0011  * TV mode selection is done by an atomic property on the encoder,
0012  * because a drm_mode_modeinfo is insufficient to distinguish between
0013  * PAL and PAL-M or NTSC and NTSC-J.
0014  */
0015 
0016 #include <drm/drm_atomic_helper.h>
0017 #include <drm/drm_edid.h>
0018 #include <drm/drm_panel.h>
0019 #include <drm/drm_probe_helper.h>
0020 #include <drm/drm_simple_kms_helper.h>
0021 #include <linux/clk.h>
0022 #include <linux/component.h>
0023 #include <linux/of_graph.h>
0024 #include <linux/of_platform.h>
0025 #include <linux/pm_runtime.h>
0026 
0027 #include "vc4_drv.h"
0028 #include "vc4_regs.h"
0029 
0030 /* WSE Registers */
0031 #define VEC_WSE_RESET           0xc0
0032 
0033 #define VEC_WSE_CONTROL         0xc4
0034 #define VEC_WSE_WSS_ENABLE      BIT(7)
0035 
0036 #define VEC_WSE_WSS_DATA        0xc8
0037 #define VEC_WSE_VPS_DATA1       0xcc
0038 #define VEC_WSE_VPS_CONTROL     0xd0
0039 
0040 /* VEC Registers */
0041 #define VEC_REVID           0x100
0042 
0043 #define VEC_CONFIG0         0x104
0044 #define VEC_CONFIG0_YDEL_MASK       GENMASK(28, 26)
0045 #define VEC_CONFIG0_YDEL(x)     ((x) << 26)
0046 #define VEC_CONFIG0_CDEL_MASK       GENMASK(25, 24)
0047 #define VEC_CONFIG0_CDEL(x)     ((x) << 24)
0048 #define VEC_CONFIG0_PBPR_FIL        BIT(18)
0049 #define VEC_CONFIG0_CHROMA_GAIN_MASK    GENMASK(17, 16)
0050 #define VEC_CONFIG0_CHROMA_GAIN_UNITY   (0 << 16)
0051 #define VEC_CONFIG0_CHROMA_GAIN_1_32    (1 << 16)
0052 #define VEC_CONFIG0_CHROMA_GAIN_1_16    (2 << 16)
0053 #define VEC_CONFIG0_CHROMA_GAIN_1_8 (3 << 16)
0054 #define VEC_CONFIG0_CBURST_GAIN_MASK    GENMASK(14, 13)
0055 #define VEC_CONFIG0_CBURST_GAIN_UNITY   (0 << 13)
0056 #define VEC_CONFIG0_CBURST_GAIN_1_128   (1 << 13)
0057 #define VEC_CONFIG0_CBURST_GAIN_1_64    (2 << 13)
0058 #define VEC_CONFIG0_CBURST_GAIN_1_32    (3 << 13)
0059 #define VEC_CONFIG0_CHRBW1      BIT(11)
0060 #define VEC_CONFIG0_CHRBW0      BIT(10)
0061 #define VEC_CONFIG0_SYNCDIS     BIT(9)
0062 #define VEC_CONFIG0_BURDIS      BIT(8)
0063 #define VEC_CONFIG0_CHRDIS      BIT(7)
0064 #define VEC_CONFIG0_PDEN        BIT(6)
0065 #define VEC_CONFIG0_YCDELAY     BIT(4)
0066 #define VEC_CONFIG0_RAMPEN      BIT(2)
0067 #define VEC_CONFIG0_YCDIS       BIT(2)
0068 #define VEC_CONFIG0_STD_MASK        GENMASK(1, 0)
0069 #define VEC_CONFIG0_NTSC_STD        0
0070 #define VEC_CONFIG0_PAL_BDGHI_STD   1
0071 #define VEC_CONFIG0_PAL_N_STD       3
0072 
0073 #define VEC_SCHPH           0x108
0074 #define VEC_SOFT_RESET          0x10c
0075 #define VEC_CLMP0_START         0x144
0076 #define VEC_CLMP0_END           0x148
0077 #define VEC_FREQ3_2         0x180
0078 #define VEC_FREQ1_0         0x184
0079 
0080 #define VEC_CONFIG1         0x188
0081 #define VEC_CONFIG_VEC_RESYNC_OFF   BIT(18)
0082 #define VEC_CONFIG_RGB219       BIT(17)
0083 #define VEC_CONFIG_CBAR_EN      BIT(16)
0084 #define VEC_CONFIG_TC_OBB       BIT(15)
0085 #define VEC_CONFIG1_OUTPUT_MODE_MASK    GENMASK(12, 10)
0086 #define VEC_CONFIG1_C_Y_CVBS        (0 << 10)
0087 #define VEC_CONFIG1_CVBS_Y_C        (1 << 10)
0088 #define VEC_CONFIG1_PR_Y_PB     (2 << 10)
0089 #define VEC_CONFIG1_RGB         (4 << 10)
0090 #define VEC_CONFIG1_Y_C_CVBS        (5 << 10)
0091 #define VEC_CONFIG1_C_CVBS_Y        (6 << 10)
0092 #define VEC_CONFIG1_C_CVBS_CVBS     (7 << 10)
0093 #define VEC_CONFIG1_DIS_CHR     BIT(9)
0094 #define VEC_CONFIG1_DIS_LUMA        BIT(8)
0095 #define VEC_CONFIG1_YCBCR_IN        BIT(6)
0096 #define VEC_CONFIG1_DITHER_TYPE_LFSR    0
0097 #define VEC_CONFIG1_DITHER_TYPE_COUNTER BIT(5)
0098 #define VEC_CONFIG1_DITHER_EN       BIT(4)
0099 #define VEC_CONFIG1_CYDELAY     BIT(3)
0100 #define VEC_CONFIG1_LUMADIS     BIT(2)
0101 #define VEC_CONFIG1_COMPDIS     BIT(1)
0102 #define VEC_CONFIG1_CUSTOM_FREQ     BIT(0)
0103 
0104 #define VEC_CONFIG2         0x18c
0105 #define VEC_CONFIG2_PROG_SCAN       BIT(15)
0106 #define VEC_CONFIG2_SYNC_ADJ_MASK   GENMASK(14, 12)
0107 #define VEC_CONFIG2_SYNC_ADJ(x)     (((x) / 2) << 12)
0108 #define VEC_CONFIG2_PBPR_EN     BIT(10)
0109 #define VEC_CONFIG2_UV_DIG_DIS      BIT(6)
0110 #define VEC_CONFIG2_RGB_DIG_DIS     BIT(5)
0111 #define VEC_CONFIG2_TMUX_MASK       GENMASK(3, 2)
0112 #define VEC_CONFIG2_TMUX_DRIVE0     (0 << 2)
0113 #define VEC_CONFIG2_TMUX_RG_COMP    (1 << 2)
0114 #define VEC_CONFIG2_TMUX_UV_YC      (2 << 2)
0115 #define VEC_CONFIG2_TMUX_SYNC_YC    (3 << 2)
0116 
0117 #define VEC_INTERRUPT_CONTROL       0x190
0118 #define VEC_INTERRUPT_STATUS        0x194
0119 #define VEC_FCW_SECAM_B         0x198
0120 #define VEC_SECAM_GAIN_VAL      0x19c
0121 
0122 #define VEC_CONFIG3         0x1a0
0123 #define VEC_CONFIG3_HORIZ_LEN_STD   (0 << 0)
0124 #define VEC_CONFIG3_HORIZ_LEN_MPEG1_SIF (1 << 0)
0125 #define VEC_CONFIG3_SHAPE_NON_LINEAR    BIT(1)
0126 
0127 #define VEC_STATUS0         0x200
0128 #define VEC_MASK0           0x204
0129 
0130 #define VEC_CFG             0x208
0131 #define VEC_CFG_SG_MODE_MASK        GENMASK(6, 5)
0132 #define VEC_CFG_SG_MODE(x)      ((x) << 5)
0133 #define VEC_CFG_SG_EN           BIT(4)
0134 #define VEC_CFG_VEC_EN          BIT(3)
0135 #define VEC_CFG_MB_EN           BIT(2)
0136 #define VEC_CFG_ENABLE          BIT(1)
0137 #define VEC_CFG_TB_EN           BIT(0)
0138 
0139 #define VEC_DAC_TEST            0x20c
0140 
0141 #define VEC_DAC_CONFIG          0x210
0142 #define VEC_DAC_CONFIG_LDO_BIAS_CTRL(x) ((x) << 24)
0143 #define VEC_DAC_CONFIG_DRIVER_CTRL(x)   ((x) << 16)
0144 #define VEC_DAC_CONFIG_DAC_CTRL(x)  (x)
0145 
0146 #define VEC_DAC_MISC            0x214
0147 #define VEC_DAC_MISC_VCD_CTRL_MASK  GENMASK(31, 16)
0148 #define VEC_DAC_MISC_VCD_CTRL(x)    ((x) << 16)
0149 #define VEC_DAC_MISC_VID_ACT        BIT(8)
0150 #define VEC_DAC_MISC_VCD_PWRDN      BIT(6)
0151 #define VEC_DAC_MISC_BIAS_PWRDN     BIT(5)
0152 #define VEC_DAC_MISC_DAC_PWRDN      BIT(2)
0153 #define VEC_DAC_MISC_LDO_PWRDN      BIT(1)
0154 #define VEC_DAC_MISC_DAC_RST_N      BIT(0)
0155 
0156 
0157 struct vc4_vec_variant {
0158     u32 dac_config;
0159 };
0160 
0161 /* General VEC hardware state. */
0162 struct vc4_vec {
0163     struct platform_device *pdev;
0164     const struct vc4_vec_variant *variant;
0165 
0166     struct drm_encoder *encoder;
0167     struct drm_connector *connector;
0168 
0169     void __iomem *regs;
0170 
0171     struct clk *clock;
0172 
0173     const struct vc4_vec_tv_mode *tv_mode;
0174 
0175     struct debugfs_regset32 regset;
0176 };
0177 
0178 #define VEC_READ(offset) readl(vec->regs + (offset))
0179 #define VEC_WRITE(offset, val) writel(val, vec->regs + (offset))
0180 
0181 /* VC4 VEC encoder KMS struct */
0182 struct vc4_vec_encoder {
0183     struct vc4_encoder base;
0184     struct vc4_vec *vec;
0185 };
0186 
0187 static inline struct vc4_vec_encoder *
0188 to_vc4_vec_encoder(struct drm_encoder *encoder)
0189 {
0190     return container_of(encoder, struct vc4_vec_encoder, base.base);
0191 }
0192 
0193 /* VC4 VEC connector KMS struct */
0194 struct vc4_vec_connector {
0195     struct drm_connector base;
0196     struct vc4_vec *vec;
0197 
0198     /* Since the connector is attached to just the one encoder,
0199      * this is the reference to it so we can do the best_encoder()
0200      * hook.
0201      */
0202     struct drm_encoder *encoder;
0203 };
0204 
0205 enum vc4_vec_tv_mode_id {
0206     VC4_VEC_TV_MODE_NTSC,
0207     VC4_VEC_TV_MODE_NTSC_J,
0208     VC4_VEC_TV_MODE_PAL,
0209     VC4_VEC_TV_MODE_PAL_M,
0210 };
0211 
0212 struct vc4_vec_tv_mode {
0213     const struct drm_display_mode *mode;
0214     void (*mode_set)(struct vc4_vec *vec);
0215 };
0216 
0217 static const struct debugfs_reg32 vec_regs[] = {
0218     VC4_REG32(VEC_WSE_CONTROL),
0219     VC4_REG32(VEC_WSE_WSS_DATA),
0220     VC4_REG32(VEC_WSE_VPS_DATA1),
0221     VC4_REG32(VEC_WSE_VPS_CONTROL),
0222     VC4_REG32(VEC_REVID),
0223     VC4_REG32(VEC_CONFIG0),
0224     VC4_REG32(VEC_SCHPH),
0225     VC4_REG32(VEC_CLMP0_START),
0226     VC4_REG32(VEC_CLMP0_END),
0227     VC4_REG32(VEC_FREQ3_2),
0228     VC4_REG32(VEC_FREQ1_0),
0229     VC4_REG32(VEC_CONFIG1),
0230     VC4_REG32(VEC_CONFIG2),
0231     VC4_REG32(VEC_INTERRUPT_CONTROL),
0232     VC4_REG32(VEC_INTERRUPT_STATUS),
0233     VC4_REG32(VEC_FCW_SECAM_B),
0234     VC4_REG32(VEC_SECAM_GAIN_VAL),
0235     VC4_REG32(VEC_CONFIG3),
0236     VC4_REG32(VEC_STATUS0),
0237     VC4_REG32(VEC_MASK0),
0238     VC4_REG32(VEC_CFG),
0239     VC4_REG32(VEC_DAC_TEST),
0240     VC4_REG32(VEC_DAC_CONFIG),
0241     VC4_REG32(VEC_DAC_MISC),
0242 };
0243 
0244 static void vc4_vec_ntsc_mode_set(struct vc4_vec *vec)
0245 {
0246     VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN);
0247     VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
0248 }
0249 
0250 static void vc4_vec_ntsc_j_mode_set(struct vc4_vec *vec)
0251 {
0252     VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD);
0253     VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
0254 }
0255 
0256 static const struct drm_display_mode ntsc_mode = {
0257     DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
0258          720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
0259          480, 480 + 3, 480 + 3 + 3, 480 + 3 + 3 + 16, 0,
0260          DRM_MODE_FLAG_INTERLACE)
0261 };
0262 
0263 static void vc4_vec_pal_mode_set(struct vc4_vec *vec)
0264 {
0265     VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD);
0266     VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
0267 }
0268 
0269 static void vc4_vec_pal_m_mode_set(struct vc4_vec *vec)
0270 {
0271     VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD);
0272     VEC_WRITE(VEC_CONFIG1,
0273           VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ);
0274     VEC_WRITE(VEC_FREQ3_2, 0x223b);
0275     VEC_WRITE(VEC_FREQ1_0, 0x61d1);
0276 }
0277 
0278 static const struct drm_display_mode pal_mode = {
0279     DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
0280          720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
0281          576, 576 + 2, 576 + 2 + 3, 576 + 2 + 3 + 20, 0,
0282          DRM_MODE_FLAG_INTERLACE)
0283 };
0284 
0285 static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
0286     [VC4_VEC_TV_MODE_NTSC] = {
0287         .mode = &ntsc_mode,
0288         .mode_set = vc4_vec_ntsc_mode_set,
0289     },
0290     [VC4_VEC_TV_MODE_NTSC_J] = {
0291         .mode = &ntsc_mode,
0292         .mode_set = vc4_vec_ntsc_j_mode_set,
0293     },
0294     [VC4_VEC_TV_MODE_PAL] = {
0295         .mode = &pal_mode,
0296         .mode_set = vc4_vec_pal_mode_set,
0297     },
0298     [VC4_VEC_TV_MODE_PAL_M] = {
0299         .mode = &pal_mode,
0300         .mode_set = vc4_vec_pal_m_mode_set,
0301     },
0302 };
0303 
0304 static enum drm_connector_status
0305 vc4_vec_connector_detect(struct drm_connector *connector, bool force)
0306 {
0307     return connector_status_unknown;
0308 }
0309 
0310 static void vc4_vec_connector_destroy(struct drm_connector *connector)
0311 {
0312     drm_connector_unregister(connector);
0313     drm_connector_cleanup(connector);
0314 }
0315 
0316 static int vc4_vec_connector_get_modes(struct drm_connector *connector)
0317 {
0318     struct drm_connector_state *state = connector->state;
0319     struct drm_display_mode *mode;
0320 
0321     mode = drm_mode_duplicate(connector->dev,
0322                   vc4_vec_tv_modes[state->tv.mode].mode);
0323     if (!mode) {
0324         DRM_ERROR("Failed to create a new display mode\n");
0325         return -ENOMEM;
0326     }
0327 
0328     drm_mode_probed_add(connector, mode);
0329 
0330     return 1;
0331 }
0332 
0333 static const struct drm_connector_funcs vc4_vec_connector_funcs = {
0334     .detect = vc4_vec_connector_detect,
0335     .fill_modes = drm_helper_probe_single_connector_modes,
0336     .destroy = vc4_vec_connector_destroy,
0337     .reset = drm_atomic_helper_connector_reset,
0338     .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
0339     .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
0340 };
0341 
0342 static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs = {
0343     .get_modes = vc4_vec_connector_get_modes,
0344 };
0345 
0346 static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev,
0347                             struct vc4_vec *vec)
0348 {
0349     struct drm_connector *connector = NULL;
0350     struct vc4_vec_connector *vec_connector;
0351 
0352     vec_connector = devm_kzalloc(dev->dev, sizeof(*vec_connector),
0353                      GFP_KERNEL);
0354     if (!vec_connector)
0355         return ERR_PTR(-ENOMEM);
0356 
0357     connector = &vec_connector->base;
0358     connector->interlace_allowed = true;
0359 
0360     vec_connector->encoder = vec->encoder;
0361     vec_connector->vec = vec;
0362 
0363     drm_connector_init(dev, connector, &vc4_vec_connector_funcs,
0364                DRM_MODE_CONNECTOR_Composite);
0365     drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs);
0366 
0367     drm_object_attach_property(&connector->base,
0368                    dev->mode_config.tv_mode_property,
0369                    VC4_VEC_TV_MODE_NTSC);
0370     vec->tv_mode = &vc4_vec_tv_modes[VC4_VEC_TV_MODE_NTSC];
0371 
0372     drm_connector_attach_encoder(connector, vec->encoder);
0373 
0374     return connector;
0375 }
0376 
0377 static void vc4_vec_encoder_disable(struct drm_encoder *encoder)
0378 {
0379     struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
0380     struct vc4_vec *vec = vc4_vec_encoder->vec;
0381     int ret;
0382 
0383     VEC_WRITE(VEC_CFG, 0);
0384     VEC_WRITE(VEC_DAC_MISC,
0385           VEC_DAC_MISC_VCD_PWRDN |
0386           VEC_DAC_MISC_BIAS_PWRDN |
0387           VEC_DAC_MISC_DAC_PWRDN |
0388           VEC_DAC_MISC_LDO_PWRDN);
0389 
0390     clk_disable_unprepare(vec->clock);
0391 
0392     ret = pm_runtime_put(&vec->pdev->dev);
0393     if (ret < 0) {
0394         DRM_ERROR("Failed to release power domain: %d\n", ret);
0395         return;
0396     }
0397 }
0398 
0399 static void vc4_vec_encoder_enable(struct drm_encoder *encoder)
0400 {
0401     struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
0402     struct vc4_vec *vec = vc4_vec_encoder->vec;
0403     int ret;
0404 
0405     ret = pm_runtime_get_sync(&vec->pdev->dev);
0406     if (ret < 0) {
0407         DRM_ERROR("Failed to retain power domain: %d\n", ret);
0408         return;
0409     }
0410 
0411     /*
0412      * We need to set the clock rate each time we enable the encoder
0413      * because there's a chance we share the same parent with the HDMI
0414      * clock, and both drivers are requesting different rates.
0415      * The good news is, these 2 encoders cannot be enabled at the same
0416      * time, thus preventing incompatible rate requests.
0417      */
0418     ret = clk_set_rate(vec->clock, 108000000);
0419     if (ret) {
0420         DRM_ERROR("Failed to set clock rate: %d\n", ret);
0421         return;
0422     }
0423 
0424     ret = clk_prepare_enable(vec->clock);
0425     if (ret) {
0426         DRM_ERROR("Failed to turn on core clock: %d\n", ret);
0427         return;
0428     }
0429 
0430     /* Reset the different blocks */
0431     VEC_WRITE(VEC_WSE_RESET, 1);
0432     VEC_WRITE(VEC_SOFT_RESET, 1);
0433 
0434     /* Disable the CGSM-A and WSE blocks */
0435     VEC_WRITE(VEC_WSE_CONTROL, 0);
0436 
0437     /* Write config common to all modes. */
0438 
0439     /*
0440      * Color subcarrier phase: phase = 360 * SCHPH / 256.
0441      * 0x28 <=> 39.375 deg.
0442      */
0443     VEC_WRITE(VEC_SCHPH, 0x28);
0444 
0445     /*
0446      * Reset to default values.
0447      */
0448     VEC_WRITE(VEC_CLMP0_START, 0xac);
0449     VEC_WRITE(VEC_CLMP0_END, 0xec);
0450     VEC_WRITE(VEC_CONFIG2,
0451           VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS);
0452     VEC_WRITE(VEC_CONFIG3, VEC_CONFIG3_HORIZ_LEN_STD);
0453     VEC_WRITE(VEC_DAC_CONFIG, vec->variant->dac_config);
0454 
0455     /* Mask all interrupts. */
0456     VEC_WRITE(VEC_MASK0, 0);
0457 
0458     vec->tv_mode->mode_set(vec);
0459 
0460     VEC_WRITE(VEC_DAC_MISC,
0461           VEC_DAC_MISC_VID_ACT | VEC_DAC_MISC_DAC_RST_N);
0462     VEC_WRITE(VEC_CFG, VEC_CFG_VEC_EN);
0463 }
0464 
0465 
0466 static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder,
0467                        const struct drm_display_mode *mode,
0468                        struct drm_display_mode *adjusted_mode)
0469 {
0470     return true;
0471 }
0472 
0473 static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder,
0474                     struct drm_crtc_state *crtc_state,
0475                     struct drm_connector_state *conn_state)
0476 {
0477     struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
0478     struct vc4_vec *vec = vc4_vec_encoder->vec;
0479 
0480     vec->tv_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
0481 }
0482 
0483 static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
0484                     struct drm_crtc_state *crtc_state,
0485                     struct drm_connector_state *conn_state)
0486 {
0487     const struct vc4_vec_tv_mode *vec_mode;
0488 
0489     vec_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
0490 
0491     if (conn_state->crtc &&
0492         !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode))
0493         return -EINVAL;
0494 
0495     return 0;
0496 }
0497 
0498 static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = {
0499     .disable = vc4_vec_encoder_disable,
0500     .enable = vc4_vec_encoder_enable,
0501     .mode_fixup = vc4_vec_encoder_mode_fixup,
0502     .atomic_check = vc4_vec_encoder_atomic_check,
0503     .atomic_mode_set = vc4_vec_encoder_atomic_mode_set,
0504 };
0505 
0506 static const struct vc4_vec_variant bcm2835_vec_variant = {
0507     .dac_config = VEC_DAC_CONFIG_DAC_CTRL(0xc) |
0508               VEC_DAC_CONFIG_DRIVER_CTRL(0xc) |
0509               VEC_DAC_CONFIG_LDO_BIAS_CTRL(0x46)
0510 };
0511 
0512 static const struct vc4_vec_variant bcm2711_vec_variant = {
0513     .dac_config = VEC_DAC_CONFIG_DAC_CTRL(0x0) |
0514               VEC_DAC_CONFIG_DRIVER_CTRL(0x80) |
0515               VEC_DAC_CONFIG_LDO_BIAS_CTRL(0x61)
0516 };
0517 
0518 static const struct of_device_id vc4_vec_dt_match[] = {
0519     { .compatible = "brcm,bcm2835-vec", .data = &bcm2835_vec_variant },
0520     { .compatible = "brcm,bcm2711-vec", .data = &bcm2711_vec_variant },
0521     { /* sentinel */ },
0522 };
0523 
0524 static const char * const tv_mode_names[] = {
0525     [VC4_VEC_TV_MODE_NTSC] = "NTSC",
0526     [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
0527     [VC4_VEC_TV_MODE_PAL] = "PAL",
0528     [VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
0529 };
0530 
0531 static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
0532 {
0533     struct platform_device *pdev = to_platform_device(dev);
0534     struct drm_device *drm = dev_get_drvdata(master);
0535     struct vc4_dev *vc4 = to_vc4_dev(drm);
0536     struct vc4_vec *vec;
0537     struct vc4_vec_encoder *vc4_vec_encoder;
0538     int ret;
0539 
0540     ret = drm_mode_create_tv_properties(drm, ARRAY_SIZE(tv_mode_names),
0541                         tv_mode_names);
0542     if (ret)
0543         return ret;
0544 
0545     vec = devm_kzalloc(dev, sizeof(*vec), GFP_KERNEL);
0546     if (!vec)
0547         return -ENOMEM;
0548 
0549     vc4_vec_encoder = devm_kzalloc(dev, sizeof(*vc4_vec_encoder),
0550                        GFP_KERNEL);
0551     if (!vc4_vec_encoder)
0552         return -ENOMEM;
0553     vc4_vec_encoder->base.type = VC4_ENCODER_TYPE_VEC;
0554     vc4_vec_encoder->vec = vec;
0555     vec->encoder = &vc4_vec_encoder->base.base;
0556 
0557     vec->pdev = pdev;
0558     vec->variant = (const struct vc4_vec_variant *)
0559         of_device_get_match_data(dev);
0560     vec->regs = vc4_ioremap_regs(pdev, 0);
0561     if (IS_ERR(vec->regs))
0562         return PTR_ERR(vec->regs);
0563     vec->regset.base = vec->regs;
0564     vec->regset.regs = vec_regs;
0565     vec->regset.nregs = ARRAY_SIZE(vec_regs);
0566 
0567     vec->clock = devm_clk_get(dev, NULL);
0568     if (IS_ERR(vec->clock)) {
0569         ret = PTR_ERR(vec->clock);
0570         if (ret != -EPROBE_DEFER)
0571             DRM_ERROR("Failed to get clock: %d\n", ret);
0572         return ret;
0573     }
0574 
0575     pm_runtime_enable(dev);
0576 
0577     drm_simple_encoder_init(drm, vec->encoder, DRM_MODE_ENCODER_TVDAC);
0578     drm_encoder_helper_add(vec->encoder, &vc4_vec_encoder_helper_funcs);
0579 
0580     vec->connector = vc4_vec_connector_init(drm, vec);
0581     if (IS_ERR(vec->connector)) {
0582         ret = PTR_ERR(vec->connector);
0583         goto err_destroy_encoder;
0584     }
0585 
0586     dev_set_drvdata(dev, vec);
0587 
0588     vc4->vec = vec;
0589 
0590     vc4_debugfs_add_regset32(drm, "vec_regs", &vec->regset);
0591 
0592     return 0;
0593 
0594 err_destroy_encoder:
0595     drm_encoder_cleanup(vec->encoder);
0596     pm_runtime_disable(dev);
0597 
0598     return ret;
0599 }
0600 
0601 static void vc4_vec_unbind(struct device *dev, struct device *master,
0602                void *data)
0603 {
0604     struct drm_device *drm = dev_get_drvdata(master);
0605     struct vc4_dev *vc4 = to_vc4_dev(drm);
0606     struct vc4_vec *vec = dev_get_drvdata(dev);
0607 
0608     vc4_vec_connector_destroy(vec->connector);
0609     drm_encoder_cleanup(vec->encoder);
0610     pm_runtime_disable(dev);
0611 
0612     vc4->vec = NULL;
0613 }
0614 
0615 static const struct component_ops vc4_vec_ops = {
0616     .bind   = vc4_vec_bind,
0617     .unbind = vc4_vec_unbind,
0618 };
0619 
0620 static int vc4_vec_dev_probe(struct platform_device *pdev)
0621 {
0622     return component_add(&pdev->dev, &vc4_vec_ops);
0623 }
0624 
0625 static int vc4_vec_dev_remove(struct platform_device *pdev)
0626 {
0627     component_del(&pdev->dev, &vc4_vec_ops);
0628     return 0;
0629 }
0630 
0631 struct platform_driver vc4_vec_driver = {
0632     .probe = vc4_vec_dev_probe,
0633     .remove = vc4_vec_dev_remove,
0634     .driver = {
0635         .name = "vc4_vec",
0636         .of_match_table = vc4_vec_dt_match,
0637     },
0638 };