summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c13
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c8
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp.c86
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp_v3.c88
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)