diff options
| author | Gopikrishnaiah Anandan <agopik@codeaurora.org> | 2016-01-22 16:07:01 -0800 |
|---|---|---|
| committer | Kyle Yan <kyan@codeaurora.org> | 2016-04-28 16:41:07 -0700 |
| commit | 2e95db147d9c4801d8b86ac77c1b088298032363 (patch) | |
| tree | 893258c5e1024005125d4999c652e8b2c56bd96a /drivers/video | |
| parent | 3c8a08cef8e55d94bf390ffb7122c1d5e828da6f (diff) | |
msm: mdss: Dither support in PingPong buffer
V3 version of mdss dither block has been moved from dspp to
ppb. Based on mdss revision the driver should enable the dither block in
dspp/ppb. Change enables driver to handle dither block in ppb.
Change-Id: Iaa11755b46417db1e2a12cb2f2b6028cd7530c0b
Signed-off-by: Gopikrishnaiah Anandan <agopik@codeaurora.org>
Signed-off-by: Ping Li <pingli@codeaurora.org>
Diffstat (limited to 'drivers/video')
| -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) |
