MDP planes can be implemented using different type of HW pipes,
RGB/VIG/DMA pipes for MDP5 and RGB/VG/DMA pipes for MDP4. Each type
of pipe has different HW capabilities such as scaling, color space
conversion, decimation... Add a variable in plane data structure
to specify the difference of each plane which comes from mdp5_cfg data
and use it to differenciate the plane operation.
V1: Initial change
V2: Fix a typo in mdp4_kms.h

Signed-off-by: Jilai Wang <jil...@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h   | 19 ++++----
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c |  7 ++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c   | 26 ++++++++++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h   | 11 +++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c   |  4 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h   | 24 +---------
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 73 ++++++++++++++++++++++---------
 drivers/gpu/drm/msm/mdp/mdp_kms.h         | 13 ++++++
 8 files changed, 114 insertions(+), 63 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
index c1ecb9d..1aaedad 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
@@ -175,27 +175,24 @@ irqreturn_t mdp4_irq(struct msm_kms *kms);
 int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
 void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
 
-static inline bool pipe_supports_yuv(enum mdp4_pipe pipe)
+static inline uint32_t mdp4_pipe_caps(enum mdp4_pipe pipe)
 {
        switch (pipe) {
        case VG1:
        case VG2:
        case VG3:
        case VG4:
-               return true;
+               return MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
+                       MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC;
+       case RGB1:
+       case RGB2:
+       case RGB3:
+               return MDP_PIPE_CAP_SCALE;
        default:
-               return false;
+               return 0;
        }
 }
 
