disp: msm: sde: decouple FETCH_PIPE_ACTIVE logic from setup_blendstages
Setup blendstages is done per LM but FETCH_PIPE_ACTIVE is per CTL. Overloading mixer blendstage setup with fetch pipe logic can lead to HW programming errors. Refactor the logic for setting FETCH_PIPE_ACTIVE by adding a new op that allows caller to provide a bitmask of all pipes required to be active on this CTL. This new logic includes support for: - 4LM use-cases, staging pipes for all LMs within a CRTC - Demura fetch-pipe without need for tracking via active_cfg (removed) Also, lower the cyclomatic complexity in setup_blendstages by moving the logic for obtaining the mixer config settings in to a helper function. Change-Id: I2907b359ffad5734be5b06f44919b5ddb1ef3f7c Signed-off-by: Steve Cohen <cohens@codeaurora.org>
Šī revīzija ir iekļauta:

revīziju iesūtīja
Gerrit - the friendly Code Review server

vecāks
947fa56080
revīzija
b9e3d4aebb
@@ -266,6 +266,13 @@ static const struct ctl_hw_flush_cfg
|
||||
intf_flush_tbl } /* SDE_HW_FLUSH_INTF */
|
||||
};
|
||||
|
||||
struct sde_ctl_mixer_cfg {
|
||||
u32 cfg;
|
||||
u32 ext;
|
||||
u32 ext2;
|
||||
u32 ext3;
|
||||
};
|
||||
|
||||
static struct sde_ctl_cfg *_ctl_offset(enum sde_ctl ctl,
|
||||
struct sde_mdss_cfg *m,
|
||||
void __iomem *addr,
|
||||
@@ -625,6 +632,23 @@ static inline int sde_hw_ctl_update_bitmask_dspp_subblk(struct sde_hw_ctl *ctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sde_hw_ctl_set_fetch_pipe_active(struct sde_hw_ctl *ctx,
|
||||
unsigned long *fetch_active)
|
||||
{
|
||||
int i;
|
||||
u32 val = 0;
|
||||
|
||||
if (fetch_active) {
|
||||
for (i = 0; i < SSPP_MAX; i++) {
|
||||
if (test_bit(i, fetch_active) &&
|
||||
fetch_tbl[i] != CTL_INVALID_BIT)
|
||||
val |= BIT(fetch_tbl[i]);
|
||||
}
|
||||
}
|
||||
|
||||
SDE_REG_WRITE(&ctx->hw, CTL_FETCH_PIPE_ACTIVE, val);
|
||||
}
|
||||
|
||||
static inline void _sde_hw_ctl_write_dspp_flushes(struct sde_hw_ctl *ctx) {
|
||||
int i;
|
||||
bool has_dspp_flushes = ctx->caps->features &
|
||||
@@ -815,35 +839,18 @@ static void sde_hw_ctl_clear_all_blendstages(struct sde_hw_ctl *ctx)
|
||||
SDE_REG_WRITE(c, CTL_FETCH_PIPE_ACTIVE, 0);
|
||||
}
|
||||
|
||||
static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
|
||||
enum sde_lm lm, struct sde_hw_stage_cfg *stage_cfg,
|
||||
struct sde_hw_stage_cfg *active_cfg)
|
||||
static void _sde_hw_ctl_get_mixer_cfg(struct sde_hw_ctl *ctx,
|
||||
struct sde_hw_stage_cfg *stage_cfg, int stages,
|
||||
struct sde_ctl_mixer_cfg *cfg)
|
||||
{
|
||||
struct sde_hw_blk_reg_map *c;
|
||||
u32 mixercfg = 0, mixercfg_ext = 0, mix, ext;
|
||||
u32 mixercfg_ext2 = 0, mixercfg_ext3 = 0;
|
||||
u32 active_fetch_pipes = 0;
|
||||
int i, j;
|
||||
u8 stages;
|
||||
int pipes_per_stage;
|
||||
int i, j, pipes_per_stage;
|
||||
u32 mix, ext;
|
||||
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
c = &ctx->hw;
|
||||
stages = _mixer_stages(ctx->mixer_hw_caps, ctx->mixer_count, lm);
|
||||
if ((int)stages < 0)
|
||||
return;
|
||||
|
||||
if (test_bit(SDE_MIXER_SOURCESPLIT,
|
||||
&ctx->mixer_hw_caps->features))
|
||||
if (test_bit(SDE_MIXER_SOURCESPLIT, &ctx->mixer_hw_caps->features))
|
||||
pipes_per_stage = PIPES_PER_STAGE;
|
||||
else
|
||||
pipes_per_stage = 1;
|
||||
|
||||
if (!stage_cfg)
|
||||
goto exit;
|
||||
|
||||
for (i = 0; i <= stages; i++) {
|
||||
/* overflow to ext register if 'i + 1 > 7' */
|
||||
mix = (i + 1) & 0x7;
|
||||
@@ -853,125 +860,127 @@ static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
|
||||
enum sde_sspp pipe = stage_cfg->stage[i][j];
|
||||
enum sde_sspp_multirect_index rect_index =
|
||||
stage_cfg->multirect_index[i][j];
|
||||
|
||||
switch (pipe) {
|
||||
case SSPP_VIG0:
|
||||
if (rect_index == SDE_SSPP_RECT_1) {
|
||||
mixercfg_ext3 |= ((i + 1) & 0xF) << 0;
|
||||
cfg->ext3 |= ((i + 1) & 0xF) << 0;
|
||||
} else {
|
||||
mixercfg |= mix << 0;
|
||||
mixercfg_ext |= ext << 0;
|
||||
cfg->cfg |= mix << 0;
|
||||
cfg->ext |= ext << 0;
|
||||
}
|
||||
break;
|
||||
case SSPP_VIG1:
|
||||
if (rect_index == SDE_SSPP_RECT_1) {
|
||||
mixercfg_ext3 |= ((i + 1) & 0xF) << 4;
|
||||
cfg->ext3 |= ((i + 1) & 0xF) << 4;
|
||||
} else {
|
||||
mixercfg |= mix << 3;
|
||||
mixercfg_ext |= ext << 2;
|
||||
cfg->cfg |= mix << 3;
|
||||
cfg->ext |= ext << 2;
|
||||
}
|
||||
break;
|
||||
case SSPP_VIG2:
|
||||
if (rect_index == SDE_SSPP_RECT_1) {
|
||||
mixercfg_ext3 |= ((i + 1) & 0xF) << 8;
|
||||
cfg->ext3 |= ((i + 1) & 0xF) << 8;
|
||||
} else {
|
||||
mixercfg |= mix << 6;
|
||||
mixercfg_ext |= ext << 4;
|
||||
cfg->cfg |= mix << 6;
|
||||
cfg->ext |= ext << 4;
|
||||
}
|
||||
break;
|
||||
case SSPP_VIG3:
|
||||
if (rect_index == SDE_SSPP_RECT_1) {
|
||||
mixercfg_ext3 |= ((i + 1) & 0xF) << 12;
|
||||
cfg->ext3 |= ((i + 1) & 0xF) << 12;
|
||||
} else {
|
||||
mixercfg |= mix << 26;
|
||||
mixercfg_ext |= ext << 6;
|
||||
cfg->cfg |= mix << 26;
|
||||
cfg->ext |= ext << 6;
|
||||
}
|
||||
break;
|
||||
case SSPP_RGB0:
|
||||
mixercfg |= mix << 9;
|
||||
mixercfg_ext |= ext << 8;
|
||||
cfg->cfg |= mix << 9;
|
||||
cfg->ext |= ext << 8;
|
||||
break;
|
||||
case SSPP_RGB1:
|
||||
mixercfg |= mix << 12;
|
||||
mixercfg_ext |= ext << 10;
|
||||
cfg->cfg |= mix << 12;
|
||||
cfg->ext |= ext << 10;
|
||||
break;
|
||||
case SSPP_RGB2:
|
||||
mixercfg |= mix << 15;
|
||||
mixercfg_ext |= ext << 12;
|
||||
cfg->cfg |= mix << 15;
|
||||
cfg->ext |= ext << 12;
|
||||
break;
|
||||
case SSPP_RGB3:
|
||||
mixercfg |= mix << 29;
|
||||
mixercfg_ext |= ext << 14;
|
||||
cfg->cfg |= mix << 29;
|
||||
cfg->ext |= ext << 14;
|
||||
break;
|
||||
case SSPP_DMA0:
|
||||
if (rect_index == SDE_SSPP_RECT_1) {
|
||||
mixercfg_ext2 |= ((i + 1) & 0xF) << 8;
|
||||
cfg->ext2 |= ((i + 1) & 0xF) << 8;
|
||||
} else {
|
||||
mixercfg |= mix << 18;
|
||||
mixercfg_ext |= ext << 16;
|
||||
cfg->cfg |= mix << 18;
|
||||
cfg->ext |= ext << 16;
|
||||
}
|
||||
break;
|
||||
case SSPP_DMA1:
|
||||
if (rect_index == SDE_SSPP_RECT_1) {
|
||||
mixercfg_ext2 |= ((i + 1) & 0xF) << 12;
|
||||
cfg->ext2 |= ((i + 1) & 0xF) << 12;
|
||||
} else {
|
||||
mixercfg |= mix << 21;
|
||||
mixercfg_ext |= ext << 18;
|
||||
cfg->cfg |= mix << 21;
|
||||
cfg->ext |= ext << 18;
|
||||
}
|
||||
break;
|
||||
case SSPP_DMA2:
|
||||
if (rect_index == SDE_SSPP_RECT_1) {
|
||||
mixercfg_ext2 |= ((i + 1) & 0xF) << 16;
|
||||
cfg->ext2 |= ((i + 1) & 0xF) << 16;
|
||||
} else {
|
||||
mix |= (i + 1) & 0xF;
|
||||
mixercfg_ext2 |= mix << 0;
|
||||
cfg->ext2 |= mix << 0;
|
||||
}
|
||||
break;
|
||||
case SSPP_DMA3:
|
||||
if (rect_index == SDE_SSPP_RECT_1) {
|
||||
mixercfg_ext2 |= ((i + 1) & 0xF) << 20;
|
||||
cfg->ext2 |= ((i + 1) & 0xF) << 20;
|
||||
} else {
|
||||
mix |= (i + 1) & 0xF;
|
||||
mixercfg_ext2 |= mix << 4;
|
||||
cfg->ext2 |= mix << 4;
|
||||
}
|
||||
break;
|
||||
case SSPP_CURSOR0:
|
||||
mixercfg_ext |= ((i + 1) & 0xF) << 20;
|
||||
cfg->ext |= ((i + 1) & 0xF) << 20;
|
||||
break;
|
||||
case SSPP_CURSOR1:
|
||||
mixercfg_ext |= ((i + 1) & 0xF) << 26;
|
||||
cfg->ext |= ((i + 1) & 0xF) << 26;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (fetch_tbl[pipe] != CTL_INVALID_BIT)
|
||||
active_fetch_pipes |= BIT(fetch_tbl[pipe]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i <= stages && active_cfg; i++) {
|
||||
enum sde_sspp pipe = active_cfg->stage[i][0];
|
||||
static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
|
||||
enum sde_lm lm, struct sde_hw_stage_cfg *stage_cfg)
|
||||
{
|
||||
struct sde_hw_blk_reg_map *c;
|
||||
struct sde_ctl_mixer_cfg cfg = { 0 };
|
||||
int stages;
|
||||
|
||||
if (pipe == SSPP_NONE)
|
||||
break;
|
||||
if (fetch_tbl[pipe] != CTL_INVALID_BIT) {
|
||||
active_fetch_pipes |= BIT(fetch_tbl[pipe]);
|
||||
SDE_DEBUG("fetch pipe %d active pipes %x\n",
|
||||
pipe, active_fetch_pipes);
|
||||
}
|
||||
}
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
exit:
|
||||
if ((!mixercfg && !mixercfg_ext && !mixercfg_ext2 && !mixercfg_ext3) ||
|
||||
stages = _mixer_stages(ctx->mixer_hw_caps, ctx->mixer_count, lm);
|
||||
if (stages < 0)
|
||||
return;
|
||||
|
||||
c = &ctx->hw;
|
||||
|
||||
if (stage_cfg)
|
||||
_sde_hw_ctl_get_mixer_cfg(ctx, stage_cfg, stages, &cfg);
|
||||
|
||||
if ((!cfg.cfg && !cfg.ext && !cfg.ext2 && !cfg.ext3) ||
|
||||
(stage_cfg && !stage_cfg->stage[0][0]))
|
||||
mixercfg |= CTL_MIXER_BORDER_OUT;
|
||||
cfg.cfg |= CTL_MIXER_BORDER_OUT;
|
||||
|
||||
SDE_REG_WRITE(c, CTL_LAYER(lm), mixercfg);
|
||||
SDE_REG_WRITE(c, CTL_LAYER_EXT(lm), mixercfg_ext);
|
||||
SDE_REG_WRITE(c, CTL_LAYER_EXT2(lm), mixercfg_ext2);
|
||||
SDE_REG_WRITE(c, CTL_LAYER_EXT3(lm), mixercfg_ext3);
|
||||
SDE_REG_WRITE(c, CTL_FETCH_PIPE_ACTIVE, active_fetch_pipes);
|
||||
SDE_REG_WRITE(c, CTL_LAYER(lm), cfg.cfg);
|
||||
SDE_REG_WRITE(c, CTL_LAYER_EXT(lm), cfg.ext);
|
||||
SDE_REG_WRITE(c, CTL_LAYER_EXT2(lm), cfg.ext2);
|
||||
SDE_REG_WRITE(c, CTL_LAYER_EXT3(lm), cfg.ext3);
|
||||
}
|
||||
|
||||
static u32 sde_hw_ctl_get_staged_sspp(struct sde_hw_ctl *ctx, enum sde_lm lm,
|
||||
@@ -1352,6 +1361,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops,
|
||||
ops->reset_post_disable = sde_hw_ctl_reset_post_disable;
|
||||
ops->get_scheduler_status = sde_hw_ctl_get_scheduler_status;
|
||||
ops->read_active_status = sde_hw_ctl_read_active_status;
|
||||
ops->set_active_pipes = sde_hw_ctl_set_fetch_pipe_active;
|
||||
} else {
|
||||
ops->update_pending_flush = sde_hw_ctl_update_pending_flush;
|
||||
ops->trigger_flush = sde_hw_ctl_trigger_flush;
|
||||
|
Atsaukties uz šo jaunā problēmā
Block a user