aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2018-11-24 17:17:39 -0500
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2019-01-13 20:51:27 -0500
commitdedd876c949e56351f27aa52bf2eddd4a447f5bb (patch)
tree542f67ca703b2883b7d70bbda597206728ef5119 /drivers/gpu/drm
parentb8a43032a7b8d7e8e7c65dfa987d8374a0de7a6e (diff)
drm: rcar-du: Disable unused DPAD outputs
DU channels are routed to DPAD outputs in an SoC-dependent way. The routing can be fixed (e.g. DU3 to DPAD0 on H3) or configurable (e.g. DU0 or DU1 to DPAD0 on D3/E3). The hardware offers no option to disconnect DPAD outputs, which are thus always driven by a DU channel. On SoCs that have less DU channels than DU outputs, such as D3 and E3, the DPAD output is always driven when all channels are in use by other outputs (such as the internal LVDS and HDMI encoders). This creates an unwanted clone on the DPAD output. However, the parallel output of the DU channels routed to DPAD can be set to fixed levels in the DU channels themselves through the DOFLR group register. Use this to turn the DPAD on or off by driving fixed signals at the output of any DU channel not routed to a DPAD output. This doesn't affect the DU output signals going to other outputs. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_group.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 7e440f61977f..9eee47969e77 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -287,6 +287,47 @@ int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu)
287 return 0; 287 return 0;
288} 288}
289 289
290static void rcar_du_group_set_dpad_levels(struct rcar_du_group *rgrp)
291{
292 static const u32 doflr_values[2] = {
293 DOFLR_HSYCFL0 | DOFLR_VSYCFL0 | DOFLR_ODDFL0 |
294 DOFLR_DISPFL0 | DOFLR_CDEFL0 | DOFLR_RGBFL0,
295 DOFLR_HSYCFL1 | DOFLR_VSYCFL1 | DOFLR_ODDFL1 |
296 DOFLR_DISPFL1 | DOFLR_CDEFL1 | DOFLR_RGBFL1,
297 };
298 static const u32 dpad_mask = BIT(RCAR_DU_OUTPUT_DPAD1)
299 | BIT(RCAR_DU_OUTPUT_DPAD0);
300 struct rcar_du_device *rcdu = rgrp->dev;
301 u32 doflr = DOFLR_CODE;
302 unsigned int i;
303
304 if (rcdu->info->gen < 2)
305 return;
306
307 /*
308 * The DPAD outputs can't be controlled directly. However, the parallel
309 * output of the DU channels routed to DPAD can be set to fixed levels
310 * through the DOFLR group register. Use this to turn the DPAD on or off
311 * by driving fixed low-level signals at the output of any DU channel
312 * not routed to a DPAD output. This doesn't affect the DU output
313 * signals going to other outputs, such as the internal LVDS and HDMI
314 * encoders.
315 */
316
317 for (i = 0; i < rgrp->num_crtcs; ++i) {
318 struct rcar_du_crtc_state *rstate;
319 struct rcar_du_crtc *rcrtc;
320
321 rcrtc = &rcdu->crtcs[rgrp->index * 2 + i];
322 rstate = to_rcar_crtc_state(rcrtc->crtc.state);
323
324 if (!(rstate->outputs & dpad_mask))
325 doflr |= doflr_values[i];
326 }
327
328 rcar_du_group_write(rgrp, DOFLR, doflr);
329}
330
290int rcar_du_group_set_routing(struct rcar_du_group *rgrp) 331int rcar_du_group_set_routing(struct rcar_du_group *rgrp)
291{ 332{
292 struct rcar_du_device *rcdu = rgrp->dev; 333 struct rcar_du_device *rcdu = rgrp->dev;
@@ -306,5 +347,7 @@ int rcar_du_group_set_routing(struct rcar_du_group *rgrp)
306 347
307 rcar_du_group_write(rgrp, DORCR, dorcr); 348 rcar_du_group_write(rgrp, DORCR, dorcr);
308 349
350 rcar_du_group_set_dpad_levels(rgrp);
351
309 return rcar_du_set_dpad0_vsp1_routing(rgrp->dev); 352 return rcar_du_set_dpad0_vsp1_routing(rgrp->dev);
310} 353}