msm: mdss: Add overlay source side histogram LUT
Allow for overlay API to set histogram LUT. Currently multiple pipes can be
specified by the overlay requests; however, only the pipe that was
allocated by the request will have the histogram LUT applied to it.
Change-Id: Ifebca3fd3cc03e4ed9df638555da1b6d850e070b
Signed-off-by: Carl Vanderlip <carlv@codeaurora.org>
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 51776db..baedd03 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -878,6 +878,7 @@
{
int i, j;
char *offset;
+ struct mdss_mdp_pipe *vig;
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
mdata->mdp_rev = MDSS_MDP_REG_READ(MDSS_MDP_REG_HW_VERSION);
@@ -899,7 +900,16 @@
writel_relaxed(j, offset);
/* swap */
- writel_relaxed(i, offset + 4);
+ writel_relaxed(1, offset + 4);
+ }
+ vig = mdata->vig_pipes;
+ for (i = 0; i < mdata->nvig_pipes; i++) {
+ offset = vig[i].base +
+ MDSS_MDP_REG_VIG_HIST_LUT_BASE;
+ for (j = 0; j < ENHIST_LUT_ENTRIES; j++)
+ writel_relaxed(j, offset);
+ /* swap */
+ writel_relaxed(1, offset + 16);
}
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
pr_debug("MDP hw init done\n");
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 27db359..eaff2f4 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -248,6 +248,7 @@
struct mdss_pipe_pp_res {
u32 igc_c0_c1[IGC_LUT_ENTRIES];
u32 igc_c2[IGC_LUT_ENTRIES];
+ u32 hist_lut[ENHIST_LUT_ENTRIES];
struct pp_hist_col_info hist;
struct pp_sts_type pp_sts;
};
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 8bb5ce1..a0ede3c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -405,6 +405,16 @@
pipe->pp_cfg.hist_cfg.block);
}
}
+ len = pipe->pp_cfg.hist_lut_cfg.len;
+ if ((pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_HIST_LUT_CFG) &&
+ (len == ENHIST_LUT_ENTRIES)) {
+ ret = copy_from_user(pipe->pp_res.hist_lut,
+ pipe->pp_cfg.hist_lut_cfg.data,
+ sizeof(uint32_t) * len);
+ if (ret)
+ return -ENOMEM;
+ pipe->pp_cfg.hist_lut_cfg.data = pipe->pp_res.hist_lut;
+ }
}
if (pipe->flags & MDP_DEINTERLACE) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 9fb4e1e..cf9a8b6 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -169,7 +169,8 @@
struct mdp_ar_gc_lut_data *lut_data);
static void pp_update_argc_lut(u32 offset,
struct mdp_pgc_lut_data *config);
-static void pp_update_hist_lut(u32 offset, struct mdp_hist_lut_data *cfg);
+static void pp_update_hist_lut(char __iomem *base,
+ struct mdp_hist_lut_data *cfg);
static void pp_pa_config(unsigned long flags, u32 base,
struct pp_sts_type *pp_sts,
struct mdp_pa_cfg *pa_config);
@@ -180,7 +181,7 @@
struct pp_sts_type *pp_sts,
struct mdp_igc_lut_data *igc_config,
u32 pipe_num);
-static void pp_enhist_config(unsigned long flags, u32 base,
+static void pp_enhist_config(unsigned long flags, char __iomem *base,
struct pp_sts_type *pp_sts,
struct mdp_hist_lut_data *enhist_cfg);
static void pp_sharp_config(char __iomem *offset,
@@ -381,7 +382,7 @@
}
}
-static void pp_enhist_config(unsigned long flags, u32 base,
+static void pp_enhist_config(unsigned long flags, char __iomem *base,
struct pp_sts_type *pp_sts,
struct mdp_hist_lut_data *enhist_cfg)
{
@@ -421,6 +422,7 @@
{
u32 opmode = 0, base = 0;
unsigned long flags = 0;
+ char __iomem *offset;
pr_debug("pnum=%x\n", pipe->num);
@@ -467,6 +469,26 @@
if (pipe->pp_res.pp_sts.pa_sts & PP_STS_ENABLE)
opmode |= (1 << 4); /* PA_EN */
}
+
+ if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_HIST_LUT_CFG) {
+ pp_enhist_config(PP_FLAGS_DIRTY_ENHIST,
+ pipe->base + MDSS_MDP_REG_VIG_HIST_LUT_BASE,
+ &pipe->pp_res.pp_sts,
+ &pipe->pp_cfg.hist_lut_cfg);
+ }
+ }
+
+ if (pipe->pp_res.pp_sts.enhist_sts & PP_STS_ENABLE) {
+ /* Enable HistLUT and PA */
+ opmode |= BIT(10) | BIT(4);
+ if (!(pipe->pp_res.pp_sts.pa_sts & PP_STS_ENABLE)) {
+ /* Program default value */
+ offset = pipe->base + MDSS_MDP_REG_VIG_PA_BASE;
+ writel_relaxed(0, offset);
+ writel_relaxed(0, offset + 4);
+ writel_relaxed(0, offset + 8);
+ writel_relaxed(0, offset + 12);
+ }
}
*op = opmode;
@@ -918,7 +940,7 @@
pp_igc_config(flags, MDSS_MDP_REG_IGC_DSPP_BASE, pp_sts,
&mdss_pp_res->igc_disp_cfg[disp_num], dspp_num);
- pp_enhist_config(flags, base + MDSS_MDP_REG_DSPP_HIST_LUT_BASE,
+ pp_enhist_config(flags, basel + MDSS_MDP_REG_DSPP_HIST_LUT_BASE,
pp_sts, &mdss_pp_res->enhist_disp_cfg[disp_num]);
if (pp_sts->pa_sts & PP_STS_ENABLE)
@@ -1617,13 +1639,17 @@
}
/* Note: Assumes that its inputs have been checked by calling function */
-static void pp_update_hist_lut(u32 offset, struct mdp_hist_lut_data *cfg)
+static void pp_update_hist_lut(char __iomem *offset,
+ struct mdp_hist_lut_data *cfg)
{
int i;
for (i = 0; i < ENHIST_LUT_ENTRIES; i++)
- MDSS_MDP_REG_WRITE(offset, cfg->data[i]);
+ writel_relaxed(cfg->data[i], offset);
/* swap */
- MDSS_MDP_REG_WRITE(offset + 4, 1);
+ if (PP_LOCAT(cfg->block) == MDSS_PP_DSPP_CFG)
+ writel_relaxed(1, offset + 4);
+ else
+ writel_relaxed(1, offset + 16);
}
int mdss_mdp_argc_config(struct mdss_mdp_ctl *ctl,
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index c686f82..b9d4a6f 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -332,6 +332,7 @@
#define MDP_OVERLAY_PP_IGC_CFG 0x8
#define MDP_OVERLAY_PP_SHARP_CFG 0x10
#define MDP_OVERLAY_PP_HIST_CFG 0x20
+#define MDP_OVERLAY_PP_HIST_LUT_CFG 0x40
#define MDP_CSC_FLAG_ENABLE 0x1
#define MDP_CSC_FLAG_YUV_IN 0x2
@@ -375,6 +376,13 @@
uint16_t num_bins;
};
+struct mdp_hist_lut_data {
+ uint32_t block;
+ uint32_t ops;
+ uint32_t len;
+ uint32_t *data;
+};
+
struct mdp_overlay_pp_params {
uint32_t config_ops;
struct mdp_csc_cfg csc_cfg;
@@ -383,6 +391,7 @@
struct mdp_igc_lut_data igc_cfg;
struct mdp_sharp_cfg sharp_cfg;
struct mdp_histogram_cfg hist_cfg;
+ struct mdp_hist_lut_data hist_lut_cfg;
};
struct mdp_overlay {
@@ -517,13 +526,6 @@
};
-struct mdp_hist_lut_data {
- uint32_t block;
- uint32_t ops;
- uint32_t len;
- uint32_t *data;
-};
-
struct mdp_lut_cfg_data {
uint32_t lut_type;
union {