0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
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
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
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
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
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
0194 struct vc4_vec_connector {
0195 struct drm_connector base;
0196 struct vc4_vec *vec;
0197
0198
0199
0200
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
0413
0414
0415
0416
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
0431 VEC_WRITE(VEC_WSE_RESET, 1);
0432 VEC_WRITE(VEC_SOFT_RESET, 1);
0433
0434
0435 VEC_WRITE(VEC_WSE_CONTROL, 0);
0436
0437
0438
0439
0440
0441
0442
0443 VEC_WRITE(VEC_SCHPH, 0x28);
0444
0445
0446
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
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 { },
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 };