summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h28
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c20
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp.c164
3 files changed, 155 insertions, 57 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index db037ed263b4..a2139f495f52 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -142,6 +142,25 @@
#define BITS_TO_BYTES(x) DIV_ROUND_UP(x, BITS_PER_BYTE)
+#define PP_PROGRAM_PA 0x1
+#define PP_PROGRAM_PCC 0x2
+#define PP_PROGRAM_IGC 0x4
+#define PP_PROGRAM_ARGC 0x8
+#define PP_PROGRAM_HIST 0x10
+#define PP_PROGRAM_DITHER 0x20
+#define PP_PROGRAM_GAMUT 0x40
+#define PP_PROGRAM_PGC 0x100
+#define PP_PROGRAM_PA_DITHER 0x400
+#define PP_PROGRAM_AD 0x800
+
+#define PP_NORMAL_PROGRAM_MASK (PP_PROGRAM_AD | PP_PROGRAM_PCC | \
+ PP_PROGRAM_HIST)
+#define PP_DEFER_PROGRAM_MASK (PP_PROGRAM_IGC | PP_PROGRAM_PGC | \
+ PP_PROGRAM_ARGC | PP_PROGRAM_GAMUT | \
+ PP_PROGRAM_PA | PP_PROGRAM_DITHER | \
+ PP_PROGRAM_PA_DITHER)
+#define PP_PROGRAM_ALL (PP_NORMAL_PROGRAM_MASK | PP_DEFER_PROGRAM_MASK)
+
enum mdss_mdp_perf_state_type {
PERF_SW_COMMIT_STATE = 0,
PERF_HW_MDP_STATE,
@@ -773,6 +792,12 @@ struct mdss_pipe_pp_res {
void *hist_lut_cfg_payload;
};
+struct mdss_mdp_pp_program_info {
+ u32 pp_program_mask;
+ u32 pp_opmode_left;
+ u32 pp_opmode_right;
+};
+
struct mdss_mdp_pipe_smp_map {
DECLARE_BITMAP(reserved, MAX_DRV_SUP_MMB_BLKS);
DECLARE_BITMAP(allocated, MAX_DRV_SUP_MMB_BLKS);
@@ -1803,7 +1828,8 @@ int mdss_mdp_pp_resume(struct msm_fb_data_type *mfd);
void mdss_mdp_pp_dest_scaler_resume(struct mdss_mdp_ctl *ctl);
int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl);
-int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl,
+ struct mdss_mdp_pp_program_info *info);
int mdss_mdp_pipe_pp_setup(struct mdss_mdp_pipe *pipe, u32 *op);
void mdss_mdp_pipe_pp_clear(struct mdss_mdp_pipe *pipe);
int mdss_mdp_pipe_sspp_setup(struct mdss_mdp_pipe *pipe, u32 *op);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index a66ecb7a57b7..553a16366042 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -5752,6 +5752,9 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
bool is_bw_released, split_lm_valid;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
u32 ctl_flush_bits = 0, sctl_flush_bits = 0;
+ /* Must initialize pp_program_info */
+ struct mdss_mdp_pp_program_info pp_program_info = {
+ PP_PROGRAM_ALL, 0, 0};
if (!ctl) {
pr_err("display function not set\n");
@@ -5864,9 +5867,13 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
mdss_mdp_ctl_split_display_enable(split_lm_valid, ctl, sctl);
ATRACE_BEGIN("postproc_programming");
- if (ctl->is_video_mode && ctl->mfd && ctl->mfd->dcm_state != DTM_ENTER)
+ if (ctl->mfd && ctl->mfd->dcm_state != DTM_ENTER) {
/* postprocessing setup, including dspp */
- mdss_mdp_pp_setup_locked(ctl);
+ if (!ctl->is_video_mode)
+ pp_program_info.pp_program_mask =
+ PP_NORMAL_PROGRAM_MASK;
+ mdss_mdp_pp_setup_locked(ctl, &pp_program_info);
+ }
if (sctl) {
if (ctl->split_flush_en) {
@@ -5922,11 +5929,17 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
}
/* Moved pp programming to post ping pong */
+ ATRACE_BEGIN("postproc_programming_deferred");
if (!ctl->is_video_mode && ctl->mfd &&
ctl->mfd->dcm_state != DTM_ENTER) {
/* postprocessing setup, including dspp */
mutex_lock(&ctl->flush_lock);
- mdss_mdp_pp_setup_locked(ctl);
+ pp_program_info.pp_program_mask = PP_DEFER_PROGRAM_MASK;
+ /*
+ * pp_program_info should not be modified beween normal and
+ * deferred stage calls.
+ */
+ mdss_mdp_pp_setup_locked(ctl, &pp_program_info);
if (sctl) {
if (ctl->split_flush_en) {
ctl->flush_bits |= sctl->flush_bits;
@@ -5939,6 +5952,7 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
ctl_flush_bits |= ctl->flush_bits;
mutex_unlock(&ctl->flush_lock);
}
+ ATRACE_END("postproc_programming_deferred");
/*
* if serialize_wait4pp is false then roi_bkup used in wait4pingpong
* will be of previous frame as expected.
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c
index f10d4fb60f52..f128f82fab04 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c
@@ -2322,7 +2322,9 @@ static void pp_dspp_opmode_config(struct mdss_mdp_ctl *ctl, u32 num,
*opmode |= MDSS_MDP_DSPP_OP_ARGC_LUT_EN;
}
-static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
+static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer,
+ u32 pp_program_mask, int *op_mode)
+
{
u32 ad_flags, flags, dspp_num, opmode = 0, ad_bypass;
struct mdp_pgc_lut_data *pgc_config;
@@ -2338,6 +2340,8 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
u32 mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
int side;
+ opmode = *op_mode;
+
if (!mixer || !mixer->ctl || !mixer->ctl->mdata)
return -EINVAL;
ctl = mixer->ctl;
@@ -2358,19 +2362,23 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
}
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
- if ((mdata->pp_block_off.dspp_gamut_off != U32_MAX) &&
- (pp_driver_ops.gamut_clk_gate_en))
- pp_driver_ops.gamut_clk_gate_en(base +
+ if (pp_program_mask & PP_PROGRAM_GAMUT) {
+ if ((mdata->pp_block_off.dspp_gamut_off != U32_MAX) &&
+ (pp_driver_ops.gamut_clk_gate_en))
+ pp_driver_ops.gamut_clk_gate_en(base +
mdata->pp_block_off.dspp_gamut_off);
-
+ }
if (disp_num < MDSS_BLOCK_DISP_NUM) {
pp_sts = &mdss_pp_res->pp_disp_sts[disp_num];
pp_sts->side_sts = side;
- ret = pp_hist_setup(&opmode, MDSS_PP_DSPP_CFG | dspp_num, mixer,
- pp_sts);
- if (ret)
- goto dspp_exit;
+ if (pp_program_mask & PP_PROGRAM_HIST) {
+ ret = pp_hist_setup(&opmode,
+ MDSS_PP_DSPP_CFG | dspp_num, mixer,
+ pp_sts);
+ if (ret)
+ goto dspp_exit;
+ }
flags = mdss_pp_res->pp_disp_flags[disp_num];
} else {
@@ -2391,7 +2399,8 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
if ((!flags) && (!(opmode)) && (!ad_flags))
goto dspp_exit;
- if (flags & PP_FLAGS_DIRTY_PA) {
+ if ((flags & PP_FLAGS_DIRTY_PA) &&
+ (pp_program_mask & PP_PROGRAM_PA)) {
if (!pp_ops[PA].pp_set_config) {
if (mdata->mdp_rev >= MDSS_MDP_HW_REV_103) {
pa_v2_cfg_data =
@@ -2412,7 +2421,8 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
DSPP);
}
}
- if (flags & PP_FLAGS_DIRTY_PCC) {
+ if ((flags & PP_FLAGS_DIRTY_PCC) &&
+ (pp_program_mask & PP_PROGRAM_PCC)) {
if (!pp_ops[PCC].pp_set_config)
pp_pcc_config(flags, base + MDSS_MDP_REG_DSPP_PCC_BASE,
pp_sts,
@@ -2429,7 +2439,8 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
}
}
- if (flags & PP_FLAGS_DIRTY_IGC) {
+ if ((flags & PP_FLAGS_DIRTY_IGC) &&
+ (pp_program_mask & PP_PROGRAM_IGC)) {
if (!pp_ops[IGC].pp_set_config) {
pp_igc_config(flags,
mdata->mdp_base + MDSS_MDP_REG_IGC_DSPP_BASE,
@@ -2449,7 +2460,8 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
DSPP);
}
- if (flags & PP_FLAGS_DIRTY_ENHIST) {
+ if ((flags & PP_FLAGS_DIRTY_ENHIST) &&
+ (pp_program_mask & PP_PROGRAM_HIST)) {
if (!pp_ops[HIST_LUT].pp_set_config) {
pp_enhist_config(flags,
base + MDSS_MDP_REG_DSPP_HIST_LUT_BASE,
@@ -2473,7 +2485,8 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
}
}
- if (flags & PP_FLAGS_DIRTY_DITHER) {
+ if ((flags & PP_FLAGS_DIRTY_DITHER) &&
+ (pp_program_mask & PP_PROGRAM_DITHER)) {
if (!pp_ops[DITHER].pp_set_config && addr) {
pp_dither_config(addr, pp_sts,
&mdss_pp_res->dither_disp_cfg[disp_num]);
@@ -2483,7 +2496,8 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
&mdss_pp_res->dither_disp_cfg[disp_num], DSPP);
}
}
- if (flags & PP_FLAGS_DIRTY_GAMUT) {
+ if ((flags & PP_FLAGS_DIRTY_GAMUT) &&
+ (pp_program_mask & PP_PROGRAM_GAMUT)) {
if (!pp_ops[GAMUT].pp_set_config) {
pp_gamut_config(&mdss_pp_res->gamut_disp_cfg[disp_num],
base, pp_sts);
@@ -2500,7 +2514,8 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
}
}
- if (flags & PP_FLAGS_DIRTY_PGC) {
+ if ((flags & PP_FLAGS_DIRTY_PGC) &&
+ (pp_program_mask & PP_PROGRAM_PGC)) {
pgc_config = &mdss_pp_res->pgc_disp_cfg[disp_num];
if (pp_ops[GC].pp_set_config) {
if (mdata->pp_block_off.dspp_pgc_off == U32_MAX) {
@@ -2526,6 +2541,7 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
}
}
if (flags & PP_FLAGS_DIRTY_PA_DITHER &&
+ (pp_program_mask & PP_PROGRAM_PA_DITHER) &&
pp_ops[PA_DITHER].pp_set_config) {
pp_ops[PA_DITHER].pp_set_config(base, pp_sts,
&mdss_pp_res->pa_dither_cfg[disp_num],
@@ -2536,7 +2552,7 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
pp_dspp_opmode_config(ctl, dspp_num, pp_sts, mdata->mdp_rev,
&opmode);
- if (ad_hw) {
+ if (ad_hw && (pp_program_mask & PP_PROGRAM_AD)) {
mutex_lock(&ad->lock);
ad_flags = ad->reg_sts;
if (ad_flags & PP_AD_STS_DIRTY_DATA)
@@ -2566,6 +2582,9 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
ctl->flush_bits |= BIT(13 + dspp_num);
wmb();
+
+ *op_mode = opmode;
+
dspp_exit:
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
return ret;
@@ -2684,6 +2703,8 @@ void mdss_mdp_pp_dest_scaler_resume(struct mdss_mdp_ctl *ctl)
int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl)
{
int ret = 0;
+ struct mdss_mdp_pp_program_info pp_program_info = {
+ PP_PROGRAM_ALL, 0, 0};
if ((!ctl->mfd) || (!mdss_pp_res))
return -EINVAL;
@@ -2695,14 +2716,15 @@ int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl)
ret = -EPERM;
goto error;
}
- ret = mdss_mdp_pp_setup_locked(ctl);
+ ret = mdss_mdp_pp_setup_locked(ctl, &pp_program_info);
error:
mutex_unlock(&ctl->lock);
return ret;
}
-int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl)
+int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl,
+ struct mdss_mdp_pp_program_info *info)
{
struct mdss_data_type *mdata;
int ret = 0, i;
@@ -2715,6 +2737,16 @@ int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl)
bool valid_ad_panel = true;
if ((!ctl) || (!ctl->mfd) || (!mdss_pp_res) || (!ctl->mdata))
return -EINVAL;
+ if (!info) {
+ pr_err("pp_program_info is NULL");
+ return -EINVAL;
+ }
+ if (!(info->pp_program_mask == PP_NORMAL_PROGRAM_MASK ||
+ info->pp_program_mask == PP_DEFER_PROGRAM_MASK ||
+ info->pp_program_mask == PP_PROGRAM_ALL)) {
+ pr_err("Invalid pp program mask : %x ", info->pp_program_mask);
+ return -EINVAL;
+ }
mdata = ctl->mdata;
/* treat fb_num the same as block logical id*/
@@ -2748,7 +2780,11 @@ int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl)
mutex_lock(&mdss_pp_mutex);
- flags = mdss_pp_res->pp_disp_flags[disp_num];
+ if (disp_num < MDSS_BLOCK_DISP_NUM)
+ flags = mdss_pp_res->pp_disp_flags[disp_num];
+ else
+ flags = 0;
+
if (pp_ops[PA].pp_set_config)
pa_v2_flags = mdss_pp_res->pa_v2_disp_cfg[disp_num].flags;
else
@@ -2759,50 +2795,72 @@ int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl)
* increase the register bus bandwidth to maximum frequency
* in order to speed up the register reprogramming.
*/
- max_bw_needed = (IS_PP_RESUME_COMMIT(flags) &&
- (IS_PP_LUT_DIRTY(flags) ||
- IS_SIX_ZONE_DIRTY(flags, pa_v2_flags)));
- if (mdata->pp_reg_bus_clt && max_bw_needed) {
- ret = mdss_update_reg_bus_vote(mdata->pp_reg_bus_clt,
- VOTE_INDEX_HIGH);
- if (ret)
- pr_err("Updated reg_bus_scale failed, ret = %d", ret);
+ if (info->pp_program_mask & PP_DEFER_PROGRAM_MASK) {
+ max_bw_needed = (IS_PP_RESUME_COMMIT(flags) &&
+ (IS_PP_LUT_DIRTY(flags) ||
+ IS_SIX_ZONE_DIRTY(flags, pa_v2_flags)));
+ if (mdata->pp_reg_bus_clt && max_bw_needed) {
+ ret = mdss_update_reg_bus_vote(mdata->pp_reg_bus_clt,
+ VOTE_INDEX_HIGH);
+ if (ret)
+ pr_err("Updated reg_bus_scale failed, ret = %d",
+ ret);
+ }
}
if (ctl->mixer_left) {
- pp_mixer_setup(ctl->mixer_left);
- pp_dspp_setup(disp_num, ctl->mixer_left);
- pp_ppb_setup(ctl->mixer_left);
+ if (info->pp_program_mask & PP_DEFER_PROGRAM_MASK) {
+ pp_mixer_setup(ctl->mixer_left);
+ pp_dspp_setup(disp_num, ctl->mixer_left,
+ info->pp_program_mask, &info->pp_opmode_left);
+ pp_ppb_setup(ctl->mixer_left);
+ } else {
+ pp_dspp_setup(disp_num, ctl->mixer_left,
+ info->pp_program_mask, &info->pp_opmode_left);
+ }
}
if (ctl->mixer_right) {
- pp_mixer_setup(ctl->mixer_right);
- pp_dspp_setup(disp_num, ctl->mixer_right);
- pp_ppb_setup(ctl->mixer_right);
+ if (info->pp_program_mask & PP_DEFER_PROGRAM_MASK) {
+ pp_mixer_setup(ctl->mixer_right);
+ pp_dspp_setup(disp_num, ctl->mixer_right,
+ info->pp_program_mask, &info->pp_opmode_right);
+ pp_ppb_setup(ctl->mixer_right);
+ } else {
+ pp_dspp_setup(disp_num, ctl->mixer_right,
+ info->pp_program_mask, &info->pp_opmode_right);
+ }
}
- if (valid_mixers && (mixer_cnt <= mdata->nmax_concurrent_ad_hw) &&
- valid_ad_panel) {
- ret = mdss_mdp_ad_ipc_reset(ctl->mfd);
- if (ret < 0)
- pr_warn("ad_setup(disp%d) returns %d\n", disp_num, ret);
+ if (info->pp_program_mask & PP_PROGRAM_AD) {
+ if (valid_mixers &&
+ (mixer_cnt <= mdata->nmax_concurrent_ad_hw) &&
+ valid_ad_panel) {
+ ret = mdss_mdp_ad_ipc_reset(ctl->mfd);
+ if (ret < 0)
+ pr_warn("ad_setup(disp%d) returns %d\n",
+ disp_num, ret);
+ }
}
- /* clear dirty flag */
- if (disp_num < MDSS_BLOCK_DISP_NUM) {
- mdss_pp_res->pp_disp_flags[disp_num] = 0;
- if (disp_num < mdata->nad_cfgs)
- mdata->ad_cfgs[disp_num].reg_sts = 0;
- }
+ if (info->pp_program_mask & PP_DEFER_PROGRAM_MASK) {
+ /* clear dirty flag */
+ if (disp_num < MDSS_BLOCK_DISP_NUM) {
+ mdss_pp_res->pp_disp_flags[disp_num] = 0;
+ if (disp_num < mdata->nad_cfgs)
+ mdata->ad_cfgs[disp_num].reg_sts = 0;
+ }
- if (mdata->pp_reg_bus_clt && max_bw_needed) {
- ret = mdss_update_reg_bus_vote(mdata->pp_reg_bus_clt,
- VOTE_INDEX_DISABLE);
- if (ret)
- pr_err("Updated reg_bus_scale failed, ret = %d", ret);
+ if (mdata->pp_reg_bus_clt && max_bw_needed) {
+ ret = mdss_update_reg_bus_vote(mdata->pp_reg_bus_clt,
+ VOTE_INDEX_DISABLE);
+ if (ret)
+ pr_err("Updated reg_bus_scale failed, ret = %d",
+ ret);
+ }
+ if (IS_PP_RESUME_COMMIT(flags))
+ mdss_pp_res->pp_disp_flags[disp_num] &=
+ ~PP_FLAGS_RESUME_COMMIT;
}
- if (IS_PP_RESUME_COMMIT(flags))
- mdss_pp_res->pp_disp_flags[disp_num] &=
- ~PP_FLAGS_RESUME_COMMIT;
mutex_unlock(&mdss_pp_mutex);
exit:
return ret;