diff options
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.h | 1 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_pp.c | 94 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c | 107 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.h | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c | 38 |
5 files changed, 194 insertions, 48 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index a6900c283df7..bee66c41ecb7 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -427,6 +427,7 @@ struct mdss_pipe_pp_res { void *pa_cfg_payload; void *pcc_cfg_payload; void *igc_cfg_payload; + void *hist_lut_cfg_payload; }; struct mdss_mdp_pipe_smp_map { diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c index 07e132100a55..3f4684a6c800 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c @@ -858,20 +858,26 @@ static int pp_vig_pipe_setup(struct mdss_mdp_pipe *pipe, u32 *op) } if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_HIST_LUT_CFG) { - pp_enhist_config(PP_FLAGS_DIRTY_ENHIST, + flags = PP_FLAGS_DIRTY_ENHIST; + if (!pp_ops[HIST_LUT].pp_set_config) { + pp_enhist_config(flags, 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) { - 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); + if ((pipe->pp_res.pp_sts.enhist_sts & PP_STS_ENABLE) && + !(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); + } + } else { + pp_ops[HIST_LUT].pp_set_config(pipe->base, + &pipe->pp_res.pp_sts, + &pipe->pp_cfg.hist_lut_cfg, + SSPP_VIG); } } @@ -1264,6 +1270,7 @@ void mdss_mdp_pipe_sspp_term(struct mdss_mdp_pipe *pipe) kfree(pipe->pp_res.pa_cfg_payload); kfree(pipe->pp_res.igc_cfg_payload); kfree(pipe->pp_res.pcc_cfg_payload); + kfree(pipe->pp_res.hist_lut_cfg_payload); memset(&pipe->pp_cfg, 0, sizeof(struct mdp_overlay_pp_params)); memset(&pipe->pp_res, 0, sizeof(struct mdss_pipe_pp_res)); } @@ -1762,6 +1769,16 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer) base + MDSS_MDP_REG_DSPP_HIST_LUT_BASE, pp_sts, &mdss_pp_res->enhist_disp_cfg[disp_num]); + + if ((pp_sts->enhist_sts & PP_STS_ENABLE) && + !(pp_sts->pa_sts & PP_STS_ENABLE)) { + /* Program default value */ + addr = base + MDSS_MDP_REG_DSPP_PA_BASE; + writel_relaxed(0, addr); + writel_relaxed(0, addr + 4); + writel_relaxed(0, addr + 8); + writel_relaxed(0, addr + 12); + } } else { /* Pass dspp num using block */ mdss_pp_res->enhist_disp_cfg[disp_num].block = dspp_num; @@ -1770,15 +1787,6 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer) } } - if (pp_sts->enhist_sts & PP_STS_ENABLE && - !(pp_sts->pa_sts & PP_STS_ENABLE)) { - /* Program default value */ - addr = base + MDSS_MDP_REG_DSPP_PA_BASE; - writel_relaxed(0, addr); - writel_relaxed(0, addr + 4); - writel_relaxed(0, addr + 8); - writel_relaxed(0, addr + 12); - } if (flags & PP_FLAGS_DIRTY_DITHER) { if (!pp_ops[DITHER].pp_set_config) { pp_dither_config(addr, pp_sts, @@ -3482,6 +3490,7 @@ int mdss_mdp_hist_lut_config(struct mdp_hist_lut_data *config, int i, ret = 0; u32 disp_num, dspp_num = 0; char __iomem *hist_addr = NULL, *base_addr = NULL; + struct mdp_pp_cache_res res_cache; if ((PP_BLOCK(config->block) < MDP_LOGICAL_BLOCK_DISP_0) || (PP_BLOCK(config->block) >= MDP_BLOCK_MAX)) @@ -3529,7 +3538,10 @@ hist_lut_clk_off: mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); } else { if (pp_ops[HIST_LUT].pp_set_config) { - ret = pp_hist_lut_cache_params(config, mdss_pp_res); + res_cache.block = DSPP; + res_cache.mdss_pp_res = mdss_pp_res; + res_cache.pipe_res = NULL; + ret = pp_hist_lut_cache_params(config, &res_cache); if (ret) { pr_err("hist_lut config failed version %d ret %d\n", config->version, ret); @@ -6201,18 +6213,36 @@ int mdss_mdp_pp_sspp_config(struct mdss_mdp_pipe *pipe) mdss_mdp_hist_stop(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) { - ret = -EFAULT; - pr_err("failed to copy the hist lut\n"); - goto exit_fail; + if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_HIST_LUT_CFG) { + if (!pp_ops[HIST_LUT].pp_set_config) { + len = pipe->pp_cfg.hist_lut_cfg.len; + if (len != ENHIST_LUT_ENTRIES) { + ret = -EINVAL; + pr_err("Invalid hist lut len: %d\n", len); + goto exit_fail; + } + ret = copy_from_user(pipe->pp_res.hist_lut, + pipe->pp_cfg.hist_lut_cfg.data, + sizeof(uint32_t) * len); + if (ret) { + ret = -EFAULT; + pr_err("failed to copy the hist lut\n"); + goto exit_fail; + } + pipe->pp_cfg.hist_lut_cfg.data = pipe->pp_res.hist_lut; + } else { + cache_res.block = SSPP_VIG; + cache_res.mdss_pp_res = NULL; + cache_res.pipe_res = pipe; + ret = pp_hist_lut_cache_params( + &pipe->pp_cfg.hist_lut_cfg, + &cache_res); + if (ret) { + pr_err("Failed to cache Hist LUT params on pipe %d, ret %d\n", + pipe->num, ret); + goto exit_fail; + } } - pipe->pp_cfg.hist_lut_cfg.data = pipe->pp_res.hist_lut; } if ((pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_PA_V2_CFG) && (pp_ops[PA].pp_set_config)) { 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 9a4b037b35f5..633527ed790c 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c @@ -134,18 +134,115 @@ static int pp_hist_lut_cache_params_v1_7(struct mdp_hist_lut_data *config, return ret; } +static int pp_hist_lut_cache_params_pipe_v1_7(struct mdp_hist_lut_data *config, + struct mdss_mdp_pipe *pipe) +{ + struct mdp_hist_lut_data_v1_7 *hist_lut_cache_data; + struct mdp_hist_lut_data_v1_7 hist_lut_usr_config; + int ret = 0; + + if (!config || !pipe) { + pr_err("Invalid param config %p pipe %p\n", + config, pipe); + return -EINVAL; + } + + if (config->ops & MDP_PP_OPS_DISABLE) { + pr_debug("Disable Hist LUT on pipe %d\n", pipe->num); + goto hist_lut_cache_pipe_exit; + } + + if (config->ops & MDP_PP_OPS_READ) { + pr_err("Read op is not supported\n"); + return -EINVAL; + } + + if (copy_from_user(&hist_lut_usr_config, + config->cfg_payload, + sizeof(struct mdp_hist_lut_data_v1_7))) { + pr_err("Failed to copy usr cfg_payload\n"); + ret = -EFAULT; + goto hist_lut_cache_pipe_exit; + } + + hist_lut_cache_data = pipe->pp_res.hist_lut_cfg_payload; + if (!hist_lut_cache_data) { + hist_lut_cache_data = kzalloc( + sizeof(struct mdp_hist_lut_data_v1_7), + GFP_KERNEL); + if (!hist_lut_cache_data) { + pr_err("failed to allocate cache_data\n"); + ret = -ENOMEM; + goto hist_lut_cache_pipe_exit; + } else + pipe->pp_res.hist_lut_cfg_payload = hist_lut_cache_data; + } + + *hist_lut_cache_data = hist_lut_usr_config; + + if (hist_lut_cache_data->len != ENHIST_LUT_ENTRIES) { + pr_err("Invalid Hist LUT length %d\n", + hist_lut_cache_data->len); + ret = -EINVAL; + goto hist_lut_cache_pipe_exit; + } + + if (copy_from_user(pipe->pp_res.hist_lut, + hist_lut_usr_config.data, + sizeof(uint32_t) * hist_lut_cache_data->len)) { + pr_err("Failed to copy usr Hist LUT data\n"); + ret = -EFAULT; + goto hist_lut_cache_pipe_exit; + } + + hist_lut_cache_data->data = pipe->pp_res.hist_lut; + +hist_lut_cache_pipe_exit: + if (ret || (config->ops & MDP_PP_OPS_DISABLE)) { + kfree(pipe->pp_res.hist_lut_cfg_payload); + pipe->pp_res.hist_lut_cfg_payload = NULL; + } + pipe->pp_cfg.hist_lut_cfg.cfg_payload = + pipe->pp_res.hist_lut_cfg_payload; + return ret; +} + int pp_hist_lut_cache_params(struct mdp_hist_lut_data *config, - struct mdss_pp_res_type *mdss_pp_res) + struct mdp_pp_cache_res *res_cache) { int ret = 0; - if (!config || !mdss_pp_res) { - pr_err("invalid param config %p pp_res %p\n", - config, mdss_pp_res); + + if (!config || !res_cache) { + pr_err("invalid param config %p res_cache %p\n", + config, res_cache); + return -EINVAL; + } + if (res_cache->block != SSPP_VIG && res_cache->block != DSPP) { + pr_err("invalid block for Hist LUT %d\n", res_cache->block); return -EINVAL; } + if (!res_cache->mdss_pp_res && !res_cache->pipe_res) { + pr_err("NULL payload for block %d mdss_pp_res %p pipe_res %p\n", + res_cache->block, res_cache->mdss_pp_res, + res_cache->pipe_res); + return -EINVAL; + } + switch (config->version) { case mdp_hist_lut_v1_7: - ret = pp_hist_lut_cache_params_v1_7(config, mdss_pp_res); + if (res_cache->block == DSPP) { + ret = pp_hist_lut_cache_params_v1_7(config, + res_cache->mdss_pp_res); + if (ret) + pr_err("failed to cache Hist LUT params for DSPP ret %d\n", + ret); + } else { + ret = pp_hist_lut_cache_params_pipe_v1_7(config, + res_cache->pipe_res); + if (ret) + pr_err("failed to cache Hist LUT params for SSPP ret %d\n", + ret); + } break; default: pr_err("unsupported hist_lut version %d\n", diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.h b/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.h index 5f6956b782ce..8e5661371bf6 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.h +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.h @@ -23,7 +23,7 @@ struct mdp_pp_cache_res { }; int pp_hist_lut_cache_params(struct mdp_hist_lut_data *config, - struct mdss_pp_res_type *mdss_pp_res); + struct mdp_pp_cache_res *res_cache); int pp_dither_cache_params(struct mdp_dither_cfg_data *config, struct mdss_pp_res_type *mdss_pp_res); diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c b/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c index 5213bbdfde46..e23e9d6143c4 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c @@ -62,10 +62,13 @@ #define IGC_DATA_MASK (BIT(12) - 1) #define IGC_DSPP_OP_MODE_EN BIT(0) -#define MDSS_MDP_DSPP_OP_PA_LUTV_FIRST_EN BIT(21) -#define REG_SSPP_VIG_HIST_LUT_BASE 0x1200 +#define HIST_LUT_VIG_OP_FIRST_EN BIT(21) +#define HIST_LUT_DSPP_OP_FIRST_EN BIT(21) +#define HIST_LUT_VIG_OP_ENABLE BIT(10) +#define HIST_LUT_DSPP_OP_ENABLE BIT(19) +#define REG_SSPP_VIG_HIST_LUT_BASE 0x1400 #define REG_DSPP_HIST_LUT_BASE 0x1400 -#define REG_SSPP_VIG_HIST_SWAP_BASE 0x100 +#define REG_SSPP_VIG_HIST_SWAP_BASE 0x300 #define REG_DSPP_HIST_SWAP_BASE 0x234 #define ENHIST_LOWER_VALUE_MASK 0x3FF #define ENHIST_UPPER_VALUE_MASK 0x3FF0000 @@ -314,6 +317,12 @@ static void pp_opmode_config(int location, struct pp_sts_type *pp_sts, case SSPP_VIG: if (pp_sts->pa_sts & PP_STS_ENABLE) pp_pa_update_vig_opmode(pp_sts->pa_sts, opmode); + if (pp_sts->enhist_sts & PP_STS_ENABLE) { + *opmode |= HIST_LUT_VIG_OP_ENABLE | + PA_VIG_OP_ENABLE; + if (pp_sts->enhist_sts & PP_STS_PA_LUT_FIRST) + *opmode |= HIST_LUT_VIG_OP_FIRST_EN; + } break; case DSPP: if (pp_sts_is_enabled(pp_sts->pa_sts, side)) @@ -321,10 +330,10 @@ static void pp_opmode_config(int location, struct pp_sts_type *pp_sts, if (pp_sts_is_enabled(pp_sts->igc_sts, side)) *opmode |= IGC_DSPP_OP_MODE_EN; if (pp_sts->enhist_sts & PP_STS_ENABLE) { - *opmode |= MDSS_MDP_DSPP_OP_HIST_LUTV_EN | - MDSS_MDP_DSPP_OP_PA_EN; + *opmode |= HIST_LUT_DSPP_OP_ENABLE | + PA_DSPP_OP_ENABLE; if (pp_sts->enhist_sts & PP_STS_PA_LUT_FIRST) - *opmode |= MDSS_MDP_DSPP_OP_PA_LUTV_FIRST_EN; + *opmode |= HIST_LUT_DSPP_OP_FIRST_EN; } if (pp_sts_is_enabled(pp_sts->dither_sts, side)) *opmode |= MDSS_MDP_DSPP_OP_DST_DITHER_EN; @@ -434,12 +443,16 @@ static int pp_hist_lut_set_config(char __iomem *base_addr, } lut_cfg_data = (struct mdp_hist_lut_data *) cfg_data; - if (lut_cfg_data->version != mdp_hist_lut_v1_7 || - !lut_cfg_data->cfg_payload) { - pr_err("invalid hist_lut version %d payload %p\n", - lut_cfg_data->version, lut_cfg_data->cfg_payload); + if (lut_cfg_data->version != mdp_hist_lut_v1_7) { + pr_err("invalid hist_lut version %d\n", lut_cfg_data->version); return -EINVAL; } + + if (lut_cfg_data->ops & MDP_PP_OPS_DISABLE) { + pr_debug("Disable Hist LUT\n"); + goto bail_out; + } + if (!(lut_cfg_data->ops & ~(MDP_PP_OPS_READ))) { pr_err("only read ops set for lut\n"); return ret; @@ -449,6 +462,11 @@ static int pp_hist_lut_set_config(char __iomem *base_addr, goto bail_out; } lut_data = lut_cfg_data->cfg_payload; + if (!lut_data) { + pr_err("invalid hist_lut cfg_payload %p\n", lut_data); + return -EINVAL; + } + if (lut_data->len != ENHIST_LUT_ENTRIES || !lut_data->data) { pr_err("invalid hist_lut len %d data %p\n", lut_data->len, lut_data->data); |
