Configure the plane source at plane setup time to source frames from
memory or from the VSP1.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas at ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_drv.h   |  2 +
 drivers/gpu/drm/rcar-du/rcar_du_group.c | 24 +++++----
 drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 +
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 16 ++++--
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 86 +++++++++++++++++++--------------
 drivers/gpu/drm/rcar-du/rcar_du_regs.h  |  1 +
 6 files changed, 82 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h 
b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 9f34fc86436a..e10b4f0d8f83 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -90,6 +90,8 @@ struct rcar_du_device {
        } props;

        unsigned int dpad0_source;
+       unsigned int vspd1_sink;
+
        struct rcar_du_lvdsenc *lvds[RCAR_DU_MAX_LVDS];

        struct {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c 
b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 8e2ffe025153..4a44ddd51766 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -49,11 +49,15 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group 
*rgrp)
        u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;

        /* The DEFR8 register for the first group also controls RGB output
-        * routing to DPAD0 for DU instances that support it.
+        * routing to DPAD0 and VSPD1 routing to DU0/1/2 for DU instances that
+        * support it.
         */
-       if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1 &&
-           rgrp->index == 0)
-               defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
+       if (rgrp->index == 0) {
+               if 
(rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1)
+                       defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
+               if (rgrp->dev->vspd1_sink == 2)
+                       defr8 |= DEFR8_VSCS;
+       }

        rcar_du_group_write(rgrp, DEFR8, defr8);
 }
@@ -162,17 +166,17 @@ void rcar_du_group_restart(struct rcar_du_group *rgrp)
        __rcar_du_group_start_stop(rgrp, true);
 }

-static int rcar_du_set_dpad0_routing(struct rcar_du_device *rcdu)
+int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu)
 {
        int ret;

        if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_EXT_CTRL_REGS))
                return 0;

-       /* RGB output routing to DPAD0 is configured in the DEFR8 register of
-        * the first group. As this function can be called with the DU0 and DU1
-        * CRTCs disabled, we need to enable the first group clock before
-        * accessing the register.
+       /* RGB output routing to DPAD0 and VSP1D routing to DU0/1/2 are
+        * configured in the DEFR8 register of the first group. As this function
+        * can be called with the DU0 and DU1 CRTCs disabled, we need to enable
+        * the first group clock before accessing the register.
         */
        ret = clk_prepare_enable(rcdu->crtcs[0].clock);
        if (ret < 0)
@@ -203,5 +207,5 @@ int rcar_du_group_set_routing(struct rcar_du_group *rgrp)

        rcar_du_group_write(rgrp, DORCR, dorcr);

-       return rcar_du_set_dpad0_routing(rgrp->dev);
+       return rcar_du_set_dpad0_vsp1_routing(rgrp->dev);
 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h 
b/drivers/gpu/drm/rcar-du/rcar_du_group.h
index d7318e1a6b00..4b1952fd4e7d 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
@@ -58,4 +58,6 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, 
bool start);
 void rcar_du_group_restart(struct rcar_du_group *rgrp);
 int rcar_du_group_set_routing(struct rcar_du_group *rgrp);

+int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu);
+
 #endif /* __RCAR_DU_GROUP_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c 
b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 455f7e466181..ba4e100e5b0f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -217,17 +217,25 @@ static void rcar_du_output_poll_changed(struct drm_device 
*dev)
  */

 static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
-                                       struct rcar_du_plane_state *state)
+                                       struct rcar_du_plane_state *new_state)
 {
-       const struct rcar_du_format_info *cur_format;
+       struct rcar_du_plane_state *cur_state;

-       cur_format = to_rcar_plane_state(plane->plane.state)->format;
+       cur_state = to_rcar_plane_state(plane->plane.state);

        /* Lowering the number of planes doesn't strictly require reallocation
         * as the extra hardware plane will be freed when committing, but doing
         * so could lead to more fragmentation.
         */
-       return !cur_format || cur_format->planes != state->format->planes;
+       if (!cur_state->format ||
+           cur_state->format->planes != new_state->format->planes)
+               return true;
+
+       /* Reallocate hardware planes if the source has changed. */
+       if (cur_state->source != new_state->source)
+               return true;
+
+       return false;
 }

 static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c 
b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index f301c15934cc..78ca353bfcf0 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -20,6 +20,7 @@
 #include <drm/drm_plane_helper.h>

 #include "rcar_du_drv.h"
+#include "rcar_du_group.h"
 #include "rcar_du_kms.h"
 #include "rcar_du_plane.h"
 #include "rcar_du_regs.h"
@@ -35,37 +36,42 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
                      data);
 }

