summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLiu Ying <Ying.Liu@freescale.com>2015-03-04 18:20:46 +0800
committerguoyin.chen <guoyin.chen@freescale.com>2015-05-08 17:23:15 +0800
commitb2ea6971ade7f20124269a7cbc4d034cfca00b07 (patch)
tree9184d7325c8c731364c3633c1d75aeae7a556e03 /drivers
parent4e83f3809bfaa1dbee8541c95aa8ff50171b5309 (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.c136
-rw-r--r--drivers/mxc/ipu3/ipu_param_mem.h170
-rw-r--r--drivers/mxc/ipu3/ipu_prv.h3
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(&params, 5, 0, 6, 5, 5, 11, 8, 16);
break;
+ case IPU_PIX_FMT_BGRA4444:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 3); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31); /* burst size */
+
+ _ipu_ch_params_set_packing(&params, 4, 4, 4, 8, 4, 12, 4, 0);
+ break;
+ case IPU_PIX_FMT_BGRA5551:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 3); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31); /* burst size */
+
+ _ipu_ch_params_set_packing(&params, 5, 1, 5, 6, 5, 11, 1, 0);
+ break;
case IPU_PIX_FMT_BGR24:
ipu_ch_param_set_field(&params, 0, 107, 3, 1); /* bits/pixel */
ipu_ch_param_set_field(&params, 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(&params, 8, 8, 8, 0, 8, 16, 8, 24);
break;
+ case IPU_PIX_FMT_AYUV:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 0); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 15); /* burst size */
+
+ _ipu_ch_params_set_packing(&params, 8, 8, 8, 16, 8, 24, 8, 0);
+ break;
case IPU_PIX_FMT_BGRA32:
case IPU_PIX_FMT_BGR32:
ipu_ch_param_set_field(&params, 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(&params, 1, 85, 4, 1); /* pix format */
+ ipu_ch_param_set_field(&params, 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(&params, 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;