disp: msm: sde: add plane staging management for 4LM topologies
When a 4LM topology is used each plane attached to a CRTC is tagged with a L/R layout value and an offset value depending on where destination X coordinate lands on the display. The layout information is used to determine SSPP to LM pair mapping and local coordinate space. This change also handles source-split and Z-order validation checks for planes staged on different mixer pairs. Change-Id: I1b20223388e65fc36a8b379ad9df23a277fcd1a5 Signed-off-by: Amine Najahi <anajahi@codeaurora.org>
This commit is contained in:
@@ -1124,7 +1124,8 @@ static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc)
|
|||||||
struct sde_crtc_state *crtc_state;
|
struct sde_crtc_state *crtc_state;
|
||||||
const struct sde_rect *lm_roi;
|
const struct sde_rect *lm_roi;
|
||||||
struct sde_hw_mixer *hw_lm;
|
struct sde_hw_mixer *hw_lm;
|
||||||
int lm_idx, lm_horiz_position;
|
bool right_mixer;
|
||||||
|
int lm_idx;
|
||||||
|
|
||||||
if (!crtc)
|
if (!crtc)
|
||||||
return;
|
return;
|
||||||
@@ -1132,26 +1133,27 @@ static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc)
|
|||||||
sde_crtc = to_sde_crtc(crtc);
|
sde_crtc = to_sde_crtc(crtc);
|
||||||
crtc_state = to_sde_crtc_state(crtc->state);
|
crtc_state = to_sde_crtc_state(crtc->state);
|
||||||
|
|
||||||
lm_horiz_position = 0;
|
|
||||||
for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) {
|
for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) {
|
||||||
struct sde_hw_mixer_cfg cfg;
|
struct sde_hw_mixer_cfg cfg;
|
||||||
|
|
||||||
lm_roi = &crtc_state->lm_roi[lm_idx];
|
lm_roi = &crtc_state->lm_roi[lm_idx];
|
||||||
hw_lm = sde_crtc->mixers[lm_idx].hw_lm;
|
hw_lm = sde_crtc->mixers[lm_idx].hw_lm;
|
||||||
|
right_mixer = lm_idx % MAX_MIXERS_PER_LAYOUT;
|
||||||
|
|
||||||
SDE_EVT32(DRMID(crtc_state->base.crtc), lm_idx,
|
SDE_EVT32(DRMID(crtc_state->base.crtc), lm_idx,
|
||||||
lm_roi->x, lm_roi->y, lm_roi->w, lm_roi->h);
|
lm_roi->x, lm_roi->y, lm_roi->w, lm_roi->h,
|
||||||
|
right_mixer);
|
||||||
|
|
||||||
if (sde_kms_rect_is_null(lm_roi))
|
if (sde_kms_rect_is_null(lm_roi))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
hw_lm->cfg.out_width = lm_roi->w;
|
hw_lm->cfg.out_width = lm_roi->w;
|
||||||
hw_lm->cfg.out_height = lm_roi->h;
|
hw_lm->cfg.out_height = lm_roi->h;
|
||||||
hw_lm->cfg.right_mixer = lm_horiz_position;
|
hw_lm->cfg.right_mixer = right_mixer;
|
||||||
|
|
||||||
cfg.out_width = lm_roi->w;
|
cfg.out_width = lm_roi->w;
|
||||||
cfg.out_height = lm_roi->h;
|
cfg.out_height = lm_roi->h;
|
||||||
cfg.right_mixer = lm_horiz_position++;
|
cfg.right_mixer = right_mixer;
|
||||||
cfg.flags = 0;
|
cfg.flags = 0;
|
||||||
hw_lm->ops.setup_mixer_out(hw_lm, &cfg);
|
hw_lm->ops.setup_mixer_out(hw_lm, &cfg);
|
||||||
}
|
}
|
||||||
@@ -1170,12 +1172,18 @@ static int pstate_cmp(const void *a, const void *b)
|
|||||||
struct plane_state *pb = (struct plane_state *)b;
|
struct plane_state *pb = (struct plane_state *)b;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int pa_zpos, pb_zpos;
|
int pa_zpos, pb_zpos;
|
||||||
|
enum sde_layout pa_layout, pb_layout;
|
||||||
|
|
||||||
pa_zpos = sde_plane_get_property(pa->sde_pstate, PLANE_PROP_ZPOS);
|
pa_zpos = sde_plane_get_property(pa->sde_pstate, PLANE_PROP_ZPOS);
|
||||||
pb_zpos = sde_plane_get_property(pb->sde_pstate, PLANE_PROP_ZPOS);
|
pb_zpos = sde_plane_get_property(pb->sde_pstate, PLANE_PROP_ZPOS);
|
||||||
|
|
||||||
|
pa_layout = pa->sde_pstate->layout;
|
||||||
|
pb_layout = pb->sde_pstate->layout;
|
||||||
|
|
||||||
if (pa_zpos != pb_zpos)
|
if (pa_zpos != pb_zpos)
|
||||||
rc = pa_zpos - pb_zpos;
|
rc = pa_zpos - pb_zpos;
|
||||||
|
else if (pa_layout != pb_layout)
|
||||||
|
rc = pa_layout - pb_layout;
|
||||||
else
|
else
|
||||||
rc = pa->drm_pstate->crtc_x - pb->drm_pstate->crtc_x;
|
rc = pa->drm_pstate->crtc_x - pb->drm_pstate->crtc_x;
|
||||||
|
|
||||||
@@ -1192,6 +1200,7 @@ static int _sde_crtc_validate_src_split_order(struct drm_crtc *crtc,
|
|||||||
struct plane_state *pstates, int cnt)
|
struct plane_state *pstates, int cnt)
|
||||||
{
|
{
|
||||||
struct plane_state *prv_pstate, *cur_pstate;
|
struct plane_state *prv_pstate, *cur_pstate;
|
||||||
|
enum sde_layout prev_layout, cur_layout;
|
||||||
struct sde_rect left_rect, right_rect;
|
struct sde_rect left_rect, right_rect;
|
||||||
struct sde_kms *sde_kms;
|
struct sde_kms *sde_kms;
|
||||||
int32_t left_pid, right_pid;
|
int32_t left_pid, right_pid;
|
||||||
@@ -1207,8 +1216,11 @@ static int _sde_crtc_validate_src_split_order(struct drm_crtc *crtc,
|
|||||||
for (i = 1; i < cnt; i++) {
|
for (i = 1; i < cnt; i++) {
|
||||||
prv_pstate = &pstates[i - 1];
|
prv_pstate = &pstates[i - 1];
|
||||||
cur_pstate = &pstates[i];
|
cur_pstate = &pstates[i];
|
||||||
|
prev_layout = prv_pstate->sde_pstate->layout;
|
||||||
|
cur_layout = cur_pstate->sde_pstate->layout;
|
||||||
|
|
||||||
if (prv_pstate->stage != cur_pstate->stage)
|
if (prv_pstate->stage != cur_pstate->stage ||
|
||||||
|
prev_layout != cur_layout)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
stage = cur_pstate->stage;
|
stage = cur_pstate->stage;
|
||||||
@@ -1267,6 +1279,7 @@ static void _sde_crtc_set_src_split_order(struct drm_crtc *crtc,
|
|||||||
struct plane_state *pstates, int cnt)
|
struct plane_state *pstates, int cnt)
|
||||||
{
|
{
|
||||||
struct plane_state *prv_pstate, *cur_pstate, *nxt_pstate;
|
struct plane_state *prv_pstate, *cur_pstate, *nxt_pstate;
|
||||||
|
enum sde_layout prev_layout, cur_layout;
|
||||||
struct sde_kms *sde_kms;
|
struct sde_kms *sde_kms;
|
||||||
struct sde_rect left_rect, right_rect;
|
struct sde_rect left_rect, right_rect;
|
||||||
int32_t left_pid, right_pid;
|
int32_t left_pid, right_pid;
|
||||||
@@ -1286,14 +1299,19 @@ static void _sde_crtc_set_src_split_order(struct drm_crtc *crtc,
|
|||||||
prv_pstate = (i > 0) ? &pstates[i - 1] : NULL;
|
prv_pstate = (i > 0) ? &pstates[i - 1] : NULL;
|
||||||
cur_pstate = &pstates[i];
|
cur_pstate = &pstates[i];
|
||||||
nxt_pstate = ((i + 1) < cnt) ? &pstates[i + 1] : NULL;
|
nxt_pstate = ((i + 1) < cnt) ? &pstates[i + 1] : NULL;
|
||||||
|
prev_layout = prv_pstate->sde_pstate->layout;
|
||||||
|
cur_layout = cur_pstate->sde_pstate->layout;
|
||||||
|
|
||||||
if ((!prv_pstate) || (prv_pstate->stage != cur_pstate->stage)) {
|
if ((!prv_pstate) || (prv_pstate->stage != cur_pstate->stage)
|
||||||
|
|| (prev_layout != cur_layout)) {
|
||||||
/*
|
/*
|
||||||
* reset if prv or nxt pipes are not in the same stage
|
* reset if prv or nxt pipes are not in the same stage
|
||||||
* as the cur pipe
|
* as the cur pipe
|
||||||
*/
|
*/
|
||||||
if ((!nxt_pstate)
|
if ((!nxt_pstate)
|
||||||
|| (nxt_pstate->stage != cur_pstate->stage))
|
|| (nxt_pstate->stage != cur_pstate->stage)
|
||||||
|
|| (nxt_pstate->sde_pstate->layout !=
|
||||||
|
cur_pstate->sde_pstate->layout))
|
||||||
cur_pstate->sde_pstate->pipe_order_flags = 0;
|
cur_pstate->sde_pstate->pipe_order_flags = 0;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -1378,8 +1396,8 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
|
|||||||
struct sde_hw_mixer *lm;
|
struct sde_hw_mixer *lm;
|
||||||
struct sde_hw_stage_cfg *stage_cfg;
|
struct sde_hw_stage_cfg *stage_cfg;
|
||||||
struct sde_rect plane_crtc_roi;
|
struct sde_rect plane_crtc_roi;
|
||||||
uint32_t stage_idx, lm_idx;
|
uint32_t stage_idx, lm_idx, layout_idx;
|
||||||
int zpos_cnt[SDE_STAGE_MAX + 1] = { 0 };
|
int zpos_cnt[MAX_LAYOUTS_PER_CRTC][SDE_STAGE_MAX + 1];
|
||||||
int i, mode, cnt = 0;
|
int i, mode, cnt = 0;
|
||||||
bool bg_alpha_enable = false, is_secure = false;
|
bool bg_alpha_enable = false, is_secure = false;
|
||||||
u32 blend_type;
|
u32 blend_type;
|
||||||
@@ -1392,7 +1410,6 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
|
|||||||
|
|
||||||
ctl = mixer->hw_ctl;
|
ctl = mixer->hw_ctl;
|
||||||
lm = mixer->hw_lm;
|
lm = mixer->hw_lm;
|
||||||
stage_cfg = &sde_crtc->stage_cfg;
|
|
||||||
cstate = to_sde_crtc_state(crtc->state);
|
cstate = to_sde_crtc_state(crtc->state);
|
||||||
pstates = kcalloc(SDE_PSTATES_MAX,
|
pstates = kcalloc(SDE_PSTATES_MAX,
|
||||||
sizeof(struct plane_state), GFP_KERNEL);
|
sizeof(struct plane_state), GFP_KERNEL);
|
||||||
@@ -1400,6 +1417,8 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
memset(fetch_active, 0, sizeof(fetch_active));
|
memset(fetch_active, 0, sizeof(fetch_active));
|
||||||
|
memset(zpos_cnt, 0, sizeof(zpos_cnt));
|
||||||
|
|
||||||
drm_atomic_crtc_for_each_plane(plane, crtc) {
|
drm_atomic_crtc_for_each_plane(plane, crtc) {
|
||||||
state = plane->state;
|
state = plane->state;
|
||||||
if (!state)
|
if (!state)
|
||||||
@@ -1451,19 +1470,31 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
|
|||||||
state->crtc_w, state->crtc_h,
|
state->crtc_w, state->crtc_h,
|
||||||
pstate->rotation, is_secure);
|
pstate->rotation, is_secure);
|
||||||
|
|
||||||
stage_idx = zpos_cnt[pstate->stage]++;
|
/*
|
||||||
|
* none or left layout will program to layer mixer
|
||||||
|
* group 0, right layout will program to layer mixer
|
||||||
|
* group 1.
|
||||||
|
*/
|
||||||
|
if (pstate->layout <= SDE_LAYOUT_LEFT)
|
||||||
|
layout_idx = 0;
|
||||||
|
else
|
||||||
|
layout_idx = 1;
|
||||||
|
|
||||||
|
stage_cfg = &sde_crtc->stage_cfg[layout_idx];
|
||||||
|
stage_idx = zpos_cnt[layout_idx][pstate->stage]++;
|
||||||
stage_cfg->stage[pstate->stage][stage_idx] =
|
stage_cfg->stage[pstate->stage][stage_idx] =
|
||||||
sde_plane_pipe(plane);
|
sde_plane_pipe(plane);
|
||||||
stage_cfg->multirect_index[pstate->stage][stage_idx] =
|
stage_cfg->multirect_index[pstate->stage][stage_idx] =
|
||||||
pstate->multirect_index;
|
pstate->multirect_index;
|
||||||
|
|
||||||
SDE_EVT32(DRMID(crtc), DRMID(plane), stage_idx,
|
SDE_EVT32(DRMID(crtc), DRMID(plane), stage_idx,
|
||||||
sde_plane_pipe(plane) - SSPP_VIG0,
|
sde_plane_pipe(plane) - SSPP_VIG0,
|
||||||
pstate->stage,
|
pstate->stage,
|
||||||
pstate->multirect_index,
|
pstate->multirect_index,
|
||||||
pstate->multirect_mode,
|
pstate->multirect_mode,
|
||||||
format->base.pixel_format,
|
format->base.pixel_format,
|
||||||
fb ? fb->modifier : 0);
|
fb ? fb->modifier : 0,
|
||||||
|
layout_idx);
|
||||||
|
|
||||||
for (lm_idx = 0; lm_idx < sde_crtc->num_mixers;
|
for (lm_idx = 0; lm_idx < sde_crtc->num_mixers;
|
||||||
lm_idx++) {
|
lm_idx++) {
|
||||||
@@ -1631,13 +1662,14 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc,
|
|||||||
_sde_crtc_swap_mixers_for_right_partial_update(crtc);
|
_sde_crtc_swap_mixers_for_right_partial_update(crtc);
|
||||||
|
|
||||||
/* initialize stage cfg */
|
/* initialize stage cfg */
|
||||||
memset(&sde_crtc->stage_cfg, 0, sizeof(struct sde_hw_stage_cfg));
|
memset(&sde_crtc->stage_cfg, 0, sizeof(sde_crtc->stage_cfg));
|
||||||
|
|
||||||
if (add_planes)
|
if (add_planes)
|
||||||
_sde_crtc_blend_setup_mixer(crtc, old_state, sde_crtc, mixer);
|
_sde_crtc_blend_setup_mixer(crtc, old_state, sde_crtc, mixer);
|
||||||
|
|
||||||
for (i = 0; i < sde_crtc->num_mixers; i++) {
|
for (i = 0; i < sde_crtc->num_mixers; i++) {
|
||||||
const struct sde_rect *lm_roi = &sde_crtc_state->lm_roi[i];
|
const struct sde_rect *lm_roi = &sde_crtc_state->lm_roi[i];
|
||||||
|
int lm_layout = i / MAX_MIXERS_PER_LAYOUT;
|
||||||
|
|
||||||
ctl = mixer[i].hw_ctl;
|
ctl = mixer[i].hw_ctl;
|
||||||
lm = mixer[i].hw_lm;
|
lm = mixer[i].hw_lm;
|
||||||
@@ -1663,7 +1695,7 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc,
|
|||||||
cfg.pending_flush_mask);
|
cfg.pending_flush_mask);
|
||||||
|
|
||||||
ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
|
ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
|
||||||
&sde_crtc->stage_cfg);
|
&sde_crtc->stage_cfg[lm_layout]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_sde_crtc_program_lm_output_roi(crtc);
|
_sde_crtc_program_lm_output_roi(crtc);
|
||||||
@@ -4650,6 +4682,7 @@ static int _sde_crtc_check_zpos(struct drm_crtc_state *state,
|
|||||||
u32 zpos_cnt = 0;
|
u32 zpos_cnt = 0;
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
struct sde_kms *kms;
|
struct sde_kms *kms;
|
||||||
|
enum sde_layout layout;
|
||||||
|
|
||||||
crtc = &sde_crtc->base;
|
crtc = &sde_crtc->base;
|
||||||
kms = _sde_crtc_get_kms(crtc);
|
kms = _sde_crtc_get_kms(crtc);
|
||||||
@@ -4678,11 +4711,14 @@ static int _sde_crtc_check_zpos(struct drm_crtc_state *state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
z_pos = -1;
|
z_pos = -1;
|
||||||
|
layout = SDE_LAYOUT_NONE;
|
||||||
for (i = 0; i < cnt; i++) {
|
for (i = 0; i < cnt; i++) {
|
||||||
/* reset counts at every new blend stage */
|
/* reset counts at every new blend stage */
|
||||||
if (pstates[i].stage != z_pos) {
|
if (pstates[i].stage != z_pos ||
|
||||||
|
pstates[i].sde_pstate->layout != layout) {
|
||||||
zpos_cnt = 0;
|
zpos_cnt = 0;
|
||||||
z_pos = pstates[i].stage;
|
z_pos = pstates[i].stage;
|
||||||
|
layout = pstates[i].sde_pstate->layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* verify z_pos setting before using it */
|
/* verify z_pos setting before using it */
|
||||||
@@ -4702,7 +4738,8 @@ static int _sde_crtc_check_zpos(struct drm_crtc_state *state,
|
|||||||
else
|
else
|
||||||
pstates[i].sde_pstate->stage = z_pos;
|
pstates[i].sde_pstate->stage = z_pos;
|
||||||
|
|
||||||
SDE_DEBUG("%s: zpos %d", sde_crtc->name, z_pos);
|
SDE_DEBUG("%s: layout %d, zpos %d", sde_crtc->name, layout,
|
||||||
|
z_pos);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -4758,6 +4795,61 @@ static int _sde_crtc_atomic_check_pstates(struct drm_crtc *crtc,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _sde_crtc_check_plane_layout(struct drm_crtc *crtc,
|
||||||
|
struct drm_crtc_state *crtc_state)
|
||||||
|
{
|
||||||
|
struct sde_kms *kms;
|
||||||
|
struct drm_plane *plane;
|
||||||
|
struct drm_plane_state *plane_state;
|
||||||
|
struct sde_plane_state *pstate;
|
||||||
|
int layout_split;
|
||||||
|
|
||||||
|
kms = _sde_crtc_get_kms(crtc);
|
||||||
|
|
||||||
|
if (!kms || !kms->catalog) {
|
||||||
|
SDE_ERROR("invalid parameters\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sde_rm_topology_is_quad_pipe(&kms->rm, crtc_state))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
|
||||||
|
plane_state = drm_atomic_get_existing_plane_state(
|
||||||
|
crtc_state->state, plane);
|
||||||
|
if (!plane_state)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pstate = to_sde_plane_state(plane_state);
|
||||||
|
layout_split = crtc_state->mode.hdisplay >> 1;
|
||||||
|
|
||||||
|
if (plane_state->crtc_x >= layout_split) {
|
||||||
|
plane_state->crtc_x -= layout_split;
|
||||||
|
pstate->layout_offset = layout_split;
|
||||||
|
pstate->layout = SDE_LAYOUT_RIGHT;
|
||||||
|
} else {
|
||||||
|
pstate->layout_offset = -1;
|
||||||
|
pstate->layout = SDE_LAYOUT_LEFT;
|
||||||
|
}
|
||||||
|
SDE_DEBUG("plane%d updated: crtc_x=%d layout=%d\n",
|
||||||
|
DRMID(plane), plane_state->crtc_x,
|
||||||
|
pstate->layout);
|
||||||
|
|
||||||
|
/* check layout boundary */
|
||||||
|
if (CHECK_LAYER_BOUNDS(plane_state->crtc_x,
|
||||||
|
plane_state->crtc_w, layout_split)) {
|
||||||
|
SDE_ERROR("invalid horizontal destination\n");
|
||||||
|
SDE_ERROR("x:%d w:%d hdisp:%d layout:%d\n",
|
||||||
|
plane_state->crtc_x,
|
||||||
|
plane_state->crtc_w,
|
||||||
|
layout_split, pstate->layout);
|
||||||
|
return -E2BIG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int sde_crtc_atomic_check(struct drm_crtc *crtc,
|
static int sde_crtc_atomic_check(struct drm_crtc *crtc,
|
||||||
struct drm_crtc_state *state)
|
struct drm_crtc_state *state)
|
||||||
{
|
{
|
||||||
@@ -4812,6 +4904,13 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = _sde_crtc_check_plane_layout(crtc, state);
|
||||||
|
if (rc) {
|
||||||
|
SDE_ERROR("crtc%d failed plane layout check %d\n",
|
||||||
|
crtc->base.id, rc);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
/* identify connectors attached to this crtc */
|
/* identify connectors attached to this crtc */
|
||||||
cstate->num_connectors = 0;
|
cstate->num_connectors = 0;
|
||||||
|
|
||||||
|
@@ -295,8 +295,7 @@ struct sde_crtc {
|
|||||||
|
|
||||||
/* output fence support */
|
/* output fence support */
|
||||||
struct sde_fence_context *output_fence;
|
struct sde_fence_context *output_fence;
|
||||||
|
struct sde_hw_stage_cfg stage_cfg[MAX_LAYOUTS_PER_CRTC];
|
||||||
struct sde_hw_stage_cfg stage_cfg;
|
|
||||||
struct dentry *debugfs_root;
|
struct dentry *debugfs_root;
|
||||||
void *priv_handle;
|
void *priv_handle;
|
||||||
|
|
||||||
|
@@ -73,6 +73,9 @@
|
|||||||
#define MAX_IMG_HEIGHT 0x3fff
|
#define MAX_IMG_HEIGHT 0x3fff
|
||||||
|
|
||||||
#define CRTC_DUAL_MIXERS 2
|
#define CRTC_DUAL_MIXERS 2
|
||||||
|
#define MAX_MIXERS_PER_CRTC 4
|
||||||
|
#define MAX_MIXERS_PER_LAYOUT 2
|
||||||
|
#define MAX_LAYOUTS_PER_CRTC (MAX_MIXERS_PER_CRTC / MAX_MIXERS_PER_LAYOUT)
|
||||||
|
|
||||||
#define SDE_COLOR_PROCESS_VER(MAJOR, MINOR) \
|
#define SDE_COLOR_PROCESS_VER(MAJOR, MINOR) \
|
||||||
((((MAJOR) & 0xFFFF) << 16) | (((MINOR) & 0xFFFF)))
|
((((MAJOR) & 0xFFFF) << 16) | (((MINOR) & 0xFFFF)))
|
||||||
|
@@ -4252,6 +4252,14 @@ sde_plane_duplicate_state(struct drm_plane *plane)
|
|||||||
|
|
||||||
__drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
|
__drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
|
||||||
|
|
||||||
|
/* reset layout offset */
|
||||||
|
if (pstate->layout_offset) {
|
||||||
|
if (pstate->layout_offset > 0)
|
||||||
|
pstate->base.crtc_x += pstate->layout_offset;
|
||||||
|
pstate->layout = SDE_LAYOUT_NONE;
|
||||||
|
pstate->layout_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return &pstate->base;
|
return &pstate->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,6 +43,21 @@
|
|||||||
SDE_PLANE_DIRTY_DMA_GC)
|
SDE_PLANE_DIRTY_DMA_GC)
|
||||||
#define SDE_PLANE_DIRTY_ALL (0xFFFFFFFF & ~(SDE_PLANE_DIRTY_CP))
|
#define SDE_PLANE_DIRTY_ALL (0xFFFFFFFF & ~(SDE_PLANE_DIRTY_CP))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum sde_layout
|
||||||
|
* Describes SSPP to LM staging layout when using more than 1 pair of LMs
|
||||||
|
* @SDE_LAYOUT_NONE : SSPPs to LMs staging layout not enabled
|
||||||
|
* @SDE_LAYOUT_LEFT : SSPPs will be staged on left two LMs
|
||||||
|
* @SDE_LAYOUT_RIGHT : SSPPs will be staged on right two LMs
|
||||||
|
* @SDE_LAYOUT_MAX :
|
||||||
|
*/
|
||||||
|
enum sde_layout {
|
||||||
|
SDE_LAYOUT_NONE = 0,
|
||||||
|
SDE_LAYOUT_LEFT,
|
||||||
|
SDE_LAYOUT_RIGHT,
|
||||||
|
SDE_LAYOUT_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum sde_plane_sclcheck_state - User scaler data status
|
* enum sde_plane_sclcheck_state - User scaler data status
|
||||||
*
|
*
|
||||||
@@ -79,6 +94,8 @@ enum sde_plane_sclcheck_state {
|
|||||||
* @defer_prepare_fb: indicate if prepare_fb call was deferred
|
* @defer_prepare_fb: indicate if prepare_fb call was deferred
|
||||||
* @pipe_order_flags: contains pipe order flags:
|
* @pipe_order_flags: contains pipe order flags:
|
||||||
* SDE_SSPP_RIGHT - right pipe in source split pair
|
* SDE_SSPP_RIGHT - right pipe in source split pair
|
||||||
|
* @layout_offset: horizontal layout offset for global coordinate
|
||||||
|
* @layout: layout for topology requiring more than 1 lm pair.
|
||||||
* @scaler3_cfg: configuration data for scaler3
|
* @scaler3_cfg: configuration data for scaler3
|
||||||
* @pixel_ext: configuration data for pixel extensions
|
* @pixel_ext: configuration data for pixel extensions
|
||||||
* @scaler_check_state: indicates status of user provided pixel extension data
|
* @scaler_check_state: indicates status of user provided pixel extension data
|
||||||
@@ -103,6 +120,8 @@ struct sde_plane_state {
|
|||||||
bool pending;
|
bool pending;
|
||||||
bool defer_prepare_fb;
|
bool defer_prepare_fb;
|
||||||
uint32_t pipe_order_flags;
|
uint32_t pipe_order_flags;
|
||||||
|
int layout_offset;
|
||||||
|
enum sde_layout layout;
|
||||||
|
|
||||||
/* scaler configuration */
|
/* scaler configuration */
|
||||||
struct sde_hw_scaler3_cfg scaler3_cfg;
|
struct sde_hw_scaler3_cfg scaler3_cfg;
|
||||||
|
@@ -2093,6 +2093,32 @@ int sde_rm_update_topology(struct sde_rm *rm,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sde_rm_topology_is_quad_pipe(struct sde_rm *rm,
|
||||||
|
struct drm_crtc_state *state)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct sde_crtc_state *cstate;
|
||||||
|
uint64_t topology = SDE_RM_TOPOLOGY_NONE;
|
||||||
|
|
||||||
|
if ((!rm) || (!state)) {
|
||||||
|
pr_err("invalid arguments: rm:%d state:%d\n",
|
||||||
|
rm == NULL, state == NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cstate = to_sde_crtc_state(state);
|
||||||
|
|
||||||
|
for (i = 0; i < cstate->num_connectors; i++) {
|
||||||
|
struct drm_connector *conn = cstate->connectors[i];
|
||||||
|
|
||||||
|
topology = sde_connector_get_topology_name(conn);
|
||||||
|
if (TOPOLOGY_QUADPIPE_MERGE_MODE(topology))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _sde_rm_release_rsvp - release resources and release a reservation
|
* _sde_rm_release_rsvp - release resources and release a reservation
|
||||||
* @rm: KMS handle
|
* @rm: KMS handle
|
||||||
|
@@ -14,6 +14,12 @@
|
|||||||
#define SINGLE_CTL 1
|
#define SINGLE_CTL 1
|
||||||
#define DUAL_CTL 2
|
#define DUAL_CTL 2
|
||||||
|
|
||||||
|
#define TOPOLOGY_QUADPIPE_MERGE_MODE(x) \
|
||||||
|
(x == SDE_RM_TOPOLOGY_QUADPIPE_3DMERGE ||\
|
||||||
|
x == SDE_RM_TOPOLOGY_QUADPIPE_3DMERGE_DSC ||\
|
||||||
|
x == SDE_RM_TOPOLOGY_QUADPIPE_DSCMERGE ||\
|
||||||
|
x == SDE_RM_TOPOLOGY_QUADPIPE_DSC4HSMERGE)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum sde_rm_topology_name - HW resource use case in use by connector
|
* enum sde_rm_topology_name - HW resource use case in use by connector
|
||||||
* @SDE_RM_TOPOLOGY_NONE: No topology in use currently
|
* @SDE_RM_TOPOLOGY_NONE: No topology in use currently
|
||||||
@@ -337,6 +343,16 @@ static inline int sde_rm_topology_get_num_lm(struct sde_rm *rm,
|
|||||||
return rm->topology_tbl[topology].num_lm;
|
return rm->topology_tbl[topology].num_lm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sde_rm_topology_is_quad_pipe - check if the topology used
|
||||||
|
* is a quad-pipe mode one
|
||||||
|
* @rm: SDE Resource Manager handle
|
||||||
|
* @state: drm state of the crtc
|
||||||
|
* @return: true if attached connector is in quad-pipe mode
|
||||||
|
*/
|
||||||
|
bool sde_rm_topology_is_quad_pipe(struct sde_rm *rm,
|
||||||
|
struct drm_crtc_state *state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_rm_ext_blk_create_reserve - Create external HW blocks
|
* sde_rm_ext_blk_create_reserve - Create external HW blocks
|
||||||
* in resource manager and reserve for specific encoder.
|
* in resource manager and reserve for specific encoder.
|
||||||
|
Reference in New Issue
Block a user