-static void rcar_du_plane_setup_scanout(struct rcar_du_plane *plane)
+static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
+                                       const struct rcar_du_plane_state *state)
 {
-       struct rcar_du_plane_state *state =
-               to_rcar_plane_state(plane->plane.state);
-       struct drm_framebuffer *fb = plane->plane.state->fb;
-       struct rcar_du_group *rgrp = plane->group;
        unsigned int src_x = state->state.src_x >> 16;
        unsigned int src_y = state->state.src_y >> 16;
        unsigned int index = state->hwindex;
-       struct drm_gem_cma_object *gem;
        unsigned int pitch;
        bool interlaced;
-       unsigned int i;
        u32 dma[2];

        interlaced = state->state.crtc->state->adjusted_mode.flags
                   & DRM_MODE_FLAG_INTERLACE;

-       /* Memory pitch (expressed in pixels). Must be doubled for interlaced
-        * operation with 32bpp formats.
-        */
-       if (state->format->planes == 2)
-               pitch = fb->pitches[0];
-       else
-               pitch = fb->pitches[0] * 8 / state->format->bpp;
+       if (state->source == RCAR_DU_PLANE_MEMORY) {
+               struct drm_framebuffer *fb = state->state.fb;
+               struct drm_gem_cma_object *gem;
+               unsigned int i;
+
+               if (state->format->planes == 2)
+                       pitch = fb->pitches[0];
+               else
+                       pitch = fb->pitches[0] * 8 / state->format->bpp;

-       for (i = 0; i < state->format->planes; ++i) {
-               gem = drm_fb_cma_get_gem_obj(fb, i);
-               dma[i] = gem->paddr + fb->offsets[i];
+               for (i = 0; i < state->format->planes; ++i) {
+                       gem = drm_fb_cma_get_gem_obj(fb, i);
+                       dma[i] = gem->paddr + fb->offsets[i];
+               }
+       } else {
+               pitch = state->state.src_w >> 16;
+               dma[0] = 0;
+               dma[1] = 0;
        }

+       /* Memory pitch (expressed in pixels). Must be doubled for interlaced
+        * operation with 32bpp formats.
+        */
        rcar_du_plane_write(rgrp, index, PnMWR,
                            (interlaced && state->format->bpp == 32) ?
                            pitch * 2 : pitch);
@@ -101,12 +107,10 @@ static void rcar_du_plane_setup_scanout(struct 
rcar_du_plane *plane)
        }
 }

-static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
-                                    unsigned int index)
+static void rcar_du_plane_setup_mode(struct rcar_du_group *rgrp,
+                                    unsigned int index,
+                                    const struct rcar_du_plane_state *state)
 {
-       struct rcar_du_plane_state *state =
-               to_rcar_plane_state(plane->plane.state);
-       struct rcar_du_group *rgrp = plane->group;
        u32 colorkey;
        u32 pnmr;

@@ -164,12 +168,10 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane 
*plane,
        }
 }

-static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
-                                      unsigned int index)
+static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
+                                      unsigned int index,
+                                      const struct rcar_du_plane_state *state)
 {
-       struct rcar_du_plane_state *state =
-               to_rcar_plane_state(plane->plane.state);
-       struct rcar_du_group *rgrp = plane->group;
        u32 ddcr2 = PnDDCR2_CODE;
        u32 ddcr4;

@@ -179,7 +181,7 @@ static void rcar_du_plane_setup_format(struct rcar_du_plane 
*plane,
         * field in DDCR4.
         */

-       rcar_du_plane_setup_mode(plane, index);
+       rcar_du_plane_setup_mode(rgrp, index, state);

        if (state->format->planes == 2) {
                if (state->hwindex != index) {
@@ -199,14 +201,16 @@ static void rcar_du_plane_setup_format(struct 
rcar_du_plane *plane,
        rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);

        ddcr4 = state->format->edf | PnDDCR4_CODE;
+       if (state->source != RCAR_DU_PLANE_MEMORY)
+               ddcr4 |= PnDDCR4_VSPS;

        rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);

        /* Destination position and size */
-       rcar_du_plane_write(rgrp, index, PnDSXR, plane->plane.state->crtc_w);
-       rcar_du_plane_write(rgrp, index, PnDSYR, plane->plane.state->crtc_h);
-       rcar_du_plane_write(rgrp, index, PnDPXR, plane->plane.state->crtc_x);
-       rcar_du_plane_write(rgrp, index, PnDPYR, plane->plane.state->crtc_y);
+       rcar_du_plane_write(rgrp, index, PnDSXR, state->state.crtc_w);
+       rcar_du_plane_write(rgrp, index, PnDSYR, state->state.crtc_h);
+       rcar_du_plane_write(rgrp, index, PnDPXR, state->state.crtc_x);
+       rcar_du_plane_write(rgrp, index, PnDPYR, state->state.crtc_y);

        /* Wrap-around and blinking, disabled */
        rcar_du_plane_write(rgrp, index, PnWASPR, 0);
@@ -219,12 +223,24 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane)
 {
        struct rcar_du_plane_state *state =
                to_rcar_plane_state(plane->plane.state);
+       struct rcar_du_group *rgrp = plane->group;

-       rcar_du_plane_setup_format(plane, state->hwindex);
+       rcar_du_plane_setup_format(rgrp, state->hwindex, state);
        if (state->format->planes == 2)
-               rcar_du_plane_setup_format(plane, (state->hwindex + 1) % 8);
+               rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
+                                          state);
+
+       rcar_du_plane_setup_scanout(rgrp, state);

-       rcar_du_plane_setup_scanout(plane);
+       if (state->source == RCAR_DU_PLANE_VSPD1) {
+               unsigned int vspd1_sink = rgrp->index ? 2 : 0;
+               struct rcar_du_device *rcdu = rgrp->dev;
+
+               if (rcdu->vspd1_sink != vspd1_sink) {
+                       rcdu->vspd1_sink = vspd1_sink;
+                       rcar_du_set_dpad0_vsp1_routing(rcdu);
+               }
+       }
 }

 static int rcar_du_plane_atomic_check(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h 
b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index 70fcbc471ebd..ac9c3e511e79 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -389,6 +389,7 @@

 #define PnDDCR4                        0x00190
 #define PnDDCR4_CODE           (0x7766 << 16)
+#define PnDDCR4_VSPS           (1 << 13)
 #define PnDDCR4_SDFS_RGB       (0 << 4)
 #define PnDDCR4_SDFS_YC                (5 << 4)
 #define PnDDCR4_SDFS_MASK      (7 << 4)
-- 
2.4.6

Reply via email to