diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index 967118d1e408..4897d2ced552 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -1106,7 +1106,7 @@ int mdss_mdp_pp_init(struct device *dev); void mdss_mdp_pp_term(struct device *dev); int mdss_mdp_pp_overlay_init(struct msm_fb_data_type *mfd); -int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 mixer_num); +int mdss_mdp_pp_resume(struct msm_fb_data_type *mfd); int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl); int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl); @@ -1121,6 +1121,8 @@ int mdss_mdp_smp_setup(struct mdss_data_type *mdata, u32 cnt, u32 size); void mdss_hw_init(struct mdss_data_type *mdata); +int mdss_mdp_mfd_valid_dspp(struct msm_fb_data_type *mfd); + int mdss_mdp_pa_config(struct mdp_pa_cfg_data *config, u32 *copyback); int mdss_mdp_pa_v2_config(struct mdp_pa_v2_cfg_data *config, u32 *copyback); int mdss_mdp_pcc_config(struct mdp_pcc_cfg_data *cfg_ptr, u32 *copyback); @@ -1131,7 +1133,7 @@ int mdss_mdp_hist_lut_config(struct mdp_hist_lut_data *config, u32 *copyback); int mdss_mdp_pp_default_overlay_config(struct msm_fb_data_type *mfd, struct mdss_panel_data *pdata); int mdss_mdp_dither_config(struct mdp_dither_cfg_data *config, u32 *copyback, - int copy_from_kernel); + int copy_from_kernel); int mdss_mdp_gamut_config(struct mdp_gamut_cfg_data *config, u32 *copyback); int mdss_mdp_hist_intr_req(struct mdss_intr *intr, u32 bits, bool en); diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 708a26492009..863bbbd8e563 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -3023,9 +3023,7 @@ static void mdss_mdp_ctl_restore_sub(struct mdss_mdp_ctl *ctl) MDSS_MDP_REG_DISP_INTF_SEL); if (ctl->mixer_left) { - mdss_mdp_pp_resume(ctl, ctl->mixer_left->num); - if (ctl->mixer_right) - mdss_mdp_pp_resume(ctl, ctl->mixer_right->num); + mdss_mdp_pp_resume(ctl->mfd); if (ctl->panel_data->panel_info.compression_mode == COMPRESSION_DSC) { @@ -3113,12 +3111,6 @@ static int mdss_mdp_ctl_start_sub(struct mdss_mdp_ctl *ctl, bool handoff) mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(i), 0); } - mixer = ctl->mixer_left; - if (mixer) { - mdss_mdp_pp_resume(ctl, mixer->num); - mixer->params_changed++; - } - temp = readl_relaxed(ctl->mdata->mdp_base + MDSS_MDP_REG_DISP_INTF_SEL); temp |= (ctl->intf_type << ((ctl->intf_num - MDSS_MDP_INTF0) * 8)); @@ -3128,7 +3120,9 @@ static int mdss_mdp_ctl_start_sub(struct mdss_mdp_ctl *ctl, bool handoff) writel_relaxed(temp, ctl->mdata->mdp_base + MDSS_MDP_REG_DISP_INTF_SEL); + mixer = ctl->mixer_left; if (mixer) { + mixer->params_changed++; outsize = (mixer->height << 16) | mixer->width; mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OUT_SIZE, outsize); @@ -3203,7 +3197,6 @@ int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff) struct mdss_mdp_mixer *mixer = ctl->mixer_right; u32 out; - mdss_mdp_pp_resume(ctl, mixer->num); mixer->params_changed++; out = (mixer->height << 16) | mixer->width; mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OUT_SIZE, out); diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 2e03603e6428..04c04b3b6427 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -1367,6 +1367,14 @@ int mdss_mdp_overlay_start(struct msm_fb_data_type *mfd) } } + /* Restore any previously configured PP features by resetting the dirty + * bits for enabled features. The dirty bits will be consumed during the + * first display commit when the PP hardware blocks are updated + */ + rc = mdss_mdp_pp_resume(mfd); + if (rc && (rc != -EPERM) && (rc != -ENODEV)) + pr_err("PP resume err %d\n", rc); + /* * Increment the overlay active count prior to calling ctl_start. * This is needed to ensure that if idle power collapse kicks in @@ -3532,6 +3540,11 @@ static int mdss_mdp_pp_ioctl(struct msm_fb_data_type *mfd, mdp_pp.op != mdp_op_calib_dcm_state)) return -EPERM; + if (!mdss_mdp_mfd_valid_dspp(mfd)) { + pr_err("invalid display num %d for PP config\n", mfd->index); + return -EPERM; + } + switch (mdp_pp.op) { case mdp_op_pa_cfg: ret = mdss_mdp_pa_config(&mdp_pp.data.pa_cfg_data, @@ -4247,6 +4260,7 @@ static struct mdss_mdp_ctl *__mdss_mdp_overlay_ctl_init( int rc = 0; struct mdss_mdp_ctl *ctl; struct mdss_panel_data *pdata; + struct mdss_overlay_private *mdp5_data; if (!mfd) return ERR_PTR(-EINVAL); @@ -4258,6 +4272,12 @@ static struct mdss_mdp_ctl *__mdss_mdp_overlay_ctl_init( goto error; } + mdp5_data = mfd_to_mdp5_data(mfd); + if (!mdp5_data) { + rc = -EINVAL; + goto error; + } + ctl = mdss_mdp_ctl_init(pdata, mfd); if (IS_ERR_OR_NULL(ctl)) { pr_err("Unable to initialize ctl for fb%d\n", @@ -4285,10 +4305,12 @@ static struct mdss_mdp_ctl *__mdss_mdp_overlay_ctl_init( } } + mdp5_data->ctl = ctl; + rc = mdss_mdp_pp_default_overlay_config(mfd, pdata); if (rc) { - pr_err("Unable to set default postprocessing configs for fb%d\n", - mfd->index); + pr_err("Unable to set default postprocessing configs for fb%d ret %d\n", + mfd->index, rc); rc = 0; } @@ -4319,7 +4341,6 @@ static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd) ctl = __mdss_mdp_overlay_ctl_init(mfd); if (IS_ERR_OR_NULL(ctl)) return PTR_ERR(ctl); - mdp5_data->ctl = ctl; } else { ctl = mdp5_data->ctl; } @@ -4334,7 +4355,7 @@ static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd) if (mdss_fb_is_power_on(mfd)) { pr_debug("panel was never turned off\n"); - rc = mdss_mdp_ctl_start(mdp5_data->ctl, false); + rc = mdss_mdp_ctl_start(ctl, false); goto panel_on; } @@ -4348,7 +4369,7 @@ static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd) rc = mdss_mdp_overlay_kickoff(mfd, NULL); } } else { - rc = mdss_mdp_ctl_setup(mdp5_data->ctl); + rc = mdss_mdp_ctl_setup(ctl); if (rc) goto end; } @@ -4563,7 +4584,6 @@ static int mdss_mdp_overlay_handoff(struct msm_fb_data_type *mfd) rc = PTR_ERR(ctl); goto error; } - mdp5_data->ctl = ctl; } else { ctl = mdp5_data->ctl; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c index 72d7e80dbebe..cb876c22a0ad 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c @@ -364,7 +364,7 @@ static int pp_read_pa_v2_regs(char __iomem *addr, static void pp_read_pa_mem_col_regs(char __iomem *addr, struct mdp_pa_mem_col_cfg *mem_col_cfg); static struct msm_fb_data_type *mdss_get_mfd_from_index(int index); -static int mdss_ad_init_checks(struct msm_fb_data_type *mfd); +static int mdss_mdp_mfd_valid_ad(struct msm_fb_data_type *mfd); static int mdss_mdp_get_ad(struct msm_fb_data_type *mfd, struct mdss_ad_info **ad); static int pp_ad_invalidate_input(struct msm_fb_data_type *mfd); @@ -391,7 +391,8 @@ static int pp_update_pcc_pipe_setup(struct mdss_mdp_pipe *pipe, u32 location); static void mdss_mdp_hist_irq_set_mask(u32 irq); static void mdss_mdp_hist_irq_clear_mask(u32 irq); static void mdss_mdp_hist_intr_notify(u32 disp); -static int mdss_mdp_panel_default_dither_config(u32 panel_bpp, u32 disp_num); +static int mdss_mdp_panel_default_dither_config(struct msm_fb_data_type *mfd, + u32 panel_bpp); static u32 last_sts, last_state; @@ -2048,28 +2049,26 @@ exit: * Set dirty and write bits on features that were enabled so they will be * reconfigured */ -int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 dspp_num) +int mdss_mdp_pp_resume(struct msm_fb_data_type *mfd) { - u32 flags = 0, disp_num, bl, ret = 0; + u32 flags = 0, disp_num, ret = 0; struct pp_sts_type pp_sts; struct mdss_ad_info *ad; - struct mdss_data_type *mdata; - struct msm_fb_data_type *bl_mfd; + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); struct mdp_pa_v2_cfg_data *pa_v2_cache_cfg = NULL; - if (!ctl || !ctl->mdata || !ctl->mfd) { - pr_err("invalid input: ctl = 0x%p, mdata = 0x%p, mfd = 0x%p\n", - ctl, (!ctl) ? NULL : ctl->mdata, - (!ctl) ? NULL : ctl->mfd); + if (!mfd) { + pr_err("invalid input: mfd = 0x%p\n", mfd); + return -EINVAL; + } + + if (!mdss_mdp_mfd_valid_dspp(mfd)) { + pr_warn("PP not supported on display num %d hw config\n", + mfd->index); return -EPERM; } - mdata = ctl->mdata; - if (dspp_num >= mdata->ndspp) { - pr_err("invalid dspp_num %d\n", dspp_num); - return -EINVAL; - } - disp_num = ctl->mfd->index; + disp_num = mfd->index; pp_sts = mdss_pp_res->pp_disp_sts[disp_num]; if (pp_sts.pa_sts & PP_STS_ENABLE) { @@ -2143,43 +2142,27 @@ int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 dspp_num) mdss_pp_res->pp_disp_flags[disp_num] |= flags; mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_RESUME_COMMIT; - if (dspp_num < mdata->nad_cfgs) { - ret = mdss_mdp_get_ad(ctl->mfd, &ad); - if (ret) { - pr_warn("Failed to get AD info, err = %d\n", ret); - return ret; - } - if (ctl->mfd->panel_info->type == WRITEBACK_PANEL) { - bl_mfd = mdss_get_mfd_from_index(0); - if (!bl_mfd) { - ret = -EINVAL; - pr_warn("Failed to get primary FB bl handle, err = %d\n", - ret); - return ret; - } - } else { - bl_mfd = ctl->mfd; - } - - mutex_lock(&ad->lock); - bl = bl_mfd->ad_bl_level; - if (PP_AD_STATE_CFG & ad->state) - pp_ad_cfg_write(&mdata->ad_off[dspp_num], ad); - if (PP_AD_STATE_INIT & ad->state) - pp_ad_init_write(&mdata->ad_off[dspp_num], ad, ctl); - if ((PP_AD_STATE_DATA & ad->state) && - (ad->sts & PP_STS_ENABLE)) { - ad->last_bl = bl; - linear_map(bl, &ad->bl_data, - bl_mfd->panel_info->bl_max, - MDSS_MDP_AD_BL_SCALE); - pp_ad_input_write(&mdata->ad_off[dspp_num], ad); - } - if ((PP_AD_STATE_VSYNC & ad->state) && ad->calc_itr) - ctl->ops.add_vsync_handler(ctl, &ad->handle); - mutex_unlock(&ad->lock); + ret = mdss_mdp_get_ad(mfd, &ad); + if (ret == -ENODEV || ret == -EPERM) { + pr_debug("AD not supported on device, disp num %d\n", + mfd->index); + return 0; + } else if (ret || !ad) { + pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n", + ret, ad); + return ret; } + mutex_lock(&ad->lock); + if (PP_AD_STATE_CFG & ad->state) + ad->sts |= PP_AD_STS_DIRTY_CFG; + if (PP_AD_STATE_INIT & ad->state) + ad->sts |= PP_AD_STS_DIRTY_INIT; + if ((PP_AD_STATE_DATA & ad->state) && + (ad->sts & PP_STS_ENABLE)) + ad->sts |= PP_AD_STS_DIRTY_DATA; + mutex_unlock(&ad->lock); + return 0; } @@ -2437,8 +2420,7 @@ int mdss_mdp_pp_default_overlay_config(struct msm_fb_data_type *mfd, return -EINVAL; } - ret = mdss_mdp_panel_default_dither_config(pdata->panel_info.bpp, - mfd->index); + ret = mdss_mdp_panel_default_dither_config(mfd, pdata->panel_info.bpp); if (ret) pr_err("Unable to configure default dither on fb%d\n", mfd->index); @@ -2455,9 +2437,10 @@ static int pp_ad_calc_bl(struct msm_fb_data_type *mfd, int bl_in, int *bl_out, struct mdss_ad_info *ad; ret = mdss_mdp_get_ad(mfd, &ad); - if (ret == -ENODEV) { - pr_debug("AD not supported on device.\n"); - return ret; + if (ret == -ENODEV || ret == -EPERM) { + pr_debug("AD not supported on device, disp num %d\n", + mfd->index); + return 0; } else if (ret || !ad) { pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n", ret, ad); @@ -3092,6 +3075,12 @@ int mdss_mdp_limited_lut_igc_config(struct mdss_mdp_ctl *ctl) if (!ctl) return -EINVAL; + if (!mdss_mdp_mfd_valid_dspp(ctl->mfd)) { + pr_warn("IGC not supported on display num %d hw configuration\n", + ctl->mfd->index); + return 0; + } + config.len = IGC_LUT_ENTRIES; config.ops = MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE; config.block = (ctl->mfd->index) + MDP_LOGICAL_BLOCK_DISP_0; @@ -3633,19 +3622,23 @@ enhist_config_exit: return ret; } -static int mdss_mdp_panel_default_dither_config(u32 panel_bpp, u32 disp_num) +static int mdss_mdp_panel_default_dither_config(struct msm_fb_data_type *mfd, + u32 panel_bpp) { int ret = 0; - struct mdp_dither_cfg_data dither = { - .block = disp_num + MDP_LOGICAL_BLOCK_DISP_0, - .flags = MDP_PP_OPS_DISABLE, - }; + struct mdp_dither_cfg_data dither; struct mdp_pp_feature_version dither_version = { .pp_feature = DITHER, }; struct mdp_dither_data_v1_7 dither_data; - dither.block = disp_num + MDP_LOGICAL_BLOCK_DISP_0; + if (!mdss_mdp_mfd_valid_dspp(mfd)) { + pr_warn("dither config not supported on display num %d\n", + mfd->index); + return 0; + } + + dither.block = mfd->index + MDP_LOGICAL_BLOCK_DISP_0; dither.flags = MDP_PP_OPS_DISABLE; ret = mdss_mdp_pp_get_version(&dither_version); @@ -4803,67 +4796,42 @@ static int pp_num_to_side(struct mdss_mdp_ctl *ctl, u32 num) return -EINVAL; } -static int mdss_ad_init_checks(struct msm_fb_data_type *mfd) +static int mdss_mdp_get_ad(struct msm_fb_data_type *mfd, + struct mdss_ad_info **ret_ad) { - u32 mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER]; - u32 mixer_num; - u32 ret = -EINVAL; - int i = 0; - struct mdss_data_type *mdata = mfd_to_mdata(mfd); - struct msm_fb_data_type *ad_mfd = mfd; + int ret = 0; + struct mdss_data_type *mdata; + struct mdss_mdp_ctl *ctl = NULL; - if (ad_mfd->ext_ad_ctrl >= 0) - ad_mfd = mdss_get_mfd_from_index(ad_mfd->ext_ad_ctrl); - - if (!ad_mfd || !mdata) - return ret; + *ret_ad = NULL; + if (!mfd) { + pr_err("invalid parameter mfd %p\n", mfd); + return -EINVAL; + } + mdata = mfd_to_mdata(mfd); if (mdata->nad_cfgs == 0) { pr_debug("Assertive Display not supported by device\n"); return -ENODEV; } - if (ad_mfd->panel_info->type == DTV_PANEL) { + if (!mdss_mdp_mfd_valid_ad(mfd)) { + pr_warn("AD not supported on display num %d hw config\n", + mfd->index); + return -EPERM; + } + + if (mfd->panel_info->type == DTV_PANEL) { pr_debug("AD not supported on external display\n"); - return ret; + return -EPERM; } - mixer_num = mdss_mdp_get_ctl_mixers(ad_mfd->index, mixer_id); - if (!mixer_num) { - pr_debug("no mixers connected, %d\n", mixer_num); - return -EHOSTDOWN; - } - if (mixer_num > mdata->nmax_concurrent_ad_hw) { - pr_debug("too many mixers, not supported, %d > %d\n", mixer_num, - mdata->nmax_concurrent_ad_hw); - return ret; - } - - do { - if (mixer_id[i] >= mdata->nad_cfgs) { - pr_err("invalid mixer input, %d\n", mixer_id[i]); - return ret; - } - i++; - } while (i < mixer_num); - - return mixer_id[0]; -} - -static int mdss_mdp_get_ad(struct msm_fb_data_type *mfd, - struct mdss_ad_info **ret_ad) -{ - int ad_num, ret = 0; - struct mdss_data_type *mdata; - struct mdss_ad_info *ad = NULL; - mdata = mfd_to_mdata(mfd); - - ad_num = mdss_ad_init_checks(mfd); - if (ad_num >= 0) - ad = &mdata->ad_cfgs[ad_num]; + ctl = mfd_to_ctl(mfd); + if ((ctl) && (ctl->mixer_left)) + *ret_ad = &mdata->ad_cfgs[ctl->mixer_left->num]; else - ret = ad_num; - *ret_ad = ad; + ret = -EPERM; + return ret; } @@ -4872,22 +4840,21 @@ static int pp_ad_invalidate_input(struct msm_fb_data_type *mfd) { int ret; struct mdss_ad_info *ad; - struct mdss_mdp_ctl *ctl; if (!mfd) { pr_err("Invalid mfd\n"); return -EINVAL; } - ctl = mfd_to_ctl(mfd); - if (!ctl) { - pr_err("Invalid ctl\n"); - return -EINVAL; - } ret = mdss_mdp_get_ad(mfd, &ad); - if (ret || !ad) { - pr_err("Fail to get ad: ret = %d, ad = 0x%p\n", ret, ad); - return -EINVAL; + if (ret == -ENODEV || ret == -EPERM) { + pr_debug("AD not supported on device, disp num %d\n", + mfd->index); + return 0; + } else if (ret || !ad) { + pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n", + ret, ad); + return ret; } pr_debug("AD backlight level changed (%d), trigger update to AD\n", mfd->ad_bl_level); @@ -4914,8 +4881,15 @@ int mdss_mdp_ad_config(struct msm_fb_data_type *mfd, u32 last_ops; ret = mdss_mdp_get_ad(mfd, &ad); - if (ret) + if (ret == -ENODEV || ret == -EPERM) { + pr_err("AD not supported on device, disp num %d\n", + mfd->index); return ret; + } else if (ret || !ad) { + pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n", + ret, ad); + return ret; + } if (mfd->panel_info->type == WRITEBACK_PANEL) { bl_mfd = mdss_get_mfd_from_index(0); if (!bl_mfd) @@ -5018,8 +4992,15 @@ int mdss_mdp_ad_input(struct msm_fb_data_type *mfd, u32 bl; ret = mdss_mdp_get_ad(mfd, &ad); - if (ret) + if (ret == -ENODEV || ret == -EPERM) { + pr_err("AD not supported on device, disp num %d\n", + mfd->index); return ret; + } else if (ret || !ad) { + pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n", + ret, ad); + return ret; + } mutex_lock(&ad->lock); if ((!PP_AD_STATE_IS_INITCFG(ad->state) && @@ -5344,10 +5325,14 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd) u32 bypass = MDSS_PP_AD_BYPASS_DEF, bl; ret = mdss_mdp_get_ad(mfd, &ad); - if (ret) { - ret = -EINVAL; - pr_debug("failed to get ad_info, err = %d\n", ret); - goto exit; + if (ret == -ENODEV || ret == -EPERM) { + pr_debug("AD not supported on device, disp num %d\n", + mfd->index); + return 0; + } else if (ret || !ad) { + pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n", + ret, ad); + return ret; } if (mfd->panel_info->type == WRITEBACK_PANEL) { bl_mfd = mdss_get_mfd_from_index(0); @@ -6510,3 +6495,31 @@ void mdss_mdp_free_layer_pp_info(struct mdp_input_layer *layer) kfree(pp_info->pcc_cfg_data.cfg_payload); kfree(pp_info); } + +int mdss_mdp_mfd_valid_dspp(struct msm_fb_data_type *mfd) +{ + struct mdss_mdp_ctl *ctl = NULL; + int valid_dspp = false; + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + + ctl = mfd_to_ctl(mfd); + valid_dspp = (ctl) && (ctl->mixer_left) && + (ctl->mixer_left->num < mdata->ndspp); + if ((ctl) && (ctl->mixer_right)) + valid_dspp &= (ctl->mixer_right->num < mdata->ndspp); + return valid_dspp; +} + +static int mdss_mdp_mfd_valid_ad(struct msm_fb_data_type *mfd) +{ + struct mdss_mdp_ctl *ctl = NULL; + int valid_ad = false; + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + + ctl = mfd_to_ctl(mfd); + valid_ad = (ctl) && (ctl->mixer_left) && + (ctl->mixer_left->num < mdata->nad_cfgs); + if ((ctl) && (ctl->mixer_right)) + valid_ad &= (ctl->mixer_right->num < mdata->nad_cfgs); + return valid_ad; +}