drm/msm/mdp5: Misc cursor plane bits
authorArchit Taneja <architt@codeaurora.org>
Mon, 16 Jan 2017 06:27:04 +0000 (11:57 +0530)
committerRob Clark <robdclark@gmail.com>
Mon, 6 Feb 2017 16:28:44 +0000 (11:28 -0500)
These are various changes added in preparation for cursor planes:

- Add a pipe_cursor block for 8x96 in mdp5_cfg.
- Add a new pipe CAP called MDP_PIPE_CAP_CURSOR. Use this to ensure we
  assign a cursor SSPP for a drm_plane with type DRM_PLANE_TYPE_CURSOR.
- Update mdp5_ctl_blend_mask/ext_blend_mask funcs to incorporate cursor
  SSPPs.
- In mdp5_ctl_blend, iterate through MAX_STAGES instead of stage_cnt,
  we need to do this because we can now have empty stages in between.
- In mdp5_crtc_atomic_check, make sure that the cursor plane has the
  highest zorder, and stage the cursor plane to the maximum stage #
  present on the HW.
- Create drm_crtc_funcs that doesn't try to implement cursors using the
  older LM cursor HW.
- Pass drm_plane_type in mdp5_plane_init instead of a bool telling
  whether plane is primary or not.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
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_pipe.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
drivers/gpu/drm/msm/mdp/mdp_kms.h

index 618b2ffed9b44a83217d4fddaaa6f615d5db8104..34ab553f6897656c0eddc14b0f65a88f9e693e11 100644 (file)
@@ -421,6 +421,16 @@ const struct mdp5_cfg_hw msm8x96_config = {
                        MDP_PIPE_CAP_SW_PIX_EXT |
                        0,
        },
+       .pipe_cursor = {
+               .count = 2,
+               .base = { 0x34000, 0x36000 },
+               .caps = MDP_PIPE_CAP_HFLIP      |
+                       MDP_PIPE_CAP_VFLIP      |
+                       MDP_PIPE_CAP_SW_PIX_EXT |
+                       MDP_PIPE_CAP_CURSOR     |
+                       0,
+       },
+
        .lm = {
                .count = 6,
                .base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
index fec966293f9aaf46a44d56b6d037de7983b5f01e..84fcb6e3a1766a88481b8f22f8e3060dafbef0e2 100644 (file)
@@ -400,6 +400,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
        struct plane_state pstates[STAGE_MAX + 1];
        const struct mdp5_cfg_hw *hw_cfg;
        const struct drm_plane_state *pstate;
+       bool cursor_plane = false;
        int cnt = 0, base = 0, i;
 
        DBG("%s: check", crtc->name);
@@ -409,6 +410,9 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
                pstates[cnt].state = to_mdp5_plane_state(pstate);
 
                cnt++;
+
+               if (plane->type == DRM_PLANE_TYPE_CURSOR)
+                       cursor_plane = true;
        }
 
        /* assign a stage based on sorted zpos property */
@@ -420,6 +424,10 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
        if ((cnt > 0) && !is_fullscreen(state, &pstates[0].state->base))
                base++;
 
+       /* trigger a warning if cursor isn't the highest zorder */
+       WARN_ON(cursor_plane &&
+               (pstates[cnt - 1].plane->type != DRM_PLANE_TYPE_CURSOR));
+
        /* verify that there are not too many planes attached to crtc
         * and that we don't have conflicting mixer stages:
         */
