msm: mdss: Add support for IGC v3 feature
IGC module is updated for mdss V3 version, which needs to be exposed to user-space. Change adds interface support to expose the IGC module to user-space clients. Change-Id: I159bca8278a1638286cc2392bb5b059e067dbb1b Signed-off-by: Gopikrishnaiah Anandan <agopik@codeaurora.org> Signed-off-by: Ping Li <pingli@codeaurora.org>
This commit is contained in:
parent
68f301791a
commit
c19f4224ab
5 changed files with 469 additions and 20 deletions
|
@ -2315,6 +2315,10 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
|
|||
&mdss_pp_res->igc_disp_cfg[disp_num],
|
||||
DSPP);
|
||||
}
|
||||
if (pp_driver_ops.igc_set_dither_strength)
|
||||
pp_driver_ops.igc_set_dither_strength(base, pp_sts,
|
||||
&mdss_pp_res->igc_disp_cfg[disp_num],
|
||||
DSPP);
|
||||
}
|
||||
|
||||
if (flags & PP_FLAGS_DIRTY_ENHIST) {
|
||||
|
@ -7454,16 +7458,25 @@ static int pp_get_driver_ops(struct mdp_pp_driver_ops *ops)
|
|||
break;
|
||||
case MDSS_MDP_HW_REV_300:
|
||||
case MDSS_MDP_HW_REV_301:
|
||||
pp_cfg = pp_get_driver_ops_v3(ops);
|
||||
/*
|
||||
* Some of the REV_300 PP features are same as REV_107.
|
||||
* Get the driver ops for both the versions and update the
|
||||
* payload/function pointers.
|
||||
*/
|
||||
mdss_pp_res->pp_data_v1_7 = NULL;
|
||||
mdss_pp_res->pp_data_v3 = NULL;
|
||||
pp_cfg = pp_get_driver_ops_v1_7(ops);
|
||||
if (IS_ERR_OR_NULL(pp_cfg)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
mdss_pp_res->pp_data_v1_7 = pp_cfg;
|
||||
pp_cfg = pp_get_driver_ops_v3(ops);
|
||||
if (IS_ERR_OR_NULL(pp_cfg)) {
|
||||
mdss_pp_res->pp_data_v1_7 = NULL;
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
mdss_pp_res->pp_data_v1_7 = pp_cfg;
|
||||
/* Currently all caching data is used from v17 for V3
|
||||
* hence setting the pointer to NULL. Will be used if we
|
||||
* have to add any caching specific to V3.
|
||||
*/
|
||||
mdss_pp_res->pp_data_v3 = NULL;
|
||||
mdss_pp_res->pp_data_v3 = pp_cfg;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -106,6 +106,9 @@ struct mdp_pp_driver_ops {
|
|||
int (*get_hist_isr_info)(u32 *isr_mask);
|
||||
bool (*is_sspp_hist_supp)(void);
|
||||
void (*gamut_clk_gate_en)(char __iomem *base_addr);
|
||||
int (*igc_set_dither_strength)(char __iomem *base_addr,
|
||||
struct pp_sts_type *pp_sts, void *cfg_data,
|
||||
u32 block_type);
|
||||
};
|
||||
|
||||
struct mdp_pa_dither_res_data_v1_7 {
|
||||
|
@ -138,6 +141,23 @@ struct mdss_pp_res_type_v1_7 {
|
|||
struct mdp_pa_dither_res_data_v1_7 pa_dither_data[MDSS_BLOCK_DISP_NUM];
|
||||
};
|
||||
|
||||
struct mdp_igc_lut_data_config {
|
||||
uint32_t table_fmt;
|
||||
uint32_t len;
|
||||
uint32_t *c0_c1_data;
|
||||
uint32_t *c2_data;
|
||||
uint32_t strength;
|
||||
};
|
||||
|
||||
struct mdss_pp_res_type_v3 {
|
||||
int (*igc_set_config)(char __iomem *base_addr,
|
||||
struct pp_sts_type *pp_sts, void *cfg_data,
|
||||
u32 block_type);
|
||||
u32 igc_table_c0_c1[MDSS_BLOCK_DISP_NUM][IGC_LUT_ENTRIES];
|
||||
u32 igc_table_c2[MDSS_BLOCK_DISP_NUM][IGC_LUT_ENTRIES];
|
||||
struct mdp_igc_lut_data_config igc_v3_data[MDSS_BLOCK_DISP_NUM];
|
||||
};
|
||||
|
||||
struct mdss_pp_res_type {
|
||||
/* logical info */
|
||||
u32 pp_disp_flags[MDSS_BLOCK_DISP_NUM];
|
||||
|
|
|
@ -94,6 +94,15 @@ static u32 pp_igc_srgb[IGC_LUT_ENTRIES] = {
|
|||
3809, 3844, 3879, 3915, 3950, 3986, 4022, 4059, 4095
|
||||
};
|
||||
|
||||
static int pp_igc_lut_cache_params_v3(struct mdp_igc_lut_data *config,
|
||||
struct mdss_pp_res_type *mdss_pp_res,
|
||||
u32 copy_from_kernel);
|
||||
|
||||
static int pp_igc_lut_cache_params_pipe_v3(struct mdp_igc_lut_data *config,
|
||||
struct mdss_mdp_pipe *pipe,
|
||||
u32 copy_from_kernel);
|
||||
|
||||
|
||||
static int pp_hist_lut_cache_params_v1_7(struct mdp_hist_lut_data *config,
|
||||
struct mdss_pp_res_type *mdss_pp_res)
|
||||
{
|
||||
|
@ -991,6 +1000,21 @@ int pp_igc_lut_cache_params(struct mdp_igc_lut_data *config,
|
|||
ret);
|
||||
}
|
||||
break;
|
||||
case mdp_igc_v3:
|
||||
if (res_cache->block == DSPP) {
|
||||
ret = pp_igc_lut_cache_params_v3(config,
|
||||
res_cache->mdss_pp_res, copy_from_kernel);
|
||||
if (ret)
|
||||
pr_err("cache DSPP IGC params fail ret %d version %d\n",
|
||||
ret, config->version);
|
||||
} else {
|
||||
ret = pp_igc_lut_cache_params_pipe_v3(config,
|
||||
res_cache->pipe_res, copy_from_kernel);
|
||||
if (ret)
|
||||
pr_err("cache SSPP IGC params fail ret %d version %d\n",
|
||||
ret, config->version);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pr_err("unsupported igc version %d\n",
|
||||
config->version);
|
||||
|
@ -1329,6 +1353,7 @@ int pp_copy_layer_igc_payload(struct mdp_overlay_pp_params *pp_info)
|
|||
{
|
||||
void *cfg_payload = NULL;
|
||||
int ret = 0;
|
||||
size_t sz = 0;
|
||||
|
||||
switch (pp_info->igc_cfg.version) {
|
||||
case mdp_igc_v1_7:
|
||||
|
@ -1343,22 +1368,34 @@ int pp_copy_layer_igc_payload(struct mdp_overlay_pp_params *pp_info)
|
|||
ret = copy_from_user(cfg_payload,
|
||||
pp_info->igc_cfg.cfg_payload,
|
||||
sizeof(struct mdp_igc_lut_data_v1_7));
|
||||
if (ret) {
|
||||
pr_err("layer list copy from user failed, IGC cfg payload = %p\n",
|
||||
pp_info->igc_cfg.cfg_payload);
|
||||
ret = -EFAULT;
|
||||
kfree(cfg_payload);
|
||||
cfg_payload = NULL;
|
||||
break;
|
||||
case mdp_igc_v3:
|
||||
cfg_payload = kmalloc(
|
||||
sizeof(struct mdp_igc_lut_data_payload),
|
||||
GFP_KERNEL);
|
||||
if (!cfg_payload) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
sz = offsetof(struct mdp_igc_lut_data_payload, strength) +
|
||||
sizeof(u32);
|
||||
ret = copy_from_user(cfg_payload,
|
||||
pp_info->igc_cfg.cfg_payload, sz);
|
||||
break;
|
||||
default:
|
||||
pr_debug("No version set, fallback to legacy IGC version\n");
|
||||
cfg_payload = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (ret) {
|
||||
pr_err("layer list copy from user failed, IGC cfg payload = %p\n",
|
||||
pp_info->igc_cfg.cfg_payload);
|
||||
ret = -EFAULT;
|
||||
kfree(cfg_payload);
|
||||
cfg_payload = NULL;
|
||||
goto exit;
|
||||
}
|
||||
pp_info->igc_cfg.cfg_payload = cfg_payload;
|
||||
return ret;
|
||||
}
|
||||
|
@ -1579,3 +1616,257 @@ int pp_pa_dither_cache_params(struct mdp_dither_cfg_data *config,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int pp_igc_lut_cache_params_v3(struct mdp_igc_lut_data *config,
|
||||
struct mdss_pp_res_type *mdss_pp_res,
|
||||
u32 copy_from_kernel)
|
||||
{
|
||||
int ret = 0;
|
||||
struct mdss_pp_res_type_v3 *res_cache;
|
||||
struct mdp_igc_lut_data_payload v3_usr_config;
|
||||
struct mdp_igc_lut_data_config *v3_cache_data, *v3_kernel_data = NULL;
|
||||
u32 disp_num, len = 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_v3) {
|
||||
pr_err("invalid pp_data_v3 %p\n", mdss_pp_res->pp_data_v3);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (config->ops & MDP_PP_OPS_READ) {
|
||||
pr_err("read op is not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
|
||||
if (!(config->ops & MDP_PP_OPS_WRITE)) {
|
||||
pr_debug("op for igc %d\n", config->ops);
|
||||
mdss_pp_res->igc_disp_cfg[disp_num] = *config;
|
||||
goto igc_config_exit;
|
||||
}
|
||||
res_cache = mdss_pp_res->pp_data_v3;
|
||||
v3_cache_data = &res_cache->igc_v3_data[disp_num];
|
||||
if (!v3_cache_data->c0_c1_data || !v3_cache_data->c2_data) {
|
||||
pr_err("invalid payload c0_c1_data %p c2_data %p\n",
|
||||
v3_cache_data->c0_c1_data, v3_cache_data->c2_data);
|
||||
goto igc_config_exit;
|
||||
}
|
||||
if (!copy_from_kernel) {
|
||||
if (copy_from_user(&v3_usr_config,
|
||||
config->cfg_payload,
|
||||
sizeof(v3_usr_config))) {
|
||||
pr_err("failed to copy igc config\n");
|
||||
ret = -EFAULT;
|
||||
goto igc_config_exit;
|
||||
}
|
||||
len = v3_usr_config.len;
|
||||
} else {
|
||||
if (!config->cfg_payload) {
|
||||
pr_err("can't copy config info NULL payload\n");
|
||||
ret = -EINVAL;
|
||||
goto igc_config_exit;
|
||||
}
|
||||
v3_kernel_data = config->cfg_payload;
|
||||
len = v3_kernel_data->len;
|
||||
}
|
||||
if (copy_from_kernel && (!v3_kernel_data->c0_c1_data ||
|
||||
!v3_kernel_data->c2_data)) {
|
||||
pr_err("copy from kernel invalid params c0_c1_data %p c2_data %p\n",
|
||||
v3_kernel_data->c0_c1_data,
|
||||
v3_kernel_data->c2_data);
|
||||
ret = -EINVAL;
|
||||
goto igc_config_exit;
|
||||
}
|
||||
if (len != IGC_LUT_ENTRIES) {
|
||||
pr_err("Invalid table size %d exp %d\n",
|
||||
len, IGC_LUT_ENTRIES);
|
||||
ret = -EINVAL;
|
||||
goto igc_config_exit;
|
||||
}
|
||||
if (copy_from_kernel) {
|
||||
memcpy(v3_cache_data->c0_c1_data,
|
||||
v3_kernel_data->c0_c1_data,
|
||||
len * sizeof(u32));
|
||||
memcpy(v3_cache_data->c2_data, v3_kernel_data->c2_data,
|
||||
len * sizeof(u32));
|
||||
v3_cache_data->len = len;
|
||||
v3_cache_data->strength = v3_kernel_data->strength;
|
||||
v3_cache_data->table_fmt = v3_kernel_data->table_fmt;
|
||||
} else {
|
||||
ret = copy_from_user(v3_cache_data->c0_c1_data,
|
||||
(u8 *)v3_usr_config.c0_c1_data,
|
||||
len * sizeof(u32));
|
||||
if (ret) {
|
||||
pr_err("copy from user failed for c0_c1_data size %zd ret %d\n",
|
||||
len * sizeof(u32), ret);
|
||||
ret = -EFAULT;
|
||||
goto igc_config_exit;
|
||||
}
|
||||
ret = copy_from_user(v3_cache_data->c2_data,
|
||||
(u8 *)v3_usr_config.c2_data,
|
||||
len * sizeof(u32));
|
||||
if (ret) {
|
||||
pr_err("copy from user failed for c2_data size %zd ret %d\n",
|
||||
len * sizeof(u32), ret);
|
||||
ret = -EFAULT;
|
||||
goto igc_config_exit;
|
||||
}
|
||||
v3_cache_data->len = len;
|
||||
v3_cache_data->strength = v3_usr_config.strength;
|
||||
v3_cache_data->table_fmt = v3_usr_config.table_fmt;
|
||||
}
|
||||
mdss_pp_res->igc_disp_cfg[disp_num] = *config;
|
||||
mdss_pp_res->igc_disp_cfg[disp_num].cfg_payload =
|
||||
(void *)v3_cache_data;
|
||||
igc_config_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pp_igc_lut_cache_params_pipe_v3(
|
||||
struct mdp_igc_lut_data *config, struct mdss_mdp_pipe *pipe,
|
||||
u32 copy_from_kernel)
|
||||
{
|
||||
struct mdp_igc_lut_data_config *v3_cache_data = NULL;
|
||||
struct mdp_igc_lut_data_payload v3_usr_config;
|
||||
u32 *c0_c1_data, *c2_data, len;
|
||||
int ret = 0, fix_up = 0, i = 0;
|
||||
u32 table_fmt = mdp_igc_rec_max, strength = 0;
|
||||
|
||||
if (!config || !pipe) {
|
||||
pr_err("invalid param config %p pipe %p\n",
|
||||
config, pipe);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (config->ops & MDP_PP_OPS_READ) {
|
||||
pr_err("read op is not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!(config->ops & MDP_PP_OPS_WRITE)) {
|
||||
pr_debug("op for gamut %d\n", config->ops);
|
||||
goto igc_config_exit;
|
||||
}
|
||||
|
||||
if (!config->cfg_payload) {
|
||||
pr_err("can't copy config info NULL payload\n");
|
||||
ret = -EINVAL;
|
||||
goto igc_config_exit;
|
||||
}
|
||||
|
||||
v3_cache_data = pipe->pp_res.igc_cfg_payload;
|
||||
if (!v3_cache_data)
|
||||
v3_cache_data = kzalloc(sizeof(*v3_cache_data), GFP_KERNEL);
|
||||
if (!v3_cache_data) {
|
||||
ret = -ENOMEM;
|
||||
goto igc_config_exit;
|
||||
} else {
|
||||
pipe->pp_res.igc_cfg_payload = v3_cache_data;
|
||||
pipe->pp_cfg.igc_cfg.cfg_payload = v3_cache_data;
|
||||
}
|
||||
|
||||
if (copy_from_kernel) {
|
||||
memcpy(v3_cache_data, config->cfg_payload,
|
||||
sizeof(*v3_cache_data));
|
||||
table_fmt = v3_cache_data->table_fmt;
|
||||
len = v3_cache_data->len;
|
||||
strength = 0;
|
||||
} else {
|
||||
memcpy(&v3_usr_config, config->cfg_payload,
|
||||
sizeof(v3_usr_config));
|
||||
table_fmt = v3_usr_config.table_fmt;
|
||||
len = v3_usr_config.len;
|
||||
strength = v3_usr_config.strength;
|
||||
}
|
||||
switch (table_fmt) {
|
||||
case mdp_igc_custom:
|
||||
if (len != IGC_LUT_ENTRIES) {
|
||||
pr_err("invalid igc len %d exp %d\n", len,
|
||||
IGC_LUT_ENTRIES);
|
||||
ret = -EINVAL;
|
||||
goto igc_config_exit;
|
||||
}
|
||||
if (!copy_from_kernel)
|
||||
break;
|
||||
c0_c1_data = v3_cache_data->c0_c1_data;
|
||||
c2_data = v3_cache_data->c2_data;
|
||||
if (!c0_c1_data || !c2_data) {
|
||||
pr_err("invalid param c0_c1_data %p c2_data %p\n",
|
||||
c0_c1_data, c2_data);
|
||||
ret = -EINVAL;
|
||||
goto igc_config_exit;
|
||||
}
|
||||
break;
|
||||
case mdp_igc_rec709:
|
||||
c0_c1_data = pp_igc_709;
|
||||
c2_data = pp_igc_709;
|
||||
v3_usr_config.len = IGC_LUT_ENTRIES;
|
||||
copy_from_kernel = 1;
|
||||
fix_up = 1;
|
||||
break;
|
||||
case mdp_igc_srgb:
|
||||
c0_c1_data = pp_igc_srgb;
|
||||
c2_data = pp_igc_srgb;
|
||||
v3_usr_config.len = IGC_LUT_ENTRIES;
|
||||
copy_from_kernel = 1;
|
||||
fix_up = 1;
|
||||
break;
|
||||
case mdp_igc_rec601:
|
||||
c0_c1_data = pp_igc_601;
|
||||
c2_data = pp_igc_601;
|
||||
v3_usr_config.len = IGC_LUT_ENTRIES;
|
||||
copy_from_kernel = 1;
|
||||
fix_up = 1;
|
||||
break;
|
||||
default:
|
||||
pr_err("invalid format %d\n", table_fmt);
|
||||
ret = -EINVAL;
|
||||
goto igc_config_exit;
|
||||
}
|
||||
v3_cache_data->c0_c1_data = pipe->pp_res.igc_c0_c1;
|
||||
v3_cache_data->c2_data = pipe->pp_res.igc_c2;
|
||||
v3_cache_data->len = IGC_LUT_ENTRIES;
|
||||
v3_cache_data->strength = strength;
|
||||
v3_cache_data->table_fmt = table_fmt;
|
||||
if (copy_from_kernel) {
|
||||
memcpy(v3_cache_data->c0_c1_data, c0_c1_data,
|
||||
IGC_LUT_ENTRIES * sizeof(u32));
|
||||
memcpy(v3_cache_data->c2_data, c2_data,
|
||||
IGC_LUT_ENTRIES * sizeof(u32));
|
||||
if (fix_up) {
|
||||
for (i = 0; i < IGC_LUT_ENTRIES; i++)
|
||||
v3_cache_data->c0_c1_data[i]
|
||||
|= (v3_cache_data->c0_c1_data[i]
|
||||
<< IGC_C1_SHIFT);
|
||||
}
|
||||
} else {
|
||||
if (copy_from_user(v3_cache_data->c0_c1_data,
|
||||
(u8 *)v3_usr_config.c0_c1_data,
|
||||
IGC_LUT_ENTRIES * sizeof(u32))) {
|
||||
pr_err("error in copying the c0_c1_data of size %zd\n",
|
||||
IGC_LUT_ENTRIES * sizeof(u32));
|
||||
ret = -EFAULT;
|
||||
goto igc_config_exit;
|
||||
}
|
||||
if (copy_from_user(v3_cache_data->c2_data,
|
||||
(u8 *)v3_usr_config.c2_data,
|
||||
IGC_LUT_ENTRIES * sizeof(u32))) {
|
||||
pr_err("error in copying the c2_data of size %zd\n",
|
||||
IGC_LUT_ENTRIES * sizeof(u32));
|
||||
ret = -EFAULT;
|
||||
}
|
||||
}
|
||||
igc_config_exit:
|
||||
if (ret || (config->ops & MDP_PP_OPS_DISABLE)) {
|
||||
kfree(v3_cache_data);
|
||||
pipe->pp_cfg.igc_cfg.cfg_payload = NULL;
|
||||
pipe->pp_res.igc_cfg_payload = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,8 @@ static u32 dither_depth_map[DITHER_DEPTH_MAP_INDEX] = {
|
|||
|
||||
#define PA_DITHER_REG_OFF 0x2C
|
||||
|
||||
#define IGC_DITHER_STRENGTH_REG_OFF 0x7E0
|
||||
|
||||
/* histogram prototypes */
|
||||
static int pp_get_hist_offset(u32 block, u32 *ctl_off);
|
||||
static int pp_hist_set_config(char __iomem *base_addr,
|
||||
|
@ -115,21 +117,53 @@ static int pp_pa_dither_set_config(char __iomem *base_addr,
|
|||
struct pp_sts_type *pp_sts, void *cfg_data,
|
||||
u32 block_type);
|
||||
|
||||
/* IGC prototypes */
|
||||
static int pp_igc_set_config(char __iomem *base_addr,
|
||||
struct pp_sts_type *pp_sts, void *cfg_data,
|
||||
u32 block_type);
|
||||
static int pp_igc_get_config(char __iomem *base_addr, void *cfg_data,
|
||||
u32 block_type, u32 disp_num);
|
||||
static int pp_igc_get_version(u32 *version);
|
||||
static int pp_igc_dither_set_strength(char __iomem *base_addr,
|
||||
struct pp_sts_type *pp_sts, void *cfg_data,
|
||||
u32 block_type);
|
||||
|
||||
static void pp_opmode_config(int location, struct pp_sts_type *pp_sts,
|
||||
u32 *opmode, int side);
|
||||
static int pp_driver_init(struct mdp_pp_driver_ops *ops);
|
||||
|
||||
static struct mdss_pp_res_type_v3 config_data;
|
||||
|
||||
static int pp_driver_init(struct mdp_pp_driver_ops *ops)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (!ops->pp_ops[IGC].pp_set_config) {
|
||||
pr_err("IGC function is not set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
config_data.igc_set_config = ops->pp_ops[IGC].pp_set_config;
|
||||
for (i = 0; i < MDSS_BLOCK_DISP_NUM; i++) {
|
||||
config_data.igc_v3_data[i].c0_c1_data =
|
||||
&config_data.igc_table_c0_c1[i][0];
|
||||
config_data.igc_v3_data[i].c2_data =
|
||||
&config_data.igc_table_c2[i][0];
|
||||
config_data.igc_v3_data[i].len = IGC_LUT_ENTRIES;
|
||||
config_data.igc_v3_data[i].strength = 0;
|
||||
config_data.igc_v3_data[i].table_fmt = mdp_igc_rec_max;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *pp_get_driver_ops_v3(struct mdp_pp_driver_ops *ops)
|
||||
{
|
||||
void *pp_cfg = NULL;
|
||||
|
||||
if (!ops) {
|
||||
pr_err("PP driver ops invalid %p\n", ops);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
pp_cfg = pp_get_driver_ops_v1_7(ops);
|
||||
if (IS_ERR_OR_NULL(pp_cfg))
|
||||
return NULL;
|
||||
if (pp_driver_init(ops))
|
||||
return ERR_PTR(-EINVAL);
|
||||
/* PA ops */
|
||||
ops->pp_ops[PA].pp_set_config = pp_pa_set_config;
|
||||
ops->pp_ops[PA].pp_get_config = pp_pa_get_config;
|
||||
|
@ -154,13 +188,18 @@ void *pp_get_driver_ops_v3(struct mdp_pp_driver_ops *ops)
|
|||
ops->pp_ops[PA_DITHER].pp_set_config = pp_pa_dither_set_config;
|
||||
ops->pp_ops[PA_DITHER].pp_get_config = NULL;
|
||||
|
||||
ops->pp_ops[IGC].pp_get_config = pp_igc_get_config;
|
||||
ops->pp_ops[IGC].pp_get_version = pp_igc_get_version;
|
||||
ops->pp_ops[IGC].pp_set_config = pp_igc_set_config;
|
||||
|
||||
/* Set opmode pointers */
|
||||
ops->pp_opmode_config = pp_opmode_config;
|
||||
|
||||
ops->get_hist_offset = pp_get_hist_offset;
|
||||
ops->gamut_clk_gate_en = NULL;
|
||||
ops->igc_set_dither_strength = pp_igc_dither_set_strength;
|
||||
|
||||
return pp_cfg;
|
||||
return &config_data;
|
||||
}
|
||||
|
||||
static int pp_get_hist_offset(u32 block, u32 *ctl_off)
|
||||
|
@ -905,3 +944,79 @@ dither_set_sts:
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pp_igc_dither_set_strength(char __iomem *base_addr,
|
||||
struct pp_sts_type *pp_sts, void *cfg_data,
|
||||
u32 block_type)
|
||||
{
|
||||
struct mdp_igc_lut_data *lut_cfg_data = cfg_data;
|
||||
struct mdp_igc_lut_data_config *v3_data = NULL;
|
||||
|
||||
if (!base_addr || !cfg_data || (block_type != DSPP) || !pp_sts
|
||||
|| (lut_cfg_data->version != mdp_igc_v3)) {
|
||||
pr_err("invalid params base_addr %p cfg_data %p block_type %d igc version %d\n",
|
||||
base_addr, cfg_data, block_type, (lut_cfg_data ?
|
||||
lut_cfg_data->version : mdp_pp_unknown));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((lut_cfg_data->ops & MDP_PP_OPS_DISABLE) ||
|
||||
!(lut_cfg_data->ops & MDP_PP_OPS_WRITE))
|
||||
return 0;
|
||||
|
||||
if (!lut_cfg_data->cfg_payload) {
|
||||
pr_err("invalid payload igc dither strenth\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
v3_data = lut_cfg_data->cfg_payload;
|
||||
writel_relaxed(v3_data->strength,
|
||||
base_addr + IGC_DITHER_STRENGTH_REG_OFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pp_igc_set_config(char __iomem *base_addr,
|
||||
struct pp_sts_type *pp_sts, void *cfg_data,
|
||||
u32 block_type)
|
||||
{
|
||||
struct mdp_igc_lut_data *lut_cfg_data = NULL, v17_cfg_data = {0};
|
||||
struct mdp_igc_lut_data_config *v3_data = NULL;
|
||||
struct mdp_igc_lut_data_v1_7 v17_lut_data = {0};
|
||||
int ret = 0;
|
||||
|
||||
if (!base_addr || !pp_sts || !cfg_data || !config_data.igc_set_config) {
|
||||
pr_err("invalid payload base_addr %p pp_sts %p cfg_data %p igc_set_config %p\n",
|
||||
base_addr, pp_sts, cfg_data,
|
||||
config_data.igc_set_config);
|
||||
return -EINVAL;
|
||||
}
|
||||
lut_cfg_data = cfg_data;
|
||||
v3_data = lut_cfg_data->cfg_payload;
|
||||
if (v3_data) {
|
||||
v17_lut_data.c0_c1_data = v3_data->c0_c1_data;
|
||||
v17_lut_data.c2_data = v3_data->c2_data;
|
||||
v17_lut_data.len = v3_data->len;
|
||||
v17_lut_data.table_fmt = v3_data->table_fmt;
|
||||
}
|
||||
memcpy(&v17_cfg_data, lut_cfg_data, sizeof(v17_cfg_data));
|
||||
v17_cfg_data.version = mdp_igc_v1_7;
|
||||
ret = config_data.igc_set_config(base_addr, pp_sts, &v17_cfg_data,
|
||||
block_type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pp_igc_get_config(char __iomem *base_addr, void *cfg_data,
|
||||
u32 block_type, u32 disp_num)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int pp_igc_get_version(u32 *version)
|
||||
{
|
||||
if (!version) {
|
||||
pr_err("invalid param version");
|
||||
return -EINVAL;
|
||||
}
|
||||
*version = mdp_igc_v3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -622,6 +622,14 @@ struct mdp_igc_lut_data_v1_7 {
|
|||
uint32_t *c2_data;
|
||||
};
|
||||
|
||||
struct mdp_igc_lut_data_payload {
|
||||
uint32_t table_fmt;
|
||||
uint32_t len;
|
||||
uint64_t __user c0_c1_data;
|
||||
uint64_t __user c2_data;
|
||||
uint32_t strength;
|
||||
};
|
||||
|
||||
struct mdp_histogram_cfg {
|
||||
uint32_t ops;
|
||||
uint32_t block;
|
||||
|
@ -1407,11 +1415,13 @@ enum {
|
|||
mdp_pcc_vmax,
|
||||
mdp_pp_legacy,
|
||||
mdp_dither_pa_v1_7,
|
||||
mdp_igc_v3,
|
||||
mdp_pp_unknown = 255
|
||||
};
|
||||
|
||||
#define mdp_dither_pa_v1_7 mdp_dither_pa_v1_7
|
||||
#define mdp_pp_unknown mdp_pp_unknown
|
||||
#define mdp_igc_v3 mdp_igc_v3
|
||||
|
||||
/* PP Features */
|
||||
enum {
|
||||
|
|
Loading…
Add table
Reference in a new issue