diff options
author | Jason Chen <b02280@freescale.com> | 2009-04-14 14:34:31 +0800 |
---|---|---|
committer | Lily Zhang <r58066@freescale.com> | 2009-04-20 17:37:44 +0800 |
commit | 29c598005df2e8b41b0d2dc412ddf3e7b676d421 (patch) | |
tree | 9880e4e8c94f11f303ab90151b09c7b479822969 | |
parent | ccff2306ce2b4a716522aaca1ce4f39506226e5f (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.c | 62 | ||||
-rw-r--r-- | drivers/mxc/ipu3/ipu_ic.c | 138 | ||||
-rw-r--r-- | 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 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; |