@@ -431,7 +439,10 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
        }
 
        for (i = 0; i < cnt; i++) {
-               pstates[i].state->stage = STAGE_BASE + i + base;
+               if (cursor_plane && (i == (cnt - 1)))
+                       pstates[i].state->stage = hw_cfg->lm.nb_stages;
+               else
+                       pstates[i].state->stage = STAGE_BASE + i + base;
                DBG("%s: assign pipe %s on stage=%d", crtc->name,
                                pstates[i].plane->name,
                                pstates[i].state->stage);
@@ -642,6 +653,16 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = {
        .cursor_move = mdp5_crtc_cursor_move,
 };
 
+static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = {
+       .set_config = drm_atomic_helper_set_config,
+       .destroy = mdp5_crtc_destroy,
+       .page_flip = drm_atomic_helper_page_flip,
+       .set_property = drm_atomic_helper_crtc_set_property,
+       .reset = drm_atomic_helper_crtc_reset,
+       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
 static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = {
        .mode_set_nofb = mdp5_crtc_mode_set_nofb,
        .disable = mdp5_crtc_disable,
@@ -775,7 +796,8 @@ void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc)
 
 /* initialize crtc */
 struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
-               struct drm_plane *plane, int id)
+                               struct drm_plane *plane,
+                               struct drm_plane *cursor_plane, int id)
 {
        struct drm_crtc *crtc = NULL;
        struct mdp5_crtc *mdp5_crtc;
@@ -796,8 +818,12 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
        mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;
        mdp5_crtc->err.irq = mdp5_crtc_err_irq;
 
-       drm_crtc_init_with_planes(dev, crtc, plane, NULL, &mdp5_crtc_funcs,
-                                 NULL);
+       if (cursor_plane)
+               drm_crtc_init_with_planes(dev, crtc, plane, cursor_plane,
+                                         &mdp5_crtc_no_lm_cursor_funcs, NULL);
+       else
+               drm_crtc_init_with_planes(dev, crtc, plane, NULL,
+                                         &mdp5_crtc_funcs, NULL);
 
        drm_flip_work_init(&mdp5_crtc->unref_cursor_work,
                        "unref cursor", unref_cursor_worker);
index ab339ce7425a755abbf9830eb9665a375ba3b78d..8b93f7e13200e8acf6c950617bed8ee968e26fb5 100644 (file)
@@ -326,6 +326,8 @@ static u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe,
        case SSPP_DMA1: return MDP5_CTL_LAYER_REG_DMA1(stage);
        case SSPP_VIG3: return MDP5_CTL_LAYER_REG_VIG3(stage);
        case SSPP_RGB3: return MDP5_CTL_LAYER_REG_RGB3(stage);
+       case SSPP_CURSOR0:
+       case SSPP_CURSOR1:
        default:        return 0;
        }
 }
@@ -333,7 +335,7 @@ static u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe,
 static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe,
                enum mdp_mixer_stage_id stage)
 {
-       if (stage < STAGE6)
+       if (stage < STAGE6 && (pipe != SSPP_CURSOR0 && pipe != SSPP_CURSOR1))
                return 0;
 
        switch (pipe) {
@@ -347,6 +349,8 @@ static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe,
        case SSPP_DMA1: return MDP5_CTL_LAYER_EXT_REG_DMA1_BIT3;
        case SSPP_VIG3: return MDP5_CTL_LAYER_EXT_REG_VIG3_BIT3;
        case SSPP_RGB3: return MDP5_CTL_LAYER_EXT_REG_RGB3_BIT3;
+       case SSPP_CURSOR0: return MDP5_CTL_LAYER_EXT_REG_CURSOR0(stage);
+       case SSPP_CURSOR1: return MDP5_CTL_LAYER_EXT_REG_CURSOR1(stage);
        default:        return 0;
        }
 }
@@ -365,7 +369,7 @@ int mdp5_ctl_blend(struct mdp5_ctl *ctl, enum mdp5_pipe *stage, u32 stage_cnt,
                start_stage = STAGE_BASE;
        }
 
-       for (i = start_stage; i < start_stage + stage_cnt; i++) {
+       for (i = start_stage; stage_cnt && i <= STAGE_MAX; i++) {
                blend_cfg |= mdp_ctl_blend_mask(stage[i], i);
                blend_ext_cfg |= mdp_ctl_blend_ext_mask(stage[i], i);
        }
@@ -422,6 +426,8 @@ u32 mdp_ctl_flush_mask_pipe(enum mdp5_pipe pipe)
        case SSPP_DMA1: return MDP5_CTL_FLUSH_DMA1;
        case SSPP_VIG3: return MDP5_CTL_FLUSH_VIG3;
        case SSPP_RGB3: return MDP5_CTL_FLUSH_RGB3;
+       case SSPP_CURSOR0: return MDP5_CTL_FLUSH_CURSOR_0;
+       case SSPP_CURSOR1: return MDP5_CTL_FLUSH_CURSOR_1;
        default:        return 0;
        }
 }
index ecfa38949aeab1a6b03d72ca652f32d6851f024d..70a1950de8ae074e1b25c00b4502409fec99a6b5 100644 (file)
@@ -441,8 +441,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
                bool primary = i < num_crtcs;
                struct drm_plane *plane;
                struct drm_crtc *crtc;
+               enum drm_plane_type type;
 
