Commit 5798c8e0 authored by Archit Taneja's avatar Archit Taneja Committed by Rob Clark

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: default avatarArchit Taneja <architt@codeaurora.org>
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent 829200ac
...@@ -421,6 +421,16 @@ const struct mdp5_cfg_hw msm8x96_config = { ...@@ -421,6 +421,16 @@ const struct mdp5_cfg_hw msm8x96_config = {
MDP_PIPE_CAP_SW_PIX_EXT | MDP_PIPE_CAP_SW_PIX_EXT |
0, 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 = { .lm = {
.count = 6, .count = 6,
.base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 }, .base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
......
...@@ -400,6 +400,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, ...@@ -400,6 +400,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
struct plane_state pstates[STAGE_MAX + 1]; struct plane_state pstates[STAGE_MAX + 1];
const struct mdp5_cfg_hw *hw_cfg; const struct mdp5_cfg_hw *hw_cfg;
const struct drm_plane_state *pstate; const struct drm_plane_state *pstate;
bool cursor_plane = false;
int cnt = 0, base = 0, i; int cnt = 0, base = 0, i;
DBG("%s: check", crtc->name); DBG("%s: check", crtc->name);
...@@ -409,6 +410,9 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, ...@@ -409,6 +410,9 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
pstates[cnt].state = to_mdp5_plane_state(pstate); pstates[cnt].state = to_mdp5_plane_state(pstate);
cnt++; cnt++;
if (plane->type == DRM_PLANE_TYPE_CURSOR)
cursor_plane = true;
} }
/* assign a stage based on sorted zpos property */ /* assign a stage based on sorted zpos property */
...@@ -420,6 +424,10 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, ...@@ -420,6 +424,10 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
if ((cnt > 0) && !is_fullscreen(state, &pstates[0].state->base)) if ((cnt > 0) && !is_fullscreen(state, &pstates[0].state->base))
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 /* verify that there are not too many planes attached to crtc
* and that we don't have conflicting mixer stages: * and that we don't have conflicting mixer stages:
*/ */
...@@ -431,6 +439,9 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, ...@@ -431,6 +439,9 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
} }
for (i = 0; i < cnt; i++) { for (i = 0; i < cnt; i++) {
if (cursor_plane && (i == (cnt - 1)))
pstates[i].state->stage = hw_cfg->lm.nb_stages;
else
pstates[i].state->stage = STAGE_BASE + i + base; pstates[i].state->stage = STAGE_BASE + i + base;
DBG("%s: assign pipe %s on stage=%d", crtc->name, DBG("%s: assign pipe %s on stage=%d", crtc->name,
pstates[i].plane->name, pstates[i].plane->name,
...@@ -642,6 +653,16 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = { ...@@ -642,6 +653,16 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = {
.cursor_move = mdp5_crtc_cursor_move, .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 = { static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = {
.mode_set_nofb = mdp5_crtc_mode_set_nofb, .mode_set_nofb = mdp5_crtc_mode_set_nofb,
.disable = mdp5_crtc_disable, .disable = mdp5_crtc_disable,
...@@ -775,7 +796,8 @@ void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc) ...@@ -775,7 +796,8 @@ void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc)
/* initialize crtc */ /* initialize crtc */
struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, 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 drm_crtc *crtc = NULL;
struct mdp5_crtc *mdp5_crtc; struct mdp5_crtc *mdp5_crtc;
...@@ -796,8 +818,12 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, ...@@ -796,8 +818,12 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq; mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;
mdp5_crtc->err.irq = mdp5_crtc_err_irq; mdp5_crtc->err.irq = mdp5_crtc_err_irq;
drm_crtc_init_with_planes(dev, crtc, plane, NULL, &mdp5_crtc_funcs, if (cursor_plane)
NULL); 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, drm_flip_work_init(&mdp5_crtc->unref_cursor_work,
"unref cursor", unref_cursor_worker); "unref cursor", unref_cursor_worker);
......
...@@ -326,6 +326,8 @@ static u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe, ...@@ -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_DMA1: return MDP5_CTL_LAYER_REG_DMA1(stage);
case SSPP_VIG3: return MDP5_CTL_LAYER_REG_VIG3(stage); case SSPP_VIG3: return MDP5_CTL_LAYER_REG_VIG3(stage);
case SSPP_RGB3: return MDP5_CTL_LAYER_REG_RGB3(stage); case SSPP_RGB3: return MDP5_CTL_LAYER_REG_RGB3(stage);
case SSPP_CURSOR0:
case SSPP_CURSOR1:
default: return 0; default: return 0;
} }
} }
...@@ -333,7 +335,7 @@ static u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe, ...@@ -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, static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe,
enum mdp_mixer_stage_id stage) enum mdp_mixer_stage_id stage)
{ {
if (stage < STAGE6) if (stage < STAGE6 && (pipe != SSPP_CURSOR0 && pipe != SSPP_CURSOR1))
return 0; return 0;
switch (pipe) { switch (pipe) {
...@@ -347,6 +349,8 @@ static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe 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_DMA1: return MDP5_CTL_LAYER_EXT_REG_DMA1_BIT3;
case SSPP_VIG3: return MDP5_CTL_LAYER_EXT_REG_VIG3_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_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; default: return 0;
} }
} }
...@@ -365,7 +369,7 @@ int mdp5_ctl_blend(struct mdp5_ctl *ctl, enum mdp5_pipe *stage, u32 stage_cnt, ...@@ -365,7 +369,7 @@ int mdp5_ctl_blend(struct mdp5_ctl *ctl, enum mdp5_pipe *stage, u32 stage_cnt,
start_stage = STAGE_BASE; 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_cfg |= mdp_ctl_blend_mask(stage[i], i);
blend_ext_cfg |= mdp_ctl_blend_ext_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) ...@@ -422,6 +426,8 @@ u32 mdp_ctl_flush_mask_pipe(enum mdp5_pipe pipe)
case SSPP_DMA1: return MDP5_CTL_FLUSH_DMA1; case SSPP_DMA1: return MDP5_CTL_FLUSH_DMA1;
case SSPP_VIG3: return MDP5_CTL_FLUSH_VIG3; case SSPP_VIG3: return MDP5_CTL_FLUSH_VIG3;
case SSPP_RGB3: return MDP5_CTL_FLUSH_RGB3; 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; default: return 0;
} }
} }
......
...@@ -441,8 +441,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) ...@@ -441,8 +441,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
bool primary = i < num_crtcs; bool primary = i < num_crtcs;
struct drm_plane *plane; struct drm_plane *plane;
struct drm_crtc *crtc; 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)) { if (IS_ERR(plane)) {
ret = PTR_ERR(plane); ret = PTR_ERR(plane);
dev_err(dev->dev, "failed to construct plane %d (%d)\n", i, ret); 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) ...@@ -453,7 +459,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
if (!primary) if (!primary)
continue; continue;
crtc = mdp5_crtc_init(dev, plane, i); crtc = mdp5_crtc_init(dev, plane, NULL, i);
if (IS_ERR(crtc)) { if (IS_ERR(crtc)) {
ret = PTR_ERR(crtc); ret = PTR_ERR(crtc);
dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret); dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret);
......
...@@ -167,6 +167,7 @@ static inline const char *pipe2name(enum mdp5_pipe pipe) ...@@ -167,6 +167,7 @@ static inline const char *pipe2name(enum mdp5_pipe pipe)
NAME(RGB0), NAME(RGB1), NAME(RGB2), NAME(RGB0), NAME(RGB1), NAME(RGB2),
NAME(DMA0), NAME(DMA1), NAME(DMA0), NAME(DMA1),
NAME(VIG3), NAME(RGB3), NAME(VIG3), NAME(RGB3),
NAME(CURSOR0), NAME(CURSOR1),
#undef NAME #undef NAME
}; };
return names[pipe]; return names[pipe];
...@@ -242,7 +243,8 @@ void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms); ...@@ -242,7 +243,8 @@ void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms);
uint32_t mdp5_plane_get_flush(struct drm_plane *plane); uint32_t mdp5_plane_get_flush(struct drm_plane *plane);
enum mdp5_pipe mdp5_plane_pipe(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); uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
...@@ -251,7 +253,8 @@ void mdp5_crtc_set_pipeline(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); struct mdp5_interface *intf, struct mdp5_ctl *ctl);
void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc); void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc);
struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, 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 drm_encoder *mdp5_encoder_init(struct drm_device *dev,
struct mdp5_interface *intf, struct mdp5_ctl *ctl); struct mdp5_interface *intf, struct mdp5_ctl *ctl);
......
...@@ -53,6 +53,14 @@ struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s, ...@@ -53,6 +53,14 @@ struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s,
if (caps & ~cur->caps) if (caps & ~cur->caps)
continue; 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 /* possible candidate, take the one with the
* fewest unneeded caps bits set: * fewest unneeded caps bits set:
*/ */
......
...@@ -344,6 +344,9 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane, ...@@ -344,6 +344,9 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
if (rotation & DRM_REFLECT_Y) if (rotation & DRM_REFLECT_Y)
caps |= MDP_PIPE_CAP_VFLIP; 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: */ /* (re)allocate hw pipe if we don't have one or caps-mismatch: */
if (!mdp5_state->hwpipe || (caps & ~mdp5_state->hwpipe->caps)) if (!mdp5_state->hwpipe || (caps & ~mdp5_state->hwpipe->caps))
new_hwpipe = true; new_hwpipe = true;
...@@ -870,12 +873,12 @@ uint32_t mdp5_plane_get_flush(struct drm_plane *plane) ...@@ -870,12 +873,12 @@ uint32_t mdp5_plane_get_flush(struct drm_plane *plane)
} }
/* initialize 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 drm_plane *plane = NULL;
struct mdp5_plane *mdp5_plane; struct mdp5_plane *mdp5_plane;
int ret; int ret;
enum drm_plane_type type;
mdp5_plane = kzalloc(sizeof(*mdp5_plane), GFP_KERNEL); mdp5_plane = kzalloc(sizeof(*mdp5_plane), GFP_KERNEL);
if (!mdp5_plane) { if (!mdp5_plane) {
...@@ -888,7 +891,6 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary) ...@@ -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, mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats,
ARRAY_SIZE(mdp5_plane->formats), false); 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, ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
mdp5_plane->formats, mdp5_plane->nformats, mdp5_plane->formats, mdp5_plane->nformats,
type, NULL); type, NULL);
......
...@@ -112,6 +112,7 @@ const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format); ...@@ -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_CSC BIT(3)
#define MDP_PIPE_CAP_DECIMATION BIT(4) #define MDP_PIPE_CAP_DECIMATION BIT(4)
#define MDP_PIPE_CAP_SW_PIX_EXT BIT(5) #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) static inline bool pipe_supports_yuv(uint32_t pipe_caps)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment