video: msm: Adding CSC support for other MDP blocks
Adding support for VG1, VG2, DMA_S and Overlay Mixer 1.
Change-Id: I95a5832a70fd893970e82dadcec1e11ed608d79c
Signed-off-by: Carl Vanderlip <carlv@codeaurora.org>
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index ba6c746..40056f0 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -1232,15 +1232,60 @@
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
+struct mdp_csc_cfg mdp_csc_convert[4] = {
+ { /*RGB2RGB*/
+ 0,
+ {
+ 0x0200, 0x0000, 0x0000,
+ 0x0000, 0x0200, 0x0000,
+ 0x0000, 0x0000, 0x0200,
+ },
+ { 0x0, 0x0, 0x0, },
+ { 0x0, 0x0, 0x0, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ },
+ { /*YUV2RGB*/
+ 0,
+ {
+ 0x0254, 0x0000, 0x0331,
+ 0x0254, 0xff37, 0xfe60,
+ 0x0254, 0x0409, 0x0000,
+ },
+ { 0xfff0, 0xff80, 0xff80, },
+ { 0x0, 0x0, 0x0, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ },
+ { /*RGB2YUV*/
+ 0,
+ {
+ 0x0083, 0x0102, 0x0032,
+ 0x1fb5, 0x1f6c, 0x00e1,
+ 0x00e1, 0x1f45, 0x1fdc
+ },
+ { 0x0, 0x0, 0x0, },
+ { 0x0010, 0x0080, 0x0080, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ { 0x0010, 0x00eb, 0x0010, 0x00f0, 0x0010, 0x00f0, },
+ },
+ { /*YUV2YUV ???*/
+ 0,
+ {
+ 0x0200, 0x0000, 0x0000,
+ 0x0000, 0x0200, 0x0000,
+ 0x0000, 0x0000, 0x0200,
+ },
+ { 0x0, 0x0, 0x0, },
+ { 0x0, 0x0, 0x0, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ },
+};
-struct mdp4_csc_matrix {
-uint32 csc_mv[9];
-uint32 csc_pre_bv[3];
-uint32 csc_post_bv[3];
-uint32 csc_pre_lv[6];
-uint32 csc_post_lv[6];
-} csc_matrix[3] = {
+struct mdp_csc_cfg csc_matrix[3] = {
{
+ (MDP_CSC_FLAG_YUV_OUT),
{
0x0254, 0x0000, 0x0331,
0x0254, 0xff37, 0xfe60,
@@ -1260,6 +1305,7 @@
},
},
{
+ (MDP_CSC_FLAG_YUV_OUT),
{
0x0254, 0x0000, 0x0331,
0x0254, 0xff37, 0xfe60,
@@ -1279,6 +1325,7 @@
},
},
{
+ (0),
{
0x0200, 0x0000, 0x0000,
0x0000, 0x0200, 0x0000,
@@ -1392,6 +1439,25 @@
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
+void mdp4_vg_csc_convert_setup(int vp_num)
+{
+ struct mdp_csc_cfg_data cfg;
+
+ switch (vp_num) {
+ case 0:
+ cfg.block = MDP_BLOCK_VG_1;
+ break;
+ case 1:
+ cfg.block = MDP_BLOCK_VG_2;
+ break;
+ default:
+ pr_err("%s - invalid vp_num = %d", __func__, vp_num);
+ return;
+ }
+ cfg.csc_data = csc_matrix[vp_num];
+ mdp4_csc_enable(&cfg);
+}
+
void mdp4_vg_csc_setup(int vp_num)
{
/* yuv2rgb */
@@ -1400,6 +1466,7 @@
mdp4_vg_csc_post_bv_setup(vp_num);
mdp4_vg_csc_pre_lv_setup(vp_num);
mdp4_vg_csc_post_lv_setup(vp_num);
+ mdp4_vg_csc_convert_setup(vp_num);
}
void mdp4_vg_csc_update(struct mdp_csc *p)
{
@@ -2347,13 +2414,15 @@
case MDP_BLOCK_DMA_P:
base = 0x93000;
break;
+ case MDP_BLOCK_DMA_S:
+ base = (mdp_rev >= MDP_REV_42) ? 0xA3000 : 0x0;
default:
break;
}
return base;
}
-static int mdp4_csc_enable(struct mdp_csc_cfg_data *config)
+int mdp4_csc_enable(struct mdp_csc_cfg_data *config)
{
uint32_t output, base, temp, mask;
@@ -2365,9 +2434,32 @@
output |= temp;
mask = 0x08 | 0x1800;
break;
+ case MDP_BLOCK_DMA_S:
+ base = 0xA0028;
+ output = (config->csc_data.flags << 3) & (0x08);
+ temp = (config->csc_data.flags << 10) & (0x1800);
+ output |= temp;
+ mask = 0x08 | 0x1800;
+ break;
case MDP_BLOCK_VG_1:
+ base = 0x20058;
+ output = (config->csc_data.flags << 11) & (0x800);
+ temp = (config->csc_data.flags << 8) & (0x600);
+ output |= temp;
+ mask = 0x800 | 0x600;
+ break;
case MDP_BLOCK_VG_2:
+ base = 0x30058;
+ output = (config->csc_data.flags << 11) & (0x800);
+ temp = (config->csc_data.flags << 8) & (0x600);
+ output |= temp;
+ mask = 0x800 | 0x600;
+ break;
case MDP_BLOCK_OVERLAY_1:
+ base = 0x18200;
+ output = config->csc_data.flags;
+ mask = 0x07;
+ break;
default:
pr_err("%s - CSC block does not exist on MDP_BLOCK = %d\n",
__func__, config->block);
@@ -2387,46 +2479,49 @@
#define CSC_LV_OFF 0x600
#define CSC_POST_OFF 0x80
-int mdp4_csc_config(struct mdp_csc_cfg_data *config)
+void mdp4_csc_write(struct mdp_csc_cfg *data, uint32_t base)
{
- int ret = 0;
int i;
- uint32_t base, *off;
-
- base = mdp4_csc_block2base(config->block);
- if (!base)
- return -EINVAL;
-
- /* TODO: implement other CSC block support */
- if (config->block != MDP_BLOCK_DMA_P) {
- pr_warn("%s: Only DMA_P currently supported by CSC.\n",
- __func__);
- return -EINVAL;
- }
+ uint32_t *off;
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- off = (uint32_t *) (MDP_BASE + base + CSC_MV_OFF);
+ off = (uint32_t *) ((uint32_t) base + CSC_MV_OFF);
for (i = 0; i < 9; i++) {
- outpdw(off, config->csc_data.csc_mv[i]);
+ outpdw(off, data->csc_mv[i]);
off++;
}
- off = (uint32_t *) (MDP_BASE + base + CSC_BV_OFF);
+ off = (uint32_t *) ((uint32_t) base + CSC_BV_OFF);
for (i = 0; i < 3; i++) {
- outpdw(off, config->csc_data.csc_pre_bv[i]);
+ outpdw(off, data->csc_pre_bv[i]);
outpdw((uint32_t *)((uint32_t)off + CSC_POST_OFF),
- config->csc_data.csc_post_bv[i]);
+ data->csc_post_bv[i]);
off++;
}
- off = (uint32_t *) (MDP_BASE + base + CSC_LV_OFF);
+ off = (uint32_t *) ((uint32_t) base + CSC_LV_OFF);
for (i = 0; i < 6; i++) {
- outpdw(off, config->csc_data.csc_pre_lv[i]);
+ outpdw(off, data->csc_pre_lv[i]);
outpdw((uint32_t *)((uint32_t)off + CSC_POST_OFF),
- config->csc_data.csc_post_lv[i]);
+ data->csc_post_lv[i]);
off++;
}
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+int mdp4_csc_config(struct mdp_csc_cfg_data *config)
+{
+ int ret = 0;
+ uint32_t base;
+
+ base = mdp4_csc_block2base(config->block);
+ if (!base) {
+ pr_warn("%s: Block type %d isn't supported by CSC.\n",
+ __func__, config->block);
+ return -EINVAL;
+ }
+
+ mdp4_csc_write(&config->csc_data, (uint32_t) (MDP_BASE + base));
ret = mdp4_csc_enable(config);