summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Chen <b02280@freescale.com>2009-04-14 14:34:31 +0800
committerLily Zhang <r58066@freescale.com>2009-04-20 17:37:44 +0800
commit29c598005df2e8b41b0d2dc412ddf3e7b676d421 (patch)
tree9880e4e8c94f11f303ab90151b09c7b479822969
parentccff2306ce2b4a716522aaca1ce4f39506226e5f (diff)
ENGR00108639 ipuv3: add IC overlay support
enable IC graphic combination feature. Signed-off-by: Jason Chen <b02280@freescale.com>
-rw-r--r--drivers/mxc/ipu3/ipu_common.c62
-rw-r--r--drivers/mxc/ipu3/ipu_ic.c138
-rw-r--r--include/linux/ipu.h8
3 files changed, 175 insertions, 33 deletions
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c
index 704fb547473b..549996008828 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 c7708a3b4fed..4a05ce5c86fd 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 81002a9421d2..0857e18c7a43 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;