diff options
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_ctl.c | 13 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_overlay.c | 8 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_pp.c | 86 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_pp.h | 3 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c | 3 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_pp_v3.c | 88 |
6 files changed, 179 insertions, 22 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index df735d60d8ce..7b4c945c1e7e 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -3053,7 +3053,7 @@ int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl) { struct mdss_mdp_ctl *split_ctl; u32 width, height; - int split_fb; + int split_fb, rc = 0; u32 max_mixer_width; struct mdss_panel_info *pinfo; @@ -3119,6 +3119,16 @@ int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl) ctl->mixer_left->valid_roi = true; ctl->mixer_left->roi_changed = true; + rc = mdss_mdp_pp_default_overlay_config(ctl->mfd, ctl->panel_data); + /* + * Ignore failure of PP config, ctl set-up can succeed. + */ + if (rc) { + pr_err("failed to set the pp config rc %dfb %d\n", rc, + ctl->mfd->index); + rc = 0; + } + if (ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) { pr_debug("dual display detected\n"); return 0; @@ -3161,7 +3171,6 @@ int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl) ctl->opmode &= ~(MDSS_MDP_CTL_OP_PACK_3D_ENABLE | MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT); } - return 0; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 00e540c860c3..e813c8b1bfcd 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -4703,14 +4703,6 @@ 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 ret %d\n", - mfd->index, rc); - rc = 0; - } - error: if (rc) return ERR_PTR(rc); diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c index 86a17d2219e5..4ec66b2c85de 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c @@ -508,6 +508,7 @@ static int pp_mfd_release_all(struct msm_fb_data_type *mfd); static int pp_mfd_ad_release_all(struct msm_fb_data_type *mfd); static int mdss_mdp_ad_ipc_reset(struct msm_fb_data_type *mfd); static int pp_get_driver_ops(struct mdp_pp_driver_ops *ops); +static int pp_ppb_setup(struct mdss_mdp_mixer *mixer); static u32 last_sts, last_state; @@ -2334,7 +2335,7 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer) } else { addr = base + MDSS_MDP_REG_DSPP_DITHER_DEPTH; pp_ops[DITHER].pp_set_config(addr, pp_sts, - &mdss_pp_res->dither_disp_cfg[disp_num], 0); + &mdss_pp_res->dither_disp_cfg[disp_num], DSPP); } } if (flags & PP_FLAGS_DIRTY_GAMUT) { @@ -2508,10 +2509,12 @@ int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl) 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 (ctl->mixer_right) { pp_mixer_setup(ctl->mixer_right); pp_dspp_setup(disp_num, ctl->mixer_right); + pp_ppb_setup(ctl->mixer_right); } if (valid_mixers && (mixer_cnt <= mdata->nmax_concurrent_ad_hw) && @@ -4274,20 +4277,38 @@ static int mdss_mdp_panel_default_dither_config(struct msm_fb_data_type *mfd, dither.version = dither_version.version_info; switch (panel_bpp) { + case 24: + dither.flags = MDP_PP_OPS_ENABLE | MDP_PP_OPS_WRITE; + switch (dither.version) { + case mdp_dither_v1_7: + dither_data.g_y_depth = 8; + dither_data.r_cr_depth = 8; + dither_data.b_cb_depth = 8; + dither.cfg_payload = &dither_data; + break; + case mdp_pp_legacy: + default: + dither.g_y_depth = 8; + dither.r_cr_depth = 8; + dither.b_cb_depth = 8; + dither.cfg_payload = NULL; + break; + } + break; case 18: dither.flags = MDP_PP_OPS_ENABLE | MDP_PP_OPS_WRITE; switch (dither.version) { case mdp_dither_v1_7: - dither_data.g_y_depth = 2; - dither_data.r_cr_depth = 2; - dither_data.b_cb_depth = 2; + dither_data.g_y_depth = 6; + dither_data.r_cr_depth = 6; + dither_data.b_cb_depth = 6; dither.cfg_payload = &dither_data; break; case mdp_pp_legacy: default: - dither.g_y_depth = 2; - dither.r_cr_depth = 2; - dither.b_cb_depth = 2; + dither.g_y_depth = 6; + dither.r_cr_depth = 6; + dither.b_cb_depth = 6; dither.cfg_payload = NULL; break; } @@ -7342,3 +7363,54 @@ static int pp_get_driver_ops(struct mdp_pp_driver_ops *ops) } return ret; } + +static int pp_ppb_setup(struct mdss_mdp_mixer *mixer) +{ + struct pp_sts_type *pp_sts; + struct mdss_mdp_ctl *ctl; + char __iomem *addr; + u32 flags, disp_num; + int ret = 0; + + if (!mixer || !mixer->ctl || !mixer->ctl->mfd) { + pr_err("invalid parameters, mixer %pK ctl %pK mfd %pK\n", + mixer, (mixer ? mixer->ctl : NULL), + (mixer ? (mixer->ctl ? mixer->ctl->mfd : NULL) : NULL)); + return -EINVAL; + } + ctl = mixer->ctl; + disp_num = ctl->mfd->index; + + if (disp_num < MDSS_BLOCK_DISP_NUM) + flags = mdss_pp_res->pp_disp_flags[disp_num]; + else + flags = 0; + if ((flags & PP_FLAGS_DIRTY_DITHER)) { + if (pp_ops[DITHER].pp_set_config) { + pp_sts = &mdss_pp_res->pp_disp_sts[disp_num]; + addr = mixer->pingpong_base; + /* if dither is supported in PPB function will + * return 0. Failure will indicate that there + * is no DITHER in PPB. In case of error skip the + * programming of CTL flush bits for dither flush. + */ + ret = pp_ops[DITHER].pp_set_config(addr, pp_sts, + &mdss_pp_res->dither_disp_cfg[disp_num], PPB); + if (!ret) { + switch (mixer->num) { + case MDSS_MDP_INTF_LAYERMIXER0: + case MDSS_MDP_INTF_LAYERMIXER1: + case MDSS_MDP_INTF_LAYERMIXER2: + ctl->flush_bits |= BIT(13) << + mixer->num; + break; + case MDSS_MDP_INTF_LAYERMIXER3: + ctl->flush_bits |= BIT(21); + break; + } + } + ret = 0; + } + } + return ret; +} diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.h b/drivers/video/fbdev/msm/mdss_mdp_pp.h index 31ddc7d49705..c5322d205bf5 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp.h +++ b/drivers/video/fbdev/msm/mdss_mdp_pp.h @@ -84,7 +84,8 @@ enum pp_config_block { SSPP_DMA, SSPP_VIG, DSPP, - LM + LM, + PPB, }; struct mdp_pp_feature_ops { diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c b/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c index 86312366571d..1470915a1253 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c @@ -539,7 +539,8 @@ static int pp_dither_set_config(char __iomem *base_addr, base_addr, cfg_data, pp_sts); return -EINVAL; } - + if (block_type != DSPP) + return -ENOTSUPP; dither_cfg_data = (struct mdp_dither_cfg_data *) cfg_data; if (dither_cfg_data->version != mdp_dither_v1_7) { diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_v3.c b/drivers/video/fbdev/msm/mdss_mdp_pp_v3.c index 1bc803452931..4920c5387e2c 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_v3.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_v3.c @@ -56,6 +56,14 @@ #define PA_LUTV_REG_OFF 0x200 #define PA_HIST_RAM_REG_OFF 0x400 +#define PPB_GLOBAL_DITHER_REG_OFF 0x30E0 +#define DITHER_MATRIX_LEN 16 +#define DITHER_DEPTH_MAP_INDEX 9 +static u32 dither_matrix[DITHER_MATRIX_LEN] = { + 15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10}; +static u32 dither_depth_map[DITHER_DEPTH_MAP_INDEX] = { + 0, 0, 0, 0, 0, 1, 2, 3, 3}; + /* histogram prototypes */ static int pp_get_hist_offset(u32 block, u32 *ctl_off); static int pp_hist_set_config(char __iomem *base_addr, @@ -470,7 +478,7 @@ pa_set_sts: static int pp_pa_get_config(char __iomem *base_addr, void *cfg_data, u32 block_type, u32 disp_num) { - return -EINVAL; + return -ENOTSUPP; } static int pp_pa_get_version(u32 *version) @@ -486,14 +494,88 @@ static int pp_pa_get_version(u32 *version) static int pp_dither_get_config(char __iomem *base_addr, void *cfg_data, u32 block_type, u32 disp_num) { - return -EINVAL; + return -ENOTSUPP; } static int pp_dither_set_config(char __iomem *base_addr, struct pp_sts_type *pp_sts, void *cfg_data, u32 block_type) { - return -EINVAL; + int i = 0; + u32 data; + struct mdp_dither_cfg_data *dither_cfg_data = NULL; + struct mdp_dither_data_v1_7 *dither_data = NULL; + char __iomem *dither_opmode = NULL; + + if (!base_addr || !cfg_data || !pp_sts) { + pr_err("invalid params base_addr %p cfg_data %p pp_sts_type %p\n", + base_addr, cfg_data, pp_sts); + return -EINVAL; + } + if (block_type != PPB) + return -ENOTSUPP; + dither_opmode = base_addr + PPB_GLOBAL_DITHER_REG_OFF; + base_addr = dither_opmode + 4; + + dither_cfg_data = (struct mdp_dither_cfg_data *) cfg_data; + + if (dither_cfg_data->version != mdp_dither_v1_7) { + pr_err("invalid dither version %d\n", dither_cfg_data->version); + return -EINVAL; + } + + if (dither_cfg_data->flags & MDP_PP_OPS_READ) { + pr_err("Invalid context for read operation\n"); + return -EINVAL; + } + + if (dither_cfg_data->flags & MDP_PP_OPS_DISABLE || + !(dither_cfg_data->flags & MDP_PP_OPS_WRITE)) { + pr_debug("non write ops set %d\n", dither_cfg_data->flags); + goto dither_set_sts; + } + + dither_data = dither_cfg_data->cfg_payload; + if (!dither_data) { + pr_err("invalid payload for dither %p\n", dither_data); + return -EINVAL; + } + + if ((dither_data->g_y_depth >= DITHER_DEPTH_MAP_INDEX) || + (dither_data->b_cb_depth >= DITHER_DEPTH_MAP_INDEX) || + (dither_data->r_cr_depth >= DITHER_DEPTH_MAP_INDEX)) { + pr_err("invalid data for dither, g_y_depth %d y_cb_depth %d r_cr_depth %d\n", + dither_data->g_y_depth, dither_data->b_cb_depth, + dither_data->r_cr_depth); + return -EINVAL; + } + data = dither_depth_map[dither_data->g_y_depth]; + data |= dither_depth_map[dither_data->b_cb_depth] << 2; + data |= dither_depth_map[dither_data->r_cr_depth] << 4; + data |= (dither_data->temporal_en) ? (1 << 8) : 0; + writel_relaxed(data, base_addr); + base_addr += 4; + for (i = 0; i < DITHER_MATRIX_LEN; i += 4) { + data = (dither_matrix[i] & REG_MASK(4)) | + ((dither_matrix[i + 1] & REG_MASK(4)) << 4) | + ((dither_matrix[i + 2] & REG_MASK(4)) << 8) | + ((dither_matrix[i + 3] & REG_MASK(4)) << 12); + writel_relaxed(data, base_addr); + base_addr += 4; + } + +dither_set_sts: + pp_sts_set_split_bits(&pp_sts->dither_sts, + dither_cfg_data->flags); + if (dither_cfg_data->flags & MDP_PP_OPS_DISABLE) { + pp_sts->dither_sts &= ~PP_STS_ENABLE; + writel_relaxed(0, dither_opmode); + } else if (dither_cfg_data->flags & MDP_PP_OPS_ENABLE) { + pp_sts->dither_sts |= PP_STS_ENABLE; + if (pp_sts_is_enabled(pp_sts->dither_sts, pp_sts->side_sts)) + writel_relaxed(BIT(0), dither_opmode); + } + return 0; } static int pp_dither_get_version(u32 *version) |