-static inline
-uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *pixel_formats,
-               uint32_t max_formats)
-{
-       return mdp_get_formats(pixel_formats, max_formats,
-                               !pipe_supports_yuv(pipe_id));
-}
-
 void mdp4_plane_install_properties(struct drm_plane *plane,
                struct drm_mode_object *obj);
 enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane);
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index 0d1dbb7..c749489 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -26,6 +26,7 @@ struct mdp4_plane {
 
        enum mdp4_pipe pipe;
 
+       uint32_t caps;
        uint32_t nformats;
        uint32_t formats[32];
 
@@ -380,9 +381,11 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
 
        mdp4_plane->pipe = pipe_id;
        mdp4_plane->name = pipe_names[pipe_id];
+       mdp4_plane->caps = mdp4_pipe_caps(pipe_id);
 
-       mdp4_plane->nformats = mdp4_get_formats(pipe_id, mdp4_plane->formats,
-                       ARRAY_SIZE(mdp4_plane->formats));
+       mdp4_plane->nformats = mdp_get_formats(mdp4_plane->formats,
+                       ARRAY_SIZE(mdp4_plane->formats),
+                       !pipe_supports_yuv(mdp4_plane->caps));
 
        type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
        ret = drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index 789b02f..ac1d58f 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -45,14 +45,20 @@ const struct mdp5_cfg_hw msm8x74_config = {
        .pipe_vig = {
                .count = 3,
                .base = { 0x01200, 0x01600, 0x01a00 },
+               .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
+                               MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
+                               MDP_PIPE_CAP_DECIMATION,
        },
        .pipe_rgb = {
                .count = 3,
                .base = { 0x01e00, 0x02200, 0x02600 },
+               .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
+                               MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
        },
        .pipe_dma = {
                .count = 2,
                .base = { 0x02a00, 0x02e00 },
+               .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
        },
        .lm = {
                .count = 5,
@@ -113,14 +119,20 @@ const struct mdp5_cfg_hw apq8084_config = {
        .pipe_vig = {
                .count = 4,
                .base = { 0x01200, 0x01600, 0x01a00, 0x01e00 },
+               .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
+                               MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
+                               MDP_PIPE_CAP_DECIMATION,
        },
        .pipe_rgb = {
                .count = 4,
                .base = { 0x02200, 0x02600, 0x02a00, 0x02e00 },
+               .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
+                               MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
        },
        .pipe_dma = {
                .count = 2,
                .base = { 0x03200, 0x03600 },
+               .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
        },
        .lm = {
                .count = 6,
@@ -174,14 +186,20 @@ const struct mdp5_cfg_hw msm8x16_config = {
        .pipe_vig = {
                .count = 1,
                .base = { 0x05000 },
+               .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
+                               MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
+                               MDP_PIPE_CAP_DECIMATION,
        },
        .pipe_rgb = {
                .count = 2,
                .base = { 0x15000, 0x17000 },
+               .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
+                               MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
        },
        .pipe_dma = {
                .count = 1,
                .base = { 0x25000 },
+               .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
        },
        .lm = {
                .count = 2, /* LM0 and LM3 */
@@ -233,16 +251,20 @@ const struct mdp5_cfg_hw msm8x94_config = {
        .pipe_vig = {
                .count = 4,
                .base = { 0x05000, 0x07000, 0x09000, 0x0b000 },
-               /* TODO: add decimation bit */
+               .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
+                               MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
+                               MDP_PIPE_CAP_DECIMATION,
        },
        .pipe_rgb = {
                .count = 4,
                .base = { 0x15000, 0x17000, 0x19000, 0x1b000 },
-               /* TODO: add decimation bit */
+               .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
+                               MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
        },
        .pipe_dma = {
                .count = 2,
                .base = { 0x25000, 0x27000 },
+               .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
        },
        .lm = {
                .count = 6,
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
index 69349ab..72e9914 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
@@ -44,6 +44,11 @@ struct mdp5_lm_block {
        uint32_t nb_stages;             /* number of stages per blender */
 };
 
+struct mdp5_pipe_block {
+       MDP5_SUB_BLOCK_DEFINITION;
+       uint32_t caps;                  /* pipe capabilities */
+};
+
 struct mdp5_ctl_block {
        MDP5_SUB_BLOCK_DEFINITION;
        uint32_t flush_hw_mask;         /* FLUSH register's hardware mask */
@@ -70,9 +75,9 @@ struct mdp5_cfg_hw {
        struct mdp5_sub_block mdp;
        struct mdp5_smp_block smp;
        struct mdp5_ctl_block ctl;
-       struct mdp5_sub_block pipe_vig;
-       struct mdp5_sub_block pipe_rgb;
-       struct mdp5_sub_block pipe_dma;
+       struct mdp5_pipe_block pipe_vig;
+       struct mdp5_pipe_block pipe_rgb;
+       struct mdp5_pipe_block pipe_dma;
        struct mdp5_lm_block  lm;
        struct mdp5_sub_block dspp;
        struct mdp5_sub_block ad;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index af0059b..cbda41d 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -339,7 +339,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
                struct drm_crtc *crtc;
 
                plane = mdp5_plane_init(dev, crtcs[i], true,
-                               hw_cfg->pipe_rgb.base[i]);
+                       hw_cfg->pipe_rgb.base[i], hw_cfg->pipe_rgb.caps);
                if (IS_ERR(plane)) {
                        ret = PTR_ERR(plane);
                        dev_err(dev->dev, "failed to construct plane for %s 
(%d)\n",
@@ -362,7 +362,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
                struct drm_plane *plane;
 
                plane = mdp5_plane_init(dev, pub_planes[i], false,
-                               hw_cfg->pipe_vig.base[i]);
+                       hw_cfg->pipe_vig.base[i], hw_cfg->pipe_vig.caps);
                if (IS_ERR(plane)) {
                        ret = PTR_ERR(plane);
                        dev_err(dev->dev, "failed to construct %s plane: %d\n",
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 06af415..8542b30 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -196,34 +196,14 @@ void mdp5_disable_vblank(struct msm_kms *kms, struct 
drm_crtc *crtc);
 int mdp5_irq_domain_init(struct mdp5_kms *mdp5_kms);
 void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms);
 
-static inline bool pipe_supports_yuv(enum mdp5_pipe pipe)
-{
-       switch (pipe) {
-       case SSPP_VIG0:
-       case SSPP_VIG1:
-       case SSPP_VIG2:
-       case SSPP_VIG3:
-               return true;
-       default:
-               return false;
-       }
-}
-
-static inline
-uint32_t mdp5_get_formats(enum mdp5_pipe pipe, uint32_t *pixel_formats,
-               uint32_t max_formats)
-{
-       return mdp_get_formats(pixel_formats, max_formats,
-                               !pipe_supports_yuv(pipe));
-}
-
 void mdp5_plane_install_properties(struct drm_plane *plane,
                struct drm_mode_object *obj);
 uint32_t mdp5_plane_get_flush(struct drm_plane *plane);
 void mdp5_plane_complete_flip(struct drm_plane *plane);
 enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
 struct drm_plane *mdp5_plane_init(struct drm_device *dev,
-               enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset);
+               enum mdp5_pipe pipe, bool private_plane,
+                uint32_t reg_offset,  uint32_t caps);
 
 uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 51bb944..1fbb17d 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -26,6 +26,7 @@ struct mdp5_plane {
 
        spinlock_t pipe_lock;   /* protect REG_MDP5_PIPE_* registers */
        uint32_t reg_offset;
+       uint32_t caps;
 
        uint32_t flush_mask;    /* used to commit pipe registers */
 
@@ -288,10 +289,33 @@ static int mdp5_plane_atomic_check(struct drm_plane 
*plane,
 {
        struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
        struct drm_plane_state *old_state = plane->state;
+       const struct mdp_format *format;
 
        DBG("%s: check (%d -> %d)", mdp5_plane->name,
                        plane_enabled(old_state), plane_enabled(state));
 
+       if (plane_enabled(state)) {
+               format = to_mdp_format(msm_framebuffer_format(state->fb));
+               if (MDP_FORMAT_IS_YUV(format) &&
+                       !pipe_supports_yuv(mdp5_plane->caps)) {
+                       dev_err(plane->dev->dev,
+                               "Pipe doesn't support YUV\n");
+
+                       return -EINVAL;
+               }
+
+               if (!(mdp5_plane->caps & MDP_PIPE_CAP_SCALE) &&
+                       (((state->src_w >> 16) != state->crtc_w) ||
+                       ((state->src_h >> 16) != state->crtc_h))) {
+                       dev_err(plane->dev->dev,
+                               "Pipe doesn't support scaling (%dx%d -> 
%dx%d)\n",
+                               state->src_w >> 16, state->src_h >> 16,
+                               state->crtc_w, state->crtc_h);
+
+                       return -EINVAL;
+               }
+       }
+
        if (plane_enabled(state) && plane_enabled(old_state)) {
                /* we cannot change SMP block configuration during scanout: */
                bool full_modeset = false;
@@ -656,24 +680,28 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
        /* not using secure mode: */
        mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0);
 
-       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
-                       phasex_step[0]);
-       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
-                       phasey_step[0]);
-       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_X(pipe),
-                       phasex_step[1]);
-       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_Y(pipe),
-                       phasey_step[1]);
-       mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe),
-                       MDP5_PIPE_DECIMATION_VERT(vdecm) |
-                       MDP5_PIPE_DECIMATION_HORZ(hdecm));
-       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), config);
-
-       if (MDP_FORMAT_IS_YUV(format))
-               csc_enable(mdp5_kms, pipe,
-                               mdp_get_default_csc_cfg(CSC_YUV2RGB));
-       else
-               csc_disable(mdp5_kms, pipe);
+       if (mdp5_plane->caps & MDP_PIPE_CAP_SCALE) {
+               mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
+                               phasex_step[0]);
+               mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
+                               phasey_step[0]);
+               mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_X(pipe),
+                               phasex_step[1]);
+               mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_Y(pipe),
+                               phasey_step[1]);
+               mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe),
+                               MDP5_PIPE_DECIMATION_VERT(vdecm) |
+                               MDP5_PIPE_DECIMATION_HORZ(hdecm));
+               mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), config);
+       }
+
+       if (mdp5_plane->caps & MDP_PIPE_CAP_CSC) {
+               if (MDP_FORMAT_IS_YUV(format))
+                       csc_enable(mdp5_kms, pipe,
+                                       mdp_get_default_csc_cfg(CSC_YUV2RGB));
+               else
+                       csc_disable(mdp5_kms, pipe);
+       }
 
        set_scanout_locked(plane, fb);
 
