linux/drivers/gpu/drm/vc4/vc4_vec.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2016 Broadcom
   4 */
   5
   6/**
   7 * DOC: VC4 SDTV module
   8 *
   9 * The VEC encoder generates PAL or NTSC composite video output.
  10 *
  11 * TV mode selection is done by an atomic property on the encoder,
  12 * because a drm_mode_modeinfo is insufficient to distinguish between
  13 * PAL and PAL-M or NTSC and NTSC-J.
  14 */
  15
  16#include <drm/drm_atomic_helper.h>
  17#include <drm/drm_edid.h>
  18#include <drm/drm_panel.h>
  19#include <drm/drm_probe_helper.h>
  20#include <drm/drm_simple_kms_helper.h>
  21#include <linux/clk.h>
  22#include <linux/component.h>
  23#include <linux/of_graph.h>
  24#include <linux/of_platform.h>
  25#include <linux/pm_runtime.h>
  26
  27#include "vc4_drv.h"
  28#include "vc4_regs.h"
  29
  30/* WSE Registers */
  31#define VEC_WSE_RESET                   0xc0
  32
  33#define VEC_WSE_CONTROL                 0xc4
  34#define VEC_WSE_WSS_ENABLE              BIT(7)
  35
  36#define VEC_WSE_WSS_DATA                0xc8
  37#define VEC_WSE_VPS_DATA1               0xcc
  38#define VEC_WSE_VPS_CONTROL             0xd0
  39
  40/* VEC Registers */
  41#define VEC_REVID                       0x100
  42
  43#define VEC_CONFIG0                     0x104
  44#define VEC_CONFIG0_YDEL_MASK           GENMASK(28, 26)
  45#define VEC_CONFIG0_YDEL(x)             ((x) << 26)
  46#define VEC_CONFIG0_CDEL_MASK           GENMASK(25, 24)
  47#define VEC_CONFIG0_CDEL(x)             ((x) << 24)
  48#define VEC_CONFIG0_PBPR_FIL            BIT(18)
  49#define VEC_CONFIG0_CHROMA_GAIN_MASK    GENMASK(17, 16)
  50#define VEC_CONFIG0_CHROMA_GAIN_UNITY   (0 << 16)
  51#define VEC_CONFIG0_CHROMA_GAIN_1_32    (1 << 16)
  52#define VEC_CONFIG0_CHROMA_GAIN_1_16    (2 << 16)
  53#define VEC_CONFIG0_CHROMA_GAIN_1_8     (3 << 16)
  54#define VEC_CONFIG0_CBURST_GAIN_MASK    GENMASK(14, 13)
  55#define VEC_CONFIG0_CBURST_GAIN_UNITY   (0 << 13)
  56#define VEC_CONFIG0_CBURST_GAIN_1_128   (1 << 13)
  57#define VEC_CONFIG0_CBURST_GAIN_1_64    (2 << 13)
  58#define VEC_CONFIG0_CBURST_GAIN_1_32    (3 << 13)
  59#define VEC_CONFIG0_CHRBW1              BIT(11)
  60#define VEC_CONFIG0_CHRBW0              BIT(10)
  61#define VEC_CONFIG0_SYNCDIS             BIT(9)
  62#define VEC_CONFIG0_BURDIS              BIT(8)
  63#define VEC_CONFIG0_CHRDIS              BIT(7)
  64#define VEC_CONFIG0_PDEN                BIT(6)
  65#define VEC_CONFIG0_YCDELAY             BIT(4)
  66#define VEC_CONFIG0_RAMPEN              BIT(2)
  67#define VEC_CONFIG0_YCDIS               BIT(2)
  68#define VEC_CONFIG0_STD_MASK            GENMASK(1, 0)
  69#define VEC_CONFIG0_NTSC_STD            0
  70#define VEC_CONFIG0_PAL_BDGHI_STD       1
  71#define VEC_CONFIG0_PAL_N_STD           3
  72
  73#define VEC_SCHPH                       0x108
  74#define VEC_SOFT_RESET                  0x10c
  75#define VEC_CLMP0_START                 0x144
  76#define VEC_CLMP0_END                   0x148
  77#define VEC_FREQ3_2                     0x180
  78#define VEC_FREQ1_0                     0x184
  79
  80#define VEC_CONFIG1                     0x188
  81#define VEC_CONFIG_VEC_RESYNC_OFF       BIT(18)
  82#define VEC_CONFIG_RGB219               BIT(17)
  83#define VEC_CONFIG_CBAR_EN              BIT(16)
  84#define VEC_CONFIG_TC_OBB               BIT(15)
  85#define VEC_CONFIG1_OUTPUT_MODE_MASK    GENMASK(12, 10)
  86#define VEC_CONFIG1_C_Y_CVBS            (0 << 10)
  87#define VEC_CONFIG1_CVBS_Y_C            (1 << 10)
  88#define VEC_CONFIG1_PR_Y_PB             (2 << 10)
  89#define VEC_CONFIG1_RGB                 (4 << 10)
  90#define VEC_CONFIG1_Y_C_CVBS            (5 << 10)
  91#define VEC_CONFIG1_C_CVBS_Y            (6 << 10)
  92#define VEC_CONFIG1_C_CVBS_CVBS         (7 << 10)
  93#define VEC_CONFIG1_DIS_CHR             BIT(9)
  94#define VEC_CONFIG1_DIS_LUMA            BIT(8)
  95#define VEC_CONFIG1_YCBCR_IN            BIT(6)
  96#define VEC_CONFIG1_DITHER_TYPE_LFSR    0
  97#define VEC_CONFIG1_DITHER_TYPE_COUNTER BIT(5)
  98#define VEC_CONFIG1_DITHER_EN           BIT(4)
  99#define VEC_CONFIG1_CYDELAY             BIT(3)
 100#define VEC_CONFIG1_LUMADIS             BIT(2)
 101#define VEC_CONFIG1_COMPDIS             BIT(1)
 102#define VEC_CONFIG1_CUSTOM_FREQ         BIT(0)
 103
 104#define VEC_CONFIG2                     0x18c
 105#define VEC_CONFIG2_PROG_SCAN           BIT(15)
 106#define VEC_CONFIG2_SYNC_ADJ_MASK       GENMASK(14, 12)
 107#define VEC_CONFIG2_SYNC_ADJ(x)         (((x) / 2) << 12)
 108#define VEC_CONFIG2_PBPR_EN             BIT(10)
 109#define VEC_CONFIG2_UV_DIG_DIS          BIT(6)
 110#define VEC_CONFIG2_RGB_DIG_DIS         BIT(5)
 111#define VEC_CONFIG2_TMUX_MASK           GENMASK(3, 2)
 112#define VEC_CONFIG2_TMUX_DRIVE0         (0 << 2)
 113#define VEC_CONFIG2_TMUX_RG_COMP        (1 << 2)
 114#define VEC_CONFIG2_TMUX_UV_YC          (2 << 2)
 115#define VEC_CONFIG2_TMUX_SYNC_YC        (3 << 2)
 116
 117#define VEC_INTERRUPT_CONTROL           0x190
 118#define VEC_INTERRUPT_STATUS            0x194
 119#define VEC_FCW_SECAM_B                 0x198
 120#define VEC_SECAM_GAIN_VAL              0x19c
 121
 122#define VEC_CONFIG3                     0x1a0
 123#define VEC_CONFIG3_HORIZ_LEN_STD       (0 << 0)
 124#define VEC_CONFIG3_HORIZ_LEN_MPEG1_SIF (1 << 0)
 125#define VEC_CONFIG3_SHAPE_NON_LINEAR    BIT(1)
 126
 127#define VEC_STATUS0                     0x200
 128#define VEC_MASK0                       0x204
 129
 130#define VEC_CFG                         0x208
 131#define VEC_CFG_SG_MODE_MASK            GENMASK(6, 5)
 132#define VEC_CFG_SG_MODE(x)              ((x) << 5)
 133#define VEC_CFG_SG_EN                   BIT(4)
 134#define VEC_CFG_VEC_EN                  BIT(3)
 135#define VEC_CFG_MB_EN                   BIT(2)
 136#define VEC_CFG_ENABLE                  BIT(1)
 137#define VEC_CFG_TB_EN                   BIT(0)
 138
 139#define VEC_DAC_TEST                    0x20c
 140
 141#define VEC_DAC_CONFIG                  0x210
 142#define VEC_DAC_CONFIG_LDO_BIAS_CTRL(x) ((x) << 24)
 143#define VEC_DAC_CONFIG_DRIVER_CTRL(x)   ((x) << 16)
 144#define VEC_DAC_CONFIG_DAC_CTRL(x)      (x)
 145
 146#define VEC_DAC_MISC                    0x214
 147#define VEC_DAC_MISC_VCD_CTRL_MASK      GENMASK(31, 16)
 148#define VEC_DAC_MISC_VCD_CTRL(x)        ((x) << 16)
 149#define VEC_DAC_MISC_VID_ACT            BIT(8)
 150#define VEC_DAC_MISC_VCD_PWRDN          BIT(6)
 151#define VEC_DAC_MISC_BIAS_PWRDN         BIT(5)
 152#define VEC_DAC_MISC_DAC_PWRDN          BIT(2)
 153#define VEC_DAC_MISC_LDO_PWRDN          BIT(1)
 154#define VEC_DAC_MISC_DAC_RST_N          BIT(0)
 155
 156
 157struct vc4_vec_variant {
 158        u32 dac_config;
 159};
 160
 161/* General VEC hardware state. */
 162struct vc4_vec {
 163        struct platform_device *pdev;
 164        const struct vc4_vec_variant *variant;
 165
 166        struct drm_encoder *encoder;
 167        struct drm_connector *connector;
 168
 169        void __iomem *regs;
 170
 171        struct clk *clock;
 172
 173        const struct vc4_vec_tv_mode *tv_mode;
 174
 175        struct debugfs_regset32 regset;
 176};
 177
 178#define VEC_READ(offset) readl(vec->regs + (offset))
 179#define VEC_WRITE(offset, val) writel(val, vec->regs + (offset))
 180
 181/* VC4 VEC encoder KMS struct */
 182struct vc4_vec_encoder {
 183        struct vc4_encoder base;
 184        struct vc4_vec *vec;
 185};
 186
 187static inline struct vc4_vec_encoder *
 188to_vc4_vec_encoder(struct drm_encoder *encoder)
 189{
 190        return container_of(encoder, struct vc4_vec_encoder, base.base);
 191}
 192
 193/* VC4 VEC connector KMS struct */
 194struct vc4_vec_connector {
 195        struct drm_connector base;
 196        struct vc4_vec *vec;
 197
 198        /* Since the connector is attached to just the one encoder,
 199         * this is the reference to it so we can do the best_encoder()
 200         * hook.
 201         */
 202        struct drm_encoder *encoder;
 203};
 204
 205enum vc4_vec_tv_mode_id {
 206        VC4_VEC_TV_MODE_NTSC,
 207        VC4_VEC_TV_MODE_NTSC_J,
 208        VC4_VEC_TV_MODE_PAL,
 209        VC4_VEC_TV_MODE_PAL_M,
 210};
 211
 212struct vc4_vec_tv_mode {
 213        const struct drm_display_mode *mode;
 214        void (*mode_set)(struct vc4_vec *vec);
 215};
 216
 217static const struct debugfs_reg32 vec_regs[] = {
 218        VC4_REG32(VEC_WSE_CONTROL),
 219        VC4_REG32(VEC_WSE_WSS_DATA),
 220        VC4_REG32(VEC_WSE_VPS_DATA1),
 221        VC4_REG32(VEC_WSE_VPS_CONTROL),
 222        VC4_REG32(VEC_REVID),
 223        VC4_REG32(VEC_CONFIG0),
 224        VC4_REG32(VEC_SCHPH),
 225        VC4_REG32(VEC_CLMP0_START),
 226        VC4_REG32(VEC_CLMP0_END),
 227        VC4_REG32(VEC_FREQ3_2),
 228        VC4_REG32(VEC_FREQ1_0),
 229        VC4_REG32(VEC_CONFIG1),
 230        VC4_REG32(VEC_CONFIG2),
 231        VC4_REG32(VEC_INTERRUPT_CONTROL),
 232        VC4_REG32(VEC_INTERRUPT_STATUS),
 233        VC4_REG32(VEC_FCW_SECAM_B),
 234        VC4_REG32(VEC_SECAM_GAIN_VAL),
 235        VC4_REG32(VEC_CONFIG3),
 236        VC4_REG32(VEC_STATUS0),
 237        VC4_REG32(VEC_MASK0),
 238        VC4_REG32(VEC_CFG),
 239        VC4_REG32(VEC_DAC_TEST),
 240        VC4_REG32(VEC_DAC_CONFIG),
 241        VC4_REG32(VEC_DAC_MISC),
 242};
 243
 244static void vc4_vec_ntsc_mode_set(struct vc4_vec *vec)
 245{
 246        VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN);
 247        VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
 248}
 249
 250static void vc4_vec_ntsc_j_mode_set(struct vc4_vec *vec)
 251{
 252        VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD);
 253        VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
 254}
 255
 256static const struct drm_display_mode ntsc_mode = {
 257        DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
 258                 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
 259                 480, 480 + 3, 480 + 3 + 3, 480 + 3 + 3 + 16, 0,
 260                 DRM_MODE_FLAG_INTERLACE)
 261};
 262
 263static void vc4_vec_pal_mode_set(struct vc4_vec *vec)
 264{
 265        VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD);
 266        VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
 267}
 268
 269static void vc4_vec_pal_m_mode_set(struct vc4_vec *vec)
 270{
 271        VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD);
 272        VEC_WRITE(VEC_CONFIG1,
 273                  VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ);
 274        VEC_WRITE(VEC_FREQ3_2, 0x223b);
 275        VEC_WRITE(VEC_FREQ1_0, 0x61d1);
 276}
 277
 278static const struct drm_display_mode pal_mode = {
 279        DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
 280                 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
 281                 576, 576 + 2, 576 + 2 + 3, 576 + 2 + 3 + 20, 0,
 282                 DRM_MODE_FLAG_INTERLACE)
 283};
 284
 285static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
 286        [VC4_VEC_TV_MODE_NTSC] = {
 287                .mode = &ntsc_mode,
 288                .mode_set = vc4_vec_ntsc_mode_set,
 289        },
 290        [VC4_VEC_TV_MODE_NTSC_J] = {
 291                .mode = &ntsc_mode,
 292                .mode_set = vc4_vec_ntsc_j_mode_set,
 293        },
 294        [VC4_VEC_TV_MODE_PAL] = {
 295                .mode = &pal_mode,
 296                .mode_set = vc4_vec_pal_mode_set,
 297        },
 298        [VC4_VEC_TV_MODE_PAL_M] = {
 299                .mode = &pal_mode,
 300                .mode_set = vc4_vec_pal_m_mode_set,
 301        },
 302};
 303
 304static enum drm_connector_status
 305vc4_vec_connector_detect(struct drm_connector *connector, bool force)
 306{
 307        return connector_status_unknown;
 308}
 309
 310static void vc4_vec_connector_destroy(struct drm_connector *connector)
 311{
 312        drm_connector_unregister(connector);
 313        drm_connector_cleanup(connector);
 314}
 315
 316static int vc4_vec_connector_get_modes(struct drm_connector *connector)
 317{
 318        struct drm_connector_state *state = connector->state;
 319        struct drm_display_mode *mode;
 320
 321        mode = drm_mode_duplicate(connector->dev,
 322                                  vc4_vec_tv_modes[state->tv.mode].mode);
 323        if (!mode) {
 324                DRM_ERROR("Failed to create a new display mode\n");
 325                return -ENOMEM;
 326        }
 327
 328        drm_mode_probed_add(connector, mode);
 329
 330        return 1;
 331}
 332
 333static const struct drm_connector_funcs vc4_vec_connector_funcs = {
 334        .detect = vc4_vec_connector_detect,
 335        .fill_modes = drm_helper_probe_single_connector_modes,
 336        .destroy = vc4_vec_connector_destroy,
 337        .reset = drm_atomic_helper_connector_reset,
 338        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 339        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 340};
 341
 342static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs = {
 343        .get_modes = vc4_vec_connector_get_modes,
 344};
 345
 346static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev,
 347                                                    struct vc4_vec *vec)
 348{
 349        struct drm_connector *connector = NULL;
 350        struct vc4_vec_connector *vec_connector;
 351
 352        vec_connector = devm_kzalloc(dev->dev, sizeof(*vec_connector),
 353                                     GFP_KERNEL);
 354        if (!vec_connector)
 355                return ERR_PTR(-ENOMEM);
 356
 357        connector = &vec_connector->base;
 358        connector->interlace_allowed = true;
 359
 360        vec_connector->encoder = vec->encoder;
 361        vec_connector->vec = vec;
 362
 363        drm_connector_init(dev, connector, &vc4_vec_connector_funcs,
 364                           DRM_MODE_CONNECTOR_Composite);
 365        drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs);
 366
 367        drm_object_attach_property(&connector->base,
 368                                   dev->mode_config.tv_mode_property,
 369                                   VC4_VEC_TV_MODE_NTSC);
 370        vec->tv_mode = &vc4_vec_tv_modes[VC4_VEC_TV_MODE_NTSC];
 371
 372        drm_connector_attach_encoder(connector, vec->encoder);
 373
 374        return connector;
 375}
 376
 377static void vc4_vec_encoder_disable(struct drm_encoder *encoder)
 378{
 379        struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
 380        struct vc4_vec *vec = vc4_vec_encoder->vec;
 381        int ret;
 382
 383        VEC_WRITE(VEC_CFG, 0);
 384        VEC_WRITE(VEC_DAC_MISC,
 385                  VEC_DAC_MISC_VCD_PWRDN |
 386                  VEC_DAC_MISC_BIAS_PWRDN |
 387                  VEC_DAC_MISC_DAC_PWRDN |
 388                  VEC_DAC_MISC_LDO_PWRDN);
 389
 390        clk_disable_unprepare(vec->clock);
 391
 392        ret = pm_runtime_put(&vec->pdev->dev);
 393        if (ret < 0) {
 394                DRM_ERROR("Failed to release power domain: %d\n", ret);
 395                return;
 396        }
 397}
 398
 399static void vc4_vec_encoder_enable(struct drm_encoder *encoder)
 400{
 401        struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
 402        struct vc4_vec *vec = vc4_vec_encoder->vec;
 403        int ret;
 404
 405        ret = pm_runtime_get_sync(&vec->pdev->dev);
 406        if (ret < 0) {
 407                DRM_ERROR("Failed to retain power domain: %d\n", ret);
 408                return;
 409        }
 410
 411        /*
 412         * We need to set the clock rate each time we enable the encoder
 413         * because there's a chance we share the same parent with the HDMI
 414         * clock, and both drivers are requesting different rates.
 415         * The good news is, these 2 encoders cannot be enabled at the same
 416         * time, thus preventing incompatible rate requests.
 417         */
 418        ret = clk_set_rate(vec->clock, 108000000);
 419        if (ret) {
 420                DRM_ERROR("Failed to set clock rate: %d\n", ret);
 421                return;
 422        }
 423
 424        ret = clk_prepare_enable(vec->clock);
 425        if (ret) {
 426                DRM_ERROR("Failed to turn on core clock: %d\n", ret);
 427                return;
 428        }
 429
 430        /* Reset the different blocks */
 431        VEC_WRITE(VEC_WSE_RESET, 1);
 432        VEC_WRITE(VEC_SOFT_RESET, 1);
 433
 434        /* Disable the CGSM-A and WSE blocks */
 435        VEC_WRITE(VEC_WSE_CONTROL, 0);
 436
 437        /* Write config common to all modes. */
 438
 439        /*
 440         * Color subcarrier phase: phase = 360 * SCHPH / 256.
 441         * 0x28 <=> 39.375 deg.
 442         */
 443        VEC_WRITE(VEC_SCHPH, 0x28);
 444
 445        /*
 446         * Reset to default values.
 447         */
 448        VEC_WRITE(VEC_CLMP0_START, 0xac);
 449        VEC_WRITE(VEC_CLMP0_END, 0xec);
 450        VEC_WRITE(VEC_CONFIG2,
 451                  VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS);
 452        VEC_WRITE(VEC_CONFIG3, VEC_CONFIG3_HORIZ_LEN_STD);
 453        VEC_WRITE(VEC_DAC_CONFIG, vec->variant->dac_config);
 454
 455        /* Mask all interrupts. */
 456        VEC_WRITE(VEC_MASK0, 0);
 457
 458        vec->tv_mode->mode_set(vec);
 459
 460        VEC_WRITE(VEC_DAC_MISC,
 461                  VEC_DAC_MISC_VID_ACT | VEC_DAC_MISC_DAC_RST_N);
 462        VEC_WRITE(VEC_CFG, VEC_CFG_VEC_EN);
 463}
 464
 465
 466static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder,
 467                                       const struct drm_display_mode *mode,
 468                                       struct drm_display_mode *adjusted_mode)
 469{
 470        return true;
 471}
 472
 473static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder,
 474                                        struct drm_crtc_state *crtc_state,
 475                                        struct drm_connector_state *conn_state)
 476{
 477        struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
 478        struct vc4_vec *vec = vc4_vec_encoder->vec;
 479
 480        vec->tv_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
 481}
 482
 483static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
 484                                        struct drm_crtc_state *crtc_state,
 485                                        struct drm_connector_state *conn_state)
 486{
 487        const struct vc4_vec_tv_mode *vec_mode;
 488
 489        vec_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
 490
 491        if (conn_state->crtc &&
 492            !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode))
 493                return -EINVAL;
 494
 495        return 0;
 496}
 497
 498static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = {
 499        .disable = vc4_vec_encoder_disable,
 500        .enable = vc4_vec_encoder_enable,
 501        .mode_fixup = vc4_vec_encoder_mode_fixup,
 502        .atomic_check = vc4_vec_encoder_atomic_check,
 503        .atomic_mode_set = vc4_vec_encoder_atomic_mode_set,
 504};
 505
 506static const struct vc4_vec_variant bcm2835_vec_variant = {
 507        .dac_config = VEC_DAC_CONFIG_DAC_CTRL(0xc) |
 508                      VEC_DAC_CONFIG_DRIVER_CTRL(0xc) |
 509                      VEC_DAC_CONFIG_LDO_BIAS_CTRL(0x46)
 510};
 511
 512static const struct vc4_vec_variant bcm2711_vec_variant = {
 513        .dac_config = VEC_DAC_CONFIG_DAC_CTRL(0x0) |
 514                      VEC_DAC_CONFIG_DRIVER_CTRL(0x80) |
 515                      VEC_DAC_CONFIG_LDO_BIAS_CTRL(0x61)
 516};
 517
 518static const struct of_device_id vc4_vec_dt_match[] = {
 519        { .compatible = "brcm,bcm2835-vec", .data = &bcm2835_vec_variant },
 520        { .compatible = "brcm,bcm2711-vec", .data = &bcm2711_vec_variant },
 521        { /* sentinel */ },
 522};
 523
 524static const char * const tv_mode_names[] = {
 525        [VC4_VEC_TV_MODE_NTSC] = "NTSC",
 526        [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
 527        [VC4_VEC_TV_MODE_PAL] = "PAL",
 528        [VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
 529};
 530
 531static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
 532{
 533        struct platform_device *pdev = to_platform_device(dev);
 534        struct drm_device *drm = dev_get_drvdata(master);
 535        struct vc4_dev *vc4 = to_vc4_dev(drm);
 536        struct vc4_vec *vec;
 537        struct vc4_vec_encoder *vc4_vec_encoder;
 538        int ret;
 539
 540        ret = drm_mode_create_tv_properties(drm, ARRAY_SIZE(tv_mode_names),
 541                                            tv_mode_names);
 542        if (ret)
 543                return ret;
 544
 545        vec = devm_kzalloc(dev, sizeof(*vec), GFP_KERNEL);
 546        if (!vec)
 547                return -ENOMEM;
 548
 549        vc4_vec_encoder = devm_kzalloc(dev, sizeof(*vc4_vec_encoder),
 550                                       GFP_KERNEL);
 551        if (!vc4_vec_encoder)
 552                return -ENOMEM;
 553        vc4_vec_encoder->base.type = VC4_ENCODER_TYPE_VEC;
 554        vc4_vec_encoder->vec = vec;
 555        vec->encoder = &vc4_vec_encoder->base.base;
 556
 557        vec->pdev = pdev;
 558        vec->variant = (const struct vc4_vec_variant *)
 559                of_device_get_match_data(dev);
 560        vec->regs = vc4_ioremap_regs(pdev, 0);
 561        if (IS_ERR(vec->regs))
 562                return PTR_ERR(vec->regs);
 563        vec->regset.base = vec->regs;
 564        vec->regset.regs = vec_regs;
 565        vec->regset.nregs = ARRAY_SIZE(vec_regs);
 566
 567        vec->clock = devm_clk_get(dev, NULL);
 568        if (IS_ERR(vec->clock)) {
 569                ret = PTR_ERR(vec->clock);
 570                if (ret != -EPROBE_DEFER)
 571                        DRM_ERROR("Failed to get clock: %d\n", ret);
 572                return ret;
 573        }
 574
 575        pm_runtime_enable(dev);
 576
 577        drm_simple_encoder_init(drm, vec->encoder, DRM_MODE_ENCODER_TVDAC);
 578        drm_encoder_helper_add(vec->encoder, &vc4_vec_encoder_helper_funcs);
 579
 580        vec->connector = vc4_vec_connector_init(drm, vec);
 581        if (IS_ERR(vec->connector)) {
 582                ret = PTR_ERR(vec->connector);
 583                goto err_destroy_encoder;
 584        }
 585
 586        dev_set_drvdata(dev, vec);
 587
 588        vc4->vec = vec;
 589
 590        vc4_debugfs_add_regset32(drm, "vec_regs", &vec->regset);
 591
 592        return 0;
 593
 594err_destroy_encoder:
 595        drm_encoder_cleanup(vec->encoder);
 596        pm_runtime_disable(dev);
 597
 598        return ret;
 599}
 600
 601static void vc4_vec_unbind(struct device *dev, struct device *master,
 602                           void *data)
 603{
 604        struct drm_device *drm = dev_get_drvdata(master);
 605        struct vc4_dev *vc4 = to_vc4_dev(drm);
 606        struct vc4_vec *vec = dev_get_drvdata(dev);
 607
 608        vc4_vec_connector_destroy(vec->connector);
 609        drm_encoder_cleanup(vec->encoder);
 610        pm_runtime_disable(dev);
 611
 612        vc4->vec = NULL;
 613}
 614
 615static const struct component_ops vc4_vec_ops = {
 616        .bind   = vc4_vec_bind,
 617        .unbind = vc4_vec_unbind,
 618};
 619
 620static int vc4_vec_dev_probe(struct platform_device *pdev)
 621{
 622        return component_add(&pdev->dev, &vc4_vec_ops);
 623}
 624
 625static int vc4_vec_dev_remove(struct platform_device *pdev)
 626{
 627        component_del(&pdev->dev, &vc4_vec_ops);
 628        return 0;
 629}
 630
 631struct platform_driver vc4_vec_driver = {
 632        .probe = vc4_vec_dev_probe,
 633        .remove = vc4_vec_dev_remove,
 634        .driver = {
 635                .name = "vc4_vec",
 636                .of_match_table = vc4_vec_dt_match,
 637        },
 638};
 639