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;