@@ -710,7 +738,8 @@ uint32_t mdp5_plane_get_flush(struct drm_plane *plane)
 
 /* initialize plane */
 struct drm_plane *mdp5_plane_init(struct drm_device *dev,
-               enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset)
+               enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset,
+               uint32_t caps)
 {
        struct drm_plane *plane = NULL;
        struct mdp5_plane *mdp5_plane;
@@ -727,9 +756,11 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
 
        mdp5_plane->pipe = pipe;
        mdp5_plane->name = pipe2name(pipe);
+       mdp5_plane->caps = caps;
 
-       mdp5_plane->nformats = mdp5_get_formats(pipe, mdp5_plane->formats,
-                       ARRAY_SIZE(mdp5_plane->formats));
+       mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats,
+               ARRAY_SIZE(mdp5_plane->formats),
+               !pipe_supports_yuv(mdp5_plane->caps));
 
        mdp5_plane->flush_mask = mdp_ctl_flush_mask_pipe(pipe);
        mdp5_plane->reg_offset = reg_offset;
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h 
b/drivers/gpu/drm/msm/mdp/mdp_kms.h
index 2d3428c..3db25df 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h
@@ -97,6 +97,19 @@ struct mdp_format {
 uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool 
rgb_only);
 const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);
 
+/* MDP pipe capabilities */
+#define MDP_PIPE_CAP_HFLIP                     BIT(0)
+#define MDP_PIPE_CAP_VFLIP                     BIT(1)
+#define MDP_PIPE_CAP_SCALE                     BIT(2)
+#define MDP_PIPE_CAP_CSC                       BIT(3)
+#define MDP_PIPE_CAP_DECIMATION                        BIT(4)
+
+static inline bool pipe_supports_yuv(uint32_t pipe_caps)
+{
+       return (pipe_caps & MDP_PIPE_CAP_SCALE) &&
+               (pipe_caps & MDP_PIPE_CAP_CSC);
+}
+
 enum csc_type {
        CSC_RGB2RGB = 0,
        CSC_YUV2RGB,
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to