[PATCH 41/133] [Jaunty SRU] ARM.imx51 Freescale:ENGR00108639 ipuv3: add IC overlay support

Brad Figg brad.figg at canonical.com
Thu Jul 9 16:48:31 UTC 2009


From: Jason Chen <b02280 at freescale.com>

enable IC graphic combination feature.

Signed-off-by: Jason Chen <b02280 at freescale.com>
Signed-off-by: Brad Figg <brad.figg at canonical.com>
---
 drivers/mxc/ipu3/ipu_common.c |   62 ++++++++++++++++++
 drivers/mxc/ipu3/ipu_ic.c     |  138 +++++++++++++++++++++++++++++++----------
 include/linux/ipu.h           |    8 +++
 3 files changed, 175 insertions(+), 33 deletions(-)

diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c
index 704fb54..5499960 100644
--- a/drivers/mxc/ipu3/ipu_common.c
+++ b/drivers/mxc/ipu3/ipu_common.c
@@ -50,6 +50,7 @@ ipu_channel_t g_ipu_csi_channel[2];
 int g_ipu_irq[2];
 int g_ipu_hw_rev;
 bool g_sec_chan_en[21];
+bool g_thrd_chan_en[21];
 uint32_t g_channel_init_mask;
 uint32_t g_channel_enable_mask;
 DEFINE_SPINLOCK(ipu_lock);
@@ -438,6 +439,8 @@ int32_t ipu_init_channel(ipu_channel_t channel, ipu_channel_params_t *params)
 
 		if (params->mem_prp_vf_mem.graphics_combine_en)
 			g_sec_chan_en[IPU_CHAN_ID(channel)] = true;
+		if (params->mem_prp_vf_mem.alpha_chan_en)
+			g_thrd_chan_en[IPU_CHAN_ID(channel)] = true;
 
 		_ipu_ic_init_prpvf(params, false);
 		break;
@@ -460,6 +463,8 @@ int32_t ipu_init_channel(ipu_channel_t channel, ipu_channel_params_t *params)
 	case MEM_PP_MEM:
 		if (params->mem_pp_mem.graphics_combine_en)
 			g_sec_chan_en[IPU_CHAN_ID(channel)] = true;
+		if (params->mem_pp_mem.alpha_chan_en)
+			g_thrd_chan_en[IPU_CHAN_ID(channel)] = true;
 		_ipu_ic_init_pp(params);
 		ipu_ic_use_count++;
 		break;
@@ -607,6 +612,7 @@ void ipu_uninit_channel(ipu_channel_t channel)
 	__raw_writel(reg & ~idma_mask(out_dma), IPU_CHA_DB_MODE_SEL(out_dma));
 
 	g_sec_chan_en[IPU_CHAN_ID(channel)] = false;
+	g_thrd_chan_en[IPU_CHAN_ID(channel)] = false;
 
 	switch (channel) {
 	case CSI_MEM0:
@@ -1324,6 +1330,8 @@ int32_t ipu_enable_channel(ipu_channel_t channel)
 	unsigned long lock_flags;
 	uint32_t in_dma;
 	uint32_t out_dma;
+	uint32_t sec_dma;
+	uint32_t thrd_dma;
 
 	if (g_channel_enable_mask & (1L << IPU_CHAN_ID(channel))) {
 		dev_err(g_ipu_dev, "Warning: channel already enabled %d\n",
@@ -1345,6 +1353,19 @@ int32_t ipu_enable_channel(ipu_channel_t channel)
 		__raw_writel(reg | idma_mask(out_dma), IDMAC_CHA_EN(out_dma));
 	}
 
+	if ((g_sec_chan_en[IPU_CHAN_ID(channel)]) &&
+		((channel == MEM_PP_MEM) || (channel == MEM_PRP_VF_MEM))) {
+		sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
+		reg = __raw_readl(IDMAC_CHA_EN(sec_dma));
+		__raw_writel(reg | idma_mask(sec_dma), IDMAC_CHA_EN(sec_dma));
+	}
+	if ((g_thrd_chan_en[IPU_CHAN_ID(channel)]) &&
+		((channel == MEM_PP_MEM) || (channel == MEM_PRP_VF_MEM))) {
+		thrd_dma = channel_2_dma(channel, IPU_ALPHA_IN_BUFFER);
+		reg = __raw_readl(IDMAC_CHA_EN(thrd_dma));
+		__raw_writel(reg | idma_mask(thrd_dma), IDMAC_CHA_EN(thrd_dma));
+	}
+
 	if ((channel == MEM_DC_SYNC) || (channel == MEM_BG_SYNC) ||
 	    (channel == MEM_FG_SYNC))
 		_ipu_dp_dc_enable(channel);
@@ -1378,6 +1399,8 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop)
 	unsigned long lock_flags;
 	uint32_t in_dma;
 	uint32_t out_dma;
+	uint32_t sec_dma = NO_DMA;
+	uint32_t thrd_dma = NO_DMA;
 	uint32_t timeout;
 
 	if ((g_channel_enable_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
@@ -1396,6 +1419,11 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop)
 		!idma_is_set(IDMAC_CHA_EN, out_dma)))
 		return -EINVAL;
 
