From 5798c8e0d3e09be71d2e937b985b17d89f0b7535 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 16 Jan 2017 11:57:04 +0530 Subject: [PATCH] drm/msm/mdp5: Misc cursor plane bits 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 Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 10 +++++++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 34 ++++++++++++++++++++--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 10 +++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 10 +++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 7 +++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c | 8 ++++++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 8 ++++-- drivers/gpu/drm/msm/mdp/mdp_kms.h | 1 + 8 files changed, 75 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c index 618b2ffed9b4..34ab553f6897 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c @@ -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 }, diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index fec966293f9a..84fcb6e3a176 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -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); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c index ab339ce7425a..8b93f7e13200 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c @@ -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; } } diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index ecfa38949aea..70a1950de8ae 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -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); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h index 40ebc5c50875..0396e8adb693 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h @@ -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); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c index 1ae9dc8d260d..35c4dabb0c0c 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c @@ -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: */ diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 939991d5f346..7409e959d810 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -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); diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h index 303130320748..7574cdfef418 100644 --- a/drivers/gpu/drm/msm/mdp/mdp_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h @@ -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) {