diff options
| author | Benet Clark <benetc@codeaurora.org> | 2014-12-30 15:10:08 -0800 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:37:21 -0700 |
| commit | 45420946b4a9ae5fbd43705fedaae46ddb48959b (patch) | |
| tree | 6ea7048d012c187d4556a878633856e75d30310b | |
| parent | c29be55aa3ae563d64890596b38b276c208bfe10 (diff) | |
msm: mdss: Add Hist LUT SSPP support
Histogram LUT (PA LUTV) is supported on source side VIG pipes in MDP.
Clients of MDP driver can enable the feature using overlay ioctl
interface. This change adds support for clients of the driver to
enable the feature.
Change-Id: I888af7d83b3de459353d7865122c40f39e937eac
Signed-off-by: Benet Clark <benetc@codeaurora.org>
| -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); |
