drm/msm/mdp: Add capabilities to MDP planes (v2)
authorjilai wang <jilaiw@codeaurora.org>
Wed, 8 Jul 2015 22:12:40 +0000 (18:12 -0400)
committerRob Clark <robdclark@gmail.com>
Sat, 15 Aug 2015 22:27:20 +0000 (18:27 -0400)
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 <jilaiw@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
drivers/gpu/drm/msm/mdp/mdp_kms.h

index 3a79966..ec19c6c 100644 (file)
@@ -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));
-}
-
 enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane);
 struct drm_plane *mdp4_plane_init(struct drm_device *dev,
                enum mdp4_pipe pipe_id, bool private_plane);
index 091cd06..e9dee36 100644 (file)
@@ -26,6 +26,7 @@ struct mdp4_plane {
 
        enum mdp4_pipe pipe;
 
+       uint32_t caps;
        uint32_t nformats;
        uint32_t formats[32];
 
@@ -382,9 +383,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,
index d42ba9e..b155104 100644 (file)
@@ -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,
@@ -115,14 +121,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,
@@ -178,14 +190,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 */
@@ -239,16 +257,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,
index 8a19d27..efb918d 100644 (file)
@@ -46,6 +46,11 @@ struct mdp5_lm_block {
        uint32_t max_height;
 };
 
+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 */
@@ -72,9 +77,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;
index 0511cae..be5f534 100644 (file)
@@ -372,7 +372,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",
@@ -395,7 +395,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",
index dc94c8f..0ef7b99 100644 (file)
@@ -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));
-}
-
 uint32_t mdp5_plane_get_flush(struct drm_plane *plane);
 void mdp5_plane_complete_flip(struct drm_plane *plane);
 void mdp5_plane_complete_commit(struct drm_plane *plane,
        struct drm_plane_state *state);
 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);
 
index 3147d89..171939e 100644 (file)
@@ -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 */
 
@@ -260,10 +261,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;
@@ -637,24 +661,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);
 
@@ -705,7 +733,8 @@ void mdp5_plane_complete_commit(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;
@@ -722,9 +751,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;
index 02c6b7f..867493d 100644 (file)
@@ -98,6 +98,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,