root/drivers/gpu/drm/vc4/vc4_vec.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_vc4_vec_encoder
  2. to_vc4_vec_connector
  3. vc4_vec_ntsc_mode_set
  4. vc4_vec_ntsc_j_mode_set
  5. vc4_vec_pal_mode_set
  6. vc4_vec_pal_m_mode_set
  7. vc4_vec_connector_detect
  8. vc4_vec_connector_destroy
  9. vc4_vec_connector_get_modes
  10. vc4_vec_connector_init
  11. vc4_vec_encoder_disable
  12. vc4_vec_encoder_enable
  13. vc4_vec_encoder_mode_fixup
  14. vc4_vec_encoder_atomic_mode_set
  15. vc4_vec_encoder_atomic_check
  16. vc4_vec_bind
  17. vc4_vec_unbind
  18. vc4_vec_dev_probe
  19. vc4_vec_dev_remove

   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 <linux/clk.h>
  21 #include <linux/component.h>
  22 #include <linux/of_graph.h>
  23 #include <linux/of_platform.h>
  24 #include <linux/pm_runtime.h>
  25 
  26 #include "vc4_drv.h"
  27 #include "vc4_regs.h"
  28 
  29 /* WSE Registers */
  30 #define VEC_WSE_RESET                   0xc0
  31 
  32 #define VEC_WSE_CONTROL                 0xc4
  33 #define VEC_WSE_WSS_ENABLE              BIT(7)
  34 
  35 #define VEC_WSE_WSS_DATA                0xc8
  36 #define VEC_WSE_VPS_DATA1               0xcc
  37 #define VEC_WSE_VPS_CONTROL             0xd0
  38 
  39 /* VEC Registers */
  40 #define VEC_REVID                       0x100
  41 
  42 #define VEC_CONFIG0                     0x104
  43 #define VEC_CONFIG0_YDEL_MASK           GENMASK(28, 26)
  44 #define VEC_CONFIG0_YDEL(x)             ((x) << 26)
  45 #define VEC_CONFIG0_CDEL_MASK           GENMASK(25, 24)
  46 #define VEC_CONFIG0_CDEL(x)             ((x) << 24)
  47 #define VEC_CONFIG0_PBPR_FIL            BIT(18)
  48 #define VEC_CONFIG0_CHROMA_GAIN_MASK    GENMASK(17, 16)
  49 #define VEC_CONFIG0_CHROMA_GAIN_UNITY   (0 << 16)
  50 #define VEC_CONFIG0_CHROMA_GAIN_1_32    (1 << 16)
  51 #define VEC_CONFIG0_CHROMA_GAIN_1_16    (2 << 16)
  52 #define VEC_CONFIG0_CHROMA_GAIN_1_8     (3 << 16)
  53 #define VEC_CONFIG0_CBURST_GAIN_MASK    GENMASK(14, 13)
  54 #define VEC_CONFIG0_CBURST_GAIN_UNITY   (0 << 13)
  55 #define VEC_CONFIG0_CBURST_GAIN_1_128   (1 << 13)
  56 #define VEC_CONFIG0_CBURST_GAIN_1_64    (2 << 13)
  57 #define VEC_CONFIG0_CBURST_GAIN_1_32    (3 << 13)
  58 #define VEC_CONFIG0_CHRBW1              BIT(11)
  59 #define VEC_CONFIG0_CHRBW0              BIT(10)
  60 #define VEC_CONFIG0_SYNCDIS             BIT(9)
  61 #define VEC_CONFIG0_BURDIS              BIT(8)
  62 #define VEC_CONFIG0_CHRDIS              BIT(7)
  63 #define VEC_CONFIG0_PDEN                BIT(6)
  64 #define VEC_CONFIG0_YCDELAY             BIT(4)
  65 #define VEC_CONFIG0_RAMPEN              BIT(2)
  66 #define VEC_CONFIG0_YCDIS               BIT(2)
  67 #define VEC_CONFIG0_STD_MASK            GENMASK(1, 0)
  68 #define VEC_CONFIG0_NTSC_STD            0
  69 #define VEC_CONFIG0_PAL_BDGHI_STD       1
  70 #define VEC_CONFIG0_PAL_N_STD           3
  71 
  72 #define VEC_SCHPH                       0x108
  73 #define VEC_SOFT_RESET                  0x10c
  74 #define VEC_CLMP0_START                 0x144
  75 #define VEC_CLMP0_END                   0x148
  76 #define VEC_FREQ3_2                     0x180
  77 #define VEC_FREQ1_0                     0x184
  78 
  79 #define VEC_CONFIG1                     0x188
  80 #define VEC_CONFIG_VEC_RESYNC_OFF       BIT(18)
  81 #define VEC_CONFIG_RGB219               BIT(17)
  82 #define VEC_CONFIG_CBAR_EN              BIT(16)
  83 #define VEC_CONFIG_TC_OBB               BIT(15)
  84 #define VEC_CONFIG1_OUTPUT_MODE_MASK    GENMASK(12, 10)
  85 #define VEC_CONFIG1_C_Y_CVBS            (0 << 10)
  86 #define VEC_CONFIG1_CVBS_Y_C            (1 << 10)
  87 #define VEC_CONFIG1_PR_Y_PB             (2 << 10)
  88 #define VEC_CONFIG1_RGB                 (4 << 10)
  89 #define VEC_CONFIG1_Y_C_CVBS            (5 << 10)
  90 #define VEC_CONFIG1_C_CVBS_Y            (6 << 10)
  91 #define VEC_CONFIG1_C_CVBS_CVBS         (7 << 10)
  92 #define VEC_CONFIG1_DIS_CHR             BIT(9)
  93 #define VEC_CONFIG1_DIS_LUMA            BIT(8)
  94 #define VEC_CONFIG1_YCBCR_IN            BIT(6)
  95 #define VEC_CONFIG1_DITHER_TYPE_LFSR    0
  96 #define VEC_CONFIG1_DITHER_TYPE_COUNTER BIT(5)
  97 #define VEC_CONFIG1_DITHER_EN           BIT(4)
  98 #define VEC_CONFIG1_CYDELAY             BIT(3)
  99 #define VEC_CONFIG1_LUMADIS             BIT(2)
 100 #define VEC_CONFIG1_COMPDIS             BIT(1)
 101 #define VEC_CONFIG1_CUSTOM_FREQ         BIT(0)
 102 
 103 #define VEC_CONFIG2                     0x18c
 104 #define VEC_CONFIG2_PROG_SCAN           BIT(15)
 105 #define VEC_CONFIG2_SYNC_ADJ_MASK       GENMASK(14, 12)
 106 #define VEC_CONFIG2_SYNC_ADJ(x)         (((x) / 2) << 12)
 107 #define VEC_CONFIG2_PBPR_EN             BIT(10)
 108 #define VEC_CONFIG2_UV_DIG_DIS          BIT(6)
 109 #define VEC_CONFIG2_RGB_DIG_DIS         BIT(5)
 110 #define VEC_CONFIG2_TMUX_MASK           GENMASK(3, 2)
 111 #define VEC_CONFIG2_TMUX_DRIVE0         (0 << 2)
 112 #define VEC_CONFIG2_TMUX_RG_COMP        (1 << 2)
 113 #define VEC_CONFIG2_TMUX_UV_YC          (2 << 2)
 114 #define VEC_CONFIG2_TMUX_SYNC_YC        (3 << 2)
 115 
 116 #define VEC_INTERRUPT_CONTROL           0x190
 117 #define VEC_INTERRUPT_STATUS            0x194
 118 #define VEC_FCW_SECAM_B                 0x198
 119 #define VEC_SECAM_GAIN_VAL              0x19c
 120 
 121 #define VEC_CONFIG3                     0x1a0
 122 #define VEC_CONFIG3_HORIZ_LEN_STD       (0 << 0)
 123 #define VEC_CONFIG3_HORIZ_LEN_MPEG1_SIF (1 << 0)
 124 #define VEC_CONFIG3_SHAPE_NON_LINEAR    BIT(1)
 125 
 126 #define VEC_STATUS0                     0x200
 127 #define VEC_MASK0                       0x204
 128 
 129 #define VEC_CFG                         0x208
 130 #define VEC_CFG_SG_MODE_MASK            GENMASK(6, 5)
 131 #define VEC_CFG_SG_MODE(x)              ((x) << 5)
 132 #define VEC_CFG_SG_EN                   BIT(4)
 133 #define VEC_CFG_VEC_EN                  BIT(3)
 134 #define VEC_CFG_MB_EN                   BIT(2)
 135 #define VEC_CFG_ENABLE                  BIT(1)
 136 #define VEC_CFG_TB_EN                   BIT(0)
 137 
 138 #define VEC_DAC_TEST                    0x20c
 139 
 140 #define VEC_DAC_CONFIG                  0x210
 141 #define VEC_DAC_CONFIG_LDO_BIAS_CTRL(x) ((x) << 24)
 142 #define VEC_DAC_CONFIG_DRIVER_CTRL(x)   ((x) << 16)
 143 #define VEC_DAC_CONFIG_DAC_CTRL(x)      (x)
 144 
 145 #define VEC_DAC_MISC                    0x214
 146 #define VEC_DAC_MISC_VCD_CTRL_MASK      GENMASK(31, 16)
 147 #define VEC_DAC_MISC_VCD_CTRL(x)        ((x) << 16)
 148 #define VEC_DAC_MISC_VID_ACT            BIT(8)
 149 #define VEC_DAC_MISC_VCD_PWRDN          BIT(6)
 150 #define VEC_DAC_MISC_BIAS_PWRDN         BIT(5)
 151 #define VEC_DAC_MISC_DAC_PWRDN          BIT(2)
 152 #define VEC_DAC_MISC_LDO_PWRDN          BIT(1)
 153 #define VEC_DAC_MISC_DAC_RST_N          BIT(0)
 154 
 155 
 156 /* General VEC hardware state. */
 157 struct vc4_vec {
 158         struct platform_device *pdev;
 159 
 160         struct drm_encoder *encoder;
 161         struct drm_connector *connector;
 162 
 163         void __iomem *regs;
 164 
 165         struct clk *clock;
 166 
 167         const struct vc4_vec_tv_mode *tv_mode;
 168 
 169         struct debugfs_regset32 regset;
 170 };
 171 
 172 #define VEC_READ(offset) readl(vec->regs + (offset))
 173 #define VEC_WRITE(offset, val) writel(val, vec->regs + (offset))
 174 
 175 /* VC4 VEC encoder KMS struct */
 176 struct vc4_vec_encoder {
 177         struct vc4_encoder base;
 178         struct vc4_vec *vec;
 179 };
 180 
 181 static inline struct vc4_vec_encoder *
 182 to_vc4_vec_encoder(struct drm_encoder *encoder)
 183 {
 184         return container_of(encoder, struct vc4_vec_encoder, base.base);
 185 }
 186 
 187 /* VC4 VEC connector KMS struct */
 188 struct vc4_vec_connector {
 189         struct drm_connector base;
 190         struct vc4_vec *vec;
 191 
 192         /* Since the connector is attached to just the one encoder,
 193          * this is the reference to it so we can do the best_encoder()
 194          * hook.
 195          */
 196         struct drm_encoder *encoder;
 197 };
 198 
 199 static inline struct vc4_vec_connector *
 200 to_vc4_vec_connector(struct drm_connector *connector)
 201 {
 202         return container_of(connector, struct vc4_vec_connector, base);
 203 }
 204 
 205 enum 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 
 212 struct vc4_vec_tv_mode {
 213         const struct drm_display_mode *mode;
 214         void (*mode_set)(struct vc4_vec *vec);
 215 };
 216 
 217 static 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 
 244 static 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 
 250 static 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 
 256 static 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 
 263 static 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 
 269 static 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 
 278 static 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 
 285 static 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 
 304 static enum drm_connector_status
 305 vc4_vec_connector_detect(struct drm_connector *connector, bool force)
 306 {
 307         return connector_status_unknown;
 308 }
 309 
 310 static void vc4_vec_connector_destroy(struct drm_connector *connector)
 311 {
 312         drm_connector_unregister(connector);
 313         drm_connector_cleanup(connector);
 314 }
 315 
 316 static 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 
 333 static 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 
 342 static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs = {
 343         .get_modes = vc4_vec_connector_get_modes,
 344 };
 345 
 346 static 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 
 377 static const struct drm_encoder_funcs vc4_vec_encoder_funcs = {
 378         .destroy = drm_encoder_cleanup,
 379 };
 380 
 381 static void vc4_vec_encoder_disable(struct drm_encoder *encoder)
 382 {
 383         struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
 384         struct vc4_vec *vec = vc4_vec_encoder->vec;
 385         int ret;
 386 
 387         VEC_WRITE(VEC_CFG, 0);
 388         VEC_WRITE(VEC_DAC_MISC,
 389                   VEC_DAC_MISC_VCD_PWRDN |
 390                   VEC_DAC_MISC_BIAS_PWRDN |
 391                   VEC_DAC_MISC_DAC_PWRDN |
 392                   VEC_DAC_MISC_LDO_PWRDN);
 393 
 394         clk_disable_unprepare(vec->clock);
 395 
 396         ret = pm_runtime_put(&vec->pdev->dev);
 397         if (ret < 0) {
 398                 DRM_ERROR("Failed to release power domain: %d\n", ret);
 399                 return;
 400         }
 401 }
 402 
 403 static void vc4_vec_encoder_enable(struct drm_encoder *encoder)
 404 {
 405         struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
 406         struct vc4_vec *vec = vc4_vec_encoder->vec;
 407         int ret;
 408 
 409         ret = pm_runtime_get_sync(&vec->pdev->dev);
 410         if (ret < 0) {
 411                 DRM_ERROR("Failed to retain power domain: %d\n", ret);
 412                 return;
 413         }
 414 
 415         /*
 416          * We need to set the clock rate each time we enable the encoder
 417          * because there's a chance we share the same parent with the HDMI
 418          * clock, and both drivers are requesting different rates.
 419          * The good news is, these 2 encoders cannot be enabled at the same
 420          * time, thus preventing incompatible rate requests.
 421          */
 422         ret = clk_set_rate(vec->clock, 108000000);
 423         if (ret) {
 424                 DRM_ERROR("Failed to set clock rate: %d\n", ret);
 425                 return;
 426         }
 427 
 428         ret = clk_prepare_enable(vec->clock);
 429         if (ret) {
 430                 DRM_ERROR("Failed to turn on core clock: %d\n", ret);
 431                 return;
 432         }
 433 
 434         /* Reset the different blocks */
 435         VEC_WRITE(VEC_WSE_RESET, 1);
 436         VEC_WRITE(VEC_SOFT_RESET, 1);
 437 
 438         /* Disable the CGSM-A and WSE blocks */
 439         VEC_WRITE(VEC_WSE_CONTROL, 0);
 440 
 441         /* Write config common to all modes. */
 442 
 443         /*
 444          * Color subcarrier phase: phase = 360 * SCHPH / 256.
 445          * 0x28 <=> 39.375 deg.
 446          */
 447         VEC_WRITE(VEC_SCHPH, 0x28);
 448 
 449         /*
 450          * Reset to default values.
 451          */
 452         VEC_WRITE(VEC_CLMP0_START, 0xac);
 453         VEC_WRITE(VEC_CLMP0_END, 0xec);
 454         VEC_WRITE(VEC_CONFIG2,
 455                   VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS);
 456         VEC_WRITE(VEC_CONFIG3, VEC_CONFIG3_HORIZ_LEN_STD);
 457         VEC_WRITE(VEC_DAC_CONFIG,
 458                   VEC_DAC_CONFIG_DAC_CTRL(0xc) |
 459                   VEC_DAC_CONFIG_DRIVER_CTRL(0xc) |
 460                   VEC_DAC_CONFIG_LDO_BIAS_CTRL(0x46));
 461 
 462         /* Mask all interrupts. */
 463         VEC_WRITE(VEC_MASK0, 0);
 464 
 465         vec->tv_mode->mode_set(vec);
 466 
 467         VEC_WRITE(VEC_DAC_MISC,
 468                   VEC_DAC_MISC_VID_ACT | VEC_DAC_MISC_DAC_RST_N);
 469         VEC_WRITE(VEC_CFG, VEC_CFG_VEC_EN);
 470 }
 471 
 472 
 473 static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder,
 474                                        const struct drm_display_mode *mode,
 475                                        struct drm_display_mode *adjusted_mode)
 476 {
 477         return true;
 478 }
 479 
 480 static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder,
 481                                         struct drm_crtc_state *crtc_state,
 482                                         struct drm_connector_state *conn_state)
 483 {
 484         struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
 485         struct vc4_vec *vec = vc4_vec_encoder->vec;
 486 
 487         vec->tv_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
 488 }
 489 
 490 static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
 491                                         struct drm_crtc_state *crtc_state,
 492                                         struct drm_connector_state *conn_state)
 493 {
 494         const struct vc4_vec_tv_mode *vec_mode;
 495 
 496         vec_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
 497 
 498         if (conn_state->crtc &&
 499             !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode))
 500                 return -EINVAL;
 501 
 502         return 0;
 503 }
 504 
 505 static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = {
 506         .disable = vc4_vec_encoder_disable,
 507         .enable = vc4_vec_encoder_enable,
 508         .mode_fixup = vc4_vec_encoder_mode_fixup,
 509         .atomic_check = vc4_vec_encoder_atomic_check,
 510         .atomic_mode_set = vc4_vec_encoder_atomic_mode_set,
 511 };
 512 
 513 static const struct of_device_id vc4_vec_dt_match[] = {
 514         { .compatible = "brcm,bcm2835-vec", .data = NULL },
 515         { /* sentinel */ },
 516 };
 517 
 518 static const char * const tv_mode_names[] = {
 519         [VC4_VEC_TV_MODE_NTSC] = "NTSC",
 520         [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
 521         [VC4_VEC_TV_MODE_PAL] = "PAL",
 522         [VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
 523 };
 524 
 525 static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
 526 {
 527         struct platform_device *pdev = to_platform_device(dev);
 528         struct drm_device *drm = dev_get_drvdata(master);
 529         struct vc4_dev *vc4 = to_vc4_dev(drm);
 530         struct vc4_vec *vec;
 531         struct vc4_vec_encoder *vc4_vec_encoder;
 532         int ret;
 533 
 534         ret = drm_mode_create_tv_properties(drm, ARRAY_SIZE(tv_mode_names),
 535                                             tv_mode_names);
 536         if (ret)
 537                 return ret;
 538 
 539         vec = devm_kzalloc(dev, sizeof(*vec), GFP_KERNEL);
 540         if (!vec)
 541                 return -ENOMEM;
 542 
 543         vc4_vec_encoder = devm_kzalloc(dev, sizeof(*vc4_vec_encoder),
 544                                        GFP_KERNEL);
 545         if (!vc4_vec_encoder)
 546                 return -ENOMEM;
 547         vc4_vec_encoder->base.type = VC4_ENCODER_TYPE_VEC;
 548         vc4_vec_encoder->vec = vec;
 549         vec->encoder = &vc4_vec_encoder->base.base;
 550 
 551         vec->pdev = pdev;
 552         vec->regs = vc4_ioremap_regs(pdev, 0);
 553         if (IS_ERR(vec->regs))
 554                 return PTR_ERR(vec->regs);
 555         vec->regset.base = vec->regs;
 556         vec->regset.regs = vec_regs;
 557         vec->regset.nregs = ARRAY_SIZE(vec_regs);
 558 
 559         vec->clock = devm_clk_get(dev, NULL);
 560         if (IS_ERR(vec->clock)) {
 561                 ret = PTR_ERR(vec->clock);
 562                 if (ret != -EPROBE_DEFER)
 563                         DRM_ERROR("Failed to get clock: %d\n", ret);
 564                 return ret;
 565         }
 566 
 567         pm_runtime_enable(dev);
 568 
 569         drm_encoder_init(drm, vec->encoder, &vc4_vec_encoder_funcs,
 570                          DRM_MODE_ENCODER_TVDAC, NULL);
 571         drm_encoder_helper_add(vec->encoder, &vc4_vec_encoder_helper_funcs);
 572 
 573         vec->connector = vc4_vec_connector_init(drm, vec);
 574         if (IS_ERR(vec->connector)) {
 575                 ret = PTR_ERR(vec->connector);
 576                 goto err_destroy_encoder;
 577         }
 578 
 579         dev_set_drvdata(dev, vec);
 580 
 581         vc4->vec = vec;
 582 
 583         vc4_debugfs_add_regset32(drm, "vec_regs", &vec->regset);
 584 
 585         return 0;
 586 
 587 err_destroy_encoder:
 588         drm_encoder_cleanup(vec->encoder);
 589         pm_runtime_disable(dev);
 590 
 591         return ret;
 592 }
 593 
 594 static void vc4_vec_unbind(struct device *dev, struct device *master,
 595                            void *data)
 596 {
 597         struct drm_device *drm = dev_get_drvdata(master);
 598         struct vc4_dev *vc4 = to_vc4_dev(drm);
 599         struct vc4_vec *vec = dev_get_drvdata(dev);
 600 
 601         vc4_vec_connector_destroy(vec->connector);
 602         drm_encoder_cleanup(vec->encoder);
 603         pm_runtime_disable(dev);
 604 
 605         vc4->vec = NULL;
 606 }
 607 
 608 static const struct component_ops vc4_vec_ops = {
 609         .bind   = vc4_vec_bind,
 610         .unbind = vc4_vec_unbind,
 611 };
 612 
 613 static int vc4_vec_dev_probe(struct platform_device *pdev)
 614 {
 615         return component_add(&pdev->dev, &vc4_vec_ops);
 616 }
 617 
 618 static int vc4_vec_dev_remove(struct platform_device *pdev)
 619 {
 620         component_del(&pdev->dev, &vc4_vec_ops);
 621         return 0;
 622 }
 623 
 624 struct platform_driver vc4_vec_driver = {
 625         .probe = vc4_vec_dev_probe,
 626         .remove = vc4_vec_dev_remove,
 627         .driver = {
 628                 .name = "vc4_vec",
 629                 .of_match_table = vc4_vec_dt_match,
 630         },
 631 };

/* [<][>][^][v][top][bottom][index][help] */