aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2018-08-22 09:05:02 -0400
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2018-09-24 17:41:04 -0400
commit9144adc5e5a99577bce0d4ee2ca3615f53b9d296 (patch)
treec4c17a883b3ad5bfd38c27fcf08c9e2f89a64be8 /drivers
parent1f98b2a4fd4632db3b585a624032b7ec785a5255 (diff)
drm: rcar-du: Cache DSYSR value to ensure known initial value
DSYSR is a DU channel register that also contains group fields. It is thus written to by both the group and CRTC code, using read-update-write sequences. As the register isn't initialized explicitly at startup time, this can lead to invalid or otherwise unexpected values being written to some of the fields if they have been modified by the firmware or just not reset properly. To fix this we can write a fully known value to the DSYSR register when turning a channel's functional clock on. However, the mix of group and channel fields complicate this. A simpler solution is to cache the register and initialize the cached value to the desired hardware defaults. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Tested-by: Jacopo Mondi <jacopo+renesas@jmondi.org> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c16
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.h5
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_group.c7
3 files changed, 17 insertions, 11 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 2f8776c1ec8f..f827fccf6416 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -57,13 +57,12 @@ static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set)
57 rcar_du_read(rcdu, rcrtc->mmio_offset + reg) | set); 57 rcar_du_read(rcdu, rcrtc->mmio_offset + reg) | set);
58} 58}
59 59
60static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg, 60void rcar_du_crtc_dsysr_clr_set(struct rcar_du_crtc *rcrtc, u32 clr, u32 set)
61 u32 clr, u32 set)
62{ 61{
63 struct rcar_du_device *rcdu = rcrtc->group->dev; 62 struct rcar_du_device *rcdu = rcrtc->group->dev;
64 u32 value = rcar_du_read(rcdu, rcrtc->mmio_offset + reg);
65 63
66 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set); 64 rcrtc->dsysr = (rcrtc->dsysr & ~clr) | set;
65 rcar_du_write(rcdu, rcrtc->mmio_offset + DSYSR, rcrtc->dsysr);
67} 66}
68 67
69/* ----------------------------------------------------------------------------- 68/* -----------------------------------------------------------------------------
@@ -576,9 +575,9 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
576 * actively driven). 575 * actively driven).
577 */ 576 */
578 interlaced = rcrtc->crtc.mode.flags & DRM_MODE_FLAG_INTERLACE; 577 interlaced = rcrtc->crtc.mode.flags & DRM_MODE_FLAG_INTERLACE;
579 rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK | DSYSR_SCM_MASK, 578 rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK | DSYSR_SCM_MASK,
580 (interlaced ? DSYSR_SCM_INT_VIDEO : 0) | 579 (interlaced ? DSYSR_SCM_INT_VIDEO : 0) |
581 DSYSR_TVM_MASTER); 580 DSYSR_TVM_MASTER);
582 581
583 rcar_du_group_start_stop(rcrtc->group, true); 582 rcar_du_group_start_stop(rcrtc->group, true);
584} 583}
@@ -645,7 +644,7 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
645 * Select switch sync mode. This stops display operation and configures 644 * Select switch sync mode. This stops display operation and configures
646 * the HSYNC and VSYNC signals as inputs. 645 * the HSYNC and VSYNC signals as inputs.
647 */ 646 */
648 rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH); 647 rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH);
649 648
650 rcar_du_group_start_stop(rcrtc->group, false); 649 rcar_du_group_start_stop(rcrtc->group, false);
651} 650}
@@ -1121,6 +1120,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
1121 rcrtc->group = rgrp; 1120 rcrtc->group = rgrp;
1122 rcrtc->mmio_offset = mmio_offsets[hwindex]; 1121 rcrtc->mmio_offset = mmio_offsets[hwindex];
1123 rcrtc->index = hwindex; 1122 rcrtc->index = hwindex;
1123 rcrtc->dsysr = (rcrtc->index % 2 ? 0 : DSYSR_DRES) | DSYSR_TVM_TVSYNC;
1124 1124
1125 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) 1125 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
1126 primary = &rcrtc->vsp->planes[rcrtc->vsp_pipe].plane; 1126 primary = &rcrtc->vsp->planes[rcrtc->vsp_pipe].plane;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index 4990bbe9ba26..59ac6e7d22c9 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -30,6 +30,7 @@ struct rcar_du_vsp;
30 * @mmio_offset: offset of the CRTC registers in the DU MMIO block 30 * @mmio_offset: offset of the CRTC registers in the DU MMIO block
31 * @index: CRTC software and hardware index 31 * @index: CRTC software and hardware index
32 * @initialized: whether the CRTC has been initialized and clocks enabled 32 * @initialized: whether the CRTC has been initialized and clocks enabled
33 * @dsysr: cached value of the DSYSR register
33 * @vblank_enable: whether vblank events are enabled on this CRTC 34 * @vblank_enable: whether vblank events are enabled on this CRTC
34 * @event: event to post when the pending page flip completes 35 * @event: event to post when the pending page flip completes
35 * @flip_wait: wait queue used to signal page flip completion 36 * @flip_wait: wait queue used to signal page flip completion
@@ -50,6 +51,8 @@ struct rcar_du_crtc {
50 unsigned int index; 51 unsigned int index;
51 bool initialized; 52 bool initialized;
52 53
54 u32 dsysr;
55
53 bool vblank_enable; 56 bool vblank_enable;
54 struct drm_pending_vblank_event *event; 57 struct drm_pending_vblank_event *event;
55 wait_queue_head_t flip_wait; 58 wait_queue_head_t flip_wait;
@@ -103,4 +106,6 @@ void rcar_du_crtc_route_output(struct drm_crtc *crtc,
103 enum rcar_du_output output); 106 enum rcar_du_output output);
104void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc); 107void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc);
105 108
109void rcar_du_crtc_dsysr_clr_set(struct rcar_du_crtc *rcrtc, u32 clr, u32 set);
110
106#endif /* __RCAR_DU_CRTC_H__ */ 111#endif /* __RCAR_DU_CRTC_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index f38703e7a10d..d85f0a1c1581 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -202,9 +202,10 @@ void rcar_du_group_put(struct rcar_du_group *rgrp)
202 202
203static void __rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start) 203static void __rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
204{ 204{
205 rcar_du_group_write(rgrp, DSYSR, 205 struct rcar_du_crtc *rcrtc = &rgrp->dev->crtcs[rgrp->index * 2];
206 (rcar_du_group_read(rgrp, DSYSR) & ~(DSYSR_DRES | DSYSR_DEN)) | 206
207 (start ? DSYSR_DEN : DSYSR_DRES)); 207 rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_DRES | DSYSR_DEN,
208 start ? DSYSR_DEN : DSYSR_DRES);
208} 209}
209 210
210void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start) 211void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)