+	if (g_sec_chan_en[IPU_CHAN_ID(channel)])
+		sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
+	if (g_thrd_chan_en[IPU_CHAN_ID(channel)])
+		thrd_dma = channel_2_dma(channel, IPU_ALPHA_IN_BUFFER);
+
 	if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC) ||
 	    (channel == MEM_DC_SYNC)) {
 		_ipu_dp_dc_disable(channel);
@@ -1403,6 +1431,10 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop)
 		timeout = 40;
 		while (idma_is_set(IDMAC_CHA_BUSY, in_dma) ||
 		       idma_is_set(IDMAC_CHA_BUSY, out_dma) ||
+			(g_sec_chan_en[IPU_CHAN_ID(channel)] &&
+			idma_is_set(IDMAC_CHA_BUSY, sec_dma)) ||
+			(g_thrd_chan_en[IPU_CHAN_ID(channel)] &&
+			idma_is_set(IDMAC_CHA_BUSY, thrd_dma)) ||
 		       (_ipu_channel_status(channel) == TASK_STAT_ACTIVE)) {
 			timeout--;
 			msleep(10);
@@ -1432,6 +1464,16 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop)
 		__raw_writel(reg & ~idma_mask(out_dma), IDMAC_CHA_EN(out_dma));
 		__raw_writel(idma_mask(out_dma), IPU_CHA_CUR_BUF(out_dma));
 	}
+	if (g_sec_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(sec_dma)) {
+		reg = __raw_readl(IDMAC_CHA_EN(sec_dma));
+		__raw_writel(reg & ~idma_mask(sec_dma), IDMAC_CHA_EN(sec_dma));
+		__raw_writel(idma_mask(sec_dma), IPU_CHA_CUR_BUF(sec_dma));
+	}
+	if (g_thrd_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(thrd_dma)) {
+		reg = __raw_readl(IDMAC_CHA_EN(thrd_dma));
+		__raw_writel(reg & ~idma_mask(thrd_dma), IDMAC_CHA_EN(thrd_dma));
+		__raw_writel(idma_mask(thrd_dma), IPU_CHA_CUR_BUF(thrd_dma));
+	}
 
 	/* Set channel buffers NOT to be ready */
 	__raw_writel(0xF0000000, IPU_GPR); /* write one to clear */
@@ -1455,6 +1497,26 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop)
 				     IPU_CHA_BUF1_RDY(out_dma));
 		}
 	}
+	if (g_sec_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(sec_dma)) {
+		if (idma_is_set(IPU_CHA_BUF0_RDY, sec_dma)) {
+			__raw_writel(idma_mask(sec_dma),
+				     IPU_CHA_BUF0_RDY(sec_dma));
+		}
+		if (idma_is_set(IPU_CHA_BUF1_RDY, sec_dma)) {
+			__raw_writel(idma_mask(sec_dma),
+				     IPU_CHA_BUF1_RDY(sec_dma));
+		}
+	}
+	if (g_thrd_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(thrd_dma)) {
+		if (idma_is_set(IPU_CHA_BUF0_RDY, thrd_dma)) {
+			__raw_writel(idma_mask(thrd_dma),
+				     IPU_CHA_BUF0_RDY(thrd_dma));
+		}
+		if (idma_is_set(IPU_CHA_BUF1_RDY, thrd_dma)) {
+			__raw_writel(idma_mask(thrd_dma),
+				     IPU_CHA_BUF1_RDY(thrd_dma));
+		}
+	}
 	__raw_writel(0x0, IPU_GPR); /* write one to set */
 
 	g_channel_enable_mask &= ~(1L << IPU_CHAN_ID(channel));
diff --git a/drivers/mxc/ipu3/ipu_ic.c b/drivers/mxc/ipu3/ipu_ic.c
index c7708a3..4a05ce5 100644
--- a/drivers/mxc/ipu3/ipu_ic.c
+++ b/drivers/mxc/ipu3/ipu_ic.c
@@ -36,7 +36,7 @@ enum {
 };
 
 static void _init_csc(uint8_t ic_task, ipu_color_space_t in_format,
-		      ipu_color_space_t out_format);
+		      ipu_color_space_t out_format, int csc_index);
 static bool _calc_resize_coeffs(uint32_t inSize, uint32_t outSize,
 				uint32_t *resizeCoeff,
 				uint32_t *downsizeCoeff);
