msm:mdss: Add gamma correction LUT feature for DSPP
Add gamma correction LUT feature for DSPP and define flags to
differentiate between gamma correction on layer mixer and DSPP.
Change-Id: I626324587bd9c7c00e3e053d101959e54b218eac
Signed-off-by: Ping Li <quicpingli@codeaurora.org>
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index b6ac126..a7f0148 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -340,6 +340,7 @@
#define MDSS_MDP_REG_DSPP_HIST_LUT_BASE 0x230
#define MDSS_MDP_REG_DSPP_PA_BASE 0x238
#define MDSS_MDP_REG_DSPP_GAMUT_BASE 0x2DC
+#define MDSS_MDP_REG_DSPP_GC_BASE 0x2B0
enum mdss_mpd_intf_index {
MDSS_MDP_NO_INTF,
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 1482935..7fd6a58 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -131,6 +131,7 @@
u32 enhist_sts;
u32 dither_sts;
u32 gamut_sts;
+ u32 pgc_sts;
};
#define PP_FLAGS_DIRTY_PA 0x1
@@ -141,6 +142,7 @@
#define PP_FLAGS_DIRTY_DITHER 0x20
#define PP_FLAGS_DIRTY_GAMUT 0x40
#define PP_FLAGS_DIRTY_HIST_COL 0x80
+#define PP_FLAGS_DIRTY_PGC 0x100
#define PP_STS_ENABLE 0x1
#define PP_STS_GAMUT_FIRST 0x2
@@ -160,6 +162,7 @@
struct mdp_pa_cfg_data pa_disp_cfg[MDSS_BLOCK_DISP_NUM];
struct mdp_pcc_cfg_data pcc_disp_cfg[MDSS_BLOCK_DISP_NUM];
struct mdp_igc_lut_data igc_disp_cfg[MDSS_BLOCK_DISP_NUM];
+ struct mdp_pgc_lut_data argc_disp_cfg[MDSS_BLOCK_DISP_NUM];
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];
@@ -287,6 +290,7 @@
struct mdp_pgc_lut_data *pgc_config;
struct pp_sts_type *pp_sts;
dspp_num = mixer->num;
+
/* no corresponding dspp */
if ((mixer->type != MDSS_MDP_MIXER_TYPE_INTF) ||
(dspp_num >= MDSS_MDP_MAX_DSPP))
@@ -299,7 +303,7 @@
pp_sts = &mdss_pp_res->pp_dspp_sts[dspp_num];
/* GC_LUT is in layer mixer */
if (flags & PP_FLAGS_DIRTY_ARGC) {
- pgc_config = &mdss_pp_res->pgc_disp_cfg[disp_num];
+ pgc_config = &mdss_pp_res->argc_disp_cfg[disp_num];
if (pgc_config->flags & MDP_PP_OPS_WRITE) {
offset = MDSS_MDP_REG_LM_OFFSET(disp_num) +
MDSS_MDP_REG_LM_GC_LUT_BASE;
@@ -378,10 +382,12 @@
struct mdp_hist_lut_data *enhist_cfg;
struct mdp_dither_cfg_data *dither_cfg;
struct pp_hist_col_info *hist_info;
+ struct mdp_pgc_lut_data *pgc_config;
struct pp_sts_type *pp_sts;
u32 data, tbl_idx, col_state;
unsigned long flag;
int i;
+
dspp_num = mixer->num;
/* no corresponding dspp */
if ((mixer->type != MDSS_MDP_MIXER_TYPE_INTF) ||
@@ -533,6 +539,20 @@
opmode |= (1 << 24); /* GAMUT_ORDER */
}
+ if (flags & PP_FLAGS_DIRTY_PGC) {
+ pgc_config = &mdss_pp_res->pgc_disp_cfg[disp_num];
+ if (pgc_config->flags & MDP_PP_OPS_WRITE) {
+ offset = base + MDSS_MDP_REG_DSPP_GC_BASE;
+ pp_update_argc_lut(offset, pgc_config);
+ }
+ if (pgc_config->flags & MDP_PP_OPS_DISABLE)
+ pp_sts->pgc_sts &= ~PP_STS_ENABLE;
+ else if (pgc_config->flags & MDP_PP_OPS_ENABLE)
+ pp_sts->pgc_sts |= PP_STS_ENABLE;
+ }
+ if (pp_sts->pgc_sts & PP_STS_ENABLE)
+ opmode |= (1 << 22);
+
MDSS_MDP_REG_WRITE(base + MDSS_MDP_REG_DSPP_OP_MODE, opmode);
ctl->flush_bits |= BIT(13 + dspp_num); /* DSPP */
return 0;
@@ -1039,18 +1059,40 @@
int mdss_mdp_argc_config(struct mdp_pgc_lut_data *config, u32 *copyback)
{
int ret = 0;
- u32 argc_offset, disp_num, dspp_num = 0;
+ u32 argc_offset = 0, disp_num, dspp_num = 0;
struct mdp_pgc_lut_data local_cfg;
+ struct mdp_pgc_lut_data *pgc_ptr;
u32 tbl_size;
- if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
- (config->block >= MDP_BLOCK_MAX))
+ if ((PP_BLOCK(config->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
+ (PP_BLOCK(config->block) >= MDP_BLOCK_MAX))
return -EINVAL;
mutex_lock(&mdss_pp_mutex);
- disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
+
+ disp_num = PP_BLOCK(config->block) - MDP_LOGICAL_BLOCK_DISP_0;
+ switch (config->block & MDSS_PP_LOCATION_MASK) {
+ case MDSS_PP_LM_CFG:
+ argc_offset = MDSS_MDP_REG_LM_OFFSET(dspp_num) +
+ MDSS_MDP_REG_LM_GC_LUT_BASE;
+ pgc_ptr = &mdss_pp_res->argc_disp_cfg[disp_num];
+ mdss_pp_res->pp_disp_flags[disp_num] |=
+ PP_FLAGS_DIRTY_ARGC;
+ break;
+ case MDSS_PP_DSPP_CFG:
+ argc_offset = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
+ MDSS_MDP_REG_DSPP_GC_BASE;
+ pgc_ptr = &mdss_pp_res->pgc_disp_cfg[disp_num];
+ mdss_pp_res->pp_disp_flags[disp_num] |=
+ PP_FLAGS_DIRTY_PGC;
+ break;
+ default:
+ goto argc_config_exit;
+ break;
+ }
tbl_size = GC_LUT_SEGMENTS * sizeof(struct mdp_ar_gc_lut_data);
+
if (config->flags & MDP_PP_OPS_READ) {
ret = pp_get_dspp_num(disp_num, &dspp_num);
if (ret) {
@@ -1059,10 +1101,6 @@
goto argc_config_exit;
}
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-
- argc_offset = MDSS_MDP_REG_LM_OFFSET(dspp_num) +
- MDSS_MDP_REG_LM_GC_LUT_BASE;
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
local_cfg = *config;
local_cfg.r_data =
&mdss_pp_res->gc_lut_r[disp_num][0];
@@ -1104,14 +1142,14 @@
ret = -EFAULT;
goto argc_config_exit;
}
- mdss_pp_res->pgc_disp_cfg[disp_num] = *config;
- mdss_pp_res->pgc_disp_cfg[disp_num].r_data =
+
+ *pgc_ptr = *config;
+ pgc_ptr->r_data =
&mdss_pp_res->gc_lut_r[disp_num][0];
- mdss_pp_res->pgc_disp_cfg[disp_num].g_data =
+ pgc_ptr->g_data =
&mdss_pp_res->gc_lut_g[disp_num][0];
- mdss_pp_res->pgc_disp_cfg[disp_num].b_data =
+ pgc_ptr->b_data =
&mdss_pp_res->gc_lut_b[disp_num][0];
- mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_ARGC;
}
argc_config_exit:
mutex_unlock(&mdss_pp_mutex);
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index fdb8fb6..56eda83 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -286,6 +286,18 @@
#define MDP_PP_IGC_FLAG_ROM0 0x10
#define MDP_PP_IGC_FLAG_ROM1 0x20
+#define MDSS_PP_DSPP_CFG 0x0000
+#define MDSS_PP_SSPP_CFG 0x4000
+#define MDSS_PP_LM_CFG 0x8000
+#define MDSS_PP_WB_CFG 0xC000
+
+#define MDSS_PP_LOCATION_MASK 0xC000
+#define MDSS_PP_LOGICAL_MASK 0x3FFF
+
+#define PP_LOCAT(var) ((var) & MDSS_PP_LOCATION_MASK)
+#define PP_BLOCK(var) ((var) & MDSS_PP_LOGICAL_MASK)
+
+
struct mdp_qseed_cfg {
uint32_t table_num;
uint32_t ops;