diff options
author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2015-04-28 18:01:45 +0300 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2015-05-25 15:34:12 +0300 |
commit | 2a57e9b5af2b96c45d8c73d34416e5dfa5dd38d9 (patch) | |
tree | c10facea26db9c7c7460fc6762c9eb3633fcff69 /drivers/gpu/drm/rcar-du/rcar_du_crtc.c | |
parent | 08058611958bc161b1de991b494373b8bce56e6b (diff) |
drm: rcar-du: Keep plane to CRTC associations when disabling a plane
Changing the plane to CRTC associations requires restarting the CRTC
group, creating visible flicker. Mitigate the issue by changing plane
association only when a plane becomes enabled, not when it get disabled.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Diffstat (limited to 'drivers/gpu/drm/rcar-du/rcar_du_crtc.c')
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 15f8d145a133..620a2c51185c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -208,9 +208,10 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) { struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES]; unsigned int num_planes = 0; + unsigned int dptsr_planes; + unsigned int hwplanes = 0; unsigned int prio = 0; unsigned int i; - u32 dptsr = 0; u32 dspr = 0; for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes); ++i) { @@ -238,37 +239,44 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) prio -= 4; dspr |= (index + 1) << prio; - dptsr |= DPTSR_PnDK(index) | DPTSR_PnTS(index); + hwplanes |= 1 << index; if (plane_format(plane)->planes == 2) { index = (index + 1) % 8; prio -= 4; dspr |= (index + 1) << prio; - dptsr |= DPTSR_PnDK(index) | DPTSR_PnTS(index); + hwplanes |= 1 << index; } } - /* Select display timing and dot clock generator 2 for planes associated - * with superposition controller 2. + /* Update the planes to display timing and dot clock generator + * associations. + * + * Updating the DPTSR register requires restarting the CRTC group, + * resulting in visible flicker. To mitigate the issue only update the + * association if needed by enabled planes. Planes being disabled will + * keep their current association. + * + * To mitigate the issue further we could pre-associate planes with + * CRTCs, either with a fixed 4/4 split, or through a module parameter. */ - if (rcrtc->index % 2) { - /* The DPTSR register is updated when the display controller is - * stopped. We thus need to restart the DU. Once again, sorry - * for the flicker. One way to mitigate the issue would be to - * pre-associate planes with CRTCs (either with a fixed 4/4 - * split, or through a module parameter). Flicker would then - * occur only if we need to break the pre-association. - */ - mutex_lock(&rcrtc->group->lock); - if (rcar_du_group_read(rcrtc->group, DPTSR) != dptsr) { - rcar_du_group_write(rcrtc->group, DPTSR, dptsr); - if (rcrtc->group->used_crtcs) - rcar_du_group_restart(rcrtc->group); - } - mutex_unlock(&rcrtc->group->lock); + mutex_lock(&rcrtc->group->lock); + + dptsr_planes = rcrtc->index % 2 ? rcrtc->group->dptsr_planes | hwplanes + : rcrtc->group->dptsr_planes & ~hwplanes; + + if (dptsr_planes != rcrtc->group->dptsr_planes) { + rcar_du_group_write(rcrtc->group, DPTSR, + (dptsr_planes << 16) | dptsr_planes); + rcrtc->group->dptsr_planes = dptsr_planes; + + if (rcrtc->group->used_crtcs) + rcar_du_group_restart(rcrtc->group); } + mutex_unlock(&rcrtc->group->lock); + rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, dspr); } |