@@ -145,15 +145,15 @@ void _ipu_ic_init_prpvf(ipu_channel_params_t *params, bool src_is_csi)
 	out_fmt = format_to_colorspace(params->mem_prp_vf_mem.out_pixel_fmt);
 	if (in_fmt == RGB) {
 		if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
-			/* Enable RGB->YCBCR CSC */
-			_init_csc(IC_TASK_VIEWFINDER, RGB, out_fmt);
+			/* Enable RGB->YCBCR CSC1 */
+			_init_csc(IC_TASK_VIEWFINDER, RGB, out_fmt, 1);
 			ic_conf |= IC_CONF_PRPVF_CSC1;
 		}
 	}
 	if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
 		if (out_fmt == RGB) {
-			/* Enable YCBCR->RGB CSC */
-			_init_csc(IC_TASK_VIEWFINDER, YCbCr, RGB);
+			/* Enable YCBCR->RGB CSC1 */
+			_init_csc(IC_TASK_VIEWFINDER, YCbCr, RGB, 1);
 			ic_conf |= IC_CONF_PRPVF_CSC1;
 		} else {
 			/* TODO: Support YUV<->YCbCr conversion? */
@@ -163,18 +163,44 @@ void _ipu_ic_init_prpvf(ipu_channel_params_t *params, bool src_is_csi)
 	if (params->mem_prp_vf_mem.graphics_combine_en) {
 		ic_conf |= IC_CONF_PRPVF_CMB;
 
-		/* need transparent CSC1 conversion */
-		_init_csc(IC_TASK_POST_PROCESSOR, RGB, RGB);
-		ic_conf |= IC_CONF_PRPVF_CSC1;	/* Enable RGB->RGB CSC */
+		if (!(ic_conf & IC_CONF_PRPVF_CSC1)) {
+			/* need transparent CSC1 conversion */
+			_init_csc(IC_TASK_VIEWFINDER, RGB, RGB, 1);
+			ic_conf |= IC_CONF_PRPVF_CSC1;  /* Enable RGB->RGB CSC */
+		}
+		in_fmt = format_to_colorspace(params->mem_prp_vf_mem.in_g_pixel_fmt);
+		out_fmt = format_to_colorspace(params->mem_prp_vf_mem.out_pixel_fmt);
+		if (in_fmt == RGB) {
+			if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
+				/* Enable RGB->YCBCR CSC2 */
+				_init_csc(IC_TASK_VIEWFINDER, RGB, out_fmt, 2);
+				ic_conf |= IC_CONF_PRPVF_CSC2;
+			}
+		}
+		if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
+			if (out_fmt == RGB) {
+				/* Enable YCBCR->RGB CSC2 */
+				_init_csc(IC_TASK_VIEWFINDER, YCbCr, RGB, 2);
+				ic_conf |= IC_CONF_PRPVF_CSC2;
+			} else {
+				/* TODO: Support YUV<->YCbCr conversion? */
+			}
+		}
 
-		if (params->mem_prp_vf_mem.global_alpha_en)
+		if (params->mem_prp_vf_mem.global_alpha_en) {
 			ic_conf |= IC_CONF_IC_GLB_LOC_A;
-		else
+			reg = __raw_readl(IC_CMBP_1);
+			reg &= ~(0xff);
+			reg |= params->mem_prp_vf_mem.alpha;
+			__raw_writel(reg, IC_CMBP_1);
+		} else
 			ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
 
