From c19f4224abb8a3fd5de40d74878bb2848497ddab Mon Sep 17 00:00:00 2001 From: Gopikrishnaiah Anandan Date: Wed, 2 Mar 2016 17:31:33 -0800 Subject: [PATCH] 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 Signed-off-by: Ping Li --- drivers/video/fbdev/msm/mdss_mdp_pp.c | 27 +- drivers/video/fbdev/msm/mdss_mdp_pp.h | 20 ++ .../fbdev/msm/mdss_mdp_pp_cache_config.c | 305 +++++++++++++++++- drivers/video/fbdev/msm/mdss_mdp_pp_v3.c | 127 +++++++- include/uapi/linux/msm_mdp.h | 10 + 5 files changed, 469 insertions(+), 20 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c index d65985a13cf1..fefb4067443a 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c @@ -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: diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.h b/drivers/video/fbdev/msm/mdss_mdp_pp.h index 9a6e9ea3300c..93406f0b4f13 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp.h +++ b/drivers/video/fbdev/msm/mdss_mdp_pp.h @@ -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]; diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c b/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c index ec9c1800787f..882145d4ff6c 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c @@ -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; +} + diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_v3.c b/drivers/video/fbdev/msm/mdss_mdp_pp_v3.c index 3d277ae5db5f..88407b3d920b 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_v3.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_v3.c @@ -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; +} + diff --git a/include/uapi/linux/msm_mdp.h b/include/uapi/linux/msm_mdp.h index afe37c7dd2bf..1c04668ffc98 100644 --- a/include/uapi/linux/msm_mdp.h +++ b/include/uapi/linux/msm_mdp.h @@ -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 {