forked from Minki/linux
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 <architt@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
This commit is contained in:
parent
829200ac91
commit
5798c8e0d3
@ -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 },
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user