drm: rcar-du: Restart the DU group when a plane source changes
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Sat, 24 Aug 2013 00:17:03 +0000 (02:17 +0200)
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Sat, 20 Feb 2016 00:58:55 +0000 (02:58 +0200)
Plane sources are configured by the VSPS bit in the PnDDCR4 register.
Although the datasheet states that the bit is updated during vertical
blanking, it seems that updates only occur when the DU group is held in
reset through the DSYSR.DRES bit. Restart the group if the source
changes.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
drivers/gpu/drm/rcar-du/rcar_du_group.c
drivers/gpu/drm/rcar-du/rcar_du_group.h
drivers/gpu/drm/rcar-du/rcar_du_plane.c

index b87b8ffb898b97383064e9a66e7c16b33718118c..e2560aa26ef4fc27e43c6f2f3768ee69fb9d8c94 100644 (file)
@@ -272,6 +272,10 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
                        rcar_du_group_restart(rcrtc->group);
        }
 
+       /* Restart the group if plane sources have changed. */
+       if (rcrtc->group->need_restart)
+               rcar_du_group_restart(rcrtc->group);
+
        mutex_unlock(&rcrtc->group->lock);
 
        rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
index 4a44ddd5176624feb78c503f1d2d2cd31d734de7..0e2b46dce56334bab65604e8fb01814e051ae634 100644 (file)
@@ -162,6 +162,8 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
 
 void rcar_du_group_restart(struct rcar_du_group *rgrp)
 {
+       rgrp->need_restart = false;
+
        __rcar_du_group_start_stop(rgrp, false);
        __rcar_du_group_start_stop(rgrp, true);
 }
index 4b1952fd4e7d4b20fc97b7b0a0f54e5700e64700..5e3adc6b31b56356a6fba3aea129bf9653829b7d 100644 (file)
@@ -32,6 +32,7 @@ struct rcar_du_device;
  * @dptsr_planes: bitmask of planes driven by dot-clock and timing generator 1
  * @num_planes: number of planes in the group
  * @planes: planes handled by the group
+ * @need_restart: the group needs to be restarted due to a configuration change
  */
 struct rcar_du_group {
        struct rcar_du_device *dev;
@@ -47,6 +48,7 @@ struct rcar_du_group {
 
        unsigned int num_planes;
        struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
+       bool need_restart;
 };
 
 u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg);
index cc383954e29a15d385d5b0055bf8184eceec60be..2fa5745fca37aacac75312542f41b8469d91e4e1 100644 (file)
@@ -275,9 +275,27 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
                                        struct drm_plane_state *old_state)
 {
        struct rcar_du_plane *rplane = to_rcar_plane(plane);
+       struct rcar_du_plane_state *old_rstate;
+       struct rcar_du_plane_state *new_rstate;
 
-       if (plane->state->crtc)
-               rcar_du_plane_setup(rplane);
+       if (!plane->state->crtc)
+               return;
+
+       rcar_du_plane_setup(rplane);
+
+       /* Check whether the source has changed from memory to live source or
+        * from live source to memory. The source has been configured by the
+        * VSPS bit in the PnDDCR4 register. Although the datasheet states that
+        * the bit is updated during vertical blanking, it seems that updates
+        * only occur when the DU group is held in reset through the DSYSR.DRES
+        * bit. We thus need to restart the group if the source changes.
+        */
+       old_rstate = to_rcar_plane_state(old_state);
+       new_rstate = to_rcar_plane_state(plane->state);
+
+       if ((old_rstate->source == RCAR_DU_PLANE_MEMORY) !=
+           (new_rstate->source == RCAR_DU_PLANE_MEMORY))
+               rplane->group->need_restart = true;
 }
 
 static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {