diff options
author | Liu Ying <Ying.Liu@freescale.com> | 2015-03-04 18:20:46 +0800 |
---|---|---|
committer | guoyin.chen <guoyin.chen@freescale.com> | 2015-05-08 17:23:15 +0800 |
commit | b2ea6971ade7f20124269a7cbc4d034cfca00b07 (patch) | |
tree | 9184d7325c8c731364c3633c1d75aeae7a556e03 /drivers | |
parent | 4e83f3809bfaa1dbee8541c95aa8ff50171b5309 (diff) |
MLK-10475-3 mxc IPUv3: common: Changes for PRE/PRG
This patchs contains IPUv3 common driver change for adding PRE/PRG support.
Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mxc/ipu3/ipu_common.c | 136 | ||||
-rw-r--r-- | drivers/mxc/ipu3/ipu_param_mem.h | 170 | ||||
-rw-r--r-- | drivers/mxc/ipu3/ipu_prv.h | 3 |
3 files changed, 254 insertions, 55 deletions
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c index 1ae9b7f9e775..9ec7c1a702aa 100644 --- a/drivers/mxc/ipu3/ipu_common.c +++ b/drivers/mxc/ipu3/ipu_common.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2005-2015 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -464,6 +464,10 @@ static int ipu_probe(struct platform_device *pdev) return ret; } + ipu->prg_clk = devm_clk_get(ipu->dev, "prg"); + if (IS_ERR(ipu->prg_clk)) + ipu->prg_clk = NULL; + ipu->online = true; platform_set_drvdata(pdev, ipu); @@ -1366,9 +1370,11 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel, break; case 27: value = 0x3 << 18; + _ipu_ch_param_set_axi_id(ipu, dma_chan, 2); break; case 28: value = 0x3 << 20; + _ipu_ch_param_set_axi_id(ipu, dma_chan, 3); break; case 45: reg = IDMAC_CH_LOCK_EN_2; @@ -1604,6 +1610,19 @@ int32_t ipu_update_channel_offset(struct ipu_soc *ipu, } EXPORT_SYMBOL(ipu_update_channel_offset); +int32_t ipu_get_channel_offset(uint32_t pixel_fmt, + uint16_t width, uint16_t height, + uint32_t stride, + uint32_t u, uint32_t v, + uint32_t vertical_offset, uint32_t horizontal_offset, + uint32_t *u_offset, uint32_t *v_offset) +{ + return __ipu_ch_offset_calc(pixel_fmt, width, height, stride, + u, v, 0, + vertical_offset, horizontal_offset, + u_offset, v_offset); +} +EXPORT_SYMBOL(ipu_get_channel_offset); /*! * This function is called to set a channel's buffer as ready. @@ -2181,6 +2200,9 @@ int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel) ipu->channel_enable_mask |= 1L << IPU_CHAN_ID(channel); + if (ipu->prg_clk) + clk_prepare_enable(ipu->prg_clk); + mutex_unlock(&ipu->mutex_lock); return 0; @@ -2466,6 +2488,9 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai ipu->channel_enable_mask &= ~(1L << IPU_CHAN_ID(channel)); + if (ipu->prg_clk) + clk_disable_unprepare(ipu->prg_clk); + mutex_unlock(&ipu->mutex_lock); return 0; @@ -2973,12 +2998,22 @@ uint32_t bytes_per_pixel(uint32_t fmt) case IPU_PIX_FMT_YVU420P: case IPU_PIX_FMT_YUV422P: case IPU_PIX_FMT_YUV444P: + case IPU_PIX_FMT_NV12: + case PRE_PIX_FMT_NV21: + case IPU_PIX_FMT_NV16: + case PRE_PIX_FMT_NV61: return 1; break; case IPU_PIX_FMT_GENERIC_16: /* generic data */ case IPU_PIX_FMT_RGB565: + case IPU_PIX_FMT_BGRA4444: + case IPU_PIX_FMT_BGRA5551: case IPU_PIX_FMT_YUYV: case IPU_PIX_FMT_UYVY: + case IPU_PIX_FMT_GPU16_SB_ST: + case IPU_PIX_FMT_GPU16_SB_SRT: + case IPU_PIX_FMT_GPU16_ST: + case IPU_PIX_FMT_GPU16_SRT: return 2; break; case IPU_PIX_FMT_BGR24: @@ -2992,6 +3027,11 @@ uint32_t bytes_per_pixel(uint32_t fmt) case IPU_PIX_FMT_RGB32: case IPU_PIX_FMT_RGBA32: case IPU_PIX_FMT_ABGR32: + case IPU_PIX_FMT_GPU32_SB_ST: + case IPU_PIX_FMT_GPU32_SB_SRT: + case IPU_PIX_FMT_GPU32_ST: + case IPU_PIX_FMT_GPU32_SRT: + case IPU_PIX_FMT_AYUV: return 4; break; default: @@ -3007,6 +3047,8 @@ ipu_color_space_t format_to_colorspace(uint32_t fmt) switch (fmt) { case IPU_PIX_FMT_RGB666: case IPU_PIX_FMT_RGB565: + case IPU_PIX_FMT_BGRA4444: + case IPU_PIX_FMT_BGRA5551: case IPU_PIX_FMT_BGR24: case IPU_PIX_FMT_RGB24: case IPU_PIX_FMT_GBR24: @@ -3017,6 +3059,14 @@ ipu_color_space_t format_to_colorspace(uint32_t fmt) case IPU_PIX_FMT_ABGR32: case IPU_PIX_FMT_LVDS666: case IPU_PIX_FMT_LVDS888: + case IPU_PIX_FMT_GPU32_SB_ST: + case IPU_PIX_FMT_GPU32_SB_SRT: + case IPU_PIX_FMT_GPU32_ST: + case IPU_PIX_FMT_GPU32_SRT: + case IPU_PIX_FMT_GPU16_SB_ST: + case IPU_PIX_FMT_GPU16_SB_SRT: + case IPU_PIX_FMT_GPU16_ST: + case IPU_PIX_FMT_GPU16_SRT: return RGB; break; @@ -3026,6 +3076,7 @@ ipu_color_space_t format_to_colorspace(uint32_t fmt) } return RGB; } +EXPORT_SYMBOL(format_to_colorspace); bool ipu_pixel_format_has_alpha(uint32_t fmt) { @@ -3048,6 +3099,89 @@ bool ipu_ch_param_bad_alpha_pos(uint32_t pixel_fmt) } EXPORT_SYMBOL(ipu_ch_param_bad_alpha_pos); +bool ipu_pixel_format_is_gpu_tile(uint32_t fmt) +{ + switch (fmt) { + case IPU_PIX_FMT_GPU32_SB_ST: + case IPU_PIX_FMT_GPU32_SB_SRT: + case IPU_PIX_FMT_GPU32_ST: + case IPU_PIX_FMT_GPU32_SRT: + case IPU_PIX_FMT_GPU16_SB_ST: + case IPU_PIX_FMT_GPU16_SB_SRT: + case IPU_PIX_FMT_GPU16_ST: + case IPU_PIX_FMT_GPU16_SRT: + return true; + default: + return false; + } +} +EXPORT_SYMBOL(ipu_pixel_format_is_gpu_tile); + +bool ipu_pixel_format_is_split_gpu_tile(uint32_t fmt) +{ + switch (fmt) { + case IPU_PIX_FMT_GPU32_SB_ST: + case IPU_PIX_FMT_GPU32_SB_SRT: + case IPU_PIX_FMT_GPU16_SB_ST: + case IPU_PIX_FMT_GPU16_SB_SRT: + return true; + default: + return false; + } +} +EXPORT_SYMBOL(ipu_pixel_format_is_split_gpu_tile); + +bool ipu_pixel_format_is_pre_yuv(uint32_t fmt) +{ + switch (fmt) { + case PRE_PIX_FMT_NV21: + case PRE_PIX_FMT_NV61: + return true; + default: + return false; + } +} +EXPORT_SYMBOL(ipu_pixel_format_is_pre_yuv); + +bool ipu_pixel_format_is_multiplanar_yuv(uint32_t fmt) +{ + switch (fmt) { + case IPU_PIX_FMT_YVU410P: + case IPU_PIX_FMT_YUV420P: + case IPU_PIX_FMT_YUV420P2: + case IPU_PIX_FMT_YVU420P: + case IPU_PIX_FMT_YUV422P: + case IPU_PIX_FMT_YVU422P: + case IPU_PIX_FMT_YUV444P: + case IPU_PIX_FMT_NV12: + case PRE_PIX_FMT_NV21: + case IPU_PIX_FMT_NV16: + case PRE_PIX_FMT_NV61: + return true; + default: + return false; + } +} +EXPORT_SYMBOL(ipu_pixel_format_is_multiplanar_yuv); + +int ipu_ch_param_get_axi_id(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type) +{ + uint32_t dma_chan = channel_2_dma(channel, type); + int axi_id; + + if (!idma_is_valid(dma_chan)) + return -EINVAL; + + _ipu_get(ipu); + mutex_lock(&ipu->mutex_lock); + axi_id = _ipu_ch_param_get_axi_id(ipu, dma_chan); + mutex_unlock(&ipu->mutex_lock); + _ipu_put(ipu); + + return axi_id; +} +EXPORT_SYMBOL(ipu_ch_param_get_axi_id); + #ifdef CONFIG_PM static int ipu_suspend(struct device *dev) { diff --git a/drivers/mxc/ipu3/ipu_param_mem.h b/drivers/mxc/ipu3/ipu_param_mem.h index 2ff622b54824..a97a7d416830 100644 --- a/drivers/mxc/ipu3/ipu_param_mem.h +++ b/drivers/mxc/ipu3/ipu_param_mem.h @@ -1,5 +1,5 @@ /* - * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2005-2015 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -304,6 +304,20 @@ static inline void _ipu_ch_param_init(struct ipu_soc *ipu, int ch, _ipu_ch_params_set_packing(¶ms, 5, 0, 6, 5, 5, 11, 8, 16); break; + case IPU_PIX_FMT_BGRA4444: + ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */ + ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */ + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */ + + _ipu_ch_params_set_packing(¶ms, 4, 4, 4, 8, 4, 12, 4, 0); + break; + case IPU_PIX_FMT_BGRA5551: + ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */ + ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */ + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */ + + _ipu_ch_params_set_packing(¶ms, 5, 1, 5, 6, 5, 11, 1, 0); + break; case IPU_PIX_FMT_BGR24: ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */ ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */ @@ -326,6 +340,13 @@ static inline void _ipu_ch_param_init(struct ipu_soc *ipu, int ch, _ipu_ch_params_set_packing(¶ms, 8, 8, 8, 0, 8, 16, 8, 24); break; + case IPU_PIX_FMT_AYUV: + ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */ + ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */ + ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */ + + _ipu_ch_params_set_packing(¶ms, 8, 8, 8, 16, 8, 24, 8, 0); + break; case IPU_PIX_FMT_BGRA32: case IPU_PIX_FMT_BGR32: ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */ @@ -432,6 +453,12 @@ static inline void _ipu_ch_param_init(struct ipu_soc *ipu, int ch, u_offset = (u == 0) ? stride * height : u; v_offset = (v == 0) ? u_offset * 2 : v; break; + case IPU_PIX_FMT_NV16: + ipu_ch_param_set_field(¶ms, 1, 85, 4, 1); /* pix format */ + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */ + uv_stride = stride; + u_offset = (u == 0) ? stride * height : u; + break; case IPU_PIX_FMT_NV12: /* BPP & pixel format */ ipu_ch_param_set_field(¶ms, 1, 85, 4, 4); /* pix format */ @@ -679,28 +706,25 @@ static inline void _ipu_ch_param_set_axi_id(struct ipu_soc *ipu, uint32_t ch, ui ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 93, 2, id); }; -/* IDMAC U/V offset changing support */ -/* U and V input is not affected, */ -/* the update is done by new calculation according to */ -/* vertical_offset and horizontal_offset */ -static inline void _ipu_ch_offset_update(struct ipu_soc *ipu, - int ch, - uint32_t pixel_fmt, - uint32_t width, - uint32_t height, - uint32_t stride, - uint32_t u, - uint32_t v, - uint32_t uv_stride, - uint32_t vertical_offset, - uint32_t horizontal_offset) +static inline int _ipu_ch_param_get_axi_id(struct ipu_soc *ipu, uint32_t ch) +{ + return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 93, 2); +} + +static inline int __ipu_ch_offset_calc(uint32_t pixel_fmt, + uint32_t width, + uint32_t height, + uint32_t stride, + uint32_t u, + uint32_t v, + uint32_t uv_stride, + uint32_t vertical_offset, + uint32_t horizontal_offset, + uint32_t *u_offset, + uint32_t *v_offset) { - uint32_t u_offset = 0; - uint32_t v_offset = 0; - uint32_t old_offset = 0; uint32_t u_fix = 0; uint32_t v_fix = 0; - int32_t sub_ch = 0; switch (pixel_fmt) { case IPU_PIX_FMT_GENERIC: @@ -717,126 +741,166 @@ static inline void _ipu_ch_offset_update(struct ipu_soc *ipu, case IPU_PIX_FMT_ABGR32: case IPU_PIX_FMT_UYVY: case IPU_PIX_FMT_YUYV: + case IPU_PIX_FMT_GPU32_SB_ST: + case IPU_PIX_FMT_GPU32_SB_SRT: + case IPU_PIX_FMT_GPU32_ST: + case IPU_PIX_FMT_GPU32_SRT: + case IPU_PIX_FMT_GPU16_SB_ST: + case IPU_PIX_FMT_GPU16_SB_SRT: + case IPU_PIX_FMT_GPU16_ST: + case IPU_PIX_FMT_GPU16_SRT: + *u_offset = 0; + *v_offset = 0; break; - case IPU_PIX_FMT_YUV420P2: case IPU_PIX_FMT_YUV420P: if (uv_stride < stride / 2) uv_stride = stride / 2; - u_offset = stride * (height - vertical_offset - 1) + + *u_offset = stride * (height - vertical_offset - 1) + (stride - horizontal_offset) + (uv_stride * vertical_offset / 2) + horizontal_offset / 2; - v_offset = u_offset + (uv_stride * height / 2); + *v_offset = *u_offset + (uv_stride * height / 2); u_fix = u ? (u + (uv_stride * vertical_offset / 2) + (horizontal_offset / 2) - (stride * vertical_offset) - (horizontal_offset)) : - u_offset; + *u_offset; v_fix = v ? (v + (uv_stride * vertical_offset / 2) + (horizontal_offset / 2) - (stride * vertical_offset) - (horizontal_offset)) : - v_offset; - + *v_offset; break; case IPU_PIX_FMT_YVU420P: if (uv_stride < stride / 2) uv_stride = stride / 2; - v_offset = stride * (height - vertical_offset - 1) + + *v_offset = stride * (height - vertical_offset - 1) + (stride - horizontal_offset) + (uv_stride * vertical_offset / 2) + horizontal_offset / 2; - u_offset = v_offset + (uv_stride * height / 2); + *u_offset = *v_offset + (uv_stride * height / 2); u_fix = u ? (u + (uv_stride * vertical_offset / 2) + (horizontal_offset / 2) - (stride * vertical_offset) - (horizontal_offset)) : - u_offset; + *u_offset; v_fix = v ? (v + (uv_stride * vertical_offset / 2) + (horizontal_offset / 2) - (stride * vertical_offset) - (horizontal_offset)) : - v_offset; - + *v_offset; break; case IPU_PIX_FMT_YVU422P: if (uv_stride < stride / 2) uv_stride = stride / 2; - v_offset = stride * (height - vertical_offset - 1) + + *v_offset = stride * (height - vertical_offset - 1) + (stride - horizontal_offset) + (uv_stride * vertical_offset) + horizontal_offset / 2; - u_offset = v_offset + uv_stride * height; + *u_offset = *v_offset + uv_stride * height; u_fix = u ? (u + (uv_stride * vertical_offset) + horizontal_offset / 2 - (stride * vertical_offset) - (horizontal_offset)) : - u_offset; + *u_offset; v_fix = v ? (v + (uv_stride * vertical_offset) + horizontal_offset / 2 - (stride * vertical_offset) - (horizontal_offset)) : - v_offset; + *v_offset; break; case IPU_PIX_FMT_YUV422P: if (uv_stride < stride / 2) uv_stride = stride / 2; - u_offset = stride * (height - vertical_offset - 1) + + *u_offset = stride * (height - vertical_offset - 1) + (stride - horizontal_offset) + (uv_stride * vertical_offset) + horizontal_offset / 2; - v_offset = u_offset + uv_stride * height; + *v_offset = *u_offset + uv_stride * height; u_fix = u ? (u + (uv_stride * vertical_offset) + horizontal_offset / 2 - (stride * vertical_offset) - (horizontal_offset)) : - u_offset; + *u_offset; v_fix = v ? (v + (uv_stride * vertical_offset) + horizontal_offset / 2 - (stride * vertical_offset) - (horizontal_offset)) : - v_offset; + *v_offset; break; - case IPU_PIX_FMT_YUV444P: uv_stride = stride; - u_offset = stride * (height - vertical_offset - 1) + + *u_offset = stride * (height - vertical_offset - 1) + (stride - horizontal_offset) + (uv_stride * vertical_offset) + horizontal_offset; - v_offset = u_offset + uv_stride * height; + *v_offset = *u_offset + uv_stride * height; u_fix = u ? (u + (uv_stride * vertical_offset) + horizontal_offset - (stride * vertical_offset) - (horizontal_offset)) : - u_offset; + *u_offset; v_fix = v ? (v + (uv_stride * vertical_offset) + horizontal_offset - (stride * vertical_offset) - (horizontal_offset)) : - v_offset; + *v_offset; break; case IPU_PIX_FMT_NV12: + case IPU_PIX_FMT_NV16: + case PRE_PIX_FMT_NV21: + case PRE_PIX_FMT_NV61: uv_stride = stride; - u_offset = stride * (height - vertical_offset - 1) + + *u_offset = stride * (height - vertical_offset - 1) + (stride - horizontal_offset) + (uv_stride * vertical_offset / 2) + horizontal_offset; + *v_offset = 0; u_fix = u ? (u + (uv_stride * vertical_offset / 2) + horizontal_offset - (stride * vertical_offset) - (horizontal_offset)) : - u_offset; - + *u_offset; break; default: - dev_err(ipu->dev, "mxc ipu: unimplemented pixel format\n"); - break; + return -EINVAL; } + if (u_fix > *u_offset) + *u_offset = u_fix; + if (v_fix > *v_offset) + *v_offset = v_fix; - if (u_fix > u_offset) - u_offset = u_fix; + return 0; +} - if (v_fix > v_offset) - v_offset = v_fix; +/* IDMAC U/V offset changing support */ +/* U and V input is not affected, */ +/* the update is done by new calculation according to */ +/* vertical_offset and horizontal_offset */ +static inline void _ipu_ch_offset_update(struct ipu_soc *ipu, + int ch, + uint32_t pixel_fmt, + uint32_t width, + uint32_t height, + uint32_t stride, + uint32_t u, + uint32_t v, + uint32_t uv_stride, + uint32_t vertical_offset, + uint32_t horizontal_offset) +{ + uint32_t u_offset = 0; + uint32_t v_offset = 0; + uint32_t old_offset = 0; + int32_t sub_ch = 0; + int ret; + + ret = __ipu_ch_offset_calc(pixel_fmt, width, height, stride, + u, v, uv_stride, + vertical_offset, horizontal_offset, + &u_offset, &v_offset); + if (ret) { + dev_err(ipu->dev, "mxc ipu: unimplemented pixel format\n"); + return; + } /* UBO and VBO are 22-bit and 8-byte aligned */ if (u_offset/8 > 0x3fffff) diff --git a/drivers/mxc/ipu3/ipu_prv.h b/drivers/mxc/ipu3/ipu_prv.h index 076339813809..a6a4602d12bb 100644 --- a/drivers/mxc/ipu3/ipu_prv.h +++ b/drivers/mxc/ipu3/ipu_prv.h @@ -1,5 +1,5 @@ /* - * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2005-2015 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -73,6 +73,7 @@ struct ipu_soc { struct clk *pixel_clk[2]; struct clk *pixel_clk_sel[2]; struct clk *csi_clk[2]; + struct clk *prg_clk; /*irq*/ int irq_sync; |