msm: mdss: Add PA support for DSPP in thulium

MDP block supports picture adjustment feature on the DSPP which can be
enabled/disabled by driver clients.  Change adds the support in post
processing driver and allows clients of driver to configure the PA block
in DSPP.

Change-Id: I22e3df32fd67fda4029eeb4740ad47917ae7e3a1
Signed-off-by: Benet Clark <benetc@codeaurora.org>
This commit is contained in:
Benet Clark 2014-12-05 17:08:29 -08:00 committed by David Keitel
parent 3524a114f2
commit d9f0e69311
6 changed files with 965 additions and 81 deletions

View file

@ -222,19 +222,6 @@ static int mdss_mdp_hscl_filter[] = {
#define PP_SSPP 0
#define PP_DSPP 1
#define PP_STS_PA_HUE_MASK 0x2
#define PP_STS_PA_SAT_MASK 0x4
#define PP_STS_PA_VAL_MASK 0x8
#define PP_STS_PA_CONT_MASK 0x10
#define PP_STS_PA_MEM_PROTECT_EN 0x20
#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_BAD_HW_NUM 255
#define PP_AD_STATE_INIT 0x2
@ -1694,14 +1681,27 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
pp_sts = &mdss_pp_res->pp_disp_sts[disp_num];
if (mdata->mdp_rev >= MDSS_MDP_HW_REV_103) {
pa_v2_cfg_data = &mdss_pp_res->pa_v2_disp_cfg[disp_num];
pp_pa_v2_config(flags, base + MDSS_MDP_REG_DSPP_PA_BASE, pp_sts,
&pa_v2_cfg_data->pa_v2_data,
PP_DSPP);
} else
pp_pa_config(flags, base + MDSS_MDP_REG_DSPP_PA_BASE, pp_sts,
&mdss_pp_res->pa_disp_cfg[disp_num]);
if (flags & PP_FLAGS_DIRTY_PA) {
if (!pp_ops[PA].pp_set_config) {
if (mdata->mdp_rev >= MDSS_MDP_HW_REV_103) {
pa_v2_cfg_data =
&mdss_pp_res->pa_v2_disp_cfg[disp_num];
pp_pa_v2_config(flags,
base + MDSS_MDP_REG_DSPP_PA_BASE,
pp_sts,
&pa_v2_cfg_data->pa_v2_data,
PP_DSPP);
} else
pp_pa_config(flags,
base + MDSS_MDP_REG_DSPP_PA_BASE,
pp_sts,
&mdss_pp_res->pa_disp_cfg[disp_num]);
} else {
pp_ops[PA].pp_set_config(base, pp_sts,
&mdss_pp_res->pa_v2_disp_cfg[disp_num],
DSPP);
}
}
if (flags & PP_FLAGS_DIRTY_PCC) {
if (!pp_ops[PCC].pp_set_config)
@ -1910,7 +1910,11 @@ int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl)
mutex_lock(&mdss_pp_mutex);
flags = mdss_pp_res->pp_disp_flags[disp_num];
pa_v2_flags = mdss_pp_res->pa_v2_disp_cfg[disp_num].pa_v2_data.flags;
if (pp_ops[PA].pp_set_config)
pa_v2_flags = mdss_pp_res->pa_v2_disp_cfg[disp_num].flags;
else
pa_v2_flags =
mdss_pp_res->pa_v2_disp_cfg[disp_num].pa_v2_data.flags;
/*
* If a LUT based PP feature needs to be reprogrammed during resume,
@ -1987,7 +1991,10 @@ int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 dspp_num)
if (pp_sts.pa_sts & PP_STS_ENABLE) {
flags |= PP_FLAGS_DIRTY_PA;
pa_v2_cache_cfg = &mdss_pp_res->pa_v2_disp_cfg[disp_num];
if (mdata->mdp_rev >= MDSS_MDP_HW_REV_103) {
if (pp_ops[PA].pp_set_config) {
if (!(pa_v2_cache_cfg->flags & MDP_PP_OPS_DISABLE))
pa_v2_cache_cfg->flags |= MDP_PP_OPS_WRITE;
} else if (mdata->mdp_rev >= MDSS_MDP_HW_REV_103) {
if (!(pa_v2_cache_cfg->pa_v2_data.flags
& MDP_PP_OPS_DISABLE))
pa_v2_cache_cfg->pa_v2_data.flags |=
@ -2461,6 +2468,7 @@ int mdss_mdp_pa_v2_config(struct mdp_pa_v2_cfg_data *config,
char __iomem *pa_addr;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
struct mdp_pa_v2_cfg_data *pa_v2_cache = NULL;
uint32_t flags = 0;
if (mdata->mdp_rev < MDSS_MDP_HW_REV_103)
return -EINVAL;
@ -2469,8 +2477,12 @@ 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 & MDSS_PP_SPLIT_MASK) ==
MDSS_PP_SPLIT_MASK) {
if (pp_ops[PA].pp_set_config)
flags = config->flags;
else
flags = config->pa_v2_data.flags;
if ((flags & MDSS_PP_SPLIT_MASK) == MDSS_PP_SPLIT_MASK) {
pr_warn("Can't set both split bits\n");
return -EINVAL;
}
@ -2478,7 +2490,7 @@ int mdss_mdp_pa_v2_config(struct mdp_pa_v2_cfg_data *config,
mutex_lock(&mdss_pp_mutex);
disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
if (config->pa_v2_data.flags & MDP_PP_OPS_READ) {
if (flags & MDP_PP_OPS_READ) {
ret = pp_get_dspp_num(disp_num, &dspp_num);
if (ret) {
pr_err("no dspp connects to disp %d\n",
@ -2489,28 +2501,50 @@ int mdss_mdp_pa_v2_config(struct mdp_pa_v2_cfg_data *config,
pa_addr = mdss_mdp_get_dspp_addr_off(dspp_num);
if (IS_ERR(pa_addr)) {
ret = PTR_ERR(pa_addr);
goto pa_config_exit;
} else
goto pa_clk_off;
}
if (pp_ops[PA].pp_get_config) {
ret = pp_ops[PA].pp_get_config(pa_addr, config,
DSPP, disp_num);
if (ret)
pr_err("PA get config failed %d\n", ret);
} else {
pa_addr += MDSS_MDP_REG_DSPP_PA_BASE;
ret = pp_read_pa_v2_regs(pa_addr,
&config->pa_v2_data,
disp_num);
if (ret)
goto pa_config_exit;
*copyback = 1;
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
} else {
if (config->pa_v2_data.flags & MDP_PP_PA_SIX_ZONE_ENABLE) {
ret = pp_copy_pa_six_zone_lut(config, disp_num);
ret = pp_read_pa_v2_regs(pa_addr,
&config->pa_v2_data,
disp_num);
if (ret)
goto pa_config_exit;
*copyback = 1;
}
pa_clk_off:
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
} else {
if (pp_ops[PA].pp_set_config) {
pr_debug("version of PA is %d\n", config->version);
ret = pp_pa_cache_params(config, mdss_pp_res);
if (ret) {
pr_err("PA config failed version %d ret %d\n",
config->version, ret);
ret = -EFAULT;
goto pa_config_exit;
}
} else {
if (flags & MDP_PP_PA_SIX_ZONE_ENABLE) {
ret = pp_copy_pa_six_zone_lut(config, disp_num);
if (ret) {
pr_err("PA copy six zone lut failed ret %d\n",
ret);
goto pa_config_exit;
}
}
pa_v2_cache = &mdss_pp_res->pa_v2_disp_cfg[disp_num];
*pa_v2_cache = *config;
pa_v2_cache->pa_v2_data.six_zone_curve_p0 =
mdss_pp_res->six_zone_lut_curve_p0[disp_num];
pa_v2_cache->pa_v2_data.six_zone_curve_p1 =
mdss_pp_res->six_zone_lut_curve_p1[disp_num];
}
pa_v2_cache = &mdss_pp_res->pa_v2_disp_cfg[disp_num];
*pa_v2_cache = *config;
pa_v2_cache->pa_v2_data.six_zone_curve_p0 =
&mdss_pp_res->six_zone_lut_curve_p0[disp_num][0];
pa_v2_cache->pa_v2_data.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;
}

View file

@ -26,6 +26,25 @@
#define PP_STS_GAMUT_FIRST 0x2
#define PP_STS_PA_LUT_FIRST 0x4
#define PP_STS_PA_HUE_MASK 0x2
#define PP_STS_PA_SAT_MASK 0x4
#define PP_STS_PA_VAL_MASK 0x8
#define PP_STS_PA_CONT_MASK 0x10
#define PP_STS_PA_MEM_PROTECT_EN 0x20
#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_STS_PA_MEM_PROT_HUE_EN 0x2000
#define PP_STS_PA_MEM_PROT_SAT_EN 0x4000
#define PP_STS_PA_MEM_PROT_VAL_EN 0x8000
#define PP_STS_PA_MEM_PROT_CONT_EN 0x10000
#define PP_STS_PA_MEM_PROT_BLEND_EN 0x20000
#define PP_STS_PA_MEM_PROT_SIX_EN 0x40000
/* Demo mode macros */
#define MDSS_SIDE_NONE 0
#define MDSS_SIDE_LEFT 1
@ -103,6 +122,8 @@ struct mdss_pp_res_type_v1_7 {
u32 igc_table_c0_c1[MDSS_BLOCK_DISP_NUM][IGC_LUT_ENTRIES];
u32 igc_table_c2[MDSS_BLOCK_DISP_NUM][IGC_LUT_ENTRIES];
u32 hist_lut[MDSS_BLOCK_DISP_NUM][ENHIST_LUT_ENTRIES];
u32 six_zone_lut_p0[MDSS_BLOCK_DISP_NUM][MDP_SIX_ZONE_LUT_SIZE];
u32 six_zone_lut_p1[MDSS_BLOCK_DISP_NUM][MDP_SIX_ZONE_LUT_SIZE];
struct mdp_pgc_lut_data_v1_7 pgc_dspp_v17_data[MDSS_BLOCK_DISP_NUM];
struct mdp_pgc_lut_data_v1_7 pgc_lm_v17_data[MDSS_BLOCK_LM_NUM];
struct mdp_igc_lut_data_v1_7 igc_v17_data[MDSS_BLOCK_DISP_NUM];
@ -110,6 +131,7 @@ struct mdss_pp_res_type_v1_7 {
struct mdp_dither_data_v1_7 dither_v17_data[MDSS_BLOCK_DISP_NUM];
struct mdp_gamut_data_v1_7 gamut_v17_data[MDSS_BLOCK_DISP_NUM];
struct mdp_pcc_data_v1_7 pcc_v17_data[MDSS_BLOCK_DISP_NUM];
struct mdp_pa_data_v1_7 pa_v17_data[MDSS_BLOCK_DISP_NUM];
};
struct mdss_pp_res_type {

View file

@ -675,3 +675,126 @@ int pp_pgc_lut_cache_params(struct mdp_pgc_lut_data *config,
}
return ret;
}
static int pp_pa_cache_params_v1_7(struct mdp_pa_v2_cfg_data *config,
struct mdss_pp_res_type *mdss_pp_res)
{
struct mdss_pp_res_type_v1_7 *res_cache;
struct mdp_pa_data_v1_7 *pa_cache_data, pa_usr_config;
int disp_num, ret = 0;
if (!config || !mdss_pp_res) {
pr_err("Invalid param config %p pp_res %p\n",
config, mdss_pp_res);
return -EINVAL;
}
if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
(config->block >= MDP_BLOCK_MAX)) {
pr_err("Invalid config block %d\n", config->block);
return -EINVAL;
}
if (!mdss_pp_res->pp_data_res) {
pr_err("Invalid pp_data_res %p\n", mdss_pp_res->pp_data_res);
return -EINVAL;
}
res_cache = mdss_pp_res->pp_data_res;
if (config->flags & MDP_PP_OPS_READ) {
pr_err("Read op is not supported\n");
return -EINVAL;
}
disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
mdss_pp_res->pa_v2_disp_cfg[disp_num] = *config;
pa_cache_data = &res_cache->pa_v17_data[disp_num];
mdss_pp_res->pa_v2_disp_cfg[disp_num].cfg_payload =
(void *) pa_cache_data;
if (copy_from_user(&pa_usr_config, config->cfg_payload,
sizeof(pa_usr_config))) {
pr_err("Failed to copy v1_7 PA\n");
ret = -EFAULT;
goto pa_config_exit;
}
if ((config->flags & MDP_PP_OPS_DISABLE)) {
pr_debug("Disable PA\n");
ret = 0;
goto pa_config_exit;
}
if (!(config->flags & MDP_PP_OPS_WRITE)) {
pr_debug("op for PA %d\n", config->flags);
ret = 0;
goto pa_config_exit;
}
memcpy(pa_cache_data, &pa_usr_config, sizeof(pa_usr_config));
/* Copy six zone LUT if six zone is enabled to be written */
if (config->flags & MDP_PP_PA_SIX_ZONE_ENABLE) {
if (pa_usr_config.six_zone_len != MDP_SIX_ZONE_LUT_SIZE) {
pr_err("Invalid six zone size, actual %d max %d\n",
pa_usr_config.six_zone_len,
MDP_SIX_ZONE_LUT_SIZE);
ret = -EINVAL;
goto pa_config_exit;
}
ret = copy_from_user(&res_cache->six_zone_lut_p0[disp_num][0],
pa_usr_config.six_zone_curve_p0,
pa_usr_config.six_zone_len * sizeof(u32));
if (ret) {
pr_err("copying six_zone_curve_p0 lut from userspace failed size %zd ret %d\n",
(sizeof(u32) * pa_usr_config.six_zone_len),
ret);
ret = -EFAULT;
goto pa_config_exit;
}
pa_cache_data->six_zone_curve_p0 =
&res_cache->six_zone_lut_p0[disp_num][0];
ret = copy_from_user(&res_cache->six_zone_lut_p1[disp_num][0],
pa_usr_config.six_zone_curve_p1,
pa_usr_config.six_zone_len * sizeof(u32));
if (ret) {
pr_err("copying six_zone_curve_p1 lut from userspace failed size %zd ret %d\n",
(sizeof(u32) * pa_usr_config.six_zone_len),
ret);
ret = -EFAULT;
goto pa_config_exit;
}
pa_cache_data->six_zone_curve_p1 =
&res_cache->six_zone_lut_p1[disp_num][0];
}
pa_config_exit:
if (ret || config->flags & MDP_PP_OPS_DISABLE) {
pa_cache_data->six_zone_len = 0;
pa_cache_data->six_zone_curve_p0 = NULL;
pa_cache_data->six_zone_curve_p1 = NULL;
}
return ret;
}
int pp_pa_cache_params(struct mdp_pa_v2_cfg_data *config,
struct mdss_pp_res_type *mdss_pp_res)
{
int ret = 0;
if (!config || !mdss_pp_res) {
pr_err("invalid param config %p pp_res %p\n",
config, mdss_pp_res);
return -EINVAL;
}
switch (config->version) {
case mdp_pa_v1_7:
ret = pp_pa_cache_params_v1_7(config, mdss_pp_res);
break;
default:
pr_err("unsupported pa version %d\n",
config->version);
ret = -EINVAL;
break;
}
return ret;
}

View file

@ -26,6 +26,8 @@ int pp_gamut_cache_params(struct mdp_gamut_cfg_data *config,
struct mdss_pp_res_type *mdss_pp_res);
int pp_pcc_cache_params(struct mdp_pcc_cfg_data *config,
struct mdss_pp_res_type *mdss_pp_res);
int pp_pa_cache_params(struct mdp_pa_v2_cfg_data *config,
struct mdss_pp_res_type *mdss_pp_res);
int pp_igc_lut_cache_params(struct mdp_igc_lut_data *config,
struct mdss_pp_res_type *mdss_pp_res,

View file

@ -92,6 +92,67 @@ static u32 dither_matrix[DITHER_MATRIX_INDEX] = {
static u32 dither_depth_map[DITHER_DEPTH_MAP_INDEX] = {
0, 0, 0, 0, 0, 1, 2, 3, 3};
#define PA_DSPP_GLOBAL_OFF 0x238
#define PA_DSPP_MEM_COL_SKIN_P0_OFF 0x254
#define PA_DSPP_MEM_COL_SKIN_P2_OFF 0x318
#define PA_DSPP_MEM_COL_SKY_P0_OFF 0x268
#define PA_DSPP_MEM_COL_SKY_P2_OFF 0x320
#define PA_DSPP_MEM_COL_FOL_P0_OFF 0x27C
#define PA_DSPP_MEM_COL_FOL_P2_OFF 0x328
#define PA_SIX_ZONE_LUT_OFF 0x248
#define PA_SIX_ZONE_REGION_OFF 0x250
#define PA_SIX_ZONE_ADJ_OFF 0x330
#define PA_VIG_GLOBAL_OFF 0x310
#define PA_VIG_MEM_COL_SKIN_P0_OFF 0x288
#define PA_VIG_MEM_COL_SKIN_P2_OFF 0x418
#define PA_VIG_MEM_COL_SKY_P0_OFF 0x29C
#define PA_VIG_MEM_COL_SKY_P2_OFF 0x420
#define PA_VIG_MEM_COL_FOL_P0_OFF 0x2B0
#define PA_VIG_MEM_COL_FOL_P2_OFF 0x428
#define PA_DSPP_HOLD_OFF 0x314
#define PA_VIG_HOLD_OFF 0x414
#define PA_GLOBAL_HUE_MASK 0xFFF
#define PA_GLOBAL_SAT_MASK 0xFFFF
#define PA_GLOBAL_VAL_MASK 0xFF
#define PA_GLOBAL_CONT_MASK 0xFF
#define PA_MEM_COL_ADJ_P0_MASK 0xFFFF07FF
#define PA_MEM_COL_HUE_REGION_MASK 0x7FF07FF
#define PA_MEM_COL_SAT_REGION_MASK 0xFFFFFF
#define PA_MEM_COL_VAL_REGION_MASK 0xFFFFFF
#define PA_SIX_ZONE_INDEX_UPDATE BIT(26)
#define PA_SIX_ZONE_VALUE_UPDATE BIT(25)
#define PA_SIX_ZONE_CURVE_MASK 0xFFF
#define PA_SIX_ZONE_ADJ_P0_MASK 0xFFFF
#define PA_HOLD_MASK 0x3
#define PA_HOLD_SAT_SHIFT 0
#define PA_HOLD_VAL_SHIFT 2
#define PA_HOLD_SKIN_SHIFT 0
#define PA_HOLD_SKY_SHIFT 4
#define PA_HOLD_FOL_SHIFT 8
#define PA_HOLD_SIX_ZONE_SHIFT 12
#define PA_HOLD_SKIN_MASK 0xF
#define PA_HOLD_SKY_MASK 0xF0
#define PA_HOLD_FOL_MASK 0xF00
#define PA_HOLD_SIX_ZONE_MASK 0xF000
#define PA_DSPP_OP_ENABLE BIT(20)
#define PA_DSPP_OP_HUE_MASK BIT(25)
#define PA_DSPP_OP_SAT_MASK BIT(26)
#define PA_DSPP_OP_VAL_MASK BIT(27)
#define PA_DSPP_OP_CONT_MASK BIT(28)
#define PA_DSPP_OP_SAT_ZERO_EXP_EN BIT(1)
#define PA_DSPP_OP_SIX_ZONE_HUE_MASK BIT(29)
#define PA_DSPP_OP_SIX_ZONE_SAT_MASK BIT(30)
#define PA_DSPP_OP_SIX_ZONE_VAL_MASK BIT(31)
#define PA_DSPP_OP_MEM_COL_SKIN_MASK BIT(5)
#define PA_DSPP_OP_MEM_COL_FOL_MASK BIT(6)
#define PA_DSPP_OP_MEM_COL_SKY_MASK BIT(7)
#define PA_DSPP_OP_MEM_PROT_HUE_EN BIT(22)
#define PA_DSPP_OP_MEM_PROT_SAT_EN BIT(23)
#define PA_DSPP_OP_MEM_PROT_VAL_EN BIT(24)
#define PA_DSPP_OP_MEM_PROT_CONT_EN BIT(18)
#define PA_DSPP_OP_MEM_PROT_BLEND_EN BIT(3)
#define PA_DSPP_OP_MEM_PROT_SIX_EN BIT(17)
static struct mdss_pp_res_type_v1_7 config_data;
static int pp_hist_lut_get_config(char __iomem *base_addr, void *cfg_data,
@ -123,6 +184,13 @@ static int pp_pcc_set_config(char __iomem *base_addr,
u32 block_type);
static int pp_pcc_get_config(char __iomem *base_addr, void *cfg_data,
u32 block_type, u32 disp_num);
/* PA prototypes */
static int pp_pa_set_config(char __iomem *base_addr,
struct pp_sts_type *pp_sts, void *cfg_data,
u32 block_type);
static int pp_pa_get_config(char __iomem *base_addr, void *cfg_data,
u32 block_type, u32 disp_num);
static void pp_pa_update_dspp_opmode(int pa_sts, u32 *opmode);
static int pp_igc_set_config(char __iomem *base_addr,
struct pp_sts_type *pp_sts, void *cfg_data,
@ -155,8 +223,8 @@ void *pp_get_driver_ops(struct mdp_pp_driver_ops *ops)
ops->pp_ops[GC].pp_get_config = pp_pgc_get_config;
/* PA ops */
ops->pp_ops[PA].pp_set_config = NULL;
ops->pp_ops[PA].pp_get_config = NULL;
ops->pp_ops[PA].pp_set_config = pp_pa_set_config;
ops->pp_ops[PA].pp_get_config = pp_pa_get_config;
/* Gamut ops */
ops->pp_ops[GAMUT].pp_set_config = pp_gamut_set_config;
@ -203,6 +271,8 @@ static void pp_opmode_config(int location, struct pp_sts_type *pp_sts,
case SSPP_VIG:
break;
case DSPP:
if (pp_sts_is_enabled(pp_sts->pa_sts, side))
pp_pa_update_dspp_opmode(pp_sts->pa_sts, opmode);
if (pp_sts_is_enabled(pp_sts->igc_sts, side))
*opmode |= IGC_DSPP_OP_MODE_EN;
if (pp_sts->enhist_sts & PP_STS_ENABLE) {
@ -889,6 +959,614 @@ static int pp_pcc_get_config(char __iomem *base_addr, void *cfg_data,
return 0;
}
static inline void pp_pa_set_global_adj_regs(char __iomem *base_addr,
struct mdp_pa_data_v1_7 *pa_data, u32 flags,
int block_type)
{
char __iomem *addr = NULL;
if (block_type == DSPP)
addr = base_addr + PA_DSPP_GLOBAL_OFF;
else
addr = base_addr + PA_VIG_GLOBAL_OFF;
if (flags & MDP_PP_PA_HUE_ENABLE)
writel_relaxed((pa_data->global_hue_adj &
PA_GLOBAL_HUE_MASK), addr);
addr += 4;
if (flags & MDP_PP_PA_SAT_ENABLE)
writel_relaxed((pa_data->global_sat_adj &
PA_GLOBAL_SAT_MASK), addr);
addr += 4;
if (flags & MDP_PP_PA_VAL_ENABLE)
writel_relaxed((pa_data->global_val_adj &
PA_GLOBAL_VAL_MASK), addr);
addr += 4;
if (flags & MDP_PP_PA_CONT_ENABLE)
writel_relaxed((pa_data->global_cont_adj &
PA_GLOBAL_CONT_MASK), addr);
}
static void pp_pa_set_mem_col_regs(char __iomem *mem_col_p0_addr,
char __iomem *mem_col_p2_addr,
struct mdp_pa_mem_col_data_v1_7 *mem_col_data)
{
writel_relaxed((mem_col_data->color_adjust_p0 &
PA_MEM_COL_ADJ_P0_MASK), mem_col_p0_addr);
mem_col_p0_addr += 4;
writel_relaxed(mem_col_data->color_adjust_p1, mem_col_p0_addr);
mem_col_p0_addr += 4;
writel_relaxed((mem_col_data->hue_region &
PA_MEM_COL_HUE_REGION_MASK), mem_col_p0_addr);
mem_col_p0_addr += 4;
writel_relaxed((mem_col_data->sat_region &
PA_MEM_COL_SAT_REGION_MASK), mem_col_p0_addr);
mem_col_p0_addr += 4;
writel_relaxed((mem_col_data->val_region &
PA_MEM_COL_VAL_REGION_MASK), mem_col_p0_addr);
writel_relaxed(mem_col_data->color_adjust_p2, mem_col_p2_addr);
mem_col_p2_addr += 4;
writel_relaxed(mem_col_data->blend_gain, mem_col_p2_addr);
}
static void pp_pa_set_mem_col(char __iomem *base_addr,
struct mdp_pa_data_v1_7 *pa_data, u32 flags,
int block_type, uint32_t *pa_hold,
uint32_t *pa_hold_mask)
{
uint32_t sat_hold = 0, val_hold = 0, mem_col_hold = 0;
u32 skin_p0_off = 0, skin_p2_off = 0;
u32 sky_p0_off = 0, sky_p2_off = 0;
u32 fol_p0_off = 0, fol_p2_off = 0;
char __iomem *mem_col_p0_addr = NULL;
char __iomem *mem_col_p2_addr = NULL;
if (block_type == DSPP) {
skin_p0_off = PA_DSPP_MEM_COL_SKIN_P0_OFF;
skin_p2_off = PA_DSPP_MEM_COL_SKIN_P2_OFF;
sky_p0_off = PA_DSPP_MEM_COL_SKY_P0_OFF;
sky_p2_off = PA_DSPP_MEM_COL_SKY_P2_OFF;
fol_p0_off = PA_DSPP_MEM_COL_FOL_P0_OFF;
fol_p2_off = PA_DSPP_MEM_COL_FOL_P2_OFF;
} else {
skin_p0_off = PA_VIG_MEM_COL_SKIN_P0_OFF;
skin_p2_off = PA_VIG_MEM_COL_SKIN_P2_OFF;
sky_p0_off = PA_VIG_MEM_COL_SKY_P0_OFF;
sky_p2_off = PA_VIG_MEM_COL_SKY_P2_OFF;
fol_p0_off = PA_VIG_MEM_COL_FOL_P0_OFF;
fol_p2_off = PA_VIG_MEM_COL_FOL_P2_OFF;
}
/* Update skin zone memory color registers */
if (flags & MDP_PP_PA_SKIN_ENABLE) {
mem_col_p0_addr = base_addr + skin_p0_off;
mem_col_p2_addr = base_addr + skin_p2_off;
pp_pa_set_mem_col_regs(mem_col_p0_addr, mem_col_p2_addr,
&pa_data->skin_cfg);
sat_hold = (pa_data->skin_cfg.sat_hold & PA_HOLD_MASK) <<
PA_HOLD_SAT_SHIFT;
val_hold = (pa_data->skin_cfg.val_hold & PA_HOLD_MASK) <<
PA_HOLD_VAL_SHIFT;
mem_col_hold = (sat_hold | val_hold) << PA_HOLD_SKIN_SHIFT;
*pa_hold |= mem_col_hold;
*pa_hold_mask |= PA_HOLD_SKIN_MASK;
}
/* Update sky zone memory color registers */
if (flags & MDP_PP_PA_SKY_ENABLE) {
mem_col_p0_addr = base_addr + sky_p0_off;
mem_col_p2_addr = base_addr + sky_p2_off;
pp_pa_set_mem_col_regs(mem_col_p0_addr, mem_col_p2_addr,
&pa_data->sky_cfg);
sat_hold = (pa_data->sky_cfg.sat_hold & PA_HOLD_MASK) <<
PA_HOLD_SAT_SHIFT;
val_hold = (pa_data->sky_cfg.val_hold & PA_HOLD_MASK) <<
PA_HOLD_VAL_SHIFT;
mem_col_hold = (sat_hold | val_hold) << PA_HOLD_SKY_SHIFT;
*pa_hold |= mem_col_hold;
*pa_hold_mask |= PA_HOLD_SKY_MASK;
}
/* Update foliage zone memory color registers */
if (flags & MDP_PP_PA_FOL_ENABLE) {
mem_col_p0_addr = base_addr + fol_p0_off;
mem_col_p2_addr = base_addr + fol_p2_off;
pp_pa_set_mem_col_regs(mem_col_p0_addr, mem_col_p2_addr,
&pa_data->fol_cfg);
sat_hold = (pa_data->fol_cfg.sat_hold & PA_HOLD_MASK) <<
PA_HOLD_SAT_SHIFT;
val_hold = (pa_data->fol_cfg.val_hold & PA_HOLD_MASK) <<
PA_HOLD_VAL_SHIFT;
mem_col_hold = (sat_hold | val_hold) << PA_HOLD_FOL_SHIFT;
*pa_hold |= mem_col_hold;
*pa_hold_mask |= PA_HOLD_FOL_MASK;
}
}
static void pp_pa_set_six_zone(char __iomem *base_addr,
struct mdp_pa_data_v1_7 *pa_data,
u32 flags,
uint32_t *pa_hold,
uint32_t *pa_hold_mask)
{
u32 data, i;
char __iomem *addr = base_addr + PA_SIX_ZONE_LUT_OFF;
uint32_t sat_hold = 0, val_hold = 0, mem_col_hold = 0;
/* Update six zone memory color registers */
if (flags & MDP_PP_PA_SIX_ZONE_ENABLE) {
if (!pa_data->six_zone_len || !pa_data->six_zone_curve_p0 ||
!pa_data->six_zone_curve_p1) {
pr_err("Invalid six zone data: len %d curve_p0 %p curve_p1 %p\n",
pa_data->six_zone_len,
pa_data->six_zone_curve_p0,
pa_data->six_zone_curve_p1);
return;
}
writel_relaxed((pa_data->six_zone_curve_p1[0] &
PA_SIX_ZONE_CURVE_MASK), addr + 4);
/* Index Update to trigger auto-incrementing LUT accesses */
data = PA_SIX_ZONE_INDEX_UPDATE;
writel_relaxed((pa_data->six_zone_curve_p0[0] &
PA_SIX_ZONE_CURVE_MASK) | data, addr);
/* Remove Index Update */
for (i = 1; i < MDP_SIX_ZONE_LUT_SIZE; i++) {
writel_relaxed((pa_data->six_zone_curve_p1[i] &
PA_SIX_ZONE_CURVE_MASK), addr + 4);
writel_relaxed((pa_data->six_zone_curve_p0[i] &
PA_SIX_ZONE_CURVE_MASK), addr);
}
addr = base_addr + PA_SIX_ZONE_REGION_OFF;
writel_relaxed(pa_data->six_zone_thresh, addr);
addr = base_addr + PA_SIX_ZONE_ADJ_OFF;
writel_relaxed((pa_data->six_zone_adj_p0 &
PA_SIX_ZONE_ADJ_P0_MASK), addr);
addr += 4;
writel_relaxed(pa_data->six_zone_adj_p1, addr);
sat_hold = (pa_data->six_zone_sat_hold & PA_HOLD_MASK) <<
PA_HOLD_SAT_SHIFT;
val_hold = (pa_data->six_zone_val_hold & PA_HOLD_MASK) <<
PA_HOLD_VAL_SHIFT;
mem_col_hold = (sat_hold | val_hold) << PA_HOLD_SIX_ZONE_SHIFT;
*pa_hold |= mem_col_hold;
*pa_hold_mask |= PA_HOLD_SIX_ZONE_MASK;
}
}
static void pp_pa_set_sts(struct pp_sts_type *pp_sts,
struct mdp_pa_data_v1_7 *pa_data,
int enable_flag,
int block_type)
{
pp_sts->pa_sts = 0;
if (enable_flag & MDP_PP_OPS_ENABLE)
pp_sts->pa_sts |= PP_STS_ENABLE;
else if (enable_flag & MDP_PP_OPS_DISABLE) {
pp_sts->pa_sts &= ~PP_STS_ENABLE;
if (block_type == DSPP)
pp_sts_set_split_bits(&pp_sts->pa_sts, enable_flag);
return;
}
/* Global HSV STS update */
if (pa_data->mode & MDP_PP_PA_HUE_MASK)
pp_sts->pa_sts |= PP_STS_PA_HUE_MASK;
if (pa_data->mode & MDP_PP_PA_SAT_MASK)
pp_sts->pa_sts |= PP_STS_PA_SAT_MASK;
if (pa_data->mode & MDP_PP_PA_VAL_MASK)
pp_sts->pa_sts |= PP_STS_PA_VAL_MASK;
if (pa_data->mode & MDP_PP_PA_CONT_MASK)
pp_sts->pa_sts |= PP_STS_PA_CONT_MASK;
if (pa_data->mode & MDP_PP_PA_SAT_ZERO_EXP_EN)
pp_sts->pa_sts |= PP_STS_PA_SAT_ZERO_EXP_EN;
/* Memory Protect STS update */
if (pa_data->mode & MDP_PP_PA_MEM_PROT_HUE_EN)
pp_sts->pa_sts |= PP_STS_PA_MEM_PROT_HUE_EN;
if (pa_data->mode & MDP_PP_PA_MEM_PROT_SAT_EN)
pp_sts->pa_sts |= PP_STS_PA_MEM_PROT_SAT_EN;
if (pa_data->mode & MDP_PP_PA_MEM_PROT_VAL_EN)
pp_sts->pa_sts |= PP_STS_PA_MEM_PROT_VAL_EN;
if (pa_data->mode & MDP_PP_PA_MEM_PROT_CONT_EN)
pp_sts->pa_sts |= PP_STS_PA_MEM_PROT_CONT_EN;
if (pa_data->mode & MDP_PP_PA_MEM_PROT_BLEND_EN)
pp_sts->pa_sts |= PP_STS_PA_MEM_PROT_BLEND_EN;
if ((block_type == DSPP) &&
(pa_data->mode & MDP_PP_PA_MEM_PROT_SIX_EN))
pp_sts->pa_sts |= PP_STS_PA_MEM_PROT_SIX_EN;
/* Memory Color STS update */
if (pa_data->mode & MDP_PP_PA_MEM_COL_SKIN_MASK)
pp_sts->pa_sts |= PP_STS_PA_MEM_COL_SKIN_MASK;
if (pa_data->mode & MDP_PP_PA_MEM_COL_SKY_MASK)
pp_sts->pa_sts |= PP_STS_PA_MEM_COL_SKY_MASK;
if (pa_data->mode & MDP_PP_PA_MEM_COL_FOL_MASK)
pp_sts->pa_sts |= PP_STS_PA_MEM_COL_FOL_MASK;
/* Six Zone STS update */
if (block_type == DSPP) {
if (pa_data->mode & MDP_PP_PA_SIX_ZONE_HUE_MASK)
pp_sts->pa_sts |= PP_STS_PA_SIX_ZONE_HUE_MASK;
if (pa_data->mode & MDP_PP_PA_SIX_ZONE_SAT_MASK)
pp_sts->pa_sts |= PP_STS_PA_SIX_ZONE_SAT_MASK;
if (pa_data->mode & MDP_PP_PA_SIX_ZONE_VAL_MASK)
pp_sts->pa_sts |= PP_STS_PA_SIX_ZONE_VAL_MASK;
pp_sts_set_split_bits(&pp_sts->pa_sts, enable_flag);
}
}
static int pp_pa_set_config(char __iomem *base_addr,
struct pp_sts_type *pp_sts, void *cfg_data,
u32 block_type)
{
struct mdp_pa_v2_cfg_data *pa_cfg_data = NULL;
struct mdp_pa_data_v1_7 *pa_data = NULL;
uint32_t pa_hold = 0, pa_hold_mask = 0, pa_hold_tmp;
char __iomem *pa_hold_addr = NULL;
int ret = 0;
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 != DSPP) && (block_type != SSPP_VIG)) {
pr_err("Invalid block type %d\n", block_type);
return -EINVAL;
}
pa_cfg_data = (struct mdp_pa_v2_cfg_data *) cfg_data;
if (pa_cfg_data->version != mdp_pa_v1_7) {
pr_err("invalid pa version %d\n", pa_cfg_data->version);
return -EINVAL;
}
if (!(pa_cfg_data->flags & ~(MDP_PP_OPS_READ))) {
pr_info("only read ops is set %d", pa_cfg_data->flags);
return 0;
}
pa_data = pa_cfg_data->cfg_payload;
if (!pa_data) {
pr_err("invalid payload for pa %p\n", pa_data);
return -EINVAL;
}
if (!(pa_cfg_data->flags & MDP_PP_OPS_WRITE)) {
pr_warn("No write flag enabled for PA flags %d\n",
pa_cfg_data->flags);
return 0;
}
pp_pa_set_global_adj_regs(base_addr, pa_data, pa_cfg_data->flags,
block_type);
pp_pa_set_mem_col(base_addr, pa_data, pa_cfg_data->flags,
block_type, &pa_hold, &pa_hold_mask);
if (block_type == DSPP)
pp_pa_set_six_zone(base_addr, pa_data, pa_cfg_data->flags,
&pa_hold, &pa_hold_mask);
/*
* Only modify the PA hold bits for PA features that have
* been updated.
*/
if (block_type == DSPP)
pa_hold_addr = base_addr + PA_DSPP_HOLD_OFF;
else
pa_hold_addr = base_addr + PA_VIG_HOLD_OFF;
pa_hold_tmp = readl_relaxed(pa_hold_addr);
pa_hold_tmp &= ~pa_hold_mask;
pa_hold |= pa_hold_tmp;
writel_relaxed(pa_hold, pa_hold_addr);
pp_pa_set_sts(pp_sts, pa_data, pa_cfg_data->flags, block_type);
return ret;
}
static inline void pp_pa_get_global_adj_regs(char __iomem *base_addr,
struct mdp_pa_data_v1_7 *pa_data, u32 flags,
int block_type)
{
char __iomem *addr = NULL;
if (block_type == DSPP)
addr = base_addr + PA_DSPP_GLOBAL_OFF;
else
addr = base_addr + PA_VIG_GLOBAL_OFF;
if (flags & MDP_PP_PA_HUE_ENABLE)
pa_data->global_hue_adj = readl_relaxed(addr) &
PA_GLOBAL_HUE_MASK;
addr += 4;
if (flags & MDP_PP_PA_SAT_ENABLE)
pa_data->global_sat_adj = readl_relaxed(addr) &
PA_GLOBAL_SAT_MASK;
addr += 4;
if (flags & MDP_PP_PA_VAL_ENABLE)
pa_data->global_val_adj = readl_relaxed(addr) &
PA_GLOBAL_VAL_MASK;
addr += 4;
if (flags & MDP_PP_PA_CONT_ENABLE)
pa_data->global_cont_adj = readl_relaxed(addr) &
PA_GLOBAL_CONT_MASK;
}
static inline void pp_pa_get_mem_col_regs(char __iomem *mem_col_p0_addr,
char __iomem *mem_col_p2_addr,
struct mdp_pa_mem_col_data_v1_7 *mem_col_data)
{
mem_col_data->color_adjust_p0 = readl_relaxed(mem_col_p0_addr) &
PA_MEM_COL_ADJ_P0_MASK;
mem_col_p0_addr += 4;
mem_col_data->color_adjust_p1 = readl_relaxed(mem_col_p0_addr);
mem_col_p0_addr += 4;
mem_col_data->hue_region = readl_relaxed(mem_col_p0_addr) &
PA_MEM_COL_HUE_REGION_MASK;
mem_col_p0_addr += 4;
mem_col_data->sat_region = readl_relaxed(mem_col_p0_addr) &
PA_MEM_COL_SAT_REGION_MASK;
mem_col_p0_addr += 4;
mem_col_data->val_region = readl_relaxed(mem_col_p0_addr) &
PA_MEM_COL_VAL_REGION_MASK;
mem_col_data->color_adjust_p2 = readl_relaxed(mem_col_p2_addr);
mem_col_p2_addr += 4;
mem_col_data->blend_gain = readl_relaxed(mem_col_p2_addr);
}
static inline void pp_pa_get_mem_col(char __iomem *base_addr,
struct mdp_pa_data_v1_7 *pa_data, u32 flags,
int block_type,
uint32_t pa_hold)
{
uint32_t mem_col_hold = 0;
u32 skin_p0_off = 0, skin_p2_off = 0;
u32 sky_p0_off = 0, sky_p2_off = 0;
u32 fol_p0_off = 0, fol_p2_off = 0;
char __iomem *mem_col_p0_addr = NULL;
char __iomem *mem_col_p2_addr = NULL;
if (block_type == DSPP) {
skin_p0_off = PA_DSPP_MEM_COL_SKIN_P0_OFF;
skin_p2_off = PA_DSPP_MEM_COL_SKIN_P2_OFF;
sky_p0_off = PA_DSPP_MEM_COL_SKY_P0_OFF;
sky_p2_off = PA_DSPP_MEM_COL_SKY_P2_OFF;
fol_p0_off = PA_DSPP_MEM_COL_FOL_P0_OFF;
fol_p2_off = PA_DSPP_MEM_COL_FOL_P2_OFF;
} else {
skin_p0_off = PA_VIG_MEM_COL_SKIN_P0_OFF;
skin_p2_off = PA_VIG_MEM_COL_SKIN_P2_OFF;
sky_p0_off = PA_VIG_MEM_COL_SKY_P0_OFF;
sky_p2_off = PA_VIG_MEM_COL_SKY_P2_OFF;
fol_p0_off = PA_VIG_MEM_COL_FOL_P0_OFF;
fol_p2_off = PA_VIG_MEM_COL_FOL_P2_OFF;
}
/* Update skin zone memory color registers */
if (flags & MDP_PP_PA_SKIN_ENABLE) {
mem_col_p0_addr = base_addr + skin_p0_off;
mem_col_p2_addr = base_addr + skin_p2_off;
pp_pa_get_mem_col_regs(mem_col_p0_addr, mem_col_p2_addr,
&pa_data->skin_cfg);
mem_col_hold = pa_hold >> PA_HOLD_SKIN_SHIFT;
pa_data->skin_cfg.sat_hold = (mem_col_hold >>
PA_HOLD_SAT_SHIFT) & PA_HOLD_MASK;
pa_data->skin_cfg.val_hold = (mem_col_hold >>
PA_HOLD_VAL_SHIFT) & PA_HOLD_MASK;
}
/* Update sky zone memory color registers */
if (flags & MDP_PP_PA_SKY_ENABLE) {
mem_col_p0_addr = base_addr + sky_p0_off;
mem_col_p2_addr = base_addr + sky_p2_off;
pp_pa_get_mem_col_regs(mem_col_p0_addr, mem_col_p2_addr,
&pa_data->sky_cfg);
mem_col_hold = pa_hold >> PA_HOLD_SKY_SHIFT;
pa_data->sky_cfg.sat_hold = (mem_col_hold >>
PA_HOLD_SAT_SHIFT) & PA_HOLD_MASK;
pa_data->sky_cfg.val_hold = (mem_col_hold >>
PA_HOLD_VAL_SHIFT) & PA_HOLD_MASK;
}
/* Update foliage zone memory color registers */
if (flags & MDP_PP_PA_FOL_ENABLE) {
mem_col_p0_addr = base_addr + fol_p0_off;
mem_col_p2_addr = base_addr + fol_p2_off;
pp_pa_get_mem_col_regs(mem_col_p0_addr, mem_col_p2_addr,
&pa_data->fol_cfg);
mem_col_hold = pa_hold >> PA_HOLD_FOL_SHIFT;
pa_data->sky_cfg.sat_hold = (mem_col_hold >>
PA_HOLD_SAT_SHIFT) & PA_HOLD_MASK;
pa_data->sky_cfg.val_hold = (mem_col_hold >>
PA_HOLD_VAL_SHIFT) & PA_HOLD_MASK;
}
}
static inline int pp_pa_get_six_zone(char __iomem *base_addr,
struct mdp_pa_data_v1_7 *pa_data, u32 flags,
u32 pa_hold)
{
uint32_t six_zone_sz = 0, six_zone_buf_sz = 0;
u32 data = 0;
char __iomem *addr = base_addr + PA_SIX_ZONE_LUT_OFF;
uint32_t *six_zone_read_buf = NULL;
uint32_t *six_zone_p0 = NULL, *six_zone_p1 = NULL;
uint32_t six_zone_hold = 0;
int ret = 0, i;
if (pa_data->six_zone_len != MDP_SIX_ZONE_LUT_SIZE) {
pr_err("Invalid six zone length %d\n",
pa_data->six_zone_len);
return -EINVAL;
}
six_zone_sz = pa_data->six_zone_len * sizeof(uint32_t);
if (!access_ok(VERIFY_WRITE, pa_data->six_zone_curve_p0,
six_zone_sz)) {
pr_err("invalid six_zone_curve_p0 addr for sz %d\n",
six_zone_sz);
return -EFAULT;
}
if (!access_ok(VERIFY_WRITE, pa_data->six_zone_curve_p1,
six_zone_sz)) {
pr_err("invalid six_zone_curve_p1 addr for sz %d\n",
six_zone_sz);
return -EFAULT;
}
six_zone_buf_sz = 2 * six_zone_sz;
six_zone_read_buf = kzalloc(six_zone_buf_sz, GFP_KERNEL);
if (!six_zone_read_buf) {
pr_err("allocation failed for six zone lut size %d\n",
six_zone_buf_sz);
ret = -ENOMEM;
goto six_zone_exit;
}
six_zone_p0 = six_zone_read_buf;
six_zone_p1 = &six_zone_read_buf[MDP_SIX_ZONE_LUT_SIZE];
data = PA_SIX_ZONE_VALUE_UPDATE | PA_SIX_ZONE_INDEX_UPDATE;
writel_relaxed(data, addr);
for (i = 0; i < MDP_SIX_ZONE_LUT_SIZE; i++) {
six_zone_p1[i] = readl_relaxed(addr + 4) &
PA_SIX_ZONE_CURVE_MASK;
six_zone_p0[i] = readl_relaxed(addr) &
PA_SIX_ZONE_CURVE_MASK;
}
addr = base_addr + PA_SIX_ZONE_REGION_OFF;
pa_data->six_zone_thresh = readl_relaxed(addr);
addr = base_addr + PA_SIX_ZONE_ADJ_OFF;
pa_data->six_zone_adj_p0 = readl_relaxed(addr) &
PA_SIX_ZONE_ADJ_P0_MASK;
addr += 4;
pa_data->six_zone_adj_p1 = readl_relaxed(addr);
if (copy_to_user(pa_data->six_zone_curve_p0, six_zone_p0,
six_zone_sz)) {
pr_err("Failed to copy six zone p0 data\n");
ret = -EFAULT;
goto six_zone_memory_exit;
}
if (copy_to_user(pa_data->six_zone_curve_p1, six_zone_p1,
six_zone_sz)) {
pr_err("Failed to copy six zone p1 data\n");
ret = -EFAULT;
goto six_zone_memory_exit;
}
six_zone_hold = pa_hold >> PA_HOLD_SIX_ZONE_SHIFT;
pa_data->six_zone_sat_hold = (six_zone_hold >> PA_HOLD_SAT_SHIFT) &
PA_HOLD_MASK;
pa_data->six_zone_val_hold = (six_zone_hold >> PA_HOLD_VAL_SHIFT) &
PA_HOLD_MASK;
six_zone_memory_exit:
kfree(six_zone_read_buf);
six_zone_exit:
return ret;
}
static int pp_pa_get_config(char __iomem *base_addr, void *cfg_data,
u32 block_type, u32 disp_num)
{
struct mdp_pa_v2_cfg_data *pa_cfg_data = NULL;
struct mdp_pa_data_v1_7 pa_data;
int ret = 0;
uint32_t pa_hold = 0;
char __iomem *pa_hold_addr = NULL;
if (!base_addr || !cfg_data) {
pr_err("invalid params base_addr %p cfg_data %p\n",
base_addr, cfg_data);
return -EINVAL;
}
if ((block_type != DSPP) && (block_type != SSPP_VIG)) {
pr_err("Invalid block type %d\n", block_type);
return -EINVAL;
}
pa_cfg_data = (struct mdp_pa_v2_cfg_data *) cfg_data;
if (pa_cfg_data->version != mdp_pa_v1_7) {
pr_err("invalid pa version %d\n", pa_cfg_data->version);
return -EINVAL;
}
if (copy_from_user(&pa_data, pa_cfg_data->cfg_payload,
sizeof(pa_data))) {
pr_err("copy from user failed for pa data\n");
return -EFAULT;
}
if (block_type == DSPP)
pa_hold_addr = base_addr + PA_DSPP_HOLD_OFF;
else
pa_hold_addr = base_addr + PA_VIG_HOLD_OFF;
pa_hold = readl_relaxed(pa_hold_addr);
if ((block_type == DSPP) &&
(pa_cfg_data->flags & MDP_PP_PA_SIX_ZONE_ENABLE)) {
ret = pp_pa_get_six_zone(base_addr,
&pa_data,
pa_cfg_data->flags,
pa_hold);
if (ret) {
pr_err("six zone read failed ret %d\n", ret);
return ret;
}
}
pp_pa_get_global_adj_regs(base_addr, &pa_data, pa_cfg_data->flags,
block_type);
pp_pa_get_mem_col(base_addr, &pa_data, pa_cfg_data->flags,
block_type, pa_hold);
ret = copy_to_user(pa_cfg_data->cfg_payload, &pa_data, sizeof(pa_data));
if (ret) {
pr_err("Failed to copy PA data to user\n");
return -EFAULT;
}
return 0;
}
static void pp_pa_update_dspp_opmode(int pa_sts, u32 *opmode)
{
*opmode |= PA_DSPP_OP_ENABLE;
if (pa_sts & PP_STS_PA_HUE_MASK)
*opmode |= PA_DSPP_OP_HUE_MASK;
if (pa_sts & PP_STS_PA_SAT_MASK)
*opmode |= PA_DSPP_OP_SAT_MASK;
if (pa_sts & PP_STS_PA_VAL_MASK)
*opmode |= PA_DSPP_OP_VAL_MASK;
if (pa_sts & PP_STS_PA_CONT_MASK)
*opmode |= PA_DSPP_OP_CONT_MASK;
if (pa_sts & PP_STS_PA_SAT_ZERO_EXP_EN)
*opmode |= PA_DSPP_OP_SAT_ZERO_EXP_EN;
if (pa_sts & PP_STS_PA_MEM_COL_SKIN_MASK)
*opmode |= PA_DSPP_OP_MEM_COL_SKIN_MASK;
if (pa_sts & PP_STS_PA_MEM_COL_FOL_MASK)
*opmode |= PA_DSPP_OP_MEM_COL_FOL_MASK;
if (pa_sts & PP_STS_PA_MEM_COL_SKY_MASK)
*opmode |= PA_DSPP_OP_MEM_COL_SKY_MASK;
if (pa_sts & PP_STS_PA_SIX_ZONE_HUE_MASK)
*opmode |= PA_DSPP_OP_SIX_ZONE_HUE_MASK;
if (pa_sts & PP_STS_PA_SIX_ZONE_SAT_MASK)
*opmode |= PA_DSPP_OP_SIX_ZONE_SAT_MASK;
if (pa_sts & PP_STS_PA_SIX_ZONE_VAL_MASK)
*opmode |= PA_DSPP_OP_SIX_ZONE_VAL_MASK;
if (pa_sts & PP_STS_PA_MEM_PROT_HUE_EN)
*opmode |= PA_DSPP_OP_MEM_PROT_HUE_EN;
if (pa_sts & PP_STS_PA_MEM_PROT_SAT_EN)
*opmode |= PA_DSPP_OP_MEM_PROT_SAT_EN;
if (pa_sts & PP_STS_PA_MEM_PROT_VAL_EN)
*opmode |= PA_DSPP_OP_MEM_PROT_VAL_EN;
if (pa_sts & PP_STS_PA_MEM_PROT_CONT_EN)
*opmode |= PA_DSPP_OP_MEM_PROT_CONT_EN;
if (pa_sts & PP_STS_PA_MEM_PROT_BLEND_EN)
*opmode |= PA_DSPP_OP_MEM_PROT_BLEND_EN;
if (pa_sts & PP_STS_PA_MEM_PROT_SIX_EN)
*opmode |= PA_DSPP_OP_MEM_PROT_SIX_EN;
}
static int pp_igc_set_config(char __iomem *base_addr,
struct pp_sts_type *pp_sts, void *cfg_data,
u32 block_type)

View file

@ -356,26 +356,6 @@ struct msmfb_writeback_data {
#define MDP_PP_IGC_FLAG_ROM0 0x10
#define MDP_PP_IGC_FLAG_ROM1 0x20
#define MDP_PP_PA_HUE_ENABLE 0x10
#define MDP_PP_PA_SAT_ENABLE 0x20
#define MDP_PP_PA_VAL_ENABLE 0x40
#define MDP_PP_PA_CONT_ENABLE 0x80
#define MDP_PP_PA_SIX_ZONE_ENABLE 0x100
#define MDP_PP_PA_SKIN_ENABLE 0x200
#define MDP_PP_PA_SKY_ENABLE 0x400
#define MDP_PP_PA_FOL_ENABLE 0x800
#define MDP_PP_PA_HUE_MASK 0x1000
#define MDP_PP_PA_SAT_MASK 0x2000
#define MDP_PP_PA_VAL_MASK 0x4000
#define MDP_PP_PA_CONT_MASK 0x8000
#define MDP_PP_PA_SIX_ZONE_HUE_MASK 0x10000
#define MDP_PP_PA_SIX_ZONE_SAT_MASK 0x20000
#define MDP_PP_PA_SIX_ZONE_VAL_MASK 0x40000
#define MDP_PP_PA_MEM_COL_SKIN_MASK 0x80000
#define MDP_PP_PA_MEM_COL_SKY_MASK 0x100000
#define MDP_PP_PA_MEM_COL_FOL_MASK 0x200000
#define MDP_PP_PA_MEM_PROTECT_EN 0x400000
#define MDP_PP_PA_SAT_ZERO_EXP_EN 0x800000
#define MDSS_PP_DSPP_CFG 0x000
#define MDSS_PP_SSPP_CFG 0x100
@ -473,18 +453,44 @@ struct mdp_pa_mem_col_cfg {
uint32_t val_region;
};
struct mdp_pa_mem_col_cfg_v1_7 {
uint32_t color_adjust_p0;
uint32_t color_adjust_p1;
uint32_t color_adjust_p2;
uint32_t blend_gain;
uint32_t hue_region;
uint32_t sat_region;
uint32_t val_region;
};
#define MDP_SIX_ZONE_LUT_SIZE 384
/* PA Write/Read extension flags */
#define MDP_PP_PA_HUE_ENABLE 0x10
#define MDP_PP_PA_SAT_ENABLE 0x20
#define MDP_PP_PA_VAL_ENABLE 0x40
#define MDP_PP_PA_CONT_ENABLE 0x80
#define MDP_PP_PA_SIX_ZONE_ENABLE 0x100
#define MDP_PP_PA_SKIN_ENABLE 0x200
#define MDP_PP_PA_SKY_ENABLE 0x400
#define MDP_PP_PA_FOL_ENABLE 0x800
/* PA masks */
/* Masks used in PA v1_7 only */
#define MDP_PP_PA_MEM_PROT_HUE_EN 0x1
#define MDP_PP_PA_MEM_PROT_SAT_EN 0x2
#define MDP_PP_PA_MEM_PROT_VAL_EN 0x4
#define MDP_PP_PA_MEM_PROT_CONT_EN 0x8
#define MDP_PP_PA_MEM_PROT_SIX_EN 0x10
#define MDP_PP_PA_MEM_PROT_BLEND_EN 0x20
/* Masks used in all PAv2 versions */
#define MDP_PP_PA_HUE_MASK 0x1000
#define MDP_PP_PA_SAT_MASK 0x2000
#define MDP_PP_PA_VAL_MASK 0x4000
#define MDP_PP_PA_CONT_MASK 0x8000
#define MDP_PP_PA_SIX_ZONE_HUE_MASK 0x10000
#define MDP_PP_PA_SIX_ZONE_SAT_MASK 0x20000
#define MDP_PP_PA_SIX_ZONE_VAL_MASK 0x40000
#define MDP_PP_PA_MEM_COL_SKIN_MASK 0x80000
#define MDP_PP_PA_MEM_COL_SKY_MASK 0x100000
#define MDP_PP_PA_MEM_COL_FOL_MASK 0x200000
#define MDP_PP_PA_MEM_PROTECT_EN 0x400000
#define MDP_PP_PA_SAT_ZERO_EXP_EN 0x800000
/* Flags for setting PA saturation and value hold */
#define MDP_PP_PA_LEFT_HOLD 0x1
#define MDP_PP_PA_RIGHT_HOLD 0x2
struct mdp_pa_v2_data {
/* Mask bits for PA features */
uint32_t flags;
@ -501,27 +507,46 @@ struct mdp_pa_v2_data {
uint32_t *six_zone_curve_p1;
};
struct mdp_pa_mem_col_data_v1_7 {
uint32_t color_adjust_p0;
uint32_t color_adjust_p1;
uint32_t color_adjust_p2;
uint32_t blend_gain;
uint8_t sat_hold;
uint8_t val_hold;
uint32_t hue_region;
uint32_t sat_region;
uint32_t val_region;
};
struct mdp_pa_data_v1_7 {
uint32_t mode;
uint32_t global_hue_adj;
uint32_t global_sat_adj;
uint32_t global_val_adj;
uint32_t global_cont_adj;
struct mdp_pa_mem_col_cfg_v1_7 skin_cfg;
struct mdp_pa_mem_col_cfg_v1_7 sky_cfg;
struct mdp_pa_mem_col_cfg_v1_7 fol_cfg;
uint32_t six_zone_len;
struct mdp_pa_mem_col_data_v1_7 skin_cfg;
struct mdp_pa_mem_col_data_v1_7 sky_cfg;
struct mdp_pa_mem_col_data_v1_7 fol_cfg;
uint32_t six_zone_thresh;
uint32_t six_zone_adj_p0;
uint32_t six_zone_adj_p1;
uint8_t six_zone_sat_hold;
uint8_t six_zone_val_hold;
uint32_t six_zone_len;
uint32_t *six_zone_curve_p0;
uint32_t *six_zone_curve_p1;
};
enum {
mdp_pa_v1_7 = 0x1,
mdp_pa_vmax,
};
struct mdp_pa_v2_cfg_data {
uint32_t version;
uint32_t block;
uint32_t flags;
uint32_t mode;
struct mdp_pa_v2_data pa_v2_data;
void *cfg_payload;
};