From 130e60d4147ed7e5f7b351133d360763ed62d99c Mon Sep 17 00:00:00 2001 From: Benet Clark Date: Fri, 4 Oct 2013 17:34:32 -0700 Subject: [PATCH] msm: mdss: Add six zone functionality for PP PAv2 Added six zone memory color adjustment for picture adjustment block in post-processing. This includes the necessary structures, flags, and register reads and writes in order to program the six zone LUT hardware block in PA Change-Id: Idb381077497e2b63399ebeb7051027a46b5dd6e1 Signed-off-by: Benet Clark --- drivers/video/fbdev/msm/mdss_mdp_hwio.h | 4 + drivers/video/fbdev/msm/mdss_mdp_pp.c | 125 ++++++++++++++++++++++-- include/uapi/linux/msm_mdp.h | 5 + 3 files changed, 127 insertions(+), 7 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h index 49337efcbabc..9dad5cd1d6ab 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h +++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h @@ -20,6 +20,7 @@ #define GC_LUT_SEGMENTS 16 #define ENHIST_LUT_ENTRIES 256 #define HIST_V_SIZE 256 +#define SIX_ZONE_LUT_ENTRIES 384 #define MDSS_MDP_HW_REV_100 0x10000000 #define MDSS_MDP_HW_REV_102 0x10020000 @@ -443,6 +444,9 @@ enum mdss_mdp_dspp_index { #define MDSS_MDP_DSPP_OP_PA_SAT_MASK BIT(26) #define MDSS_MDP_DSPP_OP_PA_VAL_MASK BIT(27) #define MDSS_MDP_DSPP_OP_PA_CONT_MASK BIT(28) +#define MDSS_MDP_DSPP_OP_PA_SIX_ZONE_HUE_MASK BIT(29) +#define MDSS_MDP_DSPP_OP_PA_SIX_ZONE_SAT_MASK BIT(30) +#define MDSS_MDP_DSPP_OP_PA_SIX_ZONE_VAL_MASK BIT(31) enum mdss_mpd_intf_index { MDSS_MDP_NO_INTF, diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c index 9f097c2b3308..1798937f6a0b 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c @@ -198,6 +198,9 @@ static u32 igc_limited[IGC_LUT_ENTRIES] = { #define PP_STS_PA_MEM_COL_SKIN_MASK 0x40 #define PP_STS_PA_MEM_COL_FOL_MASK 0x80 #define PP_STS_PA_MEM_COL_SKY_MASK 0x100 +#define PP_STS_PA_SIX_ZONE_HUE_MASK 0x200 +#define PP_STS_PA_SIX_ZONE_SAT_MASK 0x400 +#define PP_STS_PA_SIX_ZONE_VAL_MASK 0x800 #define PP_STS_PA_SAT_ZERO_EXP_EN 0x1000 #define PP_AD_STATE_INIT 0x2 @@ -276,6 +279,8 @@ struct mdss_pp_res_type { u32 enhist_lut[MDSS_BLOCK_DISP_NUM][ENHIST_LUT_ENTRIES]; struct mdp_pa_cfg pa_disp_cfg[MDSS_BLOCK_DISP_NUM]; struct mdp_pa_v2_data pa_v2_disp_cfg[MDSS_BLOCK_DISP_NUM]; + u32 six_zone_lut_curve_p0[MDSS_BLOCK_DISP_NUM][SIX_ZONE_LUT_ENTRIES]; + u32 six_zone_lut_curve_p1[MDSS_BLOCK_DISP_NUM][SIX_ZONE_LUT_ENTRIES]; struct mdp_pcc_cfg_data pcc_disp_cfg[MDSS_BLOCK_DISP_NUM]; struct mdp_igc_lut_data igc_disp_cfg[MDSS_BLOCK_DISP_NUM]; struct mdp_pgc_lut_data argc_disp_cfg[MDSS_BLOCK_DISP_NUM]; @@ -340,12 +345,16 @@ static void pp_sharp_config(char __iomem *addr, struct mdp_sharp_cfg *sharp_config); static void pp_update_pa_v2_vig_opmode(struct pp_sts_type *pp_sts, u32 *opmode); +static int pp_copy_pa_six_zone_lut(struct mdp_pa_v2_cfg_data *pa_v2_config, + u32 disp_num); static void pp_update_pa_v2_global_adj_regs(char __iomem *addr, struct mdp_pa_v2_data *pa_config); static void pp_update_pa_v2_mem_col(char __iomem *addr, struct mdp_pa_v2_data *pa_v2_config); static void pp_update_pa_v2_mem_col_regs(char __iomem *addr, struct mdp_pa_mem_col_cfg *cfg); +static void pp_update_pa_v2_six_zone_regs(char __iomem *addr, + struct mdp_pa_v2_data *pa_v2_config); static void pp_update_pa_v2_sts(struct pp_sts_type *pp_sts, struct mdp_pa_v2_data *pa_v2_config); static int pp_read_pa_v2_regs(char __iomem *addr, @@ -528,7 +537,9 @@ static void pp_pa_v2_config(unsigned long flags, char __iomem *addr, pa_v2_config); /* Update PA DSPP Regs */ if (mdp_location == PP_DSPP) { - addr += 0x1C; + addr += 0x10; + pp_update_pa_v2_six_zone_regs(addr, pa_v2_config); + addr += 0xC; pp_update_pa_v2_mem_col(addr, pa_v2_config); } else if (mdp_location == PP_SSPP) { /* Update PA SSPP Regs */ addr -= MDSS_MDP_REG_VIG_PA_BASE; @@ -591,6 +602,35 @@ static void pp_update_pa_v2_mem_col_regs(char __iomem *addr, writel_relaxed(cfg->val_region, addr); } +static void pp_update_pa_v2_six_zone_regs(char __iomem *addr, + struct mdp_pa_v2_data *pa_v2_config) +{ + int i; + u32 data; + /* Update six zone memory color registers */ + if (pa_v2_config->flags & MDP_PP_PA_SIX_ZONE_ENABLE) { + addr += 4; + writel_relaxed(pa_v2_config->six_zone_curve_p1[0], addr); + addr -= 4; + /* Index Update to trigger auto-incrementing LUT accesses */ + data = (1 << 26); + writel_relaxed((pa_v2_config->six_zone_curve_p0[0] & 0xFFF) | + data, addr); + + /* Remove Index Update */ + for (i = 1; i < SIX_ZONE_LUT_ENTRIES; i++) { + addr += 4; + writel_relaxed(pa_v2_config->six_zone_curve_p1[i], + addr); + addr -= 4; + writel_relaxed(pa_v2_config->six_zone_curve_p0[i] & + 0xFFF, addr); + } + addr += 8; + writel_relaxed(pa_v2_config->six_zone_thresh, addr); + } +} + static void pp_update_pa_v2_sts(struct pp_sts_type *pp_sts, struct mdp_pa_v2_data *pa_v2_config) { @@ -623,6 +663,14 @@ static void pp_update_pa_v2_sts(struct pp_sts_type *pp_sts, if (pa_v2_config->flags & MDP_PP_PA_MEM_COL_FOL_MASK) pp_sts->pa_sts |= PP_STS_PA_MEM_COL_FOL_MASK; + /* Six Zone STS update */ + if (pa_v2_config->flags & MDP_PP_PA_SIX_ZONE_HUE_MASK) + pp_sts->pa_sts |= PP_STS_PA_SIX_ZONE_HUE_MASK; + if (pa_v2_config->flags & MDP_PP_PA_SIX_ZONE_SAT_MASK) + pp_sts->pa_sts |= PP_STS_PA_SIX_ZONE_SAT_MASK; + if (pa_v2_config->flags & MDP_PP_PA_SIX_ZONE_VAL_MASK) + pp_sts->pa_sts |= PP_STS_PA_SIX_ZONE_VAL_MASK; + } static void pp_pcc_config(unsigned long flags, char __iomem *addr, @@ -1256,6 +1304,12 @@ static void pp_dspp_opmode_config(struct pp_sts_type *pp_sts, u32 *opmode, *opmode |= MDSS_MDP_DSPP_OP_PA_MEM_COL_FOL_MASK; if (pp_sts->pa_sts & PP_STS_PA_MEM_COL_SKY_MASK) *opmode |= MDSS_MDP_DSPP_OP_PA_MEM_COL_SKY_MASK; + if (pp_sts->pa_sts & PP_STS_PA_SIX_ZONE_HUE_MASK) + *opmode |= MDSS_MDP_DSPP_OP_PA_SIX_ZONE_HUE_MASK; + if (pp_sts->pa_sts & PP_STS_PA_SIX_ZONE_SAT_MASK) + *opmode |= MDSS_MDP_DSPP_OP_PA_SIX_ZONE_SAT_MASK; + if (pp_sts->pa_sts & PP_STS_PA_SIX_ZONE_VAL_MASK) + *opmode |= MDSS_MDP_DSPP_OP_PA_SIX_ZONE_VAL_MASK; } if (pp_sts->pcc_sts & PP_STS_ENABLE) *opmode |= MDSS_MDP_DSPP_OP_PCC_EN; /* PCC_EN */ @@ -1692,11 +1746,6 @@ int mdss_mdp_pa_v2_config(struct mdp_pa_v2_cfg_data *config, (config->block >= MDP_BLOCK_MAX)) return -EINVAL; - if (config->pa_v2_data.flags & MDP_PP_PA_SIX_ZONE_ENABLE) { - pr_err("Six zone adjustment not allowed\n"); - return -EINVAL; - } - mutex_lock(&mdss_pp_mutex); disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0; @@ -1722,8 +1771,17 @@ int mdss_mdp_pa_v2_config(struct mdp_pa_v2_cfg_data *config, *copyback = 1; mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false); } else { + if (config->pa_v2_data.flags & MDP_PP_PA_SIX_ZONE_ENABLE) { + ret = pp_copy_pa_six_zone_lut(config, disp_num); + if (ret) + goto pa_config_exit; + } mdss_pp_res->pa_v2_disp_cfg[disp_num] = config->pa_v2_data; + mdss_pp_res->pa_v2_disp_cfg[disp_num].six_zone_curve_p0 = + &mdss_pp_res->six_zone_lut_curve_p0[disp_num][0]; + mdss_pp_res->pa_v2_disp_cfg[disp_num].six_zone_curve_p1 = + &mdss_pp_res->six_zone_lut_curve_p1[disp_num][0]; mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_PA; } @@ -1737,6 +1795,9 @@ static int pp_read_pa_v2_regs(char __iomem *addr, struct mdp_pa_v2_data *pa_v2_config, u32 disp_num) { + int i; + u32 data; + if (pa_v2_config->flags & MDP_PP_PA_HUE_ENABLE) pa_v2_config->global_hue_adj = readl_relaxed(addr); addr += 4; @@ -1748,7 +1809,40 @@ static int pp_read_pa_v2_regs(char __iomem *addr, addr += 4; if (pa_v2_config->flags & MDP_PP_PA_CONT_ENABLE) pa_v2_config->global_cont_adj = readl_relaxed(addr); - addr += 0x10; + addr += 4; + + /* Six zone LUT and thresh data */ + if (pa_v2_config->flags & MDP_PP_PA_SIX_ZONE_ENABLE) { + data = (3 << 25); + writel_relaxed(data, addr); + + for (i = 0; i < SIX_ZONE_LUT_ENTRIES; i++) { + addr += 4; + mdss_pp_res->six_zone_lut_curve_p1[disp_num][i] = + readl_relaxed(addr); + addr -= 4; + mdss_pp_res->six_zone_lut_curve_p0[disp_num][i] = + readl_relaxed(addr) & 0xFFF; + } + + if (copy_to_user(pa_v2_config->six_zone_curve_p0, + &mdss_pp_res->six_zone_lut_curve_p0[disp_num][0], + SIX_ZONE_LUT_ENTRIES * sizeof(u32))) { + return -EFAULT; + } + + if (copy_to_user(pa_v2_config->six_zone_curve_p1, + &mdss_pp_res->six_zone_lut_curve_p1[disp_num][0], + SIX_ZONE_LUT_ENTRIES * sizeof(u32))) { + return -EFAULT; + } + + addr += 8; + pa_v2_config->six_zone_thresh = readl_relaxed(addr); + addr += 4; + } else { + addr += 12; + } /* Skin memory color config registers */ if (pa_v2_config->flags & MDP_PP_PA_SKIN_ENABLE) @@ -1781,6 +1875,23 @@ static void pp_read_pa_mem_col_regs(char __iomem *addr, mem_col_cfg->val_region = readl_relaxed(addr); } +static int pp_copy_pa_six_zone_lut(struct mdp_pa_v2_cfg_data *pa_v2_config, + u32 disp_num) +{ + if (copy_from_user(&mdss_pp_res->six_zone_lut_curve_p0[disp_num][0], + pa_v2_config->pa_v2_data.six_zone_curve_p0, + SIX_ZONE_LUT_ENTRIES * sizeof(u32))) { + return -EFAULT; + } + if (copy_from_user(&mdss_pp_res->six_zone_lut_curve_p1[disp_num][0], + pa_v2_config->pa_v2_data.six_zone_curve_p1, + SIX_ZONE_LUT_ENTRIES * sizeof(u32))) { + return -EFAULT; + } + + return 0; +} + static void pp_read_pcc_regs(char __iomem *addr, struct mdp_pcc_cfg_data *cfg_ptr) { diff --git a/include/uapi/linux/msm_mdp.h b/include/uapi/linux/msm_mdp.h index 3705ae885bf8..15895f9825bc 100644 --- a/include/uapi/linux/msm_mdp.h +++ b/include/uapi/linux/msm_mdp.h @@ -403,6 +403,8 @@ struct mdp_pa_mem_col_cfg { uint32_t val_region; }; +#define MDP_SIX_ZONE_TABLE_NUM 384 + struct mdp_pa_v2_data { /* Mask bits for PA features */ uint32_t flags; @@ -410,6 +412,9 @@ struct mdp_pa_v2_data { uint32_t global_sat_adj; uint32_t global_val_adj; uint32_t global_cont_adj; + uint32_t *six_zone_curve_p0; + uint32_t *six_zone_curve_p1; + uint32_t six_zone_thresh; struct mdp_pa_mem_col_cfg skin_cfg; struct mdp_pa_mem_col_cfg sky_cfg; struct mdp_pa_mem_col_cfg fol_cfg;