diff options
| author | Ken Zhang <kenz@codeaurora.org> | 2012-08-19 14:41:01 -0400 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:12:35 -0700 |
| commit | fbb2fb454d94c99addf979b18501f28ef704dd67 (patch) | |
| tree | 7f7eaa9dd269544c8b1e8c33493f5cefda198252 /drivers/video | |
| parent | 440b2987a5404a1efdacd182a7b228d1fabdea61 (diff) | |
msm: display: pp: gamut mapping support
Support gamut mapping via pp ioctl with logical display id.
Allow changing processing order with pcc.
Change-Id: Ia37afbe40b73c08fd8760bae84307889280368ce
Signed-off-by: Ken Zhang <kenz@codeaurora.org>
Diffstat (limited to 'drivers/video')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_fb.c | 4 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.h | 1 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_hwio.h | 1 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_pp.c | 148 |
4 files changed, 154 insertions, 0 deletions
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index f5650d361b4f..e4478b146e45 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -1187,6 +1187,10 @@ static int mdss_fb_handle_pp_ioctl(void __user *argp) ret = mdss_mdp_dither_config(&mdp_pp.data.dither_cfg_data, ©back); break; + case mdp_op_gamut_cfg: + ret = mdss_mdp_gamut_config(&mdp_pp.data.gamut_cfg_data, + ©back); + break; default: pr_err("Unsupported request to MDP_PP IOCTL.\n"); ret = -EINVAL; diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index 71769e00ef70..4e7a5282e1de 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -307,6 +307,7 @@ int mdss_mdp_igc_lut_config(struct mdp_igc_lut_data *config, u32 *copyback); int mdss_mdp_argc_config(struct mdp_pgc_lut_data *config, u32 *copyback); int mdss_mdp_hist_lut_config(struct mdp_hist_lut_data *config, u32 *copyback); int mdss_mdp_dither_config(struct mdp_dither_cfg_data *config, u32 *copyback); +int mdss_mdp_gamut_config(struct mdp_gamut_cfg_data *config, u32 *copyback); struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_pnum(u32 pnum); struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_locked(u32 type); diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h index 823ce88556bf..be44c7e0b43f 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h +++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h @@ -336,6 +336,7 @@ enum mdss_mdp_dspp_index { #define MDSS_MDP_REG_DSPP_DITHER_DEPTH 0x150 #define MDSS_MDP_REG_DSPP_PA_BASE 0x238 #define MDSS_MDP_REG_DSPP_HIST_LUT_BASE 0x230 +#define MDSS_MDP_REG_DSPP_GAMUT_BASE 0x2DC enum mdss_mpd_intf_index { MDSS_MDP_NO_INTF, diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c index 934234ee5f45..2037c186888e 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c @@ -74,6 +74,7 @@ struct mdp_csc_cfg mdp_csc_convert[MDSS_MDP_MAX_CSC] = { #define CSC_POST_OFF 0xC #define MDSS_BLOCK_DISP_NUM (MDP_BLOCK_MAX - MDP_LOGICAL_BLOCK_DISP_0) + #define IGC_LUT_ENTRIES 256 #define GC_LUT_SEGMENTS 16 #define ENHIST_LUT_ENTRIES 256 @@ -83,6 +84,17 @@ static u32 dither_matrix[16] = { static u32 dither_depth_map[9] = { 0, 0, 0, 0, 0, 1, 2, 3, 3}; +#define GAMUT_T0_SIZE 125 +#define GAMUT_T1_SIZE 100 +#define GAMUT_T2_SIZE 80 +#define GAMUT_T3_SIZE 100 +#define GAMUT_T4_SIZE 100 +#define GAMUT_T5_SIZE 80 +#define GAMUT_T6_SIZE 64 +#define GAMUT_T7_SIZE 80 +#define GAMUT_TOTAL_TABLE_SIZE (GAMUT_T0_SIZE + GAMUT_T1_SIZE + \ + GAMUT_T2_SIZE + GAMUT_T3_SIZE + GAMUT_T4_SIZE + \ + GAMUT_T5_SIZE + GAMUT_T6_SIZE + GAMUT_T7_SIZE) struct pp_sts_type { u32 pa_sts; @@ -92,6 +104,7 @@ struct pp_sts_type { u32 argc_sts; u32 enhist_sts; u32 dither_sts; + u32 gamut_sts; }; #define PP_FLAGS_DIRTY_PA 0x1 @@ -100,8 +113,10 @@ struct pp_sts_type { #define PP_FLAGS_DIRTY_ARGC 0x8 #define PP_FLAGS_DIRTY_ENHIST 0x10 #define PP_FLAGS_DIRTY_DITHER 0x20 +#define PP_FLAGS_DIRTY_GAMUT 0x40 #define PP_STS_ENABLE 0x1 +#define PP_STS_GAMUT_FIRST 0x2 struct mdss_pp_res_type { /* logical info */ @@ -121,6 +136,8 @@ struct mdss_pp_res_type { struct mdp_pgc_lut_data pgc_disp_cfg[MDSS_BLOCK_DISP_NUM]; struct mdp_hist_lut_data enhist_disp_cfg[MDSS_BLOCK_DISP_NUM]; struct mdp_dither_cfg_data dither_disp_cfg[MDSS_BLOCK_DISP_NUM]; + struct mdp_gamut_cfg_data gamut_disp_cfg[MDSS_BLOCK_DISP_NUM]; + uint16_t gamut_tbl[MDSS_BLOCK_DISP_NUM][GAMUT_TOTAL_TABLE_SIZE]; /* physical info */ struct pp_sts_type pp_dspp_sts[MDSS_MDP_MAX_DSPP]; }; @@ -267,6 +284,41 @@ static int pp_mixer_setup(u32 disp_num, struct mdss_mdp_ctl *ctl, } return 0; } +static void pp_gamut_config(struct mdp_gamut_cfg_data *gamut_cfg, + u32 base, + u32 *gamut_sts) +{ + u32 offset; + int i, j; + if (gamut_cfg->flags & MDP_PP_OPS_WRITE) { + offset = base + MDSS_MDP_REG_DSPP_GAMUT_BASE; + for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) { + for (j = 0; j < gamut_cfg->tbl_size[i]; j++) + MDSS_MDP_REG_WRITE(offset, + (u32)gamut_cfg->r_tbl[i][j]); + offset += 4; + } + for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) { + for (j = 0; j < gamut_cfg->tbl_size[i]; j++) + MDSS_MDP_REG_WRITE(offset, + (u32)gamut_cfg->g_tbl[i][j]); + offset += 4; + } + for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) { + for (j = 0; j < gamut_cfg->tbl_size[i]; j++) + MDSS_MDP_REG_WRITE(offset, + (u32)gamut_cfg->b_tbl[i][j]); + offset += 4; + } + if (gamut_cfg->gamut_first) + *gamut_sts |= PP_STS_GAMUT_FIRST; + } + + if (gamut_cfg->flags & MDP_PP_OPS_DISABLE) + *gamut_sts &= ~PP_STS_ENABLE; + else if (gamut_cfg->flags & MDP_PP_OPS_ENABLE) + *gamut_sts |= PP_STS_ENABLE; +} static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_ctl *ctl, struct mdss_mdp_mixer *mixer) { @@ -404,6 +456,15 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_ctl *ctl, } if (pp_sts->dither_sts & PP_STS_ENABLE) opmode |= (1 << 8); /* DITHER_EN */ + if (flags & PP_FLAGS_DIRTY_GAMUT) + pp_gamut_config(&mdss_pp_res->gamut_disp_cfg[disp_num], + base, &pp_sts->gamut_sts); + if (pp_sts->gamut_sts & PP_STS_ENABLE) { + opmode |= (1 << 23); /* GAMUT_EN */ + if (pp_sts->gamut_sts & PP_STS_GAMUT_FIRST) + opmode |= (1 << 24); /* GAMUT_ORDER */ + } + MDSS_MDP_REG_WRITE(base + MDSS_MDP_REG_DSPP_OP_MODE, opmode); ctl->flush_bits |= BIT(13 + dspp_num); /* DSPP */ return 0; @@ -1039,3 +1100,90 @@ int mdss_mdp_dither_config(struct mdp_dither_cfg_data *config, u32 *copyback) mutex_unlock(&mdss_pp_mutex); return 0; } + +int mdss_mdp_gamut_config(struct mdp_gamut_cfg_data *config, u32 *copyback) +{ + int i, j, size_total = 0, ret = 0; + u32 offset, disp_num, dspp_num = 0; + uint16_t *tbl_off; + struct mdp_gamut_cfg_data local_cfg; + + if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) || + (config->block >= MDP_BLOCK_MAX)) + return -EINVAL; + for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) + size_total += config->tbl_size[i]; + if (size_total != GAMUT_TOTAL_TABLE_SIZE) + return -EINVAL; + + mutex_lock(&mdss_pp_mutex); + disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0; + + if (config->flags & MDP_PP_OPS_READ) { + ret = pp_get_dspp_num(disp_num, &dspp_num); + if (ret) { + pr_err("%s, no dspp connects to disp %d", + __func__, disp_num); + goto gamut_config_exit; + } + mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); + + offset = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) + + MDSS_MDP_REG_DSPP_GAMUT_BASE; + for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) { + for (j = 0; j < config->tbl_size[i]; j++) + config->r_tbl[i][j] = + (u16)MDSS_MDP_REG_READ(offset); + offset += 4; + } + for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) { + for (j = 0; j < config->tbl_size[i]; j++) + config->g_tbl[i][j] = + (u16)MDSS_MDP_REG_READ(offset); + offset += 4; + } + for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) { + for (j = 0; j < config->tbl_size[i]; j++) + config->b_tbl[i][j] = + (u16)MDSS_MDP_REG_READ(offset); + offset += 4; + } + *copyback = 1; + mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false); + } else { + local_cfg = *config; + tbl_off = mdss_pp_res->gamut_tbl[disp_num]; + for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) { + local_cfg.r_tbl[i] = tbl_off; + if (copy_from_user(tbl_off, config->r_tbl[i], + config->tbl_size[i] * sizeof(uint16_t))) { + ret = -EFAULT; + goto gamut_config_exit; + } + tbl_off += local_cfg.tbl_size[i]; + } + for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) { + local_cfg.g_tbl[i] = tbl_off; + if (copy_from_user(tbl_off, config->g_tbl[i], + config->tbl_size[i] * sizeof(uint16_t))) { + ret = -EFAULT; + goto gamut_config_exit; + } + tbl_off += local_cfg.tbl_size[i]; + } + for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) { + local_cfg.b_tbl[i] = tbl_off; + if (copy_from_user(tbl_off, config->b_tbl[i], + config->tbl_size[i] * sizeof(uint16_t))) { + ret = -EFAULT; + goto gamut_config_exit; + } + tbl_off += local_cfg.tbl_size[i]; + } + mdss_pp_res->gamut_disp_cfg[disp_num] = local_cfg; + mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_GAMUT; + } +gamut_config_exit: + mutex_unlock(&mdss_pp_mutex); + return ret; +} |