-               plane = mdp5_plane_init(dev, primary);
+               if (primary)
+                       type = DRM_PLANE_TYPE_PRIMARY;
+               else
+                       type = DRM_PLANE_TYPE_OVERLAY;
+
+               plane = mdp5_plane_init(dev, type);
                if (IS_ERR(plane)) {
                        ret = PTR_ERR(plane);
                        dev_err(dev->dev, "failed to construct plane %d (%d)\n", i, ret);
@@ -453,7 +459,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
                if (!primary)
                        continue;
 
-               crtc  = mdp5_crtc_init(dev, plane, i);
+               crtc  = mdp5_crtc_init(dev, plane, NULL, i);
                if (IS_ERR(crtc)) {
                        ret = PTR_ERR(crtc);
                        dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret);
index 40ebc5c5087503df48d3e9a02f3aa3a383940636..0396e8adb693fc6bbba2103508192adaad77cb45 100644 (file)
@@ -167,6 +167,7 @@ static inline const char *pipe2name(enum mdp5_pipe pipe)
                NAME(RGB0), NAME(RGB1), NAME(RGB2),
                NAME(DMA0), NAME(DMA1),
                NAME(VIG3), NAME(RGB3),
+               NAME(CURSOR0), NAME(CURSOR1),
 #undef NAME
        };
        return names[pipe];
@@ -242,7 +243,8 @@ void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms);
 
 uint32_t mdp5_plane_get_flush(struct drm_plane *plane);
 enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
-struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary);
+struct drm_plane *mdp5_plane_init(struct drm_device *dev,
+                                 enum drm_plane_type type);
 
 uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
 
@@ -251,7 +253,8 @@ void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,
                struct mdp5_interface *intf, struct mdp5_ctl *ctl);
 void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc);
 struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
-               struct drm_plane *plane, int id);
+                               struct drm_plane *plane,
+                               struct drm_plane *cursor_plane, int id);
 
 struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
                struct mdp5_interface *intf, struct mdp5_ctl *ctl);
index 1ae9dc8d260d3822da0c005f5e900234ae21dff1..35c4dabb0c0c7d934ea2550d49a978d183acddd7 100644 (file)
@@ -53,6 +53,14 @@ struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s,
                if (caps & ~cur->caps)
                        continue;
 
+               /*
+                * don't assign a cursor pipe to a plane that isn't going to
+                * be used as a cursor
+                */
+               if (cur->caps & MDP_PIPE_CAP_CURSOR &&
+                               plane->type != DRM_PLANE_TYPE_CURSOR)
+                       continue;
+
                /* possible candidate, take the one with the
                 * fewest unneeded caps bits set:
                 */
index 939991d5f3468c0ba1aa5e1ef99c0a4695cf94d8..7409e959d810f83b4991d753f745c218cdba9a03 100644 (file)
@@ -344,6 +344,9 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
                if (rotation & DRM_REFLECT_Y)
                        caps |= MDP_PIPE_CAP_VFLIP;
 
+               if (plane->type == DRM_PLANE_TYPE_CURSOR)
+                       caps |= MDP_PIPE_CAP_CURSOR;
+
                /* (re)allocate hw pipe if we don't have one or caps-mismatch: */
                if (!mdp5_state->hwpipe || (caps & ~mdp5_state->hwpipe->caps))
                        new_hwpipe = true;
@@ -870,12 +873,12 @@ uint32_t mdp5_plane_get_flush(struct drm_plane *plane)
 }
 
 /* initialize plane */
-struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary)
+struct drm_plane *mdp5_plane_init(struct drm_device *dev,
+                                 enum drm_plane_type type)
 {
        struct drm_plane *plane = NULL;
        struct mdp5_plane *mdp5_plane;
        int ret;
-       enum drm_plane_type type;
 
        mdp5_plane = kzalloc(sizeof(*mdp5_plane), GFP_KERNEL);
        if (!mdp5_plane) {
@@ -888,7 +891,6 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary)
        mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats,
                ARRAY_SIZE(mdp5_plane->formats), false);
 
-       type = primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
        ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
                                 mdp5_plane->formats, mdp5_plane->nformats,
                                 type, NULL);
index 30313032074845c4602a9feae9c8a3d5f76c2b07..7574cdfef418b67ed391db377dc36621c0f93ea1 100644 (file)
@@ -112,6 +112,7 @@ const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);
 #define MDP_PIPE_CAP_CSC                       BIT(3)
 #define MDP_PIPE_CAP_DECIMATION                        BIT(4)
 #define MDP_PIPE_CAP_SW_PIX_EXT                        BIT(5)
+#define MDP_PIPE_CAP_CURSOR                    BIT(6)
 
 static inline bool pipe_supports_yuv(uint32_t pipe_caps)
 {