-		if (params->mem_prp_vf_mem.key_color_en)
+		if (params->mem_prp_vf_mem.key_color_en) {
 			ic_conf |= IC_CONF_KEY_COLOR_EN;
-		else
+			__raw_writel(params->mem_prp_vf_mem.key_color,
+					IC_CMBP_2);
+		} else
 			ic_conf &= ~IC_CONF_KEY_COLOR_EN;
 	} else {
 		ic_conf &= ~IC_CONF_PRPVF_CMB;
@@ -237,15 +263,15 @@ void _ipu_ic_init_prpenc(ipu_channel_params_t *params, bool src_is_csi)
 	out_fmt = format_to_colorspace(params->mem_prp_enc_mem.out_pixel_fmt);
 	if (in_fmt == RGB) {
 		if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
-			/* Enable RGB->YCBCR CSC */
-			_init_csc(IC_TASK_ENCODER, RGB, out_fmt);
+			/* Enable RGB->YCBCR CSC1 */
+			_init_csc(IC_TASK_ENCODER, RGB, out_fmt, 1);
 			ic_conf |= IC_CONF_PRPENC_CSC1;
 		}
 	}
 	if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
 		if (out_fmt == RGB) {
-			/* Enable YCBCR->RGB CSC */
-			_init_csc(IC_TASK_ENCODER, YCbCr, RGB);
+			/* Enable YCBCR->RGB CSC1 */
+			_init_csc(IC_TASK_ENCODER, YCbCr, RGB, 1);
 			ic_conf |= IC_CONF_PRPENC_CSC1;
 		} else {
 			/* TODO: Support YUV<->YCbCr conversion? */
@@ -309,15 +335,15 @@ void _ipu_ic_init_pp(ipu_channel_params_t *params)
 	out_fmt = format_to_colorspace(params->mem_pp_mem.out_pixel_fmt);
 	if (in_fmt == RGB) {
 		if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
-			/* Enable RGB->YCBCR CSC */
-			_init_csc(IC_TASK_POST_PROCESSOR, RGB, out_fmt);
+			/* Enable RGB->YCBCR CSC1 */
+			_init_csc(IC_TASK_POST_PROCESSOR, RGB, out_fmt, 1);
 			ic_conf |= IC_CONF_PP_CSC1;
 		}
 	}
 	if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
 		if (out_fmt == RGB) {
-			/* Enable YCBCR->RGB CSC */
-			_init_csc(IC_TASK_POST_PROCESSOR, YCbCr, RGB);
+			/* Enable YCBCR->RGB CSC1 */
+			_init_csc(IC_TASK_POST_PROCESSOR, YCbCr, RGB, 1);
 			ic_conf |= IC_CONF_PP_CSC1;
 		} else {
 			/* TODO: Support YUV<->YCbCr conversion? */
@@ -327,18 +353,45 @@ void _ipu_ic_init_pp(ipu_channel_params_t *params)
 	if (params->mem_pp_mem.graphics_combine_en) {
 		ic_conf |= IC_CONF_PP_CMB;
 
-		/* need transparent CSC1 conversion */
-		_init_csc(IC_TASK_POST_PROCESSOR, RGB, RGB);
-		ic_conf |= IC_CONF_PP_CSC1;	/* Enable RGB->RGB CSC */
+		if (!(ic_conf & IC_CONF_PP_CSC1)) {
+			/* need transparent CSC1 conversion */
+			_init_csc(IC_TASK_POST_PROCESSOR, RGB, RGB, 1);
+			ic_conf |= IC_CONF_PP_CSC1;  /* Enable RGB->RGB CSC */
+		}
 
-		if (params->mem_pp_mem.global_alpha_en)
+		in_fmt = format_to_colorspace(params->mem_pp_mem.in_g_pixel_fmt);
+		out_fmt = format_to_colorspace(params->mem_pp_mem.out_pixel_fmt);
+		if (in_fmt == RGB) {
+			if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
+				/* Enable RGB->YCBCR CSC2 */
+				_init_csc(IC_TASK_POST_PROCESSOR, RGB, out_fmt, 2);
+				ic_conf |= IC_CONF_PP_CSC2;
+			}
+		}
+		if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
+			if (out_fmt == RGB) {
+				/* Enable YCBCR->RGB CSC2 */
+				_init_csc(IC_TASK_POST_PROCESSOR, YCbCr, RGB, 2);
+				ic_conf |= IC_CONF_PP_CSC2;
+			} else {
+				/* TODO: Support YUV<->YCbCr conversion? */
+			}
+		}
+
+		if (params->mem_pp_mem.global_alpha_en) {
 			ic_conf |= IC_CONF_IC_GLB_LOC_A;
-		else
+			reg = __raw_readl(IC_CMBP_1);
+			reg &= ~(0xff00);
+			reg |= (params->mem_pp_mem.alpha << 8);
+			__raw_writel(reg, IC_CMBP_1);
+		} else
 			ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
 
