Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/rcar-du: Add support for multiple groups

The R8A7790 DU has 3 CRTCs, split in two groups. Support them.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

+63 -30
+14 -11
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
··· 91 91 static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) 92 92 { 93 93 const struct drm_display_mode *mode = &rcrtc->crtc.mode; 94 - struct rcar_du_device *rcdu = rcrtc->group->dev; 95 94 unsigned long clk; 96 95 u32 value; 97 96 u32 div; ··· 100 101 div = DIV_ROUND_CLOSEST(clk, mode->clock * 1000); 101 102 div = clamp(div, 1U, 64U) - 1; 102 103 103 - rcar_du_write(rcdu, rcrtc->index ? ESCR2 : ESCR, 104 - ESCR_DCLKSEL_CLKS | div); 105 - rcar_du_write(rcdu, rcrtc->index ? OTAR2 : OTAR, 0); 104 + rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? ESCR2 : ESCR, 105 + ESCR_DCLKSEL_CLKS | div); 106 + rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0); 106 107 107 108 /* Signal polarities */ 108 109 value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL) ··· 142 143 void rcar_du_crtc_update_planes(struct drm_crtc *crtc) 143 144 { 144 145 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); 145 - struct rcar_du_device *rcdu = rcrtc->group->dev; 146 146 struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES]; 147 147 unsigned int num_planes = 0; 148 148 unsigned int prio = 0; ··· 187 189 /* Select display timing and dot clock generator 2 for planes associated 188 190 * with superposition controller 2. 189 191 */ 190 - if (rcrtc->index) { 191 - u32 value = rcar_du_read(rcdu, DPTSR); 192 + if (rcrtc->index % 2) { 193 + u32 value = rcar_du_group_read(rcrtc->group, DPTSR); 192 194 193 195 /* The DPTSR register is updated when the display controller is 194 196 * stopped. We thus need to restart the DU. Once again, sorry ··· 198 200 * occur only if we need to break the pre-association. 199 201 */ 200 202 if (value != dptsr) { 201 - rcar_du_write(rcdu, DPTSR, dptsr); 203 + rcar_du_group_write(rcrtc->group, DPTSR, dptsr); 202 204 if (rcrtc->group->used_crtcs) 203 205 rcar_du_group_restart(rcrtc->group); 204 206 } 205 207 } 206 208 207 - rcar_du_write(rcdu, rcrtc->index ? DS2PR : DS1PR, dspr); 209 + rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 210 + dspr); 208 211 } 209 212 210 213 static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc) ··· 527 528 528 529 int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) 529 530 { 531 + static const unsigned int mmio_offsets[] = { 532 + DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET 533 + }; 534 + 530 535 struct rcar_du_device *rcdu = rgrp->dev; 531 536 struct platform_device *pdev = to_platform_device(rcdu->dev); 532 537 struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index]; ··· 556 553 } 557 554 558 555 rcrtc->group = rgrp; 559 - rcrtc->mmio_offset = index ? DISP2_REG_OFFSET : 0; 556 + rcrtc->mmio_offset = mmio_offsets[index]; 560 557 rcrtc->index = index; 561 558 rcrtc->dpms = DRM_MODE_DPMS_OFF; 562 - rcrtc->plane = &rgrp->planes.planes[index]; 559 + rcrtc->plane = &rgrp->planes.planes[index % 2]; 563 560 564 561 rcrtc->plane->crtc = crtc; 565 562
+2
drivers/gpu/drm/rcar-du/rcar_du_drv.c
··· 218 218 219 219 static const struct rcar_du_device_info rcar_du_r8a7779_info = { 220 220 .features = 0, 221 + .num_crtcs = 2, 221 222 }; 222 223 223 224 static const struct rcar_du_device_info rcar_du_r8a7790_info = { 224 225 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_ALIGN_128B, 226 + .num_crtcs = 3, 225 227 }; 226 228 227 229 static const struct platform_device_id rcar_du_id_table[] = {
+4 -2
drivers/gpu/drm/rcar-du/rcar_du_drv.h
··· 31 31 /* 32 32 * struct rcar_du_device_info - DU model-specific information 33 33 * @features: device features (RCAR_DU_FEATURE_*) 34 + * @num_crtcs: total number of CRTCs 34 35 */ 35 36 struct rcar_du_device_info { 36 37 unsigned int features; 38 + unsigned int num_crtcs; 37 39 }; 38 40 39 41 struct rcar_du_device { ··· 47 45 48 46 struct drm_device *ddev; 49 47 50 - struct rcar_du_crtc crtcs[2]; 48 + struct rcar_du_crtc crtcs[3]; 51 49 unsigned int num_crtcs; 52 50 53 - struct rcar_du_group group; 51 + struct rcar_du_group groups[2]; 54 52 }; 55 53 56 54 static inline bool rcar_du_has(struct rcar_du_device *rcdu,
+2 -2
drivers/gpu/drm/rcar-du/rcar_du_group.c
··· 33 33 #include "rcar_du_group.h" 34 34 #include "rcar_du_regs.h" 35 35 36 - static u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg) 36 + u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg) 37 37 { 38 38 return rcar_du_read(rgrp->dev, rgrp->mmio_offset + reg); 39 39 } 40 40 41 - static void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data) 41 + void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data) 42 42 { 43 43 rcar_du_write(rgrp->dev, rgrp->mmio_offset + reg, data); 44 44 }
+3
drivers/gpu/drm/rcar-du/rcar_du_group.h
··· 38 38 struct rcar_du_planes planes; 39 39 }; 40 40 41 + u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg); 42 + void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data); 43 + 41 44 int rcar_du_group_get(struct rcar_du_group *rgrp); 42 45 void rcar_du_group_put(struct rcar_du_group *rgrp); 43 46 void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start);
+31 -12
drivers/gpu/drm/rcar-du/rcar_du_kms.c
··· 172 172 173 173 int rcar_du_modeset_init(struct rcar_du_device *rcdu) 174 174 { 175 + static const unsigned int mmio_offsets[] = { 176 + DU0_REG_OFFSET, DU2_REG_OFFSET 177 + }; 178 + 175 179 struct drm_device *dev = rcdu->ddev; 176 180 struct drm_encoder *encoder; 181 + unsigned int num_groups; 177 182 unsigned int i; 178 183 int ret; 179 184 ··· 190 185 rcdu->ddev->mode_config.max_height = 2047; 191 186 rcdu->ddev->mode_config.funcs = &rcar_du_mode_config_funcs; 192 187 193 - rcdu->group.dev = rcdu; 194 - rcdu->group.index = 0; 195 - rcdu->group.used_crtcs = 0; 188 + rcdu->num_crtcs = rcdu->info->num_crtcs; 196 189 197 - ret = rcar_du_planes_init(&rcdu->group); 198 - if (ret < 0) 199 - return ret; 190 + /* Initialize the groups. */ 191 + num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2); 200 192 201 - for (i = 0; i < ARRAY_SIZE(rcdu->crtcs); ++i) { 202 - ret = rcar_du_crtc_create(&rcdu->group, i); 193 + for (i = 0; i < num_groups; ++i) { 194 + struct rcar_du_group *rgrp = &rcdu->groups[i]; 195 + 196 + rgrp->dev = rcdu; 197 + rgrp->mmio_offset = mmio_offsets[i]; 198 + rgrp->index = i; 199 + 200 + ret = rcar_du_planes_init(rgrp); 203 201 if (ret < 0) 204 202 return ret; 205 203 } 206 204 207 - rcdu->num_crtcs = i; 205 + /* Create the CRTCs. */ 206 + for (i = 0; i < rcdu->num_crtcs; ++i) { 207 + struct rcar_du_group *rgrp = &rcdu->groups[i / 2]; 208 208 209 + ret = rcar_du_crtc_create(rgrp, i); 210 + if (ret < 0) 211 + return ret; 212 + } 213 + 214 + /* Initialize the encoders. */ 209 215 for (i = 0; i < rcdu->pdata->num_encoders; ++i) { 210 216 const struct rcar_du_encoder_data *pdata = 211 217 &rcdu->pdata->encoders[i]; ··· 245 229 encoder->possible_clones = 1 << 0; 246 230 } 247 231 248 - ret = rcar_du_planes_register(&rcdu->group); 249 - if (ret < 0) 250 - return ret; 232 + /* Now that the CRTCs have been initialized register the planes. */ 233 + for (i = 0; i < num_groups; ++i) { 234 + ret = rcar_du_planes_register(&rcdu->groups[i]); 235 + if (ret < 0) 236 + return ret; 237 + } 251 238 252 239 drm_kms_helper_poll_init(rcdu->ddev); 253 240
+4 -2
drivers/gpu/drm/rcar-du/rcar_du_plane.c
··· 480 480 { 481 481 struct rcar_du_planes *planes = &rgrp->planes; 482 482 struct rcar_du_device *rcdu = rgrp->dev; 483 + unsigned int crtcs; 483 484 unsigned int i; 484 485 int ret; 486 + 487 + crtcs = ((1 << rcdu->num_crtcs) - 1) & (3 << (2 * rgrp->index)); 485 488 486 489 for (i = 0; i < RCAR_DU_NUM_KMS_PLANES; ++i) { 487 490 struct rcar_du_kms_plane *plane; ··· 496 493 plane->hwplane = &planes->planes[i + 2]; 497 494 plane->hwplane->zpos = 1; 498 495 499 - ret = drm_plane_init(rcdu->ddev, &plane->plane, 500 - (1 << rcdu->num_crtcs) - 1, 496 + ret = drm_plane_init(rcdu->ddev, &plane->plane, crtcs, 501 497 &rcar_du_plane_funcs, formats, 502 498 ARRAY_SIZE(formats), false); 503 499 if (ret < 0)
+3 -1
drivers/gpu/drm/rcar-du/rcar_du_regs.h
··· 13 13 #ifndef __RCAR_DU_REGS_H__ 14 14 #define __RCAR_DU_REGS_H__ 15 15 16 - #define DISP2_REG_OFFSET 0x30000 16 + #define DU0_REG_OFFSET 0x00000 17 + #define DU1_REG_OFFSET 0x30000 18 + #define DU2_REG_OFFSET 0x40000 17 19 18 20 /* ----------------------------------------------------------------------------- 19 21 * Display Control Registers