-		if (params->mem_pp_mem.key_color_en)
+		if (params->mem_pp_mem.key_color_en) {
 			ic_conf |= IC_CONF_KEY_COLOR_EN;
-		else
+			__raw_writel(params->mem_pp_mem.key_color,
+					IC_CMBP_2);
+		} else
 			ic_conf &= ~IC_CONF_KEY_COLOR_EN;
 	} else {
 		ic_conf &= ~IC_CONF_PP_CMB;
@@ -467,6 +520,19 @@ int _ipu_ic_idma_init(int dma_chan, uint16_t width, uint16_t height,
 		ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
 		ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
 	}
+
+	if (dma_chan == 14) {	/* PRP VF graphics combining input - CB3 */
+		if (burst_size == 16)
+			ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
+		else
+			ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
+	} else if (dma_chan == 15) {	/* PP graphics combining input - CB4 */
+		if (burst_size == 16)
+			ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
+		else
+			ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
+	}
+
 	__raw_writel(ic_idmac_1, IC_IDMAC_1);
 	__raw_writel(ic_idmac_2, IC_IDMAC_2);
 	__raw_writel(ic_idmac_3, IC_IDMAC_3);
@@ -475,7 +541,7 @@ int _ipu_ic_idma_init(int dma_chan, uint16_t width, uint16_t height,
 }
 
 static void _init_csc(uint8_t ic_task, ipu_color_space_t in_format,
-		      ipu_color_space_t out_format)
+		      ipu_color_space_t out_format, int csc_index)
 {
 
 /*     Y = R *  .299 + G *  .587 + B *  .114;
@@ -513,15 +579,21 @@ static void _init_csc(uint8_t ic_task, ipu_color_space_t in_format,
 	if (ic_task == IC_TASK_ENCODER) {
 		base = ipu_tpmem_base + 0x2008 / 4;
 	} else if (ic_task == IC_TASK_VIEWFINDER) {
-		base = ipu_tpmem_base + 0x4028 / 4;
+		if (csc_index == 1)
+			base = ipu_tpmem_base + 0x4028 / 4;
+		else
+			base = ipu_tpmem_base + 0x4040 / 4;
 	} else if (ic_task == IC_TASK_POST_PROCESSOR) {
-		base = ipu_tpmem_base + 0x6060 / 4;
+		if (csc_index == 1)
+			base = ipu_tpmem_base + 0x6060 / 4;
+		else
+			base = ipu_tpmem_base + 0x6078 / 4;
 	} else {
 		BUG();
 	}
 
 	if ((in_format == YCbCr) && (out_format == RGB)) {
-		/* Init CSC1 (YCbCr->RGB) */
+		/* Init CSC (YCbCr->RGB) */
 		param = (ycbcr2rgb_coeff[3][0] << 27) |
 			(ycbcr2rgb_coeff[0][0] << 18) |
 			(ycbcr2rgb_coeff[1][1] << 9) | ycbcr2rgb_coeff[2][2];
@@ -544,7 +616,7 @@ static void _init_csc(uint8_t ic_task, ipu_color_space_t in_format,
 		param = (ycbcr2rgb_coeff[3][2] >> 5);
 		__raw_writel(param, base++);
 	} else if ((in_format == RGB) && (out_format == YCbCr)) {
-		/* Init CSC1 (RGB->YCbCr) */
+		/* Init CSC (RGB->YCbCr) */
 		param = (rgb2ycbcr_coeff[3][0] << 27) |
 			(rgb2ycbcr_coeff[0][0] << 18) |
 			(rgb2ycbcr_coeff[1][1] << 9) | rgb2ycbcr_coeff[2][2];
@@ -567,7 +639,7 @@ static void _init_csc(uint8_t ic_task, ipu_color_space_t in_format,
 		param = (rgb2ycbcr_coeff[3][2] >> 5);
 		__raw_writel(param, base++);
 	} else if ((in_format == RGB) && (out_format == RGB)) {
-		/* Init CSC1 */
+		/* Init CSC */
 		param =
 		    (rgb2rgb_coeff[3][0] << 27) | (rgb2rgb_coeff[0][0] << 18) |
 		    (rgb2rgb_coeff[1][1] << 9) | rgb2rgb_coeff[2][2];
diff --git a/include/linux/ipu.h b/include/linux/ipu.h
index 81002a9..0857e18 100644
--- a/include/linux/ipu.h
+++ b/include/linux/ipu.h
@@ -347,6 +347,10 @@ typedef union {
 		bool graphics_combine_en;
 		bool global_alpha_en;
 		bool key_color_en;
+		uint32_t in_g_pixel_fmt;
+		uint8_t alpha;
+		uint32_t key_color;
+		bool alpha_chan_en;
 	} mem_prp_vf_mem;
 	struct {
 		uint32_t temp;
@@ -364,6 +368,10 @@ typedef union {
 		bool graphics_combine_en;
 		bool global_alpha_en;
 		bool key_color_en;
+		uint32_t in_g_pixel_fmt;
+		uint8_t alpha;
+		uint32_t key_color;
+		bool alpha_chan_en;
 	} mem_pp_mem;
 	struct {
 		uint32_t temp;
-- 
1.6.0.4





More information about the kernel-team mailing list