Re: [PATCH v2 1/5] gpu: ipu-v3: Move i.MX IPUv3 core driver out of staging

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Am Montag, den 26.05.2014, 16:19 +0200 schrieb Philipp Zabel:
> The i.MX Image Processing Unit (IPU) contains a number of image processing
> blocks that sit right in the middle between DRM and V4L2. Some of the modules,
> such as Display Controller, Processor, and Interface (DC, DP, DI) or CMOS
> Sensor Interface (CSI) and their FIFOs could be assigned to either framework,
> but others, such as the dma controller (IDMAC) and image converter (IC) can
> be used by both.
> The IPUv3 core driver provides an internal API to access the modules, to be
> used by both DRM and V4L2 IPUv3 drivers.
>
>Signed-off-by: Lucas Stach <l.stach@xxxxxxxxxxxxxx>
>Signed-off-by: Philipp Zabel <p.zabel@xxxxxxxxxxxxxx>

And here is a complete version of the move without format-patch -M
parameter:

---
 drivers/gpu/Makefile                        |    1 +
 drivers/gpu/ipu-v3/Kconfig                  |    7 +
 drivers/gpu/ipu-v3/Makefile                 |    3 +
 drivers/gpu/ipu-v3/ipu-common.c             | 1292 +++++++++++++++++++++++++++
 drivers/gpu/ipu-v3/ipu-dc.c                 |  460 ++++++++++
 drivers/gpu/ipu-v3/ipu-di.c                 |  730 +++++++++++++++
 drivers/gpu/ipu-v3/ipu-dmfc.c               |  436 +++++++++
 drivers/gpu/ipu-v3/ipu-dp.c                 |  363 ++++++++
 drivers/gpu/ipu-v3/ipu-prv.h                |  209 +++++
 drivers/staging/imx-drm/Kconfig             |   11 +-
 drivers/staging/imx-drm/Makefile            |    1 -
 drivers/staging/imx-drm/imx-hdmi.c          |    2 +-
 drivers/staging/imx-drm/imx-tve.c           |    2 +-
 drivers/staging/imx-drm/ipu-v3/Makefile     |    3 -
 drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h |  331 -------
 drivers/staging/imx-drm/ipu-v3/ipu-common.c | 1292 ---------------------------
 drivers/staging/imx-drm/ipu-v3/ipu-dc.c     |  461 ----------
 drivers/staging/imx-drm/ipu-v3/ipu-di.c     |  730 ---------------
 drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c   |  436 ---------
 drivers/staging/imx-drm/ipu-v3/ipu-dp.c     |  363 --------
 drivers/staging/imx-drm/ipu-v3/ipu-prv.h    |  209 -----
 drivers/staging/imx-drm/ipuv3-crtc.c        |    2 +-
 drivers/staging/imx-drm/ipuv3-plane.c       |    2 +-
 drivers/video/Kconfig                       |    1 +
 include/video/imx-ipu-v3.h                  |  331 +++++++
 25 files changed, 3838 insertions(+), 3840 deletions(-)
 create mode 100644 drivers/gpu/ipu-v3/Kconfig
 create mode 100644 drivers/gpu/ipu-v3/Makefile
 create mode 100644 drivers/gpu/ipu-v3/ipu-common.c
 create mode 100644 drivers/gpu/ipu-v3/ipu-dc.c
 create mode 100644 drivers/gpu/ipu-v3/ipu-di.c
 create mode 100644 drivers/gpu/ipu-v3/ipu-dmfc.c
 create mode 100644 drivers/gpu/ipu-v3/ipu-dp.c
 create mode 100644 drivers/gpu/ipu-v3/ipu-prv.h
 delete mode 100644 drivers/staging/imx-drm/ipu-v3/Makefile
 delete mode 100644 drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
 delete mode 100644 drivers/staging/imx-drm/ipu-v3/ipu-common.c
 delete mode 100644 drivers/staging/imx-drm/ipu-v3/ipu-dc.c
 delete mode 100644 drivers/staging/imx-drm/ipu-v3/ipu-di.c
 delete mode 100644 drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
 delete mode 100644 drivers/staging/imx-drm/ipu-v3/ipu-dp.c
 delete mode 100644 drivers/staging/imx-drm/ipu-v3/ipu-prv.h
 create mode 100644 include/video/imx-ipu-v3.h

diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile
index d8a22c2..70da9eb 100644
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -1,2 +1,3 @@
 obj-y			+= drm/ vga/
 obj-$(CONFIG_TEGRA_HOST1X)	+= host1x/
+obj-$(CONFIG_IMX_IPUV3_CORE)	+= ipu-v3/
diff --git a/drivers/gpu/ipu-v3/Kconfig b/drivers/gpu/ipu-v3/Kconfig
new file mode 100644
index 0000000..2f228a2
--- /dev/null
+++ b/drivers/gpu/ipu-v3/Kconfig
@@ -0,0 +1,7 @@
+config IMX_IPUV3_CORE
+	tristate "IPUv3 core support"
+	depends on SOC_IMX5 || SOC_IMX6Q || SOC_IMX6SL || ARCH_MULTIPLATFORM
+	depends on RESET_CONTROLLER
+	help
+	  Choose this if you have a i.MX5/6 system and want to use the Image
+	  Processing Unit. This option only enables IPU base support.
diff --git a/drivers/gpu/ipu-v3/Makefile b/drivers/gpu/ipu-v3/Makefile
new file mode 100644
index 0000000..d21cc37
--- /dev/null
+++ b/drivers/gpu/ipu-v3/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
+
+imx-ipu-v3-objs := ipu-common.o ipu-dc.o ipu-di.o ipu-dp.o ipu-dmfc.o
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
new file mode 100644
index 0000000..ad99477
--- /dev/null
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -0,0 +1,1292 @@
+/*
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/reset.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/list.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_device.h>
+
+#include <drm/drm_fourcc.h>
+
+#include <video/imx-ipu-v3.h>
+#include "ipu-prv.h"
+
+static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
+{
+	return readl(ipu->cm_reg + offset);
+}
+
+static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset)
+{
+	writel(value, ipu->cm_reg + offset);
+}
+
+static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
+{
+	return readl(ipu->idmac_reg + offset);
+}
+
+static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
+		unsigned offset)
+{
+	writel(value, ipu->idmac_reg + offset);
+}
+
+void ipu_srm_dp_sync_update(struct ipu_soc *ipu)
+{
+	u32 val;
+
+	val = ipu_cm_read(ipu, IPU_SRM_PRI2);
+	val |= 0x8;
+	ipu_cm_write(ipu, val, IPU_SRM_PRI2);
+}
+EXPORT_SYMBOL_GPL(ipu_srm_dp_sync_update);
+
+struct ipu_ch_param __iomem *ipu_get_cpmem(struct ipuv3_channel *channel)
+{
+	struct ipu_soc *ipu = channel->ipu;
+
+	return ipu->cpmem_base + channel->num;
+}
+EXPORT_SYMBOL_GPL(ipu_get_cpmem);
+
+void ipu_cpmem_set_high_priority(struct ipuv3_channel *channel)
+{
+	struct ipu_soc *ipu = channel->ipu;
+	struct ipu_ch_param __iomem *p = ipu_get_cpmem(channel);
+	u32 val;
+
+	if (ipu->ipu_type == IPUV3EX)
+		ipu_ch_param_write_field(p, IPU_FIELD_ID, 1);
+
+	val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(channel->num));
+	val |= 1 << (channel->num % 32);
+	ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(channel->num));
+};
+EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
+
+void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 v)
+{
+	u32 bit = (wbs >> 8) % 160;
+	u32 size = wbs & 0xff;
+	u32 word = (wbs >> 8) / 160;
+	u32 i = bit / 32;
+	u32 ofs = bit % 32;
+	u32 mask = (1 << size) - 1;
+	u32 val;
+
+	pr_debug("%s %d %d %d\n", __func__, word, bit , size);
+
+	val = readl(&base->word[word].data[i]);
+	val &= ~(mask << ofs);
+	val |= v << ofs;
+	writel(val, &base->word[word].data[i]);
+
+	if ((bit + size - 1) / 32 > i) {
+		val = readl(&base->word[word].data[i + 1]);
+		val &= ~(mask >> (ofs ? (32 - ofs) : 0));
+		val |= v >> (ofs ? (32 - ofs) : 0);
+		writel(val, &base->word[word].data[i + 1]);
+	}
+}
+EXPORT_SYMBOL_GPL(ipu_ch_param_write_field);
+
+u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs)
+{
+	u32 bit = (wbs >> 8) % 160;
+	u32 size = wbs & 0xff;
+	u32 word = (wbs >> 8) / 160;
+	u32 i = bit / 32;
+	u32 ofs = bit % 32;
+	u32 mask = (1 << size) - 1;
+	u32 val = 0;
+
+	pr_debug("%s %d %d %d\n", __func__, word, bit , size);
+
+	val = (readl(&base->word[word].data[i]) >> ofs) & mask;
+
+	if ((bit + size - 1) / 32 > i) {
+		u32 tmp;
+		tmp = readl(&base->word[word].data[i + 1]);
+		tmp &= mask >> (ofs ? (32 - ofs) : 0);
+		val |= tmp << (ofs ? (32 - ofs) : 0);
+	}
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(ipu_ch_param_read_field);
+
+int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *p,
+		const struct ipu_rgb *rgb)
+{
+	int bpp = 0, npb = 0, ro, go, bo, to;
+
+	ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
+	go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
+	bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
+	to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
+
+	ipu_ch_param_write_field(p, IPU_FIELD_WID0, rgb->red.length - 1);
+	ipu_ch_param_write_field(p, IPU_FIELD_OFS0, ro);
+	ipu_ch_param_write_field(p, IPU_FIELD_WID1, rgb->green.length - 1);
+	ipu_ch_param_write_field(p, IPU_FIELD_OFS1, go);
+	ipu_ch_param_write_field(p, IPU_FIELD_WID2, rgb->blue.length - 1);
+	ipu_ch_param_write_field(p, IPU_FIELD_OFS2, bo);
+
+	if (rgb->transp.length) {
+		ipu_ch_param_write_field(p, IPU_FIELD_WID3,
+				rgb->transp.length - 1);
+		ipu_ch_param_write_field(p, IPU_FIELD_OFS3, to);
+	} else {
+		ipu_ch_param_write_field(p, IPU_FIELD_WID3, 7);
+		ipu_ch_param_write_field(p, IPU_FIELD_OFS3,
+				rgb->bits_per_pixel);
+	}
+
+	switch (rgb->bits_per_pixel) {
+	case 32:
+		bpp = 0;
+		npb = 15;
+		break;
+	case 24:
+		bpp = 1;
+		npb = 19;
+		break;
+	case 16:
+		bpp = 3;
+		npb = 31;
+		break;
+	case 8:
+		bpp = 5;
+		npb = 63;
+		break;
+	default:
+		return -EINVAL;
+	}
+	ipu_ch_param_write_field(p, IPU_FIELD_BPP, bpp);
+	ipu_ch_param_write_field(p, IPU_FIELD_NPB, npb);
+	ipu_ch_param_write_field(p, IPU_FIELD_PFS, 7); /* rgb mode */
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
+
+int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p,
+		int width)
+{
+	int bpp = 0, npb = 0;
+
+	switch (width) {
+	case 32:
+		bpp = 0;
+		npb = 15;
+		break;
+	case 24:
+		bpp = 1;
+		npb = 19;
+		break;
+	case 16:
+		bpp = 3;
+		npb = 31;
+		break;
+	case 8:
+		bpp = 5;
+		npb = 63;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ipu_ch_param_write_field(p, IPU_FIELD_BPP, bpp);
+	ipu_ch_param_write_field(p, IPU_FIELD_NPB, npb);
+	ipu_ch_param_write_field(p, IPU_FIELD_PFS, 6); /* raw mode */
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
+
+void ipu_cpmem_set_yuv_interleaved(struct ipu_ch_param __iomem *p,
+				   u32 pixel_format)
+{
+	switch (pixel_format) {
+	case V4L2_PIX_FMT_UYVY:
+		ipu_ch_param_write_field(p, IPU_FIELD_BPP, 3);    /* bits/pixel */
+		ipu_ch_param_write_field(p, IPU_FIELD_PFS, 0xA);  /* pix format */
+		ipu_ch_param_write_field(p, IPU_FIELD_NPB, 31);   /* burst size */
+		break;
+	case V4L2_PIX_FMT_YUYV:
+		ipu_ch_param_write_field(p, IPU_FIELD_BPP, 3);    /* bits/pixel */
+		ipu_ch_param_write_field(p, IPU_FIELD_PFS, 0x8);  /* pix format */
+		ipu_ch_param_write_field(p, IPU_FIELD_NPB, 31);   /* burst size */
+		break;
+	}
+}
+EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
+
+void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p,
+		u32 pixel_format, int stride, int u_offset, int v_offset)
+{
+	switch (pixel_format) {
+	case V4L2_PIX_FMT_YUV420:
+		ipu_ch_param_write_field(p, IPU_FIELD_SLUV, (stride / 2) - 1);
+		ipu_ch_param_write_field(p, IPU_FIELD_UBO, u_offset / 8);
+		ipu_ch_param_write_field(p, IPU_FIELD_VBO, v_offset / 8);
+		break;
+	case V4L2_PIX_FMT_YVU420:
+		ipu_ch_param_write_field(p, IPU_FIELD_SLUV, (stride / 2) - 1);
+		ipu_ch_param_write_field(p, IPU_FIELD_UBO, v_offset / 8);
+		ipu_ch_param_write_field(p, IPU_FIELD_VBO, u_offset / 8);
+		break;
+	}
+}
+EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
+
+void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format,
+		int stride, int height)
+{
+	int u_offset, v_offset;
+	int uv_stride = 0;
+
+	switch (pixel_format) {
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		uv_stride = stride / 2;
+		u_offset = stride * height;
+		v_offset = u_offset + (uv_stride * height / 2);
+		ipu_cpmem_set_yuv_planar_full(p, pixel_format, stride,
+				u_offset, v_offset);
+		break;
+	}
+}
+EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar);
+
+static const struct ipu_rgb def_rgb_32 = {
+	.red	= { .offset = 16, .length = 8, },
+	.green	= { .offset =  8, .length = 8, },
+	.blue	= { .offset =  0, .length = 8, },
+	.transp = { .offset = 24, .length = 8, },
+	.bits_per_pixel = 32,
+};
+
+static const struct ipu_rgb def_bgr_32 = {
+	.red	= { .offset =  0, .length = 8, },
+	.green	= { .offset =  8, .length = 8, },
+	.blue	= { .offset = 16, .length = 8, },
+	.transp = { .offset = 24, .length = 8, },
+	.bits_per_pixel = 32,
+};
+
+static const struct ipu_rgb def_rgb_24 = {
+	.red	= { .offset = 16, .length = 8, },
+	.green	= { .offset =  8, .length = 8, },
+	.blue	= { .offset =  0, .length = 8, },
+	.transp = { .offset =  0, .length = 0, },
+	.bits_per_pixel = 24,
+};
+
+static const struct ipu_rgb def_bgr_24 = {
+	.red	= { .offset =  0, .length = 8, },
+	.green	= { .offset =  8, .length = 8, },
+	.blue	= { .offset = 16, .length = 8, },
+	.transp = { .offset =  0, .length = 0, },
+	.bits_per_pixel = 24,
+};
+
+static const struct ipu_rgb def_rgb_16 = {
+	.red	= { .offset = 11, .length = 5, },
+	.green	= { .offset =  5, .length = 6, },
+	.blue	= { .offset =  0, .length = 5, },
+	.transp = { .offset =  0, .length = 0, },
+	.bits_per_pixel = 16,
+};
+
+static const struct ipu_rgb def_bgr_16 = {
+	.red	= { .offset =  0, .length = 5, },
+	.green	= { .offset =  5, .length = 6, },
+	.blue	= { .offset = 11, .length = 5, },
+	.transp = { .offset =  0, .length = 0, },
+	.bits_per_pixel = 16,
+};
+
+#define Y_OFFSET(pix, x, y)	((x) + pix->width * (y))
+#define U_OFFSET(pix, x, y)	((pix->width * pix->height) + \
+					(pix->width * (y) / 4) + (x) / 2)
+#define V_OFFSET(pix, x, y)	((pix->width * pix->height) + \
+					(pix->width * pix->height / 4) + \
+					(pix->width * (y) / 4) + (x) / 2)
+
+int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 drm_fourcc)
+{
+	switch (drm_fourcc) {
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+		/* pix format */
+		ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 2);
+		/* burst size */
+		ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 63);
+		break;
+	case DRM_FORMAT_UYVY:
+		/* bits/pixel */
+		ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3);
+		/* pix format */
+		ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 0xA);
+		/* burst size */
+		ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31);
+		break;
+	case DRM_FORMAT_YUYV:
+		/* bits/pixel */
+		ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3);
+		/* pix format */
+		ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 0x8);
+		/* burst size */
+		ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31);
+		break;
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_XBGR8888:
+		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_32);
+		break;
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XRGB8888:
+		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32);
+		break;
+	case DRM_FORMAT_BGR888:
+		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_24);
+		break;
+	case DRM_FORMAT_RGB888:
+		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_24);
+		break;
+	case DRM_FORMAT_RGB565:
+		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_16);
+		break;
+	case DRM_FORMAT_BGR565:
+		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_16);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
+
+/*
+ * The V4L2 spec defines packed RGB formats in memory byte order, which from
+ * point of view of the IPU corresponds to little-endian words with the first
+ * component in the least significant bits.
+ * The DRM pixel formats and IPU internal representation are ordered the other
+ * way around, with the first named component ordered at the most significant
+ * bits. Further, V4L2 formats are not well defined:
+ *     http://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
+ * We choose the interpretation which matches GStreamer behavior.
+ */
+static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
+{
+	switch (pixelformat) {
+	case V4L2_PIX_FMT_RGB565:
+		/*
+		 * Here we choose the 'corrected' interpretation of RGBP, a
+		 * little-endian 16-bit word with the red component at the most
+		 * significant bits:
+		 * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
+		 */
+		return DRM_FORMAT_RGB565;
+	case V4L2_PIX_FMT_BGR24:
+		/* B G R <=> [24:0] R:G:B */
+		return DRM_FORMAT_RGB888;
+	case V4L2_PIX_FMT_RGB24:
+		/* R G B <=> [24:0] B:G:R */
+		return DRM_FORMAT_BGR888;
+	case V4L2_PIX_FMT_BGR32:
+		/* B G R A <=> [32:0] A:B:G:R */
+		return DRM_FORMAT_XRGB8888;
+	case V4L2_PIX_FMT_RGB32:
+		/* R G B A <=> [32:0] A:B:G:R */
+		return DRM_FORMAT_XBGR8888;
+	case V4L2_PIX_FMT_UYVY:
+		return DRM_FORMAT_UYVY;
+	case V4L2_PIX_FMT_YUYV:
+		return DRM_FORMAT_YUYV;
+	case V4L2_PIX_FMT_YUV420:
+		return DRM_FORMAT_YUV420;
+	case V4L2_PIX_FMT_YVU420:
+		return DRM_FORMAT_YVU420;
+	}
+
+	return -EINVAL;
+}
+
+enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
+{
+	switch (drm_fourcc) {
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_RGBX8888:
+	case DRM_FORMAT_BGRX8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_RGBA8888:
+	case DRM_FORMAT_BGRA8888:
+		return IPUV3_COLORSPACE_RGB;
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+		return IPUV3_COLORSPACE_YUV;
+	default:
+		return IPUV3_COLORSPACE_UNKNOWN;
+	}
+}
+EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace);
+
+int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem,
+		struct ipu_image *image)
+{
+	struct v4l2_pix_format *pix = &image->pix;
+	int y_offset, u_offset, v_offset;
+
+	pr_debug("%s: resolution: %dx%d stride: %d\n",
+			__func__, pix->width, pix->height,
+			pix->bytesperline);
+
+	ipu_cpmem_set_resolution(cpmem, image->rect.width,
+			image->rect.height);
+	ipu_cpmem_set_stride(cpmem, pix->bytesperline);
+
+	ipu_cpmem_set_fmt(cpmem, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
+
+	switch (pix->pixelformat) {
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		y_offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
+		u_offset = U_OFFSET(pix, image->rect.left,
+				image->rect.top) - y_offset;
+		v_offset = V_OFFSET(pix, image->rect.left,
+				image->rect.top) - y_offset;
+
+		ipu_cpmem_set_yuv_planar_full(cpmem, pix->pixelformat,
+				pix->bytesperline, u_offset, v_offset);
+		ipu_cpmem_set_buffer(cpmem, 0, image->phys + y_offset);
+		break;
+	case V4L2_PIX_FMT_UYVY:
+	case V4L2_PIX_FMT_YUYV:
+		ipu_cpmem_set_buffer(cpmem, 0, image->phys +
+				image->rect.left * 2 +
+				image->rect.top * image->pix.bytesperline);
+		break;
+	case V4L2_PIX_FMT_RGB32:
+	case V4L2_PIX_FMT_BGR32:
+		ipu_cpmem_set_buffer(cpmem, 0, image->phys +
+				image->rect.left * 4 +
+				image->rect.top * image->pix.bytesperline);
+		break;
+	case V4L2_PIX_FMT_RGB565:
+		ipu_cpmem_set_buffer(cpmem, 0, image->phys +
+				image->rect.left * 2 +
+				image->rect.top * image->pix.bytesperline);
+		break;
+	case V4L2_PIX_FMT_RGB24:
+	case V4L2_PIX_FMT_BGR24:
+		ipu_cpmem_set_buffer(cpmem, 0, image->phys +
+				image->rect.left * 3 +
+				image->rect.top * image->pix.bytesperline);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_cpmem_set_image);
+
+enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
+{
+	switch (pixelformat) {
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+	case V4L2_PIX_FMT_UYVY:
+	case V4L2_PIX_FMT_YUYV:
+		return IPUV3_COLORSPACE_YUV;
+	case V4L2_PIX_FMT_RGB32:
+	case V4L2_PIX_FMT_BGR32:
+	case V4L2_PIX_FMT_RGB24:
+	case V4L2_PIX_FMT_BGR24:
+	case V4L2_PIX_FMT_RGB565:
+		return IPUV3_COLORSPACE_RGB;
+	default:
+		return IPUV3_COLORSPACE_UNKNOWN;
+	}
+}
+EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace);
+
+struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num)
+{
+	struct ipuv3_channel *channel;
+
+	dev_dbg(ipu->dev, "%s %d\n", __func__, num);
+
+	if (num > 63)
+		return ERR_PTR(-ENODEV);
+
+	mutex_lock(&ipu->channel_lock);
+
+	channel = &ipu->channel[num];
+
+	if (channel->busy) {
+		channel = ERR_PTR(-EBUSY);
+		goto out;
+	}
+
+	channel->busy = true;
+	channel->num = num;
+
+out:
+	mutex_unlock(&ipu->channel_lock);
+
+	return channel;
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_get);
+
+void ipu_idmac_put(struct ipuv3_channel *channel)
+{
+	struct ipu_soc *ipu = channel->ipu;
+
+	dev_dbg(ipu->dev, "%s %d\n", __func__, channel->num);
+
+	mutex_lock(&ipu->channel_lock);
+
+	channel->busy = false;
+
+	mutex_unlock(&ipu->channel_lock);
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_put);
+
+#define idma_mask(ch)			(1 << (ch & 0x1f))
+
+void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
+		bool doublebuffer)
+{
+	struct ipu_soc *ipu = channel->ipu;
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&ipu->lock, flags);
+
+	reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
+	if (doublebuffer)
+		reg |= idma_mask(channel->num);
+	else
+		reg &= ~idma_mask(channel->num);
+	ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num));
+
+	spin_unlock_irqrestore(&ipu->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer);
+
+int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
+{
+	unsigned long lock_flags;
+	u32 val;
+
+	spin_lock_irqsave(&ipu->lock, lock_flags);
+
+	val = ipu_cm_read(ipu, IPU_DISP_GEN);
+
+	if (mask & IPU_CONF_DI0_EN)
+		val |= IPU_DI0_COUNTER_RELEASE;
+	if (mask & IPU_CONF_DI1_EN)
+		val |= IPU_DI1_COUNTER_RELEASE;
+
+	ipu_cm_write(ipu, val, IPU_DISP_GEN);
+
+	val = ipu_cm_read(ipu, IPU_CONF);
+	val |= mask;
+	ipu_cm_write(ipu, val, IPU_CONF);
+
+	spin_unlock_irqrestore(&ipu->lock, lock_flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_module_enable);
+
+int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
+{
+	unsigned long lock_flags;
+	u32 val;
+
+	spin_lock_irqsave(&ipu->lock, lock_flags);
+
+	val = ipu_cm_read(ipu, IPU_CONF);
+	val &= ~mask;
+	ipu_cm_write(ipu, val, IPU_CONF);
+
+	val = ipu_cm_read(ipu, IPU_DISP_GEN);
+
+	if (mask & IPU_CONF_DI0_EN)
+		val &= ~IPU_DI0_COUNTER_RELEASE;
+	if (mask & IPU_CONF_DI1_EN)
+		val &= ~IPU_DI1_COUNTER_RELEASE;
+
+	ipu_cm_write(ipu, val, IPU_DISP_GEN);
+
+	spin_unlock_irqrestore(&ipu->lock, lock_flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_module_disable);
+
+void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
+{
+	struct ipu_soc *ipu = channel->ipu;
+	unsigned int chno = channel->num;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ipu->lock, flags);
+
+	/* Mark buffer as ready. */
+	if (buf_num == 0)
+		ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
+	else
+		ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
+
+	spin_unlock_irqrestore(&ipu->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer);
+
+int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
+{
+	struct ipu_soc *ipu = channel->ipu;
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ipu->lock, flags);
+
+	val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
+	val |= idma_mask(channel->num);
+	ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
+
+	spin_unlock_irqrestore(&ipu->lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
+
+bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno)
+{
+	return (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(chno)) & idma_mask(chno));
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_channel_busy);
+
+int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
+{
+	struct ipu_soc *ipu = channel->ipu;
+	unsigned long timeout;
+
+	timeout = jiffies + msecs_to_jiffies(ms);
+	while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) &
+			idma_mask(channel->num)) {
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+		cpu_relax();
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
+
+int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms)
+{
+	unsigned long timeout;
+
+	timeout = jiffies + msecs_to_jiffies(ms);
+	ipu_cm_write(ipu, BIT(irq % 32), IPU_INT_STAT(irq / 32));
+	while (!(ipu_cm_read(ipu, IPU_INT_STAT(irq / 32) & BIT(irq % 32)))) {
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+		cpu_relax();
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_wait_interrupt);
+
+int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
+{
+	struct ipu_soc *ipu = channel->ipu;
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ipu->lock, flags);
+
+	/* Disable DMA channel(s) */
+	val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
+	val &= ~idma_mask(channel->num);
+	ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
+
+	/* Set channel buffers NOT to be ready */
+	ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */
+
+	if (ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num)) &
+			idma_mask(channel->num)) {
+		ipu_cm_write(ipu, idma_mask(channel->num),
+			     IPU_CHA_BUF0_RDY(channel->num));
+	}
+
+	if (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num)) &
+			idma_mask(channel->num)) {
+		ipu_cm_write(ipu, idma_mask(channel->num),
+			     IPU_CHA_BUF1_RDY(channel->num));
+	}
+
+	ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
+
+	/* Reset the double buffer */
+	val = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
+	val &= ~idma_mask(channel->num);
+	ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num));
+
+	spin_unlock_irqrestore(&ipu->lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel);
+
+static int ipu_memory_reset(struct ipu_soc *ipu)
+{
+	unsigned long timeout;
+
+	ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
+
+	timeout = jiffies + msecs_to_jiffies(1000);
+	while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
+		if (time_after(jiffies, timeout))
+			return -ETIME;
+		cpu_relax();
+	}
+
+	return 0;
+}
+
+struct ipu_devtype {
+	const char *name;
+	unsigned long cm_ofs;
+	unsigned long cpmem_ofs;
+	unsigned long srm_ofs;
+	unsigned long tpm_ofs;
+	unsigned long disp0_ofs;
+	unsigned long disp1_ofs;
+	unsigned long dc_tmpl_ofs;
+	unsigned long vdi_ofs;
+	enum ipuv3_type type;
+};
+
+static struct ipu_devtype ipu_type_imx51 = {
+	.name = "IPUv3EX",
+	.cm_ofs = 0x1e000000,
+	.cpmem_ofs = 0x1f000000,
+	.srm_ofs = 0x1f040000,
+	.tpm_ofs = 0x1f060000,
+	.disp0_ofs = 0x1e040000,
+	.disp1_ofs = 0x1e048000,
+	.dc_tmpl_ofs = 0x1f080000,
+	.vdi_ofs = 0x1e068000,
+	.type = IPUV3EX,
+};
+
+static struct ipu_devtype ipu_type_imx53 = {
+	.name = "IPUv3M",
+	.cm_ofs = 0x06000000,
+	.cpmem_ofs = 0x07000000,
+	.srm_ofs = 0x07040000,
+	.tpm_ofs = 0x07060000,
+	.disp0_ofs = 0x06040000,
+	.disp1_ofs = 0x06048000,
+	.dc_tmpl_ofs = 0x07080000,
+	.vdi_ofs = 0x06068000,
+	.type = IPUV3M,
+};
+
+static struct ipu_devtype ipu_type_imx6q = {
+	.name = "IPUv3H",
+	.cm_ofs = 0x00200000,
+	.cpmem_ofs = 0x00300000,
+	.srm_ofs = 0x00340000,
+	.tpm_ofs = 0x00360000,
+	.disp0_ofs = 0x00240000,
+	.disp1_ofs = 0x00248000,
+	.dc_tmpl_ofs = 0x00380000,
+	.vdi_ofs = 0x00268000,
+	.type = IPUV3H,
+};
+
+static const struct of_device_id imx_ipu_dt_ids[] = {
+	{ .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, },
+	{ .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, },
+	{ .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_ipu_dt_ids);
+
+static int ipu_submodules_init(struct ipu_soc *ipu,
+		struct platform_device *pdev, unsigned long ipu_base,
+		struct clk *ipu_clk)
+{
+	char *unit;
+	int ret;
+	struct device *dev = &pdev->dev;
+	const struct ipu_devtype *devtype = ipu->devtype;
+
+	ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs,
+			IPU_CONF_DI0_EN, ipu_clk);
+	if (ret) {
+		unit = "di0";
+		goto err_di_0;
+	}
+
+	ret = ipu_di_init(ipu, dev, 1, ipu_base + devtype->disp1_ofs,
+			IPU_CONF_DI1_EN, ipu_clk);
+	if (ret) {
+		unit = "di1";
+		goto err_di_1;
+	}
+
+	ret = ipu_dc_init(ipu, dev, ipu_base + devtype->cm_ofs +
+			IPU_CM_DC_REG_OFS, ipu_base + devtype->dc_tmpl_ofs);
+	if (ret) {
+		unit = "dc_template";
+		goto err_dc;
+	}
+
+	ret = ipu_dmfc_init(ipu, dev, ipu_base +
+			devtype->cm_ofs + IPU_CM_DMFC_REG_OFS, ipu_clk);
+	if (ret) {
+		unit = "dmfc";
+		goto err_dmfc;
+	}
+
+	ret = ipu_dp_init(ipu, dev, ipu_base + devtype->srm_ofs);
+	if (ret) {
+		unit = "dp";
+		goto err_dp;
+	}
+
+	return 0;
+
+err_dp:
+	ipu_dmfc_exit(ipu);
+err_dmfc:
+	ipu_dc_exit(ipu);
+err_dc:
+	ipu_di_exit(ipu, 1);
+err_di_1:
+	ipu_di_exit(ipu, 0);
+err_di_0:
+	dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret);
+	return ret;
+}
+
+static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
+{
+	unsigned long status;
+	int i, bit, irq;
+
+	for (i = 0; i < num_regs; i++) {
+
+		status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i]));
+		status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i]));
+
+		for_each_set_bit(bit, &status, 32) {
+			irq = irq_linear_revmap(ipu->domain,
+						regs[i] * 32 + bit);
+			if (irq)
+				generic_handle_irq(irq);
+		}
+	}
+}
+
+static void ipu_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
+	const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14};
+	struct irq_chip *chip = irq_get_chip(irq);
+
+	chained_irq_enter(chip, desc);
+
+	ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
+
+	chained_irq_exit(chip, desc);
+}
+
+static void ipu_err_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
+	const int int_reg[] = { 4, 5, 8, 9};
+	struct irq_chip *chip = irq_get_chip(irq);
+
+	chained_irq_enter(chip, desc);
+
+	ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
+
+	chained_irq_exit(chip, desc);
+}
+
+int ipu_map_irq(struct ipu_soc *ipu, int irq)
+{
+	int virq;
+
+	virq = irq_linear_revmap(ipu->domain, irq);
+	if (!virq)
+		virq = irq_create_mapping(ipu->domain, irq);
+
+	return virq;
+}
+EXPORT_SYMBOL_GPL(ipu_map_irq);
+
+int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
+		enum ipu_channel_irq irq_type)
+{
+	return ipu_map_irq(ipu, irq_type + channel->num);
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
+
+static void ipu_submodules_exit(struct ipu_soc *ipu)
+{
+	ipu_dp_exit(ipu);
+	ipu_dmfc_exit(ipu);
+	ipu_dc_exit(ipu);
+	ipu_di_exit(ipu, 1);
+	ipu_di_exit(ipu, 0);
+}
+
+static int platform_remove_devices_fn(struct device *dev, void *unused)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	platform_device_unregister(pdev);
+
+	return 0;
+}
+
+static void platform_device_unregister_children(struct platform_device *pdev)
+{
+	device_for_each_child(&pdev->dev, NULL, platform_remove_devices_fn);
+}
+
+struct ipu_platform_reg {
+	struct ipu_client_platformdata pdata;
+	const char *name;
+};
+
+static const struct ipu_platform_reg client_reg[] = {
+	{
+		.pdata = {
+			.di = 0,
+			.dc = 5,
+			.dp = IPU_DP_FLOW_SYNC_BG,
+			.dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
+			.dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
+		},
+		.name = "imx-ipuv3-crtc",
+	}, {
+		.pdata = {
+			.di = 1,
+			.dc = 1,
+			.dp = -EINVAL,
+			.dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC,
+			.dma[1] = -EINVAL,
+		},
+		.name = "imx-ipuv3-crtc",
+	},
+};
+
+static DEFINE_MUTEX(ipu_client_id_mutex);
+static int ipu_client_id;
+
+static int ipu_add_client_devices(struct ipu_soc *ipu)
+{
+	struct device *dev = ipu->dev;
+	unsigned i;
+	int id, ret;
+
+	mutex_lock(&ipu_client_id_mutex);
+	id = ipu_client_id;
+	ipu_client_id += ARRAY_SIZE(client_reg);
+	mutex_unlock(&ipu_client_id_mutex);
+
+	for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
+		const struct ipu_platform_reg *reg = &client_reg[i];
+		struct platform_device *pdev;
+
+		pdev = platform_device_register_data(dev, reg->name,
+			id++, &reg->pdata, sizeof(reg->pdata));
+
+		if (IS_ERR(pdev))
+			goto err_register;
+	}
+
+	return 0;
+
+err_register:
+	platform_device_unregister_children(to_platform_device(dev));
+
+	return ret;
+}
+
+
+static int ipu_irq_init(struct ipu_soc *ipu)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	unsigned long unused[IPU_NUM_IRQS / 32] = {
+		0x400100d0, 0xffe000fd,
+		0x400100d0, 0xffe000fd,
+		0x400100d0, 0xffe000fd,
+		0x4077ffff, 0xffe7e1fd,
+		0x23fffffe, 0x8880fff0,
+		0xf98fe7d0, 0xfff81fff,
+		0x400100d0, 0xffe000fd,
+		0x00000000,
+	};
+	int ret, i;
+
+	ipu->domain = irq_domain_add_linear(ipu->dev->of_node, IPU_NUM_IRQS,
+					    &irq_generic_chip_ops, ipu);
+	if (!ipu->domain) {
+		dev_err(ipu->dev, "failed to add irq domain\n");
+		return -ENODEV;
+	}
+
+	ret = irq_alloc_domain_generic_chips(ipu->domain, 32, 1, "IPU",
+					     handle_level_irq, 0,
+					     IRQF_VALID, 0);
+	if (ret < 0) {
+		dev_err(ipu->dev, "failed to alloc generic irq chips\n");
+		irq_domain_remove(ipu->domain);
+		return ret;
+	}
+
+	for (i = 0; i < IPU_NUM_IRQS; i += 32) {
+		gc = irq_get_domain_generic_chip(ipu->domain, i);
+		gc->reg_base = ipu->cm_reg;
+		gc->unused = unused[i / 32];
+		ct = gc->chip_types;
+		ct->chip.irq_ack = irq_gc_ack_set_bit;
+		ct->chip.irq_mask = irq_gc_mask_clr_bit;
+		ct->chip.irq_unmask = irq_gc_mask_set_bit;
+		ct->regs.ack = IPU_INT_STAT(i / 32);
+		ct->regs.mask = IPU_INT_CTRL(i / 32);
+	}
+
+	irq_set_chained_handler(ipu->irq_sync, ipu_irq_handler);
+	irq_set_handler_data(ipu->irq_sync, ipu);
+	irq_set_chained_handler(ipu->irq_err, ipu_err_irq_handler);
+	irq_set_handler_data(ipu->irq_err, ipu);
+
+	return 0;
+}
+
+static void ipu_irq_exit(struct ipu_soc *ipu)
+{
+	int i, irq;
+
+	irq_set_chained_handler(ipu->irq_err, NULL);
+	irq_set_handler_data(ipu->irq_err, NULL);
+	irq_set_chained_handler(ipu->irq_sync, NULL);
+	irq_set_handler_data(ipu->irq_sync, NULL);
+
+	/* TODO: remove irq_domain_generic_chips */
+
+	for (i = 0; i < IPU_NUM_IRQS; i++) {
+		irq = irq_linear_revmap(ipu->domain, i);
+		if (irq)
+			irq_dispose_mapping(irq);
+	}
+
+	irq_domain_remove(ipu->domain);
+}
+
+static int ipu_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *of_id =
+			of_match_device(imx_ipu_dt_ids, &pdev->dev);
+	struct ipu_soc *ipu;
+	struct resource *res;
+	unsigned long ipu_base;
+	int i, ret, irq_sync, irq_err;
+	const struct ipu_devtype *devtype;
+
+	devtype = of_id->data;
+
+	irq_sync = platform_get_irq(pdev, 0);
+	irq_err = platform_get_irq(pdev, 1);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	dev_dbg(&pdev->dev, "irq_sync: %d irq_err: %d\n",
+			irq_sync, irq_err);
+
+	if (!res || irq_sync < 0 || irq_err < 0)
+		return -ENODEV;
+
+	ipu_base = res->start;
+
+	ipu = devm_kzalloc(&pdev->dev, sizeof(*ipu), GFP_KERNEL);
+	if (!ipu)
+		return -ENODEV;
+
+	for (i = 0; i < 64; i++)
+		ipu->channel[i].ipu = ipu;
+	ipu->devtype = devtype;
+	ipu->ipu_type = devtype->type;
+
+	spin_lock_init(&ipu->lock);
+	mutex_init(&ipu->channel_lock);
+
+	dev_dbg(&pdev->dev, "cm_reg:   0x%08lx\n",
+			ipu_base + devtype->cm_ofs);
+	dev_dbg(&pdev->dev, "idmac:    0x%08lx\n",
+			ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
+	dev_dbg(&pdev->dev, "cpmem:    0x%08lx\n",
+			ipu_base + devtype->cpmem_ofs);
+	dev_dbg(&pdev->dev, "disp0:    0x%08lx\n",
+			ipu_base + devtype->disp0_ofs);
+	dev_dbg(&pdev->dev, "disp1:    0x%08lx\n",
+			ipu_base + devtype->disp1_ofs);
+	dev_dbg(&pdev->dev, "srm:      0x%08lx\n",
+			ipu_base + devtype->srm_ofs);
+	dev_dbg(&pdev->dev, "tpm:      0x%08lx\n",
+			ipu_base + devtype->tpm_ofs);
+	dev_dbg(&pdev->dev, "dc:       0x%08lx\n",
+			ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS);
+	dev_dbg(&pdev->dev, "ic:       0x%08lx\n",
+			ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS);
+	dev_dbg(&pdev->dev, "dmfc:     0x%08lx\n",
+			ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS);
+	dev_dbg(&pdev->dev, "vdi:      0x%08lx\n",
+			ipu_base + devtype->vdi_ofs);
+
+	ipu->cm_reg = devm_ioremap(&pdev->dev,
+			ipu_base + devtype->cm_ofs, PAGE_SIZE);
+	ipu->idmac_reg = devm_ioremap(&pdev->dev,
+			ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS,
+			PAGE_SIZE);
+	ipu->cpmem_base = devm_ioremap(&pdev->dev,
+			ipu_base + devtype->cpmem_ofs, PAGE_SIZE);
+
+	if (!ipu->cm_reg || !ipu->idmac_reg || !ipu->cpmem_base)
+		return -ENOMEM;
+
+	ipu->clk = devm_clk_get(&pdev->dev, "bus");
+	if (IS_ERR(ipu->clk)) {
+		ret = PTR_ERR(ipu->clk);
+		dev_err(&pdev->dev, "clk_get failed with %d", ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, ipu);
+
+	ret = clk_prepare_enable(ipu->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret);
+		return ret;
+	}
+
+	ipu->dev = &pdev->dev;
+	ipu->irq_sync = irq_sync;
+	ipu->irq_err = irq_err;
+
+	ret = ipu_irq_init(ipu);
+	if (ret)
+		goto out_failed_irq;
+
+	ret = device_reset(&pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to reset: %d\n", ret);
+		goto out_failed_reset;
+	}
+	ret = ipu_memory_reset(ipu);
+	if (ret)
+		goto out_failed_reset;
+
+	/* Set MCU_T to divide MCU access window into 2 */
+	ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
+			IPU_DISP_GEN);
+
+	ret = ipu_submodules_init(ipu, pdev, ipu_base, ipu->clk);
+	if (ret)
+		goto failed_submodules_init;
+
+	ret = ipu_add_client_devices(ipu);
+	if (ret) {
+		dev_err(&pdev->dev, "adding client devices failed with %d\n",
+				ret);
+		goto failed_add_clients;
+	}
+
+	dev_info(&pdev->dev, "%s probed\n", devtype->name);
+
+	return 0;
+
+failed_add_clients:
+	ipu_submodules_exit(ipu);
+failed_submodules_init:
+out_failed_reset:
+	ipu_irq_exit(ipu);
+out_failed_irq:
+	clk_disable_unprepare(ipu->clk);
+	return ret;
+}
+
+static int ipu_remove(struct platform_device *pdev)
+{
+	struct ipu_soc *ipu = platform_get_drvdata(pdev);
+
+	platform_device_unregister_children(pdev);
+	ipu_submodules_exit(ipu);
+	ipu_irq_exit(ipu);
+
+	clk_disable_unprepare(ipu->clk);
+
+	return 0;
+}
+
+static struct platform_driver imx_ipu_driver = {
+	.driver = {
+		.name = "imx-ipuv3",
+		.of_match_table = imx_ipu_dt_ids,
+	},
+	.probe = ipu_probe,
+	.remove = ipu_remove,
+};
+
+module_platform_driver(imx_ipu_driver);
+
+MODULE_ALIAS("platform:imx-ipuv3");
+MODULE_DESCRIPTION("i.MX IPU v3 driver");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c
new file mode 100644
index 0000000..2326c75
--- /dev/null
+++ b/drivers/gpu/ipu-v3/ipu-dc.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <video/imx-ipu-v3.h>
+#include "ipu-prv.h"
+
+#define DC_MAP_CONF_PTR(n)	(0x108 + ((n) & ~0x1) * 2)
+#define DC_MAP_CONF_VAL(n)	(0x144 + ((n) & ~0x1) * 2)
+
+#define DC_EVT_NF		0
+#define DC_EVT_NL		1
+#define DC_EVT_EOF		2
+#define DC_EVT_NFIELD		3
+#define DC_EVT_EOL		4
+#define DC_EVT_EOFIELD		5
+#define DC_EVT_NEW_ADDR		6
+#define DC_EVT_NEW_CHAN		7
+#define DC_EVT_NEW_DATA		8
+
+#define DC_EVT_NEW_ADDR_W_0	0
+#define DC_EVT_NEW_ADDR_W_1	1
+#define DC_EVT_NEW_CHAN_W_0	2
+#define DC_EVT_NEW_CHAN_W_1	3
+#define DC_EVT_NEW_DATA_W_0	4
+#define DC_EVT_NEW_DATA_W_1	5
+#define DC_EVT_NEW_ADDR_R_0	6
+#define DC_EVT_NEW_ADDR_R_1	7
+#define DC_EVT_NEW_CHAN_R_0	8
+#define DC_EVT_NEW_CHAN_R_1	9
+#define DC_EVT_NEW_DATA_R_0	10
+#define DC_EVT_NEW_DATA_R_1	11
+
+#define DC_WR_CH_CONF		0x0
+#define DC_WR_CH_ADDR		0x4
+#define DC_RL_CH(evt)		(8 + ((evt) & ~0x1) * 2)
+
+#define DC_GEN			0xd4
+#define DC_DISP_CONF1(disp)	(0xd8 + (disp) * 4)
+#define DC_DISP_CONF2(disp)	(0xe8 + (disp) * 4)
+#define DC_STAT			0x1c8
+
+#define WROD(lf)		(0x18 | ((lf) << 1))
+#define WRG			0x01
+#define WCLK			0xc9
+
+#define SYNC_WAVE 0
+#define NULL_WAVE (-1)
+
+#define DC_GEN_SYNC_1_6_SYNC	(2 << 1)
+#define DC_GEN_SYNC_PRIORITY_1	(1 << 7)
+
+#define DC_WR_CH_CONF_WORD_SIZE_8		(0 << 0)
+#define DC_WR_CH_CONF_WORD_SIZE_16		(1 << 0)
+#define DC_WR_CH_CONF_WORD_SIZE_24		(2 << 0)
+#define DC_WR_CH_CONF_WORD_SIZE_32		(3 << 0)
+#define DC_WR_CH_CONF_DISP_ID_PARALLEL(i)	(((i) & 0x1) << 3)
+#define DC_WR_CH_CONF_DISP_ID_SERIAL		(2 << 3)
+#define DC_WR_CH_CONF_DISP_ID_ASYNC		(3 << 4)
+#define DC_WR_CH_CONF_FIELD_MODE		(1 << 9)
+#define DC_WR_CH_CONF_PROG_TYPE_NORMAL		(4 << 5)
+#define DC_WR_CH_CONF_PROG_TYPE_MASK		(7 << 5)
+#define DC_WR_CH_CONF_PROG_DI_ID		(1 << 2)
+#define DC_WR_CH_CONF_PROG_DISP_ID(i)		(((i) & 0x1) << 3)
+
+#define IPU_DC_NUM_CHANNELS	10
+
+struct ipu_dc_priv;
+
+enum ipu_dc_map {
+	IPU_DC_MAP_RGB24,
+	IPU_DC_MAP_RGB565,
+	IPU_DC_MAP_GBR24, /* TVEv2 */
+	IPU_DC_MAP_BGR666,
+	IPU_DC_MAP_LVDS666,
+	IPU_DC_MAP_BGR24,
+};
+
+struct ipu_dc {
+	/* The display interface number assigned to this dc channel */
+	unsigned int		di;
+	void __iomem		*base;
+	struct ipu_dc_priv	*priv;
+	int			chno;
+	bool			in_use;
+};
+
+struct ipu_dc_priv {
+	void __iomem		*dc_reg;
+	void __iomem		*dc_tmpl_reg;
+	struct ipu_soc		*ipu;
+	struct device		*dev;
+	struct ipu_dc		channels[IPU_DC_NUM_CHANNELS];
+	struct mutex		mutex;
+	struct completion	comp;
+	int			dc_irq;
+	int			dp_irq;
+};
+
+static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
+{
+	u32 reg;
+
+	reg = readl(dc->base + DC_RL_CH(event));
+	reg &= ~(0xffff << (16 * (event & 0x1)));
+	reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
+	writel(reg, dc->base + DC_RL_CH(event));
+}
+
+static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand,
+		int map, int wave, int glue, int sync, int stop)
+{
+	struct ipu_dc_priv *priv = dc->priv;
+	u32 reg1, reg2;
+
+	if (opcode == WCLK) {
+		reg1 = (operand << 20) & 0xfff00000;
+		reg2 = operand >> 12 | opcode << 1 | stop << 9;
+	} else if (opcode == WRG) {
+		reg1 = sync | glue << 4 | ++wave << 11 | ((operand << 15) & 0xffff8000);
+		reg2 = operand >> 17 | opcode << 7 | stop << 9;
+	} else {
+		reg1 = sync | glue << 4 | ++wave << 11 | ++map << 15 | ((operand << 20) & 0xfff00000);
+		reg2 = operand >> 12 | opcode << 4 | stop << 9;
+	}
+	writel(reg1, priv->dc_tmpl_reg + word * 8);
+	writel(reg2, priv->dc_tmpl_reg + word * 8 + 4);
+}
+
+static int ipu_pixfmt_to_map(u32 fmt)
+{
+	switch (fmt) {
+	case V4L2_PIX_FMT_RGB24:
+		return IPU_DC_MAP_RGB24;
+	case V4L2_PIX_FMT_RGB565:
+		return IPU_DC_MAP_RGB565;
+	case IPU_PIX_FMT_GBR24:
+		return IPU_DC_MAP_GBR24;
+	case V4L2_PIX_FMT_BGR666:
+		return IPU_DC_MAP_BGR666;
+	case v4l2_fourcc('L', 'V', 'D', '6'):
+		return IPU_DC_MAP_LVDS666;
+	case V4L2_PIX_FMT_BGR24:
+		return IPU_DC_MAP_BGR24;
+	default:
+		return -EINVAL;
+	}
+}
+
+int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
+		u32 pixel_fmt, u32 width)
+{
+	struct ipu_dc_priv *priv = dc->priv;
+	u32 reg = 0;
+	int map;
+
+	dc->di = ipu_di_get_num(di);
+
+	map = ipu_pixfmt_to_map(pixel_fmt);
+	if (map < 0) {
+		dev_dbg(priv->dev, "IPU_DISP: No MAP\n");
+		return map;
+	}
+
+	if (interlaced) {
+		dc_link_event(dc, DC_EVT_NL, 0, 3);
+		dc_link_event(dc, DC_EVT_EOL, 0, 2);
+		dc_link_event(dc, DC_EVT_NEW_DATA, 0, 1);
+
+		/* Init template microcode */
+		dc_write_tmpl(dc, 0, WROD(0), 0, map, SYNC_WAVE, 0, 8, 1);
+	} else {
+		if (dc->di) {
+			dc_link_event(dc, DC_EVT_NL, 2, 3);
+			dc_link_event(dc, DC_EVT_EOL, 3, 2);
+			dc_link_event(dc, DC_EVT_NEW_DATA, 1, 1);
+			/* Init template microcode */
+			dc_write_tmpl(dc, 2, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1);
+			dc_write_tmpl(dc, 3, WROD(0), 0, map, SYNC_WAVE, 4, 5, 0);
+			dc_write_tmpl(dc, 4, WRG, 0, map, NULL_WAVE, 0, 0, 1);
+			dc_write_tmpl(dc, 1, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
+		} else {
+			dc_link_event(dc, DC_EVT_NL, 5, 3);
+			dc_link_event(dc, DC_EVT_EOL, 6, 2);
+			dc_link_event(dc, DC_EVT_NEW_DATA, 8, 1);
+			/* Init template microcode */
+			dc_write_tmpl(dc, 5, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1);
+			dc_write_tmpl(dc, 6, WROD(0), 0, map, SYNC_WAVE, 4, 5, 0);
+			dc_write_tmpl(dc, 7, WRG, 0, map, NULL_WAVE, 0, 0, 1);
+			dc_write_tmpl(dc, 8, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
+		}
+	}
+	dc_link_event(dc, DC_EVT_NF, 0, 0);
+	dc_link_event(dc, DC_EVT_NFIELD, 0, 0);
+	dc_link_event(dc, DC_EVT_EOF, 0, 0);
+	dc_link_event(dc, DC_EVT_EOFIELD, 0, 0);
+	dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0);
+	dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0);
+
+	reg = readl(dc->base + DC_WR_CH_CONF);
+	if (interlaced)
+		reg |= DC_WR_CH_CONF_FIELD_MODE;
+	else
+		reg &= ~DC_WR_CH_CONF_FIELD_MODE;
+	writel(reg, dc->base + DC_WR_CH_CONF);
+
+	writel(0x0, dc->base + DC_WR_CH_ADDR);
+	writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
+
+void ipu_dc_enable(struct ipu_soc *ipu)
+{
+	ipu_module_enable(ipu, IPU_CONF_DC_EN);
+}
+EXPORT_SYMBOL_GPL(ipu_dc_enable);
+
+void ipu_dc_enable_channel(struct ipu_dc *dc)
+{
+	int di;
+	u32 reg;
+
+	di = dc->di;
+
+	reg = readl(dc->base + DC_WR_CH_CONF);
+	reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL;
+	writel(reg, dc->base + DC_WR_CH_CONF);
+}
+EXPORT_SYMBOL_GPL(ipu_dc_enable_channel);
+
+static irqreturn_t dc_irq_handler(int irq, void *dev_id)
+{
+	struct ipu_dc *dc = dev_id;
+	u32 reg;
+
+	reg = readl(dc->base + DC_WR_CH_CONF);
+	reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
+	writel(reg, dc->base + DC_WR_CH_CONF);
+
+	/* The Freescale BSP kernel clears DIx_COUNTER_RELEASE here */
+
+	complete(&dc->priv->comp);
+	return IRQ_HANDLED;
+}
+
+void ipu_dc_disable_channel(struct ipu_dc *dc)
+{
+	struct ipu_dc_priv *priv = dc->priv;
+	int irq, ret;
+	u32 val;
+
+	/* TODO: Handle MEM_FG_SYNC differently from MEM_BG_SYNC */
+	if (dc->chno == 1)
+		irq = priv->dc_irq;
+	else if (dc->chno == 5)
+		irq = priv->dp_irq;
+	else
+		return;
+
+	init_completion(&priv->comp);
+	enable_irq(irq);
+	ret = wait_for_completion_timeout(&priv->comp, msecs_to_jiffies(50));
+	disable_irq(irq);
+	if (ret <= 0) {
+		dev_warn(priv->dev, "DC stop timeout after 50 ms\n");
+
+		val = readl(dc->base + DC_WR_CH_CONF);
+		val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
+		writel(val, dc->base + DC_WR_CH_CONF);
+	}
+}
+EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
+
+void ipu_dc_disable(struct ipu_soc *ipu)
+{
+	ipu_module_disable(ipu, IPU_CONF_DC_EN);
+}
+EXPORT_SYMBOL_GPL(ipu_dc_disable);
+
+static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map,
+		int byte_num, int offset, int mask)
+{
+	int ptr = map * 3 + byte_num;
+	u32 reg;
+
+	reg = readl(priv->dc_reg + DC_MAP_CONF_VAL(ptr));
+	reg &= ~(0xffff << (16 * (ptr & 0x1)));
+	reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
+	writel(reg, priv->dc_reg + DC_MAP_CONF_VAL(ptr));
+
+	reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
+	reg &= ~(0x1f << ((16 * (map & 0x1)) + (5 * byte_num)));
+	reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
+	writel(reg, priv->dc_reg + DC_MAP_CONF_PTR(map));
+}
+
+static void ipu_dc_map_clear(struct ipu_dc_priv *priv, int map)
+{
+	u32 reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
+
+	writel(reg & ~(0xffff << (16 * (map & 0x1))),
+		     priv->dc_reg + DC_MAP_CONF_PTR(map));
+}
+
+struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel)
+{
+	struct ipu_dc_priv *priv = ipu->dc_priv;
+	struct ipu_dc *dc;
+
+	if (channel >= IPU_DC_NUM_CHANNELS)
+		return ERR_PTR(-ENODEV);
+
+	dc = &priv->channels[channel];
+
+	mutex_lock(&priv->mutex);
+
+	if (dc->in_use) {
+		mutex_unlock(&priv->mutex);
+		return ERR_PTR(-EBUSY);
+	}
+
+	dc->in_use = true;
+
+	mutex_unlock(&priv->mutex);
+
+	return dc;
+}
+EXPORT_SYMBOL_GPL(ipu_dc_get);
+
+void ipu_dc_put(struct ipu_dc *dc)
+{
+	struct ipu_dc_priv *priv = dc->priv;
+
+	mutex_lock(&priv->mutex);
+	dc->in_use = false;
+	mutex_unlock(&priv->mutex);
+}
+EXPORT_SYMBOL_GPL(ipu_dc_put);
+
+int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
+		unsigned long base, unsigned long template_base)
+{
+	struct ipu_dc_priv *priv;
+	static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c,
+		0x78, 0, 0x94, 0xb4};
+	int i, ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	mutex_init(&priv->mutex);
+
+	priv->dev = dev;
+	priv->ipu = ipu;
+	priv->dc_reg = devm_ioremap(dev, base, PAGE_SIZE);
+	priv->dc_tmpl_reg = devm_ioremap(dev, template_base, PAGE_SIZE);
+	if (!priv->dc_reg || !priv->dc_tmpl_reg)
+		return -ENOMEM;
+
+	for (i = 0; i < IPU_DC_NUM_CHANNELS; i++) {
+		priv->channels[i].chno = i;
+		priv->channels[i].priv = priv;
+		priv->channels[i].base = priv->dc_reg + channel_offsets[i];
+	}
+
+	priv->dc_irq = ipu_map_irq(ipu, IPU_IRQ_DC_FC_1);
+	if (!priv->dc_irq)
+		return -EINVAL;
+	ret = devm_request_irq(dev, priv->dc_irq, dc_irq_handler, 0, NULL,
+			       &priv->channels[1]);
+	if (ret < 0)
+		return ret;
+	disable_irq(priv->dc_irq);
+	priv->dp_irq = ipu_map_irq(ipu, IPU_IRQ_DP_SF_END);
+	if (!priv->dp_irq)
+		return -EINVAL;
+	ret = devm_request_irq(dev, priv->dp_irq, dc_irq_handler, 0, NULL,
+			       &priv->channels[5]);
+	if (ret < 0)
+		return ret;
+	disable_irq(priv->dp_irq);
+
+	writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) |
+			DC_WR_CH_CONF_PROG_DI_ID,
+			priv->channels[1].base + DC_WR_CH_CONF);
+	writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(0),
+			priv->channels[5].base + DC_WR_CH_CONF);
+
+	writel(DC_GEN_SYNC_1_6_SYNC | DC_GEN_SYNC_PRIORITY_1,
+		priv->dc_reg + DC_GEN);
+
+	ipu->dc_priv = priv;
+
+	dev_dbg(dev, "DC base: 0x%08lx template base: 0x%08lx\n",
+			base, template_base);
+
+	/* rgb24 */
+	ipu_dc_map_clear(priv, IPU_DC_MAP_RGB24);
+	ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 0, 7, 0xff); /* blue */
+	ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 1, 15, 0xff); /* green */
+	ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 2, 23, 0xff); /* red */
+
+	/* rgb565 */
+	ipu_dc_map_clear(priv, IPU_DC_MAP_RGB565);
+	ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 0, 4, 0xf8); /* blue */
+	ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 1, 10, 0xfc); /* green */
+	ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 2, 15, 0xf8); /* red */
+
+	/* gbr24 */
+	ipu_dc_map_clear(priv, IPU_DC_MAP_GBR24);
+	ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 2, 15, 0xff); /* green */
+	ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 1, 7, 0xff); /* blue */
+	ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 0, 23, 0xff); /* red */
+
+	/* bgr666 */
+	ipu_dc_map_clear(priv, IPU_DC_MAP_BGR666);
+	ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 0, 5, 0xfc); /* blue */
+	ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 1, 11, 0xfc); /* green */
+	ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 2, 17, 0xfc); /* red */
+
+	/* lvds666 */
+	ipu_dc_map_clear(priv, IPU_DC_MAP_LVDS666);
+	ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 0, 5, 0xfc); /* blue */
+	ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 1, 13, 0xfc); /* green */
+	ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 2, 21, 0xfc); /* red */
+
+	/* bgr24 */
+	ipu_dc_map_clear(priv, IPU_DC_MAP_BGR24);
+	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 2, 7, 0xff); /* red */
+	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
+	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
+
+	return 0;
+}
+
+void ipu_dc_exit(struct ipu_soc *ipu)
+{
+}
diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
new file mode 100644
index 0000000..c490ba4
--- /dev/null
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -0,0 +1,730 @@
+/*
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <video/imx-ipu-v3.h>
+#include "ipu-prv.h"
+
+struct ipu_di {
+	void __iomem *base;
+	int id;
+	u32 module;
+	struct clk *clk_di;	/* display input clock */
+	struct clk *clk_ipu;	/* IPU bus clock */
+	struct clk *clk_di_pixel; /* resulting pixel clock */
+	bool inuse;
+	struct ipu_soc *ipu;
+};
+
+static DEFINE_MUTEX(di_mutex);
+
+struct di_sync_config {
+	int run_count;
+	int run_src;
+	int offset_count;
+	int offset_src;
+	int repeat_count;
+	int cnt_clr_src;
+	int cnt_polarity_gen_en;
+	int cnt_polarity_clr_src;
+	int cnt_polarity_trigger_src;
+	int cnt_up;
+	int cnt_down;
+};
+
+enum di_pins {
+	DI_PIN11 = 0,
+	DI_PIN12 = 1,
+	DI_PIN13 = 2,
+	DI_PIN14 = 3,
+	DI_PIN15 = 4,
+	DI_PIN16 = 5,
+	DI_PIN17 = 6,
+	DI_PIN_CS = 7,
+
+	DI_PIN_SER_CLK = 0,
+	DI_PIN_SER_RS = 1,
+};
+
+enum di_sync_wave {
+	DI_SYNC_NONE = 0,
+	DI_SYNC_CLK = 1,
+	DI_SYNC_INT_HSYNC = 2,
+	DI_SYNC_HSYNC = 3,
+	DI_SYNC_VSYNC = 4,
+	DI_SYNC_DE = 6,
+};
+
+#define SYNC_WAVE 0
+
+#define DI_GENERAL		0x0000
+#define DI_BS_CLKGEN0		0x0004
+#define DI_BS_CLKGEN1		0x0008
+#define DI_SW_GEN0(gen)		(0x000c + 4 * ((gen) - 1))
+#define DI_SW_GEN1(gen)		(0x0030 + 4 * ((gen) - 1))
+#define DI_STP_REP(gen)		(0x0148 + 4 * (((gen) - 1)/2))
+#define DI_SYNC_AS_GEN		0x0054
+#define DI_DW_GEN(gen)		(0x0058 + 4 * (gen))
+#define DI_DW_SET(gen, set)	(0x0088 + 4 * ((gen) + 0xc * (set)))
+#define DI_SER_CONF		0x015c
+#define DI_SSC			0x0160
+#define DI_POL			0x0164
+#define DI_AW0			0x0168
+#define DI_AW1			0x016c
+#define DI_SCR_CONF		0x0170
+#define DI_STAT			0x0174
+
+#define DI_SW_GEN0_RUN_COUNT(x)			((x) << 19)
+#define DI_SW_GEN0_RUN_SRC(x)			((x) << 16)
+#define DI_SW_GEN0_OFFSET_COUNT(x)		((x) << 3)
+#define DI_SW_GEN0_OFFSET_SRC(x)		((x) << 0)
+
+#define DI_SW_GEN1_CNT_POL_GEN_EN(x)		((x) << 29)
+#define DI_SW_GEN1_CNT_CLR_SRC(x)		((x) << 25)
+#define DI_SW_GEN1_CNT_POL_TRIGGER_SRC(x)	((x) << 12)
+#define DI_SW_GEN1_CNT_POL_CLR_SRC(x)		((x) << 9)
+#define DI_SW_GEN1_CNT_DOWN(x)			((x) << 16)
+#define DI_SW_GEN1_CNT_UP(x)			(x)
+#define DI_SW_GEN1_AUTO_RELOAD			(0x10000000)
+
+#define DI_DW_GEN_ACCESS_SIZE_OFFSET		24
+#define DI_DW_GEN_COMPONENT_SIZE_OFFSET		16
+
+#define DI_GEN_POLARITY_1			(1 << 0)
+#define DI_GEN_POLARITY_2			(1 << 1)
+#define DI_GEN_POLARITY_3			(1 << 2)
+#define DI_GEN_POLARITY_4			(1 << 3)
+#define DI_GEN_POLARITY_5			(1 << 4)
+#define DI_GEN_POLARITY_6			(1 << 5)
+#define DI_GEN_POLARITY_7			(1 << 6)
+#define DI_GEN_POLARITY_8			(1 << 7)
+#define DI_GEN_POLARITY_DISP_CLK		(1 << 17)
+#define DI_GEN_DI_CLK_EXT			(1 << 20)
+#define DI_GEN_DI_VSYNC_EXT			(1 << 21)
+
+#define DI_POL_DRDY_DATA_POLARITY		(1 << 7)
+#define DI_POL_DRDY_POLARITY_15			(1 << 4)
+
+#define DI_VSYNC_SEL_OFFSET			13
+
+static inline u32 ipu_di_read(struct ipu_di *di, unsigned offset)
+{
+	return readl(di->base + offset);
+}
+
+static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset)
+{
+	writel(value, di->base + offset);
+}
+
+static void ipu_di_data_wave_config(struct ipu_di *di,
+				     int wave_gen,
+				     int access_size, int component_size)
+{
+	u32 reg;
+	reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
+	    (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
+	ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
+}
+
+static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin,
+		int set, int up, int down)
+{
+	u32 reg;
+
+	reg = ipu_di_read(di, DI_DW_GEN(wave_gen));
+	reg &= ~(0x3 << (di_pin * 2));
+	reg |= set << (di_pin * 2);
+	ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
+
+	ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set));
+}
+
+static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config,
+		int start, int count)
+{
+	u32 reg;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		struct di_sync_config *c = &config[i];
+		int wave_gen = start + i + 1;
+
+		if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) ||
+				(c->repeat_count >= 0x1000) ||
+				(c->cnt_up >= 0x400) ||
+				(c->cnt_down >= 0x400)) {
+			dev_err(di->ipu->dev, "DI%d counters out of range.\n",
+					di->id);
+			return;
+		}
+
+		reg = DI_SW_GEN0_RUN_COUNT(c->run_count) |
+			DI_SW_GEN0_RUN_SRC(c->run_src) |
+			DI_SW_GEN0_OFFSET_COUNT(c->offset_count) |
+			DI_SW_GEN0_OFFSET_SRC(c->offset_src);
+		ipu_di_write(di, reg, DI_SW_GEN0(wave_gen));
+
+		reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) |
+			DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) |
+			DI_SW_GEN1_CNT_POL_TRIGGER_SRC(
+					c->cnt_polarity_trigger_src) |
+			DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) |
+			DI_SW_GEN1_CNT_DOWN(c->cnt_down) |
+			DI_SW_GEN1_CNT_UP(c->cnt_up);
+
+		/* Enable auto reload */
+		if (c->repeat_count == 0)
+			reg |= DI_SW_GEN1_AUTO_RELOAD;
+
+		ipu_di_write(di, reg, DI_SW_GEN1(wave_gen));
+
+		reg = ipu_di_read(di, DI_STP_REP(wave_gen));
+		reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1)));
+		reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1));
+		ipu_di_write(di, reg, DI_STP_REP(wave_gen));
+	}
+}
+
+static void ipu_di_sync_config_interlaced(struct ipu_di *di,
+		struct ipu_di_signal_cfg *sig)
+{
+	u32 h_total = sig->width + sig->h_sync_width +
+		sig->h_start_width + sig->h_end_width;
+	u32 v_total = sig->height + sig->v_sync_width +
+		sig->v_start_width + sig->v_end_width;
+	u32 reg;
+	struct di_sync_config cfg[] = {
+		{
+			.run_count = h_total / 2 - 1,
+			.run_src = DI_SYNC_CLK,
+		}, {
+			.run_count = h_total - 11,
+			.run_src = DI_SYNC_CLK,
+			.cnt_down = 4,
+		}, {
+			.run_count = v_total * 2 - 1,
+			.run_src = DI_SYNC_INT_HSYNC,
+			.offset_count = 1,
+			.offset_src = DI_SYNC_INT_HSYNC,
+			.cnt_down = 4,
+		}, {
+			.run_count = v_total / 2 - 1,
+			.run_src = DI_SYNC_HSYNC,
+			.offset_count = sig->v_start_width,
+			.offset_src = DI_SYNC_HSYNC,
+			.repeat_count = 2,
+			.cnt_clr_src = DI_SYNC_VSYNC,
+		}, {
+			.run_src = DI_SYNC_HSYNC,
+			.repeat_count = sig->height / 2,
+			.cnt_clr_src = 4,
+		}, {
+			.run_count = v_total - 1,
+			.run_src = DI_SYNC_HSYNC,
+		}, {
+			.run_count = v_total / 2 - 1,
+			.run_src = DI_SYNC_HSYNC,
+			.offset_count = 9,
+			.offset_src = DI_SYNC_HSYNC,
+			.repeat_count = 2,
+			.cnt_clr_src = DI_SYNC_VSYNC,
+		}, {
+			.run_src = DI_SYNC_CLK,
+			.offset_count = sig->h_start_width,
+			.offset_src = DI_SYNC_CLK,
+			.repeat_count = sig->width,
+			.cnt_clr_src = 5,
+		}, {
+			.run_count = v_total - 1,
+			.run_src = DI_SYNC_INT_HSYNC,
+			.offset_count = v_total / 2,
+			.offset_src = DI_SYNC_INT_HSYNC,
+			.cnt_clr_src = DI_SYNC_HSYNC,
+			.cnt_down = 4,
+		}
+	};
+
+	ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
+
+	/* set gentime select and tag sel */
+	reg = ipu_di_read(di, DI_SW_GEN1(9));
+	reg &= 0x1FFFFFFF;
+	reg |= (3 - 1) << 29 | 0x00008000;
+	ipu_di_write(di, reg, DI_SW_GEN1(9));
+
+	ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF);
+}
+
+static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
+		struct ipu_di_signal_cfg *sig, int div)
+{
+	u32 h_total = sig->width + sig->h_sync_width + sig->h_start_width +
+		sig->h_end_width;
+	u32 v_total = sig->height + sig->v_sync_width + sig->v_start_width +
+		sig->v_end_width;
+	struct di_sync_config cfg[] = {
+		{
+			/* 1: INT_HSYNC */
+			.run_count = h_total - 1,
+			.run_src = DI_SYNC_CLK,
+		} , {
+			/* PIN2: HSYNC */
+			.run_count = h_total - 1,
+			.run_src = DI_SYNC_CLK,
+			.offset_count = div * sig->v_to_h_sync,
+			.offset_src = DI_SYNC_CLK,
+			.cnt_polarity_gen_en = 1,
+			.cnt_polarity_trigger_src = DI_SYNC_CLK,
+			.cnt_down = sig->h_sync_width * 2,
+		} , {
+			/* PIN3: VSYNC */
+			.run_count = v_total - 1,
+			.run_src = DI_SYNC_INT_HSYNC,
+			.cnt_polarity_gen_en = 1,
+			.cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
+			.cnt_down = sig->v_sync_width * 2,
+		} , {
+			/* 4: Line Active */
+			.run_src = DI_SYNC_HSYNC,
+			.offset_count = sig->v_sync_width + sig->v_start_width,
+			.offset_src = DI_SYNC_HSYNC,
+			.repeat_count = sig->height,
+			.cnt_clr_src = DI_SYNC_VSYNC,
+		} , {
+			/* 5: Pixel Active, referenced by DC */
+			.run_src = DI_SYNC_CLK,
+			.offset_count = sig->h_sync_width + sig->h_start_width,
+			.offset_src = DI_SYNC_CLK,
+			.repeat_count = sig->width,
+			.cnt_clr_src = 5, /* Line Active */
+		} , {
+			/* unused */
+		} , {
+			/* unused */
+		} , {
+			/* unused */
+		} , {
+			/* unused */
+		},
+	};
+	/* can't use #7 and #8 for line active and pixel active counters */
+	struct di_sync_config cfg_vga[] = {
+		{
+			/* 1: INT_HSYNC */
+			.run_count = h_total - 1,
+			.run_src = DI_SYNC_CLK,
+		} , {
+			/* 2: VSYNC */
+			.run_count = v_total - 1,
+			.run_src = DI_SYNC_INT_HSYNC,
+		} , {
+			/* 3: Line Active */
+			.run_src = DI_SYNC_INT_HSYNC,
+			.offset_count = sig->v_sync_width + sig->v_start_width,
+			.offset_src = DI_SYNC_INT_HSYNC,
+			.repeat_count = sig->height,
+			.cnt_clr_src = 3 /* VSYNC */,
+		} , {
+			/* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */
+			.run_count = h_total - 1,
+			.run_src = DI_SYNC_CLK,
+			.offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
+			.offset_src = DI_SYNC_CLK,
+			.cnt_polarity_gen_en = 1,
+			.cnt_polarity_trigger_src = DI_SYNC_CLK,
+			.cnt_down = sig->h_sync_width * 2,
+		} , {
+			/* 5: Pixel Active signal to DC */
+			.run_src = DI_SYNC_CLK,
+			.offset_count = sig->h_sync_width + sig->h_start_width,
+			.offset_src = DI_SYNC_CLK,
+			.repeat_count = sig->width,
+			.cnt_clr_src = 4, /* Line Active */
+		} , {
+			/* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */
+			.run_count = v_total - 1,
+			.run_src = DI_SYNC_INT_HSYNC,
+			.offset_count = 1, /* magic value from Freescale TVE driver */
+			.offset_src = DI_SYNC_INT_HSYNC,
+			.cnt_polarity_gen_en = 1,
+			.cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
+			.cnt_down = sig->v_sync_width * 2,
+		} , {
+			/* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */
+			.run_count = h_total - 1,
+			.run_src = DI_SYNC_CLK,
+			.offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
+			.offset_src = DI_SYNC_CLK,
+			.cnt_polarity_gen_en = 1,
+			.cnt_polarity_trigger_src = DI_SYNC_CLK,
+			.cnt_down = sig->h_sync_width * 2,
+		} , {
+			/* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */
+			.run_count = v_total - 1,
+			.run_src = DI_SYNC_INT_HSYNC,
+			.offset_count = 1, /* magic value from Freescale TVE driver */
+			.offset_src = DI_SYNC_INT_HSYNC,
+			.cnt_polarity_gen_en = 1,
+			.cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
+			.cnt_down = sig->v_sync_width * 2,
+		} , {
+			/* unused */
+		},
+	};
+
+	ipu_di_write(di, v_total - 1, DI_SCR_CONF);
+	if (sig->hsync_pin == 2 && sig->vsync_pin == 3)
+		ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
+	else
+		ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
+}
+
+static void ipu_di_config_clock(struct ipu_di *di,
+	const struct ipu_di_signal_cfg *sig)
+{
+	struct clk *clk;
+	unsigned clkgen0;
+	uint32_t val;
+
+	if (sig->clkflags & IPU_DI_CLKMODE_EXT) {
+		/*
+		 * CLKMODE_EXT means we must use the DI clock: this is
+		 * needed for things like LVDS which needs to feed the
+		 * DI and LDB with the same pixel clock.
+		 */
+		clk = di->clk_di;
+
+		if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
+			/*
+			 * CLKMODE_SYNC means that we want the DI to be
+			 * clocked at the same rate as the parent clock.
+			 * This is needed (eg) for LDB which needs to be
+			 * fed with the same pixel clock.  We assume that
+			 * the LDB clock has already been set correctly.
+			 */
+			clkgen0 = 1 << 4;
+		} else {
+			/*
+			 * We can use the divider.  We should really have
+			 * a flag here indicating whether the bridge can
+			 * cope with a fractional divider or not.  For the
+			 * time being, let's go for simplicitly and
+			 * reliability.
+			 */
+			unsigned long in_rate;
+			unsigned div;
+
+			clk_set_rate(clk, sig->pixelclock);
+
+			in_rate = clk_get_rate(clk);
+			div = (in_rate + sig->pixelclock / 2) / sig->pixelclock;
+			if (div == 0)
+				div = 1;
+
+			clkgen0 = div << 4;
+		}
+	} else {
+		/*
+		 * For other interfaces, we can arbitarily select between
+		 * the DI specific clock and the internal IPU clock.  See
+		 * DI_GENERAL bit 20.  We select the IPU clock if it can
+		 * give us a clock rate within 1% of the requested frequency,
+		 * otherwise we use the DI clock.
+		 */
+		unsigned long rate, clkrate;
+		unsigned div, error;
+
+		clkrate = clk_get_rate(di->clk_ipu);
+		div = (clkrate + sig->pixelclock / 2) / sig->pixelclock;
+		rate = clkrate / div;
+
+		error = rate / (sig->pixelclock / 1000);
+
+		dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
+			rate, div, (signed)(error - 1000) / 10, error % 10);
+
+		/* Allow a 1% error */
+		if (error < 1010 && error >= 990) {
+			clk = di->clk_ipu;
+
+			clkgen0 = div << 4;
+		} else {
+			unsigned long in_rate;
+			unsigned div;
+
+			clk = di->clk_di;
+
+			clk_set_rate(clk, sig->pixelclock);
+
+			in_rate = clk_get_rate(clk);
+			div = (in_rate + sig->pixelclock / 2) / sig->pixelclock;
+			if (div == 0)
+				div = 1;
+
+			clkgen0 = div << 4;
+		}
+	}
+
+	di->clk_di_pixel = clk;
+
+	/* Set the divider */
+	ipu_di_write(di, clkgen0, DI_BS_CLKGEN0);
+
+	/*
+	 * Set the high/low periods.  Bits 24:16 give us the falling edge,
+	 * and bits 8:0 give the rising edge.  LSB is fraction, and is
+	 * based on the divider above.  We want a 50% duty cycle, so set
+	 * the falling edge to be half the divider.
+	 */
+	ipu_di_write(di, (clkgen0 >> 4) << 16, DI_BS_CLKGEN1);
+
+	/* Finally select the input clock */
+	val = ipu_di_read(di, DI_GENERAL) & ~DI_GEN_DI_CLK_EXT;
+	if (clk == di->clk_di)
+		val |= DI_GEN_DI_CLK_EXT;
+	ipu_di_write(di, val, DI_GENERAL);
+
+	dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
+		sig->pixelclock,
+		clk_get_rate(di->clk_ipu),
+		clk_get_rate(di->clk_di),
+		clk == di->clk_di ? "DI" : "IPU",
+		clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
+}
+
+int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
+{
+	u32 reg;
+	u32 di_gen, vsync_cnt;
+	u32 div;
+	u32 h_total, v_total;
+
+	dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
+		di->id, sig->width, sig->height);
+
+	if ((sig->v_sync_width == 0) || (sig->h_sync_width == 0))
+		return -EINVAL;
+
+	h_total = sig->width + sig->h_sync_width + sig->h_start_width +
+		sig->h_end_width;
+	v_total = sig->height + sig->v_sync_width + sig->v_start_width +
+		sig->v_end_width;
+
+	dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
+		clk_get_rate(di->clk_ipu),
+		clk_get_rate(di->clk_di),
+		sig->pixelclock);
+
+	mutex_lock(&di_mutex);
+
+	ipu_di_config_clock(di, sig);
+
+	div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
+	div = div / 16;		/* Now divider is integer portion */
+
+	/* Setup pixel clock timing */
+	/* Down time is half of period */
+	ipu_di_write(di, (div << 16), DI_BS_CLKGEN1);
+
+	ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1);
+	ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
+
+	di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT;
+	di_gen |= DI_GEN_DI_VSYNC_EXT;
+
+	if (sig->interlaced) {
+		ipu_di_sync_config_interlaced(di, sig);
+
+		/* set y_sel = 1 */
+		di_gen |= 0x10000000;
+		di_gen |= DI_GEN_POLARITY_5;
+		di_gen |= DI_GEN_POLARITY_8;
+
+		vsync_cnt = 7;
+
+		if (sig->Hsync_pol)
+			di_gen |= DI_GEN_POLARITY_3;
+		if (sig->Vsync_pol)
+			di_gen |= DI_GEN_POLARITY_2;
+	} else {
+		ipu_di_sync_config_noninterlaced(di, sig, div);
+
+		vsync_cnt = 3;
+		if (di->id == 1)
+			/*
+			 * TODO: change only for TVEv2, parallel display
+			 * uses pin 2 / 3
+			 */
+			if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3))
+				vsync_cnt = 6;
+
+		if (sig->Hsync_pol) {
+			if (sig->hsync_pin == 2)
+				di_gen |= DI_GEN_POLARITY_2;
+			else if (sig->hsync_pin == 4)
+				di_gen |= DI_GEN_POLARITY_4;
+			else if (sig->hsync_pin == 7)
+				di_gen |= DI_GEN_POLARITY_7;
+		}
+		if (sig->Vsync_pol) {
+			if (sig->vsync_pin == 3)
+				di_gen |= DI_GEN_POLARITY_3;
+			else if (sig->vsync_pin == 6)
+				di_gen |= DI_GEN_POLARITY_6;
+			else if (sig->vsync_pin == 8)
+				di_gen |= DI_GEN_POLARITY_8;
+		}
+	}
+
+	if (sig->clk_pol)
+		di_gen |= DI_GEN_POLARITY_DISP_CLK;
+
+	ipu_di_write(di, di_gen, DI_GENERAL);
+
+	ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002,
+		     DI_SYNC_AS_GEN);
+
+	reg = ipu_di_read(di, DI_POL);
+	reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
+
+	if (sig->enable_pol)
+		reg |= DI_POL_DRDY_POLARITY_15;
+	if (sig->data_pol)
+		reg |= DI_POL_DRDY_DATA_POLARITY;
+
+	ipu_di_write(di, reg, DI_POL);
+
+	mutex_unlock(&di_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);
+
+int ipu_di_enable(struct ipu_di *di)
+{
+	int ret;
+
+	WARN_ON(IS_ERR(di->clk_di_pixel));
+
+	ret = clk_prepare_enable(di->clk_di_pixel);
+	if (ret)
+		return ret;
+
+	ipu_module_enable(di->ipu, di->module);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_di_enable);
+
+int ipu_di_disable(struct ipu_di *di)
+{
+	WARN_ON(IS_ERR(di->clk_di_pixel));
+
+	ipu_module_disable(di->ipu, di->module);
+
+	clk_disable_unprepare(di->clk_di_pixel);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_di_disable);
+
+int ipu_di_get_num(struct ipu_di *di)
+{
+	return di->id;
+}
+EXPORT_SYMBOL_GPL(ipu_di_get_num);
+
+static DEFINE_MUTEX(ipu_di_lock);
+
+struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp)
+{
+	struct ipu_di *di;
+
+	if (disp > 1)
+		return ERR_PTR(-EINVAL);
+
+	di = ipu->di_priv[disp];
+
+	mutex_lock(&ipu_di_lock);
+
+	if (di->inuse) {
+		di = ERR_PTR(-EBUSY);
+		goto out;
+	}
+
+	di->inuse = true;
+out:
+	mutex_unlock(&ipu_di_lock);
+
+	return di;
+}
+EXPORT_SYMBOL_GPL(ipu_di_get);
+
+void ipu_di_put(struct ipu_di *di)
+{
+	mutex_lock(&ipu_di_lock);
+
+	di->inuse = false;
+
+	mutex_unlock(&ipu_di_lock);
+}
+EXPORT_SYMBOL_GPL(ipu_di_put);
+
+int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
+		unsigned long base,
+		u32 module, struct clk *clk_ipu)
+{
+	struct ipu_di *di;
+
+	if (id > 1)
+		return -ENODEV;
+
+	di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
+	if (!di)
+		return -ENOMEM;
+
+	ipu->di_priv[id] = di;
+
+	di->clk_di = devm_clk_get(dev, id ? "di1" : "di0");
+	if (IS_ERR(di->clk_di))
+		return PTR_ERR(di->clk_di);
+
+	di->module = module;
+	di->id = id;
+	di->clk_ipu = clk_ipu;
+	di->base = devm_ioremap(dev, base, PAGE_SIZE);
+	if (!di->base)
+		return -ENOMEM;
+
+	ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
+
+	dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
+			id, base, di->base);
+	di->inuse = false;
+	di->ipu = ipu;
+
+	return 0;
+}
+
+void ipu_di_exit(struct ipu_soc *ipu, int id)
+{
+}
diff --git a/drivers/gpu/ipu-v3/ipu-dmfc.c b/drivers/gpu/ipu-v3/ipu-dmfc.c
new file mode 100644
index 0000000..042c395
--- /dev/null
+++ b/drivers/gpu/ipu-v3/ipu-dmfc.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+
+#include <video/imx-ipu-v3.h>
+#include "ipu-prv.h"
+
+#define DMFC_RD_CHAN		0x0000
+#define DMFC_WR_CHAN		0x0004
+#define DMFC_WR_CHAN_DEF	0x0008
+#define DMFC_DP_CHAN		0x000c
+#define DMFC_DP_CHAN_DEF	0x0010
+#define DMFC_GENERAL1		0x0014
+#define DMFC_GENERAL2		0x0018
+#define DMFC_IC_CTRL		0x001c
+#define DMFC_WR_CHAN_ALT	0x0020
+#define DMFC_WR_CHAN_DEF_ALT	0x0024
+#define DMFC_DP_CHAN_ALT	0x0028
+#define DMFC_DP_CHAN_DEF_ALT	0x002c
+#define DMFC_GENERAL1_ALT	0x0030
+#define DMFC_STAT		0x0034
+
+#define DMFC_WR_CHAN_1_28		0
+#define DMFC_WR_CHAN_2_41		8
+#define DMFC_WR_CHAN_1C_42		16
+#define DMFC_WR_CHAN_2C_43		24
+
+#define DMFC_DP_CHAN_5B_23		0
+#define DMFC_DP_CHAN_5F_27		8
+#define DMFC_DP_CHAN_6B_24		16
+#define DMFC_DP_CHAN_6F_29		24
+
+#define DMFC_FIFO_SIZE_64		(3 << 3)
+#define DMFC_FIFO_SIZE_128		(2 << 3)
+#define DMFC_FIFO_SIZE_256		(1 << 3)
+#define DMFC_FIFO_SIZE_512		(0 << 3)
+
+#define DMFC_SEGMENT(x)			((x & 0x7) << 0)
+#define DMFC_BURSTSIZE_128		(0 << 6)
+#define DMFC_BURSTSIZE_64		(1 << 6)
+#define DMFC_BURSTSIZE_32		(2 << 6)
+#define DMFC_BURSTSIZE_16		(3 << 6)
+
+struct dmfc_channel_data {
+	int		ipu_channel;
+	unsigned long	channel_reg;
+	unsigned long	shift;
+	unsigned	eot_shift;
+	unsigned	max_fifo_lines;
+};
+
+static const struct dmfc_channel_data dmfcdata[] = {
+	{
+		.ipu_channel	= IPUV3_CHANNEL_MEM_BG_SYNC,
+		.channel_reg	= DMFC_DP_CHAN,
+		.shift		= DMFC_DP_CHAN_5B_23,
+		.eot_shift	= 20,
+		.max_fifo_lines	= 3,
+	}, {
+		.ipu_channel	= 24,
+		.channel_reg	= DMFC_DP_CHAN,
+		.shift		= DMFC_DP_CHAN_6B_24,
+		.eot_shift	= 22,
+		.max_fifo_lines	= 1,
+	}, {
+		.ipu_channel	= IPUV3_CHANNEL_MEM_FG_SYNC,
+		.channel_reg	= DMFC_DP_CHAN,
+		.shift		= DMFC_DP_CHAN_5F_27,
+		.eot_shift	= 21,
+		.max_fifo_lines	= 2,
+	}, {
+		.ipu_channel	= IPUV3_CHANNEL_MEM_DC_SYNC,
+		.channel_reg	= DMFC_WR_CHAN,
+		.shift		= DMFC_WR_CHAN_1_28,
+		.eot_shift	= 16,
+		.max_fifo_lines	= 2,
+	}, {
+		.ipu_channel	= 29,
+		.channel_reg	= DMFC_DP_CHAN,
+		.shift		= DMFC_DP_CHAN_6F_29,
+		.eot_shift	= 23,
+		.max_fifo_lines	= 1,
+	},
+};
+
+#define DMFC_NUM_CHANNELS	ARRAY_SIZE(dmfcdata)
+
+struct ipu_dmfc_priv;
+
+struct dmfc_channel {
+	unsigned			slots;
+	unsigned			slotmask;
+	unsigned			segment;
+	int				burstsize;
+	struct ipu_soc			*ipu;
+	struct ipu_dmfc_priv		*priv;
+	const struct dmfc_channel_data	*data;
+};
+
+struct ipu_dmfc_priv {
+	struct ipu_soc *ipu;
+	struct device *dev;
+	struct dmfc_channel channels[DMFC_NUM_CHANNELS];
+	struct mutex mutex;
+	unsigned long bandwidth_per_slot;
+	void __iomem *base;
+	int use_count;
+};
+
+int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
+{
+	struct ipu_dmfc_priv *priv = dmfc->priv;
+	mutex_lock(&priv->mutex);
+
+	if (!priv->use_count)
+		ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
+
+	priv->use_count++;
+
+	mutex_unlock(&priv->mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
+
+static void ipu_dmfc_wait_fifos(struct ipu_dmfc_priv *priv)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+
+	while ((readl(priv->base + DMFC_STAT) & 0x02fff000) != 0x02fff000) {
+		if (time_after(jiffies, timeout)) {
+			dev_warn(priv->dev,
+				 "Timeout waiting for DMFC FIFOs to clear\n");
+			break;
+		}
+		cpu_relax();
+	}
+}
+
+void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
+{
+	struct ipu_dmfc_priv *priv = dmfc->priv;
+
+	mutex_lock(&priv->mutex);
+
+	priv->use_count--;
+
+	if (!priv->use_count) {
+		ipu_dmfc_wait_fifos(priv);
+		ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
+	}
+
+	if (priv->use_count < 0)
+		priv->use_count = 0;
+
+	mutex_unlock(&priv->mutex);
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
+
+static int ipu_dmfc_setup_channel(struct dmfc_channel *dmfc, int slots,
+		int segment, int burstsize)
+{
+	struct ipu_dmfc_priv *priv = dmfc->priv;
+	u32 val, field;
+
+	dev_dbg(priv->dev,
+			"dmfc: using %d slots starting from segment %d for IPU channel %d\n",
+			slots, segment, dmfc->data->ipu_channel);
+
+	switch (slots) {
+	case 1:
+		field = DMFC_FIFO_SIZE_64;
+		break;
+	case 2:
+		field = DMFC_FIFO_SIZE_128;
+		break;
+	case 4:
+		field = DMFC_FIFO_SIZE_256;
+		break;
+	case 8:
+		field = DMFC_FIFO_SIZE_512;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (burstsize) {
+	case 16:
+		field |= DMFC_BURSTSIZE_16;
+		break;
+	case 32:
+		field |= DMFC_BURSTSIZE_32;
+		break;
+	case 64:
+		field |= DMFC_BURSTSIZE_64;
+		break;
+	case 128:
+		field |= DMFC_BURSTSIZE_128;
+		break;
+	}
+
+	field |= DMFC_SEGMENT(segment);
+
+	val = readl(priv->base + dmfc->data->channel_reg);
+
+	val &= ~(0xff << dmfc->data->shift);
+	val |= field << dmfc->data->shift;
+
+	writel(val, priv->base + dmfc->data->channel_reg);
+
+	dmfc->slots = slots;
+	dmfc->segment = segment;
+	dmfc->burstsize = burstsize;
+	dmfc->slotmask = ((1 << slots) - 1) << segment;
+
+	return 0;
+}
+
+static int dmfc_bandwidth_to_slots(struct ipu_dmfc_priv *priv,
+		unsigned long bandwidth)
+{
+	int slots = 1;
+
+	while (slots * priv->bandwidth_per_slot < bandwidth)
+		slots *= 2;
+
+	return slots;
+}
+
+static int dmfc_find_slots(struct ipu_dmfc_priv *priv, int slots)
+{
+	unsigned slotmask_need, slotmask_used = 0;
+	int i, segment = 0;
+
+	slotmask_need = (1 << slots) - 1;
+
+	for (i = 0; i < DMFC_NUM_CHANNELS; i++)
+		slotmask_used |= priv->channels[i].slotmask;
+
+	while (slotmask_need <= 0xff) {
+		if (!(slotmask_used & slotmask_need))
+			return segment;
+
+		slotmask_need <<= 1;
+		segment++;
+	}
+
+	return -EBUSY;
+}
+
+void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc)
+{
+	struct ipu_dmfc_priv *priv = dmfc->priv;
+	int i;
+
+	dev_dbg(priv->dev, "dmfc: freeing %d slots starting from segment %d\n",
+			dmfc->slots, dmfc->segment);
+
+	mutex_lock(&priv->mutex);
+
+	if (!dmfc->slots)
+		goto out;
+
+	dmfc->slotmask = 0;
+	dmfc->slots = 0;
+	dmfc->segment = 0;
+
+	for (i = 0; i < DMFC_NUM_CHANNELS; i++)
+		priv->channels[i].slotmask = 0;
+
+	for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
+		if (priv->channels[i].slots > 0) {
+			priv->channels[i].segment =
+				dmfc_find_slots(priv, priv->channels[i].slots);
+			priv->channels[i].slotmask =
+				((1 << priv->channels[i].slots) - 1) <<
+				priv->channels[i].segment;
+		}
+	}
+
+	for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
+		if (priv->channels[i].slots > 0)
+			ipu_dmfc_setup_channel(&priv->channels[i],
+					priv->channels[i].slots,
+					priv->channels[i].segment,
+					priv->channels[i].burstsize);
+	}
+out:
+	mutex_unlock(&priv->mutex);
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_free_bandwidth);
+
+int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
+		unsigned long bandwidth_pixel_per_second, int burstsize)
+{
+	struct ipu_dmfc_priv *priv = dmfc->priv;
+	int slots = dmfc_bandwidth_to_slots(priv, bandwidth_pixel_per_second);
+	int segment = -1, ret = 0;
+
+	dev_dbg(priv->dev, "dmfc: trying to allocate %ldMpixel/s for IPU channel %d\n",
+			bandwidth_pixel_per_second / 1000000,
+			dmfc->data->ipu_channel);
+
+	ipu_dmfc_free_bandwidth(dmfc);
+
+	mutex_lock(&priv->mutex);
+
+	if (slots > 8) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* For the MEM_BG channel, first try to allocate twice the slots */
+	if (dmfc->data->ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC)
+		segment = dmfc_find_slots(priv, slots * 2);
+	else if (slots < 2)
+		/* Always allocate at least 128*4 bytes (2 slots) */
+		slots = 2;
+
+	if (segment >= 0)
+		slots *= 2;
+	else
+		segment = dmfc_find_slots(priv, slots);
+	if (segment < 0) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ipu_dmfc_setup_channel(dmfc, slots, segment, burstsize);
+
+out:
+	mutex_unlock(&priv->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_alloc_bandwidth);
+
+int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width)
+{
+	struct ipu_dmfc_priv *priv = dmfc->priv;
+	u32 dmfc_gen1;
+
+	dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
+
+	if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
+		dmfc_gen1 |= 1 << dmfc->data->eot_shift;
+	else
+		dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
+
+	writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_init_channel);
+
+struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
+{
+	struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
+	int i;
+
+	for (i = 0; i < DMFC_NUM_CHANNELS; i++)
+		if (dmfcdata[i].ipu_channel == ipu_channel)
+			return &priv->channels[i];
+	return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_get);
+
+void ipu_dmfc_put(struct dmfc_channel *dmfc)
+{
+	ipu_dmfc_free_bandwidth(dmfc);
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_put);
+
+int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
+		struct clk *ipu_clk)
+{
+	struct ipu_dmfc_priv *priv;
+	int i;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->base = devm_ioremap(dev, base, PAGE_SIZE);
+	if (!priv->base)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	priv->ipu = ipu;
+	mutex_init(&priv->mutex);
+
+	ipu->dmfc_priv = priv;
+
+	for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
+		priv->channels[i].priv = priv;
+		priv->channels[i].ipu = ipu;
+		priv->channels[i].data = &dmfcdata[i];
+	}
+
+	writel(0x0, priv->base + DMFC_WR_CHAN);
+	writel(0x0, priv->base + DMFC_DP_CHAN);
+
+	/*
+	 * We have a total bandwidth of clkrate * 4pixel divided
+	 * into 8 slots.
+	 */
+	priv->bandwidth_per_slot = clk_get_rate(ipu_clk) * 4 / 8;
+
+	dev_dbg(dev, "dmfc: 8 slots with %ldMpixel/s bandwidth each\n",
+			priv->bandwidth_per_slot / 1000000);
+
+	writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
+	writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
+	writel(0x00000003, priv->base + DMFC_GENERAL1);
+
+	return 0;
+}
+
+void ipu_dmfc_exit(struct ipu_soc *ipu)
+{
+}
diff --git a/drivers/gpu/ipu-v3/ipu-dp.c b/drivers/gpu/ipu-v3/ipu-dp.c
new file mode 100644
index 0000000..98686ed
--- /dev/null
+++ b/drivers/gpu/ipu-v3/ipu-dp.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+#include <video/imx-ipu-v3.h>
+#include "ipu-prv.h"
+
+#define DP_SYNC 0
+#define DP_ASYNC0 0x60
+#define DP_ASYNC1 0xBC
+
+#define DP_COM_CONF		0x0
+#define DP_GRAPH_WIND_CTRL	0x0004
+#define DP_FG_POS		0x0008
+#define DP_CSC_A_0		0x0044
+#define DP_CSC_A_1		0x0048
+#define DP_CSC_A_2		0x004C
+#define DP_CSC_A_3		0x0050
+#define DP_CSC_0		0x0054
+#define DP_CSC_1		0x0058
+
+#define DP_COM_CONF_FG_EN		(1 << 0)
+#define DP_COM_CONF_GWSEL		(1 << 1)
+#define DP_COM_CONF_GWAM		(1 << 2)
+#define DP_COM_CONF_GWCKE		(1 << 3)
+#define DP_COM_CONF_CSC_DEF_MASK	(3 << 8)
+#define DP_COM_CONF_CSC_DEF_OFFSET	8
+#define DP_COM_CONF_CSC_DEF_FG		(3 << 8)
+#define DP_COM_CONF_CSC_DEF_BG		(2 << 8)
+#define DP_COM_CONF_CSC_DEF_BOTH	(1 << 8)
+
+#define IPUV3_NUM_FLOWS		3
+
+struct ipu_dp_priv;
+
+struct ipu_dp {
+	u32 flow;
+	bool in_use;
+	bool foreground;
+	enum ipu_color_space in_cs;
+};
+
+struct ipu_flow {
+	struct ipu_dp foreground;
+	struct ipu_dp background;
+	enum ipu_color_space out_cs;
+	void __iomem *base;
+	struct ipu_dp_priv *priv;
+};
+
+struct ipu_dp_priv {
+	struct ipu_soc *ipu;
+	struct device *dev;
+	void __iomem *base;
+	struct ipu_flow flow[IPUV3_NUM_FLOWS];
+	struct mutex mutex;
+	int use_count;
+};
+
+static u32 ipu_dp_flow_base[] = {DP_SYNC, DP_ASYNC0, DP_ASYNC1};
+
+static inline struct ipu_flow *to_flow(struct ipu_dp *dp)
+{
+	if (dp->foreground)
+		return container_of(dp, struct ipu_flow, foreground);
+	else
+		return container_of(dp, struct ipu_flow, background);
+}
+
+int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
+		u8 alpha, bool bg_chan)
+{
+	struct ipu_flow *flow = to_flow(dp);
+	struct ipu_dp_priv *priv = flow->priv;
+	u32 reg;
+
+	mutex_lock(&priv->mutex);
+
+	reg = readl(flow->base + DP_COM_CONF);
+	if (bg_chan)
+		reg &= ~DP_COM_CONF_GWSEL;
+	else
+		reg |= DP_COM_CONF_GWSEL;
+	writel(reg, flow->base + DP_COM_CONF);
+
+	if (enable) {
+		reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & 0x00FFFFFFL;
+		writel(reg | ((u32) alpha << 24),
+			     flow->base + DP_GRAPH_WIND_CTRL);
+
+		reg = readl(flow->base + DP_COM_CONF);
+		writel(reg | DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
+	} else {
+		reg = readl(flow->base + DP_COM_CONF);
+		writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
+	}
+
+	ipu_srm_dp_sync_update(priv->ipu);
+
+	mutex_unlock(&priv->mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha);
+
+int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
+{
+	struct ipu_flow *flow = to_flow(dp);
+	struct ipu_dp_priv *priv = flow->priv;
+
+	writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS);
+
+	ipu_srm_dp_sync_update(priv->ipu);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos);
+
+static void ipu_dp_csc_init(struct ipu_flow *flow,
+		enum ipu_color_space in,
+		enum ipu_color_space out,
+		u32 place)
+{
+	u32 reg;
+
+	reg = readl(flow->base + DP_COM_CONF);
+	reg &= ~DP_COM_CONF_CSC_DEF_MASK;
+
+	if (in == out) {
+		writel(reg, flow->base + DP_COM_CONF);
+		return;
+	}
+
+	if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) {
+		writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0);
+		writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1);
+		writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2);
+		writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3);
+		writel(0x3d6 | (0x0000 << 16) | (2 << 30),
+				flow->base + DP_CSC_0);
+		writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
+				flow->base + DP_CSC_1);
+	} else {
+		writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
+		writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1);
+		writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2);
+		writel(0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3);
+		writel(0x000 | (0x3e42 << 16) | (1 << 30),
+				flow->base + DP_CSC_0);
+		writel(0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30),
+				flow->base + DP_CSC_1);
+	}
+
+	reg |= place;
+
+	writel(reg, flow->base + DP_COM_CONF);
+}
+
+int ipu_dp_setup_channel(struct ipu_dp *dp,
+		enum ipu_color_space in,
+		enum ipu_color_space out)
+{
+	struct ipu_flow *flow = to_flow(dp);
+	struct ipu_dp_priv *priv = flow->priv;
+
+	mutex_lock(&priv->mutex);
+
+	dp->in_cs = in;
+
+	if (!dp->foreground)
+		flow->out_cs = out;
+
+	if (flow->foreground.in_cs == flow->background.in_cs) {
+		/*
+		 * foreground and background are of same colorspace, put
+		 * colorspace converter after combining unit.
+		 */
+		ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs,
+				DP_COM_CONF_CSC_DEF_BOTH);
+	} else {
+		if (flow->foreground.in_cs == flow->out_cs)
+			/*
+			 * foreground identical to output, apply color
+			 * conversion on background
+			 */
+			ipu_dp_csc_init(flow, flow->background.in_cs,
+					flow->out_cs, DP_COM_CONF_CSC_DEF_BG);
+		else
+			ipu_dp_csc_init(flow, flow->foreground.in_cs,
+					flow->out_cs, DP_COM_CONF_CSC_DEF_FG);
+	}
+
+	ipu_srm_dp_sync_update(priv->ipu);
+
+	mutex_unlock(&priv->mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
+
+int ipu_dp_enable(struct ipu_soc *ipu)
+{
+	struct ipu_dp_priv *priv = ipu->dp_priv;
+
+	mutex_lock(&priv->mutex);
+
+	if (!priv->use_count)
+		ipu_module_enable(priv->ipu, IPU_CONF_DP_EN);
+
+	priv->use_count++;
+
+	mutex_unlock(&priv->mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_enable);
+
+int ipu_dp_enable_channel(struct ipu_dp *dp)
+{
+	struct ipu_flow *flow = to_flow(dp);
+	struct ipu_dp_priv *priv = flow->priv;
+	u32 reg;
+
+	if (!dp->foreground)
+		return 0;
+
+	mutex_lock(&priv->mutex);
+
+	reg = readl(flow->base + DP_COM_CONF);
+	reg |= DP_COM_CONF_FG_EN;
+	writel(reg, flow->base + DP_COM_CONF);
+
+	ipu_srm_dp_sync_update(priv->ipu);
+
+	mutex_unlock(&priv->mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_enable_channel);
+
+void ipu_dp_disable_channel(struct ipu_dp *dp)
+{
+	struct ipu_flow *flow = to_flow(dp);
+	struct ipu_dp_priv *priv = flow->priv;
+	u32 reg, csc;
+
+	if (!dp->foreground)
+		return;
+
+	mutex_lock(&priv->mutex);
+
+	reg = readl(flow->base + DP_COM_CONF);
+	csc = reg & DP_COM_CONF_CSC_DEF_MASK;
+	if (csc == DP_COM_CONF_CSC_DEF_FG)
+		reg &= ~DP_COM_CONF_CSC_DEF_MASK;
+
+	reg &= ~DP_COM_CONF_FG_EN;
+	writel(reg, flow->base + DP_COM_CONF);
+
+	writel(0, flow->base + DP_FG_POS);
+	ipu_srm_dp_sync_update(priv->ipu);
+
+	if (ipu_idmac_channel_busy(priv->ipu, IPUV3_CHANNEL_MEM_BG_SYNC))
+		ipu_wait_interrupt(priv->ipu, IPU_IRQ_DP_SF_END, 50);
+
+	mutex_unlock(&priv->mutex);
+}
+EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
+
+void ipu_dp_disable(struct ipu_soc *ipu)
+{
+	struct ipu_dp_priv *priv = ipu->dp_priv;
+
+	mutex_lock(&priv->mutex);
+
+	priv->use_count--;
+
+	if (!priv->use_count)
+		ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
+
+	if (priv->use_count < 0)
+		priv->use_count = 0;
+
+	mutex_unlock(&priv->mutex);
+}
+EXPORT_SYMBOL_GPL(ipu_dp_disable);
+
+struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
+{
+	struct ipu_dp_priv *priv = ipu->dp_priv;
+	struct ipu_dp *dp;
+
+	if ((flow >> 1) >= IPUV3_NUM_FLOWS)
+		return ERR_PTR(-EINVAL);
+
+	if (flow & 1)
+		dp = &priv->flow[flow >> 1].foreground;
+	else
+		dp = &priv->flow[flow >> 1].background;
+
+	if (dp->in_use)
+		return ERR_PTR(-EBUSY);
+
+	dp->in_use = true;
+
+	return dp;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_get);
+
+void ipu_dp_put(struct ipu_dp *dp)
+{
+	dp->in_use = false;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_put);
+
+int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
+{
+	struct ipu_dp_priv *priv;
+	int i;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	priv->dev = dev;
+	priv->ipu = ipu;
+
+	ipu->dp_priv = priv;
+
+	priv->base = devm_ioremap(dev, base, PAGE_SIZE);
+	if (!priv->base)
+		return -ENOMEM;
+
+	mutex_init(&priv->mutex);
+
+	for (i = 0; i < IPUV3_NUM_FLOWS; i++) {
+		priv->flow[i].foreground.foreground = true;
+		priv->flow[i].base = priv->base + ipu_dp_flow_base[i];
+		priv->flow[i].priv = priv;
+	}
+
+	return 0;
+}
+
+void ipu_dp_exit(struct ipu_soc *ipu)
+{
+}
diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h
new file mode 100644
index 0000000..72e1158
--- /dev/null
+++ b/drivers/gpu/ipu-v3/ipu-prv.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+#ifndef __IPU_PRV_H__
+#define __IPU_PRV_H__
+
+struct ipu_soc;
+
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include <video/imx-ipu-v3.h>
+
+#define IPUV3_CHANNEL_CSI0			 0
+#define IPUV3_CHANNEL_CSI1			 1
+#define IPUV3_CHANNEL_CSI2			 2
+#define IPUV3_CHANNEL_CSI3			 3
+#define IPUV3_CHANNEL_MEM_BG_SYNC		23
+#define IPUV3_CHANNEL_MEM_FG_SYNC		27
+#define IPUV3_CHANNEL_MEM_DC_SYNC		28
+#define IPUV3_CHANNEL_MEM_FG_SYNC_ALPHA		31
+#define IPUV3_CHANNEL_MEM_DC_ASYNC		41
+#define IPUV3_CHANNEL_ROT_ENC_MEM		45
+#define IPUV3_CHANNEL_ROT_VF_MEM		46
+#define IPUV3_CHANNEL_ROT_PP_MEM		47
+#define IPUV3_CHANNEL_ROT_ENC_MEM_OUT		48
+#define IPUV3_CHANNEL_ROT_VF_MEM_OUT		49
+#define IPUV3_CHANNEL_ROT_PP_MEM_OUT		50
+#define IPUV3_CHANNEL_MEM_BG_SYNC_ALPHA		51
+
+#define IPU_MCU_T_DEFAULT	8
+#define IPU_CM_IDMAC_REG_OFS	0x00008000
+#define IPU_CM_IC_REG_OFS	0x00020000
+#define IPU_CM_IRT_REG_OFS	0x00028000
+#define IPU_CM_CSI0_REG_OFS	0x00030000
+#define IPU_CM_CSI1_REG_OFS	0x00038000
+#define IPU_CM_SMFC_REG_OFS	0x00050000
+#define IPU_CM_DC_REG_OFS	0x00058000
+#define IPU_CM_DMFC_REG_OFS	0x00060000
+
+/* Register addresses */
+/* IPU Common registers */
+#define IPU_CM_REG(offset)	(offset)
+
+#define IPU_CONF			IPU_CM_REG(0)
+
+#define IPU_SRM_PRI1			IPU_CM_REG(0x00a0)
+#define IPU_SRM_PRI2			IPU_CM_REG(0x00a4)
+#define IPU_FS_PROC_FLOW1		IPU_CM_REG(0x00a8)
+#define IPU_FS_PROC_FLOW2		IPU_CM_REG(0x00ac)
+#define IPU_FS_PROC_FLOW3		IPU_CM_REG(0x00b0)
+#define IPU_FS_DISP_FLOW1		IPU_CM_REG(0x00b4)
+#define IPU_FS_DISP_FLOW2		IPU_CM_REG(0x00b8)
+#define IPU_SKIP			IPU_CM_REG(0x00bc)
+#define IPU_DISP_ALT_CONF		IPU_CM_REG(0x00c0)
+#define IPU_DISP_GEN			IPU_CM_REG(0x00c4)
+#define IPU_DISP_ALT1			IPU_CM_REG(0x00c8)
+#define IPU_DISP_ALT2			IPU_CM_REG(0x00cc)
+#define IPU_DISP_ALT3			IPU_CM_REG(0x00d0)
+#define IPU_DISP_ALT4			IPU_CM_REG(0x00d4)
+#define IPU_SNOOP			IPU_CM_REG(0x00d8)
+#define IPU_MEM_RST			IPU_CM_REG(0x00dc)
+#define IPU_PM				IPU_CM_REG(0x00e0)
+#define IPU_GPR				IPU_CM_REG(0x00e4)
+#define IPU_CHA_DB_MODE_SEL(ch)		IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
+#define IPU_ALT_CHA_DB_MODE_SEL(ch)	IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
+#define IPU_CHA_CUR_BUF(ch)		IPU_CM_REG(0x023C + 4 * ((ch) / 32))
+#define IPU_ALT_CUR_BUF0		IPU_CM_REG(0x0244)
+#define IPU_ALT_CUR_BUF1		IPU_CM_REG(0x0248)
+#define IPU_SRM_STAT			IPU_CM_REG(0x024C)
+#define IPU_PROC_TASK_STAT		IPU_CM_REG(0x0250)
+#define IPU_DISP_TASK_STAT		IPU_CM_REG(0x0254)
+#define IPU_CHA_BUF0_RDY(ch)		IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
+#define IPU_CHA_BUF1_RDY(ch)		IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
+#define IPU_ALT_CHA_BUF0_RDY(ch)	IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
+#define IPU_ALT_CHA_BUF1_RDY(ch)	IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
+
+#define IPU_INT_CTRL(n)		IPU_CM_REG(0x003C + 4 * (n))
+#define IPU_INT_STAT(n)		IPU_CM_REG(0x0200 + 4 * (n))
+
+#define IPU_DI0_COUNTER_RELEASE			(1 << 24)
+#define IPU_DI1_COUNTER_RELEASE			(1 << 25)
+
+#define IPU_IDMAC_REG(offset)	(offset)
+
+#define IDMAC_CONF			IPU_IDMAC_REG(0x0000)
+#define IDMAC_CHA_EN(ch)		IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
+#define IDMAC_SEP_ALPHA			IPU_IDMAC_REG(0x000c)
+#define IDMAC_ALT_SEP_ALPHA		IPU_IDMAC_REG(0x0010)
+#define IDMAC_CHA_PRI(ch)		IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
+#define IDMAC_WM_EN(ch)			IPU_IDMAC_REG(0x001c + 4 * ((ch) / 32))
+#define IDMAC_CH_LOCK_EN_1		IPU_IDMAC_REG(0x0024)
+#define IDMAC_CH_LOCK_EN_2		IPU_IDMAC_REG(0x0028)
+#define IDMAC_SUB_ADDR_0		IPU_IDMAC_REG(0x002c)
+#define IDMAC_SUB_ADDR_1		IPU_IDMAC_REG(0x0030)
+#define IDMAC_SUB_ADDR_2		IPU_IDMAC_REG(0x0034)
+#define IDMAC_BAND_EN(ch)		IPU_IDMAC_REG(0x0040 + 4 * ((ch) / 32))
+#define IDMAC_CHA_BUSY(ch)		IPU_IDMAC_REG(0x0100 + 4 * ((ch) / 32))
+
+#define IPU_NUM_IRQS	(32 * 15)
+
+enum ipu_modules {
+	IPU_CONF_CSI0_EN		= (1 << 0),
+	IPU_CONF_CSI1_EN		= (1 << 1),
+	IPU_CONF_IC_EN			= (1 << 2),
+	IPU_CONF_ROT_EN			= (1 << 3),
+	IPU_CONF_ISP_EN			= (1 << 4),
+	IPU_CONF_DP_EN			= (1 << 5),
+	IPU_CONF_DI0_EN			= (1 << 6),
+	IPU_CONF_DI1_EN			= (1 << 7),
+	IPU_CONF_SMFC_EN		= (1 << 8),
+	IPU_CONF_DC_EN			= (1 << 9),
+	IPU_CONF_DMFC_EN		= (1 << 10),
+
+	IPU_CONF_VDI_EN			= (1 << 12),
+
+	IPU_CONF_IDMAC_DIS		= (1 << 22),
+
+	IPU_CONF_IC_DMFC_SEL		= (1 << 25),
+	IPU_CONF_IC_DMFC_SYNC		= (1 << 26),
+	IPU_CONF_VDI_DMFC_SYNC		= (1 << 27),
+
+	IPU_CONF_CSI0_DATA_SOURCE	= (1 << 28),
+	IPU_CONF_CSI1_DATA_SOURCE	= (1 << 29),
+	IPU_CONF_IC_INPUT		= (1 << 30),
+	IPU_CONF_CSI_SEL		= (1 << 31),
+};
+
+struct ipuv3_channel {
+	unsigned int num;
+
+	bool enabled;
+	bool busy;
+
+	struct ipu_soc *ipu;
+};
+
+struct ipu_dc_priv;
+struct ipu_dmfc_priv;
+struct ipu_di;
+struct ipu_devtype;
+
+struct ipu_soc {
+	struct device		*dev;
+	const struct ipu_devtype	*devtype;
+	enum ipuv3_type		ipu_type;
+	spinlock_t		lock;
+	struct mutex		channel_lock;
+
+	void __iomem		*cm_reg;
+	void __iomem		*idmac_reg;
+	struct ipu_ch_param __iomem	*cpmem_base;
+
+	int			usecount;
+
+	struct clk		*clk;
+
+	struct ipuv3_channel	channel[64];
+
+	int			irq_sync;
+	int			irq_err;
+	struct irq_domain	*domain;
+
+	struct ipu_dc_priv	*dc_priv;
+	struct ipu_dp_priv	*dp_priv;
+	struct ipu_dmfc_priv	*dmfc_priv;
+	struct ipu_di		*di_priv[2];
+};
+
+void ipu_srm_dp_sync_update(struct ipu_soc *ipu);
+
+int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
+int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
+
+bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
+int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms);
+
+int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
+		unsigned long base, u32 module, struct clk *ipu_clk);
+void ipu_di_exit(struct ipu_soc *ipu, int id);
+
+int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
+		struct clk *ipu_clk);
+void ipu_dmfc_exit(struct ipu_soc *ipu);
+
+int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
+void ipu_dp_exit(struct ipu_soc *ipu);
+
+int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
+		unsigned long template_base);
+void ipu_dc_exit(struct ipu_soc *ipu);
+
+int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
+void ipu_cpmem_exit(struct ipu_soc *ipu);
+
+#endif				/* __IPU_PRV_H__ */
diff --git a/drivers/staging/imx-drm/Kconfig b/drivers/staging/imx-drm/Kconfig
index c6e8ba7..82fb758 100644
--- a/drivers/staging/imx-drm/Kconfig
+++ b/drivers/staging/imx-drm/Kconfig
@@ -39,19 +39,10 @@ config DRM_IMX_LDB
 	  Choose this to enable the internal LVDS Display Bridge (LDB)
 	  found on i.MX53 and i.MX6 processors.
 
-config DRM_IMX_IPUV3_CORE
-	tristate "IPUv3 core support"
-	depends on DRM_IMX
-	depends on RESET_CONTROLLER
-	help
-	  Choose this if you have a i.MX5/6 system and want
-	  to use the IPU. This option only enables IPU base
-	  support.
-
 config DRM_IMX_IPUV3
 	tristate "DRM Support for i.MX IPUv3"
 	depends on DRM_IMX
-	depends on DRM_IMX_IPUV3_CORE
+	depends on IMX_IPUV3_CORE
 	help
 	  Choose this if you have a i.MX5 or i.MX6 processor.
 
diff --git a/drivers/staging/imx-drm/Makefile b/drivers/staging/imx-drm/Makefile
index 129e3a3..582c438 100644
--- a/drivers/staging/imx-drm/Makefile
+++ b/drivers/staging/imx-drm/Makefile
@@ -6,7 +6,6 @@ obj-$(CONFIG_DRM_IMX) += imxdrm.o
 obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += parallel-display.o
 obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o
 obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
-obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += ipu-v3/
 
 imx-ipuv3-crtc-objs  := ipuv3-crtc.o ipuv3-plane.o
 obj-$(CONFIG_DRM_IMX_IPUV3)	+= imx-ipuv3-crtc.o
diff --git a/drivers/staging/imx-drm/imx-hdmi.c b/drivers/staging/imx-drm/imx-hdmi.c
index 1b44048..e7f3de5 100644
--- a/drivers/staging/imx-drm/imx-hdmi.c
+++ b/drivers/staging/imx-drm/imx-hdmi.c
@@ -27,8 +27,8 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder_slave.h>
+#include <video/imx-ipu-v3.h>
 
-#include "ipu-v3/imx-ipu-v3.h"
 #include "imx-hdmi.h"
 #include "imx-drm.h"
 
diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c
index a23f4f7..b12fb17 100644
--- a/drivers/staging/imx-drm/imx-tve.c
+++ b/drivers/staging/imx-drm/imx-tve.c
@@ -30,8 +30,8 @@
 #include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <video/imx-ipu-v3.h>
 
-#include "ipu-v3/imx-ipu-v3.h"
 #include "imx-drm.h"
 
 #define TVE_COM_CONF_REG	0x00
diff --git a/drivers/staging/imx-drm/ipu-v3/Makefile b/drivers/staging/imx-drm/ipu-v3/Makefile
deleted file mode 100644
index 28ed72e..0000000
--- a/drivers/staging/imx-drm/ipu-v3/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += imx-ipu-v3.o
-
-imx-ipu-v3-objs := ipu-common.o ipu-dc.o ipu-di.o ipu-dp.o ipu-dmfc.o
diff --git a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
deleted file mode 100644
index c2c6fab..0000000
--- a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Copyright 2005-2009 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU Lesser General
- * Public License.  You may obtain a copy of the GNU Lesser General
- * Public License Version 2.1 or later at the following locations:
- *
- * http://www.opensource.org/licenses/lgpl-license.html
- * http://www.gnu.org/copyleft/lgpl.html
- */
-
-#ifndef __DRM_IPU_H__
-#define __DRM_IPU_H__
-
-#include <linux/types.h>
-#include <linux/videodev2.h>
-#include <linux/bitmap.h>
-#include <linux/fb.h>
-
-struct ipu_soc;
-
-enum ipuv3_type {
-	IPUV3EX,
-	IPUV3M,
-	IPUV3H,
-};
-
-#define IPU_PIX_FMT_GBR24	v4l2_fourcc('G', 'B', 'R', '3')
-
-/*
- * Bitfield of Display Interface signal polarities.
- */
-struct ipu_di_signal_cfg {
-	unsigned datamask_en:1;
-	unsigned interlaced:1;
-	unsigned odd_field_first:1;
-	unsigned clksel_en:1;
-	unsigned clkidle_en:1;
-	unsigned data_pol:1;	/* true = inverted */
-	unsigned clk_pol:1;	/* true = rising edge */
-	unsigned enable_pol:1;
-	unsigned Hsync_pol:1;	/* true = active high */
-	unsigned Vsync_pol:1;
-
-	u16 width;
-	u16 height;
-	u32 pixel_fmt;
-	u16 h_start_width;
-	u16 h_sync_width;
-	u16 h_end_width;
-	u16 v_start_width;
-	u16 v_sync_width;
-	u16 v_end_width;
-	u32 v_to_h_sync;
-	unsigned long pixelclock;
-#define IPU_DI_CLKMODE_SYNC	(1 << 0)
-#define IPU_DI_CLKMODE_EXT	(1 << 1)
-	unsigned long clkflags;
-
-	u8 hsync_pin;
-	u8 vsync_pin;
-};
-
-enum ipu_color_space {
-	IPUV3_COLORSPACE_RGB,
-	IPUV3_COLORSPACE_YUV,
-	IPUV3_COLORSPACE_UNKNOWN,
-};
-
-struct ipuv3_channel;
-
-enum ipu_channel_irq {
-	IPU_IRQ_EOF = 0,
-	IPU_IRQ_NFACK = 64,
-	IPU_IRQ_NFB4EOF = 128,
-	IPU_IRQ_EOS = 192,
-};
-
-int ipu_map_irq(struct ipu_soc *ipu, int irq);
-int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
-		enum ipu_channel_irq irq);
-
-#define IPU_IRQ_DP_SF_START		(448 + 2)
-#define IPU_IRQ_DP_SF_END		(448 + 3)
-#define IPU_IRQ_BG_SF_END		IPU_IRQ_DP_SF_END,
-#define IPU_IRQ_DC_FC_0			(448 + 8)
-#define IPU_IRQ_DC_FC_1			(448 + 9)
-#define IPU_IRQ_DC_FC_2			(448 + 10)
-#define IPU_IRQ_DC_FC_3			(448 + 11)
-#define IPU_IRQ_DC_FC_4			(448 + 12)
-#define IPU_IRQ_DC_FC_6			(448 + 13)
-#define IPU_IRQ_VSYNC_PRE_0		(448 + 14)
-#define IPU_IRQ_VSYNC_PRE_1		(448 + 15)
-
-/*
- * IPU Image DMA Controller (idmac) functions
- */
-struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned channel);
-void ipu_idmac_put(struct ipuv3_channel *);
-
-int ipu_idmac_enable_channel(struct ipuv3_channel *channel);
-int ipu_idmac_disable_channel(struct ipuv3_channel *channel);
-int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms);
-
-void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
-		bool doublebuffer);
-void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num);
-
-/*
- * IPU Display Controller (dc) functions
- */
-struct ipu_dc;
-struct ipu_di;
-struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel);
-void ipu_dc_put(struct ipu_dc *dc);
-int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
-		u32 pixel_fmt, u32 width);
-void ipu_dc_enable(struct ipu_soc *ipu);
-void ipu_dc_enable_channel(struct ipu_dc *dc);
-void ipu_dc_disable_channel(struct ipu_dc *dc);
-void ipu_dc_disable(struct ipu_soc *ipu);
-
-/*
- * IPU Display Interface (di) functions
- */
-struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp);
-void ipu_di_put(struct ipu_di *);
-int ipu_di_disable(struct ipu_di *);
-int ipu_di_enable(struct ipu_di *);
-int ipu_di_get_num(struct ipu_di *);
-int ipu_di_init_sync_panel(struct ipu_di *, struct ipu_di_signal_cfg *sig);
-
-/*
- * IPU Display Multi FIFO Controller (dmfc) functions
- */
-struct dmfc_channel;
-int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc);
-void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc);
-int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
-		unsigned long bandwidth_mbs, int burstsize);
-void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc);
-int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width);
-struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipuv3_channel);
-void ipu_dmfc_put(struct dmfc_channel *dmfc);
-
-/*
- * IPU Display Processor (dp) functions
- */
-#define IPU_DP_FLOW_SYNC_BG	0
-#define IPU_DP_FLOW_SYNC_FG	1
-#define IPU_DP_FLOW_ASYNC0_BG	2
-#define IPU_DP_FLOW_ASYNC0_FG	3
-#define IPU_DP_FLOW_ASYNC1_BG	4
-#define IPU_DP_FLOW_ASYNC1_FG	5
-
-struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow);
-void ipu_dp_put(struct ipu_dp *);
-int ipu_dp_enable(struct ipu_soc *ipu);
-int ipu_dp_enable_channel(struct ipu_dp *dp);
-void ipu_dp_disable_channel(struct ipu_dp *dp);
-void ipu_dp_disable(struct ipu_soc *ipu);
-int ipu_dp_setup_channel(struct ipu_dp *dp,
-		enum ipu_color_space in, enum ipu_color_space out);
-int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos);
-int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha,
-		bool bg_chan);
-
-#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
-
-#define IPU_FIELD_UBO		IPU_CPMEM_WORD(0, 46, 22)
-#define IPU_FIELD_VBO		IPU_CPMEM_WORD(0, 68, 22)
-#define IPU_FIELD_IOX		IPU_CPMEM_WORD(0, 90, 4)
-#define IPU_FIELD_RDRW		IPU_CPMEM_WORD(0, 94, 1)
-#define IPU_FIELD_SO		IPU_CPMEM_WORD(0, 113, 1)
-#define IPU_FIELD_SLY		IPU_CPMEM_WORD(1, 102, 14)
-#define IPU_FIELD_SLUV		IPU_CPMEM_WORD(1, 128, 14)
-
-#define IPU_FIELD_XV		IPU_CPMEM_WORD(0, 0, 10)
-#define IPU_FIELD_YV		IPU_CPMEM_WORD(0, 10, 9)
-#define IPU_FIELD_XB		IPU_CPMEM_WORD(0, 19, 13)
-#define IPU_FIELD_YB		IPU_CPMEM_WORD(0, 32, 12)
-#define IPU_FIELD_NSB_B		IPU_CPMEM_WORD(0, 44, 1)
-#define IPU_FIELD_CF		IPU_CPMEM_WORD(0, 45, 1)
-#define IPU_FIELD_SX		IPU_CPMEM_WORD(0, 46, 12)
-#define IPU_FIELD_SY		IPU_CPMEM_WORD(0, 58, 11)
-#define IPU_FIELD_NS		IPU_CPMEM_WORD(0, 69, 10)
-#define IPU_FIELD_SDX		IPU_CPMEM_WORD(0, 79, 7)
-#define IPU_FIELD_SM		IPU_CPMEM_WORD(0, 86, 10)
-#define IPU_FIELD_SCC		IPU_CPMEM_WORD(0, 96, 1)
-#define IPU_FIELD_SCE		IPU_CPMEM_WORD(0, 97, 1)
-#define IPU_FIELD_SDY		IPU_CPMEM_WORD(0, 98, 7)
-#define IPU_FIELD_SDRX		IPU_CPMEM_WORD(0, 105, 1)
-#define IPU_FIELD_SDRY		IPU_CPMEM_WORD(0, 106, 1)
-#define IPU_FIELD_BPP		IPU_CPMEM_WORD(0, 107, 3)
-#define IPU_FIELD_DEC_SEL	IPU_CPMEM_WORD(0, 110, 2)
-#define IPU_FIELD_DIM		IPU_CPMEM_WORD(0, 112, 1)
-#define IPU_FIELD_BNDM		IPU_CPMEM_WORD(0, 114, 3)
-#define IPU_FIELD_BM		IPU_CPMEM_WORD(0, 117, 2)
-#define IPU_FIELD_ROT		IPU_CPMEM_WORD(0, 119, 1)
-#define IPU_FIELD_HF		IPU_CPMEM_WORD(0, 120, 1)
-#define IPU_FIELD_VF		IPU_CPMEM_WORD(0, 121, 1)
-#define IPU_FIELD_THE		IPU_CPMEM_WORD(0, 122, 1)
-#define IPU_FIELD_CAP		IPU_CPMEM_WORD(0, 123, 1)
-#define IPU_FIELD_CAE		IPU_CPMEM_WORD(0, 124, 1)
-#define IPU_FIELD_FW		IPU_CPMEM_WORD(0, 125, 13)
-#define IPU_FIELD_FH		IPU_CPMEM_WORD(0, 138, 12)
-#define IPU_FIELD_EBA0		IPU_CPMEM_WORD(1, 0, 29)
-#define IPU_FIELD_EBA1		IPU_CPMEM_WORD(1, 29, 29)
-#define IPU_FIELD_ILO		IPU_CPMEM_WORD(1, 58, 20)
-#define IPU_FIELD_NPB		IPU_CPMEM_WORD(1, 78, 7)
-#define IPU_FIELD_PFS		IPU_CPMEM_WORD(1, 85, 4)
-#define IPU_FIELD_ALU		IPU_CPMEM_WORD(1, 89, 1)
-#define IPU_FIELD_ALBM		IPU_CPMEM_WORD(1, 90, 3)
-#define IPU_FIELD_ID		IPU_CPMEM_WORD(1, 93, 2)
-#define IPU_FIELD_TH		IPU_CPMEM_WORD(1, 95, 7)
-#define IPU_FIELD_SL		IPU_CPMEM_WORD(1, 102, 14)
-#define IPU_FIELD_WID0		IPU_CPMEM_WORD(1, 116, 3)
-#define IPU_FIELD_WID1		IPU_CPMEM_WORD(1, 119, 3)
-#define IPU_FIELD_WID2		IPU_CPMEM_WORD(1, 122, 3)
-#define IPU_FIELD_WID3		IPU_CPMEM_WORD(1, 125, 3)
-#define IPU_FIELD_OFS0		IPU_CPMEM_WORD(1, 128, 5)
-#define IPU_FIELD_OFS1		IPU_CPMEM_WORD(1, 133, 5)
-#define IPU_FIELD_OFS2		IPU_CPMEM_WORD(1, 138, 5)
-#define IPU_FIELD_OFS3		IPU_CPMEM_WORD(1, 143, 5)
-#define IPU_FIELD_SXYS		IPU_CPMEM_WORD(1, 148, 1)
-#define IPU_FIELD_CRE		IPU_CPMEM_WORD(1, 149, 1)
-#define IPU_FIELD_DEC_SEL2	IPU_CPMEM_WORD(1, 150, 1)
-
-struct ipu_cpmem_word {
-	u32 data[5];
-	u32 res[3];
-};
-
-struct ipu_ch_param {
-	struct ipu_cpmem_word word[2];
-};
-
-void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 v);
-u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs);
-struct ipu_ch_param __iomem *ipu_get_cpmem(struct ipuv3_channel *channel);
-void ipu_ch_param_dump(struct ipu_ch_param __iomem *p);
-
-static inline void ipu_ch_param_zero(struct ipu_ch_param __iomem *p)
-{
-	int i;
-	void __iomem *base = p;
-
-	for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
-		writel(0, base + i * sizeof(u32));
-}
-
-static inline void ipu_cpmem_set_buffer(struct ipu_ch_param __iomem *p,
-		int bufnum, dma_addr_t buf)
-{
-	if (bufnum)
-		ipu_ch_param_write_field(p, IPU_FIELD_EBA1, buf >> 3);
-	else
-		ipu_ch_param_write_field(p, IPU_FIELD_EBA0, buf >> 3);
-}
-
-static inline void ipu_cpmem_set_resolution(struct ipu_ch_param __iomem *p,
-		int xres, int yres)
-{
-	ipu_ch_param_write_field(p, IPU_FIELD_FW, xres - 1);
-	ipu_ch_param_write_field(p, IPU_FIELD_FH, yres - 1);
-}
-
-static inline void ipu_cpmem_set_stride(struct ipu_ch_param __iomem *p,
-		int stride)
-{
-	ipu_ch_param_write_field(p, IPU_FIELD_SLY, stride - 1);
-}
-
-void ipu_cpmem_set_high_priority(struct ipuv3_channel *channel);
-
-struct ipu_rgb {
-	struct fb_bitfield	red;
-	struct fb_bitfield	green;
-	struct fb_bitfield	blue;
-	struct fb_bitfield	transp;
-	int			bits_per_pixel;
-};
-
-struct ipu_image {
-	struct v4l2_pix_format pix;
-	struct v4l2_rect rect;
-	dma_addr_t phys;
-};
-
-int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p,
-		int width);
-
-int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *,
-		const struct ipu_rgb *rgb);
-
-static inline void ipu_cpmem_interlaced_scan(struct ipu_ch_param *p,
-		int stride)
-{
-	ipu_ch_param_write_field(p, IPU_FIELD_SO, 1);
-	ipu_ch_param_write_field(p, IPU_FIELD_ILO, stride / 8);
-	ipu_ch_param_write_field(p, IPU_FIELD_SLY, (stride * 2) - 1);
-};
-
-void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format,
-			int stride, int height);
-void ipu_cpmem_set_yuv_interleaved(struct ipu_ch_param __iomem *p,
-				   u32 pixel_format);
-void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p,
-		u32 pixel_format, int stride, int u_offset, int v_offset);
-int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat);
-int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem,
-		struct ipu_image *image);
-
-enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc);
-enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat);
-
-static inline void ipu_cpmem_set_burstsize(struct ipu_ch_param __iomem *p,
-		int burstsize)
-{
-	ipu_ch_param_write_field(p, IPU_FIELD_NPB, burstsize - 1);
-};
-
-struct ipu_client_platformdata {
-	int di;
-	int dc;
-	int dp;
-	int dmfc;
-	int dma[2];
-};
-
-#endif /* __DRM_IPU_H__ */
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
deleted file mode 100644
index a1f7b20..0000000
--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+++ /dev/null
@@ -1,1292 +0,0 @@
-/*
- * Copyright (c) 2010 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-#include <linux/module.h>
-#include <linux/export.h>
-#include <linux/types.h>
-#include <linux/reset.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/list.h>
-#include <linux/irq.h>
-#include <linux/irqchip/chained_irq.h>
-#include <linux/irqdomain.h>
-#include <linux/of_device.h>
-
-#include <drm/drm_fourcc.h>
-
-#include "imx-ipu-v3.h"
-#include "ipu-prv.h"
-
-static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
-{
-	return readl(ipu->cm_reg + offset);
-}
-
-static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset)
-{
-	writel(value, ipu->cm_reg + offset);
-}
-
-static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
-{
-	return readl(ipu->idmac_reg + offset);
-}
-
-static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
-		unsigned offset)
-{
-	writel(value, ipu->idmac_reg + offset);
-}
-
-void ipu_srm_dp_sync_update(struct ipu_soc *ipu)
-{
-	u32 val;
-
-	val = ipu_cm_read(ipu, IPU_SRM_PRI2);
-	val |= 0x8;
-	ipu_cm_write(ipu, val, IPU_SRM_PRI2);
-}
-EXPORT_SYMBOL_GPL(ipu_srm_dp_sync_update);
-
-struct ipu_ch_param __iomem *ipu_get_cpmem(struct ipuv3_channel *channel)
-{
-	struct ipu_soc *ipu = channel->ipu;
-
-	return ipu->cpmem_base + channel->num;
-}
-EXPORT_SYMBOL_GPL(ipu_get_cpmem);
-
-void ipu_cpmem_set_high_priority(struct ipuv3_channel *channel)
-{
-	struct ipu_soc *ipu = channel->ipu;
-	struct ipu_ch_param __iomem *p = ipu_get_cpmem(channel);
-	u32 val;
-
-	if (ipu->ipu_type == IPUV3EX)
-		ipu_ch_param_write_field(p, IPU_FIELD_ID, 1);
-
-	val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(channel->num));
-	val |= 1 << (channel->num % 32);
-	ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(channel->num));
-};
-EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
-
-void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 v)
-{
-	u32 bit = (wbs >> 8) % 160;
-	u32 size = wbs & 0xff;
-	u32 word = (wbs >> 8) / 160;
-	u32 i = bit / 32;
-	u32 ofs = bit % 32;
-	u32 mask = (1 << size) - 1;
-	u32 val;
-
-	pr_debug("%s %d %d %d\n", __func__, word, bit , size);
-
-	val = readl(&base->word[word].data[i]);
-	val &= ~(mask << ofs);
-	val |= v << ofs;
-	writel(val, &base->word[word].data[i]);
-
-	if ((bit + size - 1) / 32 > i) {
-		val = readl(&base->word[word].data[i + 1]);
-		val &= ~(mask >> (ofs ? (32 - ofs) : 0));
-		val |= v >> (ofs ? (32 - ofs) : 0);
-		writel(val, &base->word[word].data[i + 1]);
-	}
-}
-EXPORT_SYMBOL_GPL(ipu_ch_param_write_field);
-
-u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs)
-{
-	u32 bit = (wbs >> 8) % 160;
-	u32 size = wbs & 0xff;
-	u32 word = (wbs >> 8) / 160;
-	u32 i = bit / 32;
-	u32 ofs = bit % 32;
-	u32 mask = (1 << size) - 1;
-	u32 val = 0;
-
-	pr_debug("%s %d %d %d\n", __func__, word, bit , size);
-
-	val = (readl(&base->word[word].data[i]) >> ofs) & mask;
-
-	if ((bit + size - 1) / 32 > i) {
-		u32 tmp;
-		tmp = readl(&base->word[word].data[i + 1]);
-		tmp &= mask >> (ofs ? (32 - ofs) : 0);
-		val |= tmp << (ofs ? (32 - ofs) : 0);
-	}
-
-	return val;
-}
-EXPORT_SYMBOL_GPL(ipu_ch_param_read_field);
-
-int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *p,
-		const struct ipu_rgb *rgb)
-{
-	int bpp = 0, npb = 0, ro, go, bo, to;
-
-	ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
-	go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
-	bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
-	to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
-
-	ipu_ch_param_write_field(p, IPU_FIELD_WID0, rgb->red.length - 1);
-	ipu_ch_param_write_field(p, IPU_FIELD_OFS0, ro);
-	ipu_ch_param_write_field(p, IPU_FIELD_WID1, rgb->green.length - 1);
-	ipu_ch_param_write_field(p, IPU_FIELD_OFS1, go);
-	ipu_ch_param_write_field(p, IPU_FIELD_WID2, rgb->blue.length - 1);
-	ipu_ch_param_write_field(p, IPU_FIELD_OFS2, bo);
-
-	if (rgb->transp.length) {
-		ipu_ch_param_write_field(p, IPU_FIELD_WID3,
-				rgb->transp.length - 1);
-		ipu_ch_param_write_field(p, IPU_FIELD_OFS3, to);
-	} else {
-		ipu_ch_param_write_field(p, IPU_FIELD_WID3, 7);
-		ipu_ch_param_write_field(p, IPU_FIELD_OFS3,
-				rgb->bits_per_pixel);
-	}
-
-	switch (rgb->bits_per_pixel) {
-	case 32:
-		bpp = 0;
-		npb = 15;
-		break;
-	case 24:
-		bpp = 1;
-		npb = 19;
-		break;
-	case 16:
-		bpp = 3;
-		npb = 31;
-		break;
-	case 8:
-		bpp = 5;
-		npb = 63;
-		break;
-	default:
-		return -EINVAL;
-	}
-	ipu_ch_param_write_field(p, IPU_FIELD_BPP, bpp);
-	ipu_ch_param_write_field(p, IPU_FIELD_NPB, npb);
-	ipu_ch_param_write_field(p, IPU_FIELD_PFS, 7); /* rgb mode */
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
-
-int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p,
-		int width)
-{
-	int bpp = 0, npb = 0;
-
-	switch (width) {
-	case 32:
-		bpp = 0;
-		npb = 15;
-		break;
-	case 24:
-		bpp = 1;
-		npb = 19;
-		break;
-	case 16:
-		bpp = 3;
-		npb = 31;
-		break;
-	case 8:
-		bpp = 5;
-		npb = 63;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	ipu_ch_param_write_field(p, IPU_FIELD_BPP, bpp);
-	ipu_ch_param_write_field(p, IPU_FIELD_NPB, npb);
-	ipu_ch_param_write_field(p, IPU_FIELD_PFS, 6); /* raw mode */
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
-
-void ipu_cpmem_set_yuv_interleaved(struct ipu_ch_param __iomem *p,
-				   u32 pixel_format)
-{
-	switch (pixel_format) {
-	case V4L2_PIX_FMT_UYVY:
-		ipu_ch_param_write_field(p, IPU_FIELD_BPP, 3);    /* bits/pixel */
-		ipu_ch_param_write_field(p, IPU_FIELD_PFS, 0xA);  /* pix format */
-		ipu_ch_param_write_field(p, IPU_FIELD_NPB, 31);   /* burst size */
-		break;
-	case V4L2_PIX_FMT_YUYV:
-		ipu_ch_param_write_field(p, IPU_FIELD_BPP, 3);    /* bits/pixel */
-		ipu_ch_param_write_field(p, IPU_FIELD_PFS, 0x8);  /* pix format */
-		ipu_ch_param_write_field(p, IPU_FIELD_NPB, 31);   /* burst size */
-		break;
-	}
-}
-EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
-
-void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p,
-		u32 pixel_format, int stride, int u_offset, int v_offset)
-{
-	switch (pixel_format) {
-	case V4L2_PIX_FMT_YUV420:
-		ipu_ch_param_write_field(p, IPU_FIELD_SLUV, (stride / 2) - 1);
-		ipu_ch_param_write_field(p, IPU_FIELD_UBO, u_offset / 8);
-		ipu_ch_param_write_field(p, IPU_FIELD_VBO, v_offset / 8);
-		break;
-	case V4L2_PIX_FMT_YVU420:
-		ipu_ch_param_write_field(p, IPU_FIELD_SLUV, (stride / 2) - 1);
-		ipu_ch_param_write_field(p, IPU_FIELD_UBO, v_offset / 8);
-		ipu_ch_param_write_field(p, IPU_FIELD_VBO, u_offset / 8);
-		break;
-	}
-}
-EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
-
-void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format,
-		int stride, int height)
-{
-	int u_offset, v_offset;
-	int uv_stride = 0;
-
-	switch (pixel_format) {
-	case V4L2_PIX_FMT_YUV420:
-	case V4L2_PIX_FMT_YVU420:
-		uv_stride = stride / 2;
-		u_offset = stride * height;
-		v_offset = u_offset + (uv_stride * height / 2);
-		ipu_cpmem_set_yuv_planar_full(p, pixel_format, stride,
-				u_offset, v_offset);
-		break;
-	}
-}
-EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar);
-
-static const struct ipu_rgb def_rgb_32 = {
-	.red	= { .offset = 16, .length = 8, },
-	.green	= { .offset =  8, .length = 8, },
-	.blue	= { .offset =  0, .length = 8, },
-	.transp = { .offset = 24, .length = 8, },
-	.bits_per_pixel = 32,
-};
-
-static const struct ipu_rgb def_bgr_32 = {
-	.red	= { .offset =  0, .length = 8, },
-	.green	= { .offset =  8, .length = 8, },
-	.blue	= { .offset = 16, .length = 8, },
-	.transp = { .offset = 24, .length = 8, },
-	.bits_per_pixel = 32,
-};
-
-static const struct ipu_rgb def_rgb_24 = {
-	.red	= { .offset = 16, .length = 8, },
-	.green	= { .offset =  8, .length = 8, },
-	.blue	= { .offset =  0, .length = 8, },
-	.transp = { .offset =  0, .length = 0, },
-	.bits_per_pixel = 24,
-};
-
-static const struct ipu_rgb def_bgr_24 = {
-	.red	= { .offset =  0, .length = 8, },
-	.green	= { .offset =  8, .length = 8, },
-	.blue	= { .offset = 16, .length = 8, },
-	.transp = { .offset =  0, .length = 0, },
-	.bits_per_pixel = 24,
-};
-
-static const struct ipu_rgb def_rgb_16 = {
-	.red	= { .offset = 11, .length = 5, },
-	.green	= { .offset =  5, .length = 6, },
-	.blue	= { .offset =  0, .length = 5, },
-	.transp = { .offset =  0, .length = 0, },
-	.bits_per_pixel = 16,
-};
-
-static const struct ipu_rgb def_bgr_16 = {
-	.red	= { .offset =  0, .length = 5, },
-	.green	= { .offset =  5, .length = 6, },
-	.blue	= { .offset = 11, .length = 5, },
-	.transp = { .offset =  0, .length = 0, },
-	.bits_per_pixel = 16,
-};
-
-#define Y_OFFSET(pix, x, y)	((x) + pix->width * (y))
-#define U_OFFSET(pix, x, y)	((pix->width * pix->height) + \
-					(pix->width * (y) / 4) + (x) / 2)
-#define V_OFFSET(pix, x, y)	((pix->width * pix->height) + \
-					(pix->width * pix->height / 4) + \
-					(pix->width * (y) / 4) + (x) / 2)
-
-int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 drm_fourcc)
-{
-	switch (drm_fourcc) {
-	case DRM_FORMAT_YUV420:
-	case DRM_FORMAT_YVU420:
-		/* pix format */
-		ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 2);
-		/* burst size */
-		ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 63);
-		break;
-	case DRM_FORMAT_UYVY:
-		/* bits/pixel */
-		ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3);
-		/* pix format */
-		ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 0xA);
-		/* burst size */
-		ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31);
-		break;
-	case DRM_FORMAT_YUYV:
-		/* bits/pixel */
-		ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3);
-		/* pix format */
-		ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 0x8);
-		/* burst size */
-		ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31);
-		break;
-	case DRM_FORMAT_ABGR8888:
-	case DRM_FORMAT_XBGR8888:
-		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_32);
-		break;
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_XRGB8888:
-		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32);
-		break;
-	case DRM_FORMAT_BGR888:
-		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_24);
-		break;
-	case DRM_FORMAT_RGB888:
-		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_24);
-		break;
-	case DRM_FORMAT_RGB565:
-		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_16);
-		break;
-	case DRM_FORMAT_BGR565:
-		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_16);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
-
-/*
- * The V4L2 spec defines packed RGB formats in memory byte order, which from
- * point of view of the IPU corresponds to little-endian words with the first
- * component in the least significant bits.
- * The DRM pixel formats and IPU internal representation are ordered the other
- * way around, with the first named component ordered at the most significant
- * bits. Further, V4L2 formats are not well defined:
- *     http://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
- * We choose the interpretation which matches GStreamer behavior.
- */
-static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
-{
-	switch (pixelformat) {
-	case V4L2_PIX_FMT_RGB565:
-		/*
-		 * Here we choose the 'corrected' interpretation of RGBP, a
-		 * little-endian 16-bit word with the red component at the most
-		 * significant bits:
-		 * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
-		 */
-		return DRM_FORMAT_RGB565;
-	case V4L2_PIX_FMT_BGR24:
-		/* B G R <=> [24:0] R:G:B */
-		return DRM_FORMAT_RGB888;
-	case V4L2_PIX_FMT_RGB24:
-		/* R G B <=> [24:0] B:G:R */
-		return DRM_FORMAT_BGR888;
-	case V4L2_PIX_FMT_BGR32:
-		/* B G R A <=> [32:0] A:B:G:R */
-		return DRM_FORMAT_XRGB8888;
-	case V4L2_PIX_FMT_RGB32:
-		/* R G B A <=> [32:0] A:B:G:R */
-		return DRM_FORMAT_XBGR8888;
-	case V4L2_PIX_FMT_UYVY:
-		return DRM_FORMAT_UYVY;
-	case V4L2_PIX_FMT_YUYV:
-		return DRM_FORMAT_YUYV;
-	case V4L2_PIX_FMT_YUV420:
-		return DRM_FORMAT_YUV420;
-	case V4L2_PIX_FMT_YVU420:
-		return DRM_FORMAT_YVU420;
-	}
-
-	return -EINVAL;
-}
-
-enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
-{
-	switch (drm_fourcc) {
-	case DRM_FORMAT_RGB565:
-	case DRM_FORMAT_BGR565:
-	case DRM_FORMAT_RGB888:
-	case DRM_FORMAT_BGR888:
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_XBGR8888:
-	case DRM_FORMAT_RGBX8888:
-	case DRM_FORMAT_BGRX8888:
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_ABGR8888:
-	case DRM_FORMAT_RGBA8888:
-	case DRM_FORMAT_BGRA8888:
-		return IPUV3_COLORSPACE_RGB;
-	case DRM_FORMAT_YUYV:
-	case DRM_FORMAT_UYVY:
-	case DRM_FORMAT_YUV420:
-	case DRM_FORMAT_YVU420:
-		return IPUV3_COLORSPACE_YUV;
-	default:
-		return IPUV3_COLORSPACE_UNKNOWN;
-	}
-}
-EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace);
-
-int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem,
-		struct ipu_image *image)
-{
-	struct v4l2_pix_format *pix = &image->pix;
-	int y_offset, u_offset, v_offset;
-
-	pr_debug("%s: resolution: %dx%d stride: %d\n",
-			__func__, pix->width, pix->height,
-			pix->bytesperline);
-
-	ipu_cpmem_set_resolution(cpmem, image->rect.width,
-			image->rect.height);
-	ipu_cpmem_set_stride(cpmem, pix->bytesperline);
-
-	ipu_cpmem_set_fmt(cpmem, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
-
-	switch (pix->pixelformat) {
-	case V4L2_PIX_FMT_YUV420:
-	case V4L2_PIX_FMT_YVU420:
-		y_offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
-		u_offset = U_OFFSET(pix, image->rect.left,
-				image->rect.top) - y_offset;
-		v_offset = V_OFFSET(pix, image->rect.left,
-				image->rect.top) - y_offset;
-
-		ipu_cpmem_set_yuv_planar_full(cpmem, pix->pixelformat,
-				pix->bytesperline, u_offset, v_offset);
-		ipu_cpmem_set_buffer(cpmem, 0, image->phys + y_offset);
-		break;
-	case V4L2_PIX_FMT_UYVY:
-	case V4L2_PIX_FMT_YUYV:
-		ipu_cpmem_set_buffer(cpmem, 0, image->phys +
-				image->rect.left * 2 +
-				image->rect.top * image->pix.bytesperline);
-		break;
-	case V4L2_PIX_FMT_RGB32:
-	case V4L2_PIX_FMT_BGR32:
-		ipu_cpmem_set_buffer(cpmem, 0, image->phys +
-				image->rect.left * 4 +
-				image->rect.top * image->pix.bytesperline);
-		break;
-	case V4L2_PIX_FMT_RGB565:
-		ipu_cpmem_set_buffer(cpmem, 0, image->phys +
-				image->rect.left * 2 +
-				image->rect.top * image->pix.bytesperline);
-		break;
-	case V4L2_PIX_FMT_RGB24:
-	case V4L2_PIX_FMT_BGR24:
-		ipu_cpmem_set_buffer(cpmem, 0, image->phys +
-				image->rect.left * 3 +
-				image->rect.top * image->pix.bytesperline);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_cpmem_set_image);
-
-enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
-{
-	switch (pixelformat) {
-	case V4L2_PIX_FMT_YUV420:
-	case V4L2_PIX_FMT_YVU420:
-	case V4L2_PIX_FMT_UYVY:
-	case V4L2_PIX_FMT_YUYV:
-		return IPUV3_COLORSPACE_YUV;
-	case V4L2_PIX_FMT_RGB32:
-	case V4L2_PIX_FMT_BGR32:
-	case V4L2_PIX_FMT_RGB24:
-	case V4L2_PIX_FMT_BGR24:
-	case V4L2_PIX_FMT_RGB565:
-		return IPUV3_COLORSPACE_RGB;
-	default:
-		return IPUV3_COLORSPACE_UNKNOWN;
-	}
-}
-EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace);
-
-struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num)
-{
-	struct ipuv3_channel *channel;
-
-	dev_dbg(ipu->dev, "%s %d\n", __func__, num);
-
-	if (num > 63)
-		return ERR_PTR(-ENODEV);
-
-	mutex_lock(&ipu->channel_lock);
-
-	channel = &ipu->channel[num];
-
-	if (channel->busy) {
-		channel = ERR_PTR(-EBUSY);
-		goto out;
-	}
-
-	channel->busy = true;
-	channel->num = num;
-
-out:
-	mutex_unlock(&ipu->channel_lock);
-
-	return channel;
-}
-EXPORT_SYMBOL_GPL(ipu_idmac_get);
-
-void ipu_idmac_put(struct ipuv3_channel *channel)
-{
-	struct ipu_soc *ipu = channel->ipu;
-
-	dev_dbg(ipu->dev, "%s %d\n", __func__, channel->num);
-
-	mutex_lock(&ipu->channel_lock);
-
-	channel->busy = false;
-
-	mutex_unlock(&ipu->channel_lock);
-}
-EXPORT_SYMBOL_GPL(ipu_idmac_put);
-
-#define idma_mask(ch)			(1 << (ch & 0x1f))
-
-void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
-		bool doublebuffer)
-{
-	struct ipu_soc *ipu = channel->ipu;
-	unsigned long flags;
-	u32 reg;
-
-	spin_lock_irqsave(&ipu->lock, flags);
-
-	reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
-	if (doublebuffer)
-		reg |= idma_mask(channel->num);
-	else
-		reg &= ~idma_mask(channel->num);
-	ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num));
-
-	spin_unlock_irqrestore(&ipu->lock, flags);
-}
-EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer);
-
-int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
-{
-	unsigned long lock_flags;
-	u32 val;
-
-	spin_lock_irqsave(&ipu->lock, lock_flags);
-
-	val = ipu_cm_read(ipu, IPU_DISP_GEN);
-
-	if (mask & IPU_CONF_DI0_EN)
-		val |= IPU_DI0_COUNTER_RELEASE;
-	if (mask & IPU_CONF_DI1_EN)
-		val |= IPU_DI1_COUNTER_RELEASE;
-
-	ipu_cm_write(ipu, val, IPU_DISP_GEN);
-
-	val = ipu_cm_read(ipu, IPU_CONF);
-	val |= mask;
-	ipu_cm_write(ipu, val, IPU_CONF);
-
-	spin_unlock_irqrestore(&ipu->lock, lock_flags);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_module_enable);
-
-int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
-{
-	unsigned long lock_flags;
-	u32 val;
-
-	spin_lock_irqsave(&ipu->lock, lock_flags);
-
-	val = ipu_cm_read(ipu, IPU_CONF);
-	val &= ~mask;
-	ipu_cm_write(ipu, val, IPU_CONF);
-
-	val = ipu_cm_read(ipu, IPU_DISP_GEN);
-
-	if (mask & IPU_CONF_DI0_EN)
-		val &= ~IPU_DI0_COUNTER_RELEASE;
-	if (mask & IPU_CONF_DI1_EN)
-		val &= ~IPU_DI1_COUNTER_RELEASE;
-
-	ipu_cm_write(ipu, val, IPU_DISP_GEN);
-
-	spin_unlock_irqrestore(&ipu->lock, lock_flags);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_module_disable);
-
-void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
-{
-	struct ipu_soc *ipu = channel->ipu;
-	unsigned int chno = channel->num;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ipu->lock, flags);
-
-	/* Mark buffer as ready. */
-	if (buf_num == 0)
-		ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
-	else
-		ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
-
-	spin_unlock_irqrestore(&ipu->lock, flags);
-}
-EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer);
-
-int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
-{
-	struct ipu_soc *ipu = channel->ipu;
-	u32 val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ipu->lock, flags);
-
-	val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
-	val |= idma_mask(channel->num);
-	ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
-
-	spin_unlock_irqrestore(&ipu->lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
-
-bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno)
-{
-	return (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(chno)) & idma_mask(chno));
-}
-EXPORT_SYMBOL_GPL(ipu_idmac_channel_busy);
-
-int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
-{
-	struct ipu_soc *ipu = channel->ipu;
-	unsigned long timeout;
-
-	timeout = jiffies + msecs_to_jiffies(ms);
-	while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) &
-			idma_mask(channel->num)) {
-		if (time_after(jiffies, timeout))
-			return -ETIMEDOUT;
-		cpu_relax();
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
-
-int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms)
-{
-	unsigned long timeout;
-
-	timeout = jiffies + msecs_to_jiffies(ms);
-	ipu_cm_write(ipu, BIT(irq % 32), IPU_INT_STAT(irq / 32));
-	while (!(ipu_cm_read(ipu, IPU_INT_STAT(irq / 32) & BIT(irq % 32)))) {
-		if (time_after(jiffies, timeout))
-			return -ETIMEDOUT;
-		cpu_relax();
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_wait_interrupt);
-
-int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
-{
-	struct ipu_soc *ipu = channel->ipu;
-	u32 val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ipu->lock, flags);
-
-	/* Disable DMA channel(s) */
-	val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
-	val &= ~idma_mask(channel->num);
-	ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
-
-	/* Set channel buffers NOT to be ready */
-	ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */
-
-	if (ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num)) &
-			idma_mask(channel->num)) {
-		ipu_cm_write(ipu, idma_mask(channel->num),
-			     IPU_CHA_BUF0_RDY(channel->num));
-	}
-
-	if (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num)) &
-			idma_mask(channel->num)) {
-		ipu_cm_write(ipu, idma_mask(channel->num),
-			     IPU_CHA_BUF1_RDY(channel->num));
-	}
-
-	ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
-
-	/* Reset the double buffer */
-	val = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
-	val &= ~idma_mask(channel->num);
-	ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num));
-
-	spin_unlock_irqrestore(&ipu->lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel);
-
-static int ipu_memory_reset(struct ipu_soc *ipu)
-{
-	unsigned long timeout;
-
-	ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
-
-	timeout = jiffies + msecs_to_jiffies(1000);
-	while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
-		if (time_after(jiffies, timeout))
-			return -ETIME;
-		cpu_relax();
-	}
-
-	return 0;
-}
-
-struct ipu_devtype {
-	const char *name;
-	unsigned long cm_ofs;
-	unsigned long cpmem_ofs;
-	unsigned long srm_ofs;
-	unsigned long tpm_ofs;
-	unsigned long disp0_ofs;
-	unsigned long disp1_ofs;
-	unsigned long dc_tmpl_ofs;
-	unsigned long vdi_ofs;
-	enum ipuv3_type type;
-};
-
-static struct ipu_devtype ipu_type_imx51 = {
-	.name = "IPUv3EX",
-	.cm_ofs = 0x1e000000,
-	.cpmem_ofs = 0x1f000000,
-	.srm_ofs = 0x1f040000,
-	.tpm_ofs = 0x1f060000,
-	.disp0_ofs = 0x1e040000,
-	.disp1_ofs = 0x1e048000,
-	.dc_tmpl_ofs = 0x1f080000,
-	.vdi_ofs = 0x1e068000,
-	.type = IPUV3EX,
-};
-
-static struct ipu_devtype ipu_type_imx53 = {
-	.name = "IPUv3M",
-	.cm_ofs = 0x06000000,
-	.cpmem_ofs = 0x07000000,
-	.srm_ofs = 0x07040000,
-	.tpm_ofs = 0x07060000,
-	.disp0_ofs = 0x06040000,
-	.disp1_ofs = 0x06048000,
-	.dc_tmpl_ofs = 0x07080000,
-	.vdi_ofs = 0x06068000,
-	.type = IPUV3M,
-};
-
-static struct ipu_devtype ipu_type_imx6q = {
-	.name = "IPUv3H",
-	.cm_ofs = 0x00200000,
-	.cpmem_ofs = 0x00300000,
-	.srm_ofs = 0x00340000,
-	.tpm_ofs = 0x00360000,
-	.disp0_ofs = 0x00240000,
-	.disp1_ofs = 0x00248000,
-	.dc_tmpl_ofs = 0x00380000,
-	.vdi_ofs = 0x00268000,
-	.type = IPUV3H,
-};
-
-static const struct of_device_id imx_ipu_dt_ids[] = {
-	{ .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, },
-	{ .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, },
-	{ .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, },
-	{ /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, imx_ipu_dt_ids);
-
-static int ipu_submodules_init(struct ipu_soc *ipu,
-		struct platform_device *pdev, unsigned long ipu_base,
-		struct clk *ipu_clk)
-{
-	char *unit;
-	int ret;
-	struct device *dev = &pdev->dev;
-	const struct ipu_devtype *devtype = ipu->devtype;
-
-	ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs,
-			IPU_CONF_DI0_EN, ipu_clk);
-	if (ret) {
-		unit = "di0";
-		goto err_di_0;
-	}
-
-	ret = ipu_di_init(ipu, dev, 1, ipu_base + devtype->disp1_ofs,
-			IPU_CONF_DI1_EN, ipu_clk);
-	if (ret) {
-		unit = "di1";
-		goto err_di_1;
-	}
-
-	ret = ipu_dc_init(ipu, dev, ipu_base + devtype->cm_ofs +
-			IPU_CM_DC_REG_OFS, ipu_base + devtype->dc_tmpl_ofs);
-	if (ret) {
-		unit = "dc_template";
-		goto err_dc;
-	}
-
-	ret = ipu_dmfc_init(ipu, dev, ipu_base +
-			devtype->cm_ofs + IPU_CM_DMFC_REG_OFS, ipu_clk);
-	if (ret) {
-		unit = "dmfc";
-		goto err_dmfc;
-	}
-
-	ret = ipu_dp_init(ipu, dev, ipu_base + devtype->srm_ofs);
-	if (ret) {
-		unit = "dp";
-		goto err_dp;
-	}
-
-	return 0;
-
-err_dp:
-	ipu_dmfc_exit(ipu);
-err_dmfc:
-	ipu_dc_exit(ipu);
-err_dc:
-	ipu_di_exit(ipu, 1);
-err_di_1:
-	ipu_di_exit(ipu, 0);
-err_di_0:
-	dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret);
-	return ret;
-}
-
-static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
-{
-	unsigned long status;
-	int i, bit, irq;
-
-	for (i = 0; i < num_regs; i++) {
-
-		status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i]));
-		status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i]));
-
-		for_each_set_bit(bit, &status, 32) {
-			irq = irq_linear_revmap(ipu->domain,
-						regs[i] * 32 + bit);
-			if (irq)
-				generic_handle_irq(irq);
-		}
-	}
-}
-
-static void ipu_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-	struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
-	const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14};
-	struct irq_chip *chip = irq_get_chip(irq);
-
-	chained_irq_enter(chip, desc);
-
-	ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
-
-	chained_irq_exit(chip, desc);
-}
-
-static void ipu_err_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-	struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
-	const int int_reg[] = { 4, 5, 8, 9};
-	struct irq_chip *chip = irq_get_chip(irq);
-
-	chained_irq_enter(chip, desc);
-
-	ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
-
-	chained_irq_exit(chip, desc);
-}
-
-int ipu_map_irq(struct ipu_soc *ipu, int irq)
-{
-	int virq;
-
-	virq = irq_linear_revmap(ipu->domain, irq);
-	if (!virq)
-		virq = irq_create_mapping(ipu->domain, irq);
-
-	return virq;
-}
-EXPORT_SYMBOL_GPL(ipu_map_irq);
-
-int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
-		enum ipu_channel_irq irq_type)
-{
-	return ipu_map_irq(ipu, irq_type + channel->num);
-}
-EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
-
-static void ipu_submodules_exit(struct ipu_soc *ipu)
-{
-	ipu_dp_exit(ipu);
-	ipu_dmfc_exit(ipu);
-	ipu_dc_exit(ipu);
-	ipu_di_exit(ipu, 1);
-	ipu_di_exit(ipu, 0);
-}
-
-static int platform_remove_devices_fn(struct device *dev, void *unused)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-
-	platform_device_unregister(pdev);
-
-	return 0;
-}
-
-static void platform_device_unregister_children(struct platform_device *pdev)
-{
-	device_for_each_child(&pdev->dev, NULL, platform_remove_devices_fn);
-}
-
-struct ipu_platform_reg {
-	struct ipu_client_platformdata pdata;
-	const char *name;
-};
-
-static const struct ipu_platform_reg client_reg[] = {
-	{
-		.pdata = {
-			.di = 0,
-			.dc = 5,
-			.dp = IPU_DP_FLOW_SYNC_BG,
-			.dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
-			.dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
-		},
-		.name = "imx-ipuv3-crtc",
-	}, {
-		.pdata = {
-			.di = 1,
-			.dc = 1,
-			.dp = -EINVAL,
-			.dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC,
-			.dma[1] = -EINVAL,
-		},
-		.name = "imx-ipuv3-crtc",
-	},
-};
-
-static DEFINE_MUTEX(ipu_client_id_mutex);
-static int ipu_client_id;
-
-static int ipu_add_client_devices(struct ipu_soc *ipu)
-{
-	struct device *dev = ipu->dev;
-	unsigned i;
-	int id, ret;
-
-	mutex_lock(&ipu_client_id_mutex);
-	id = ipu_client_id;
-	ipu_client_id += ARRAY_SIZE(client_reg);
-	mutex_unlock(&ipu_client_id_mutex);
-
-	for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
-		const struct ipu_platform_reg *reg = &client_reg[i];
-		struct platform_device *pdev;
-
-		pdev = platform_device_register_data(dev, reg->name,
-			id++, &reg->pdata, sizeof(reg->pdata));
-
-		if (IS_ERR(pdev))
-			goto err_register;
-	}
-
-	return 0;
-
-err_register:
-	platform_device_unregister_children(to_platform_device(dev));
-
-	return ret;
-}
-
-
-static int ipu_irq_init(struct ipu_soc *ipu)
-{
-	struct irq_chip_generic *gc;
-	struct irq_chip_type *ct;
-	unsigned long unused[IPU_NUM_IRQS / 32] = {
-		0x400100d0, 0xffe000fd,
-		0x400100d0, 0xffe000fd,
-		0x400100d0, 0xffe000fd,
-		0x4077ffff, 0xffe7e1fd,
-		0x23fffffe, 0x8880fff0,
-		0xf98fe7d0, 0xfff81fff,
-		0x400100d0, 0xffe000fd,
-		0x00000000,
-	};
-	int ret, i;
-
-	ipu->domain = irq_domain_add_linear(ipu->dev->of_node, IPU_NUM_IRQS,
-					    &irq_generic_chip_ops, ipu);
-	if (!ipu->domain) {
-		dev_err(ipu->dev, "failed to add irq domain\n");
-		return -ENODEV;
-	}
-
-	ret = irq_alloc_domain_generic_chips(ipu->domain, 32, 1, "IPU",
-					     handle_level_irq, 0,
-					     IRQF_VALID, 0);
-	if (ret < 0) {
-		dev_err(ipu->dev, "failed to alloc generic irq chips\n");
-		irq_domain_remove(ipu->domain);
-		return ret;
-	}
-
-	for (i = 0; i < IPU_NUM_IRQS; i += 32) {
-		gc = irq_get_domain_generic_chip(ipu->domain, i);
-		gc->reg_base = ipu->cm_reg;
-		gc->unused = unused[i / 32];
-		ct = gc->chip_types;
-		ct->chip.irq_ack = irq_gc_ack_set_bit;
-		ct->chip.irq_mask = irq_gc_mask_clr_bit;
-		ct->chip.irq_unmask = irq_gc_mask_set_bit;
-		ct->regs.ack = IPU_INT_STAT(i / 32);
-		ct->regs.mask = IPU_INT_CTRL(i / 32);
-	}
-
-	irq_set_chained_handler(ipu->irq_sync, ipu_irq_handler);
-	irq_set_handler_data(ipu->irq_sync, ipu);
-	irq_set_chained_handler(ipu->irq_err, ipu_err_irq_handler);
-	irq_set_handler_data(ipu->irq_err, ipu);
-
-	return 0;
-}
-
-static void ipu_irq_exit(struct ipu_soc *ipu)
-{
-	int i, irq;
-
-	irq_set_chained_handler(ipu->irq_err, NULL);
-	irq_set_handler_data(ipu->irq_err, NULL);
-	irq_set_chained_handler(ipu->irq_sync, NULL);
-	irq_set_handler_data(ipu->irq_sync, NULL);
-
-	/* TODO: remove irq_domain_generic_chips */
-
-	for (i = 0; i < IPU_NUM_IRQS; i++) {
-		irq = irq_linear_revmap(ipu->domain, i);
-		if (irq)
-			irq_dispose_mapping(irq);
-	}
-
-	irq_domain_remove(ipu->domain);
-}
-
-static int ipu_probe(struct platform_device *pdev)
-{
-	const struct of_device_id *of_id =
-			of_match_device(imx_ipu_dt_ids, &pdev->dev);
-	struct ipu_soc *ipu;
-	struct resource *res;
-	unsigned long ipu_base;
-	int i, ret, irq_sync, irq_err;
-	const struct ipu_devtype *devtype;
-
-	devtype = of_id->data;
-
-	irq_sync = platform_get_irq(pdev, 0);
-	irq_err = platform_get_irq(pdev, 1);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	dev_dbg(&pdev->dev, "irq_sync: %d irq_err: %d\n",
-			irq_sync, irq_err);
-
-	if (!res || irq_sync < 0 || irq_err < 0)
-		return -ENODEV;
-
-	ipu_base = res->start;
-
-	ipu = devm_kzalloc(&pdev->dev, sizeof(*ipu), GFP_KERNEL);
-	if (!ipu)
-		return -ENODEV;
-
-	for (i = 0; i < 64; i++)
-		ipu->channel[i].ipu = ipu;
-	ipu->devtype = devtype;
-	ipu->ipu_type = devtype->type;
-
-	spin_lock_init(&ipu->lock);
-	mutex_init(&ipu->channel_lock);
-
-	dev_dbg(&pdev->dev, "cm_reg:   0x%08lx\n",
-			ipu_base + devtype->cm_ofs);
-	dev_dbg(&pdev->dev, "idmac:    0x%08lx\n",
-			ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
-	dev_dbg(&pdev->dev, "cpmem:    0x%08lx\n",
-			ipu_base + devtype->cpmem_ofs);
-	dev_dbg(&pdev->dev, "disp0:    0x%08lx\n",
-			ipu_base + devtype->disp0_ofs);
-	dev_dbg(&pdev->dev, "disp1:    0x%08lx\n",
-			ipu_base + devtype->disp1_ofs);
-	dev_dbg(&pdev->dev, "srm:      0x%08lx\n",
-			ipu_base + devtype->srm_ofs);
-	dev_dbg(&pdev->dev, "tpm:      0x%08lx\n",
-			ipu_base + devtype->tpm_ofs);
-	dev_dbg(&pdev->dev, "dc:       0x%08lx\n",
-			ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS);
-	dev_dbg(&pdev->dev, "ic:       0x%08lx\n",
-			ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS);
-	dev_dbg(&pdev->dev, "dmfc:     0x%08lx\n",
-			ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS);
-	dev_dbg(&pdev->dev, "vdi:      0x%08lx\n",
-			ipu_base + devtype->vdi_ofs);
-
-	ipu->cm_reg = devm_ioremap(&pdev->dev,
-			ipu_base + devtype->cm_ofs, PAGE_SIZE);
-	ipu->idmac_reg = devm_ioremap(&pdev->dev,
-			ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS,
-			PAGE_SIZE);
-	ipu->cpmem_base = devm_ioremap(&pdev->dev,
-			ipu_base + devtype->cpmem_ofs, PAGE_SIZE);
-
-	if (!ipu->cm_reg || !ipu->idmac_reg || !ipu->cpmem_base)
-		return -ENOMEM;
-
-	ipu->clk = devm_clk_get(&pdev->dev, "bus");
-	if (IS_ERR(ipu->clk)) {
-		ret = PTR_ERR(ipu->clk);
-		dev_err(&pdev->dev, "clk_get failed with %d", ret);
-		return ret;
-	}
-
-	platform_set_drvdata(pdev, ipu);
-
-	ret = clk_prepare_enable(ipu->clk);
-	if (ret) {
-		dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret);
-		return ret;
-	}
-
-	ipu->dev = &pdev->dev;
-	ipu->irq_sync = irq_sync;
-	ipu->irq_err = irq_err;
-
-	ret = ipu_irq_init(ipu);
-	if (ret)
-		goto out_failed_irq;
-
-	ret = device_reset(&pdev->dev);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to reset: %d\n", ret);
-		goto out_failed_reset;
-	}
-	ret = ipu_memory_reset(ipu);
-	if (ret)
-		goto out_failed_reset;
-
-	/* Set MCU_T to divide MCU access window into 2 */
-	ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
-			IPU_DISP_GEN);
-
-	ret = ipu_submodules_init(ipu, pdev, ipu_base, ipu->clk);
-	if (ret)
-		goto failed_submodules_init;
-
-	ret = ipu_add_client_devices(ipu);
-	if (ret) {
-		dev_err(&pdev->dev, "adding client devices failed with %d\n",
-				ret);
-		goto failed_add_clients;
-	}
-
-	dev_info(&pdev->dev, "%s probed\n", devtype->name);
-
-	return 0;
-
-failed_add_clients:
-	ipu_submodules_exit(ipu);
-failed_submodules_init:
-out_failed_reset:
-	ipu_irq_exit(ipu);
-out_failed_irq:
-	clk_disable_unprepare(ipu->clk);
-	return ret;
-}
-
-static int ipu_remove(struct platform_device *pdev)
-{
-	struct ipu_soc *ipu = platform_get_drvdata(pdev);
-
-	platform_device_unregister_children(pdev);
-	ipu_submodules_exit(ipu);
-	ipu_irq_exit(ipu);
-
-	clk_disable_unprepare(ipu->clk);
-
-	return 0;
-}
-
-static struct platform_driver imx_ipu_driver = {
-	.driver = {
-		.name = "imx-ipuv3",
-		.of_match_table = imx_ipu_dt_ids,
-	},
-	.probe = ipu_probe,
-	.remove = ipu_remove,
-};
-
-module_platform_driver(imx_ipu_driver);
-
-MODULE_ALIAS("platform:imx-ipuv3");
-MODULE_DESCRIPTION("i.MX IPU v3 driver");
-MODULE_AUTHOR("Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
deleted file mode 100644
index 784a4a1..0000000
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright (c) 2010 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <linux/export.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-
-#include "../imx-drm.h"
-#include "imx-ipu-v3.h"
-#include "ipu-prv.h"
-
-#define DC_MAP_CONF_PTR(n)	(0x108 + ((n) & ~0x1) * 2)
-#define DC_MAP_CONF_VAL(n)	(0x144 + ((n) & ~0x1) * 2)
-
-#define DC_EVT_NF		0
-#define DC_EVT_NL		1
-#define DC_EVT_EOF		2
-#define DC_EVT_NFIELD		3
-#define DC_EVT_EOL		4
-#define DC_EVT_EOFIELD		5
-#define DC_EVT_NEW_ADDR		6
-#define DC_EVT_NEW_CHAN		7
-#define DC_EVT_NEW_DATA		8
-
-#define DC_EVT_NEW_ADDR_W_0	0
-#define DC_EVT_NEW_ADDR_W_1	1
-#define DC_EVT_NEW_CHAN_W_0	2
-#define DC_EVT_NEW_CHAN_W_1	3
-#define DC_EVT_NEW_DATA_W_0	4
-#define DC_EVT_NEW_DATA_W_1	5
-#define DC_EVT_NEW_ADDR_R_0	6
-#define DC_EVT_NEW_ADDR_R_1	7
-#define DC_EVT_NEW_CHAN_R_0	8
-#define DC_EVT_NEW_CHAN_R_1	9
-#define DC_EVT_NEW_DATA_R_0	10
-#define DC_EVT_NEW_DATA_R_1	11
-
-#define DC_WR_CH_CONF		0x0
-#define DC_WR_CH_ADDR		0x4
-#define DC_RL_CH(evt)		(8 + ((evt) & ~0x1) * 2)
-
-#define DC_GEN			0xd4
-#define DC_DISP_CONF1(disp)	(0xd8 + (disp) * 4)
-#define DC_DISP_CONF2(disp)	(0xe8 + (disp) * 4)
-#define DC_STAT			0x1c8
-
-#define WROD(lf)		(0x18 | ((lf) << 1))
-#define WRG			0x01
-#define WCLK			0xc9
-
-#define SYNC_WAVE 0
-#define NULL_WAVE (-1)
-
-#define DC_GEN_SYNC_1_6_SYNC	(2 << 1)
-#define DC_GEN_SYNC_PRIORITY_1	(1 << 7)
-
-#define DC_WR_CH_CONF_WORD_SIZE_8		(0 << 0)
-#define DC_WR_CH_CONF_WORD_SIZE_16		(1 << 0)
-#define DC_WR_CH_CONF_WORD_SIZE_24		(2 << 0)
-#define DC_WR_CH_CONF_WORD_SIZE_32		(3 << 0)
-#define DC_WR_CH_CONF_DISP_ID_PARALLEL(i)	(((i) & 0x1) << 3)
-#define DC_WR_CH_CONF_DISP_ID_SERIAL		(2 << 3)
-#define DC_WR_CH_CONF_DISP_ID_ASYNC		(3 << 4)
-#define DC_WR_CH_CONF_FIELD_MODE		(1 << 9)
-#define DC_WR_CH_CONF_PROG_TYPE_NORMAL		(4 << 5)
-#define DC_WR_CH_CONF_PROG_TYPE_MASK		(7 << 5)
-#define DC_WR_CH_CONF_PROG_DI_ID		(1 << 2)
-#define DC_WR_CH_CONF_PROG_DISP_ID(i)		(((i) & 0x1) << 3)
-
-#define IPU_DC_NUM_CHANNELS	10
-
-struct ipu_dc_priv;
-
-enum ipu_dc_map {
-	IPU_DC_MAP_RGB24,
-	IPU_DC_MAP_RGB565,
-	IPU_DC_MAP_GBR24, /* TVEv2 */
-	IPU_DC_MAP_BGR666,
-	IPU_DC_MAP_LVDS666,
-	IPU_DC_MAP_BGR24,
-};
-
-struct ipu_dc {
-	/* The display interface number assigned to this dc channel */
-	unsigned int		di;
-	void __iomem		*base;
-	struct ipu_dc_priv	*priv;
-	int			chno;
-	bool			in_use;
-};
-
-struct ipu_dc_priv {
-	void __iomem		*dc_reg;
-	void __iomem		*dc_tmpl_reg;
-	struct ipu_soc		*ipu;
-	struct device		*dev;
-	struct ipu_dc		channels[IPU_DC_NUM_CHANNELS];
-	struct mutex		mutex;
-	struct completion	comp;
-	int			dc_irq;
-	int			dp_irq;
-};
-
-static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
-{
-	u32 reg;
-
-	reg = readl(dc->base + DC_RL_CH(event));
-	reg &= ~(0xffff << (16 * (event & 0x1)));
-	reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
-	writel(reg, dc->base + DC_RL_CH(event));
-}
-
-static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand,
-		int map, int wave, int glue, int sync, int stop)
-{
-	struct ipu_dc_priv *priv = dc->priv;
-	u32 reg1, reg2;
-
-	if (opcode == WCLK) {
-		reg1 = (operand << 20) & 0xfff00000;
-		reg2 = operand >> 12 | opcode << 1 | stop << 9;
-	} else if (opcode == WRG) {
-		reg1 = sync | glue << 4 | ++wave << 11 | ((operand << 15) & 0xffff8000);
-		reg2 = operand >> 17 | opcode << 7 | stop << 9;
-	} else {
-		reg1 = sync | glue << 4 | ++wave << 11 | ++map << 15 | ((operand << 20) & 0xfff00000);
-		reg2 = operand >> 12 | opcode << 4 | stop << 9;
-	}
-	writel(reg1, priv->dc_tmpl_reg + word * 8);
-	writel(reg2, priv->dc_tmpl_reg + word * 8 + 4);
-}
-
-static int ipu_pixfmt_to_map(u32 fmt)
-{
-	switch (fmt) {
-	case V4L2_PIX_FMT_RGB24:
-		return IPU_DC_MAP_RGB24;
-	case V4L2_PIX_FMT_RGB565:
-		return IPU_DC_MAP_RGB565;
-	case IPU_PIX_FMT_GBR24:
-		return IPU_DC_MAP_GBR24;
-	case V4L2_PIX_FMT_BGR666:
-		return IPU_DC_MAP_BGR666;
-	case v4l2_fourcc('L', 'V', 'D', '6'):
-		return IPU_DC_MAP_LVDS666;
-	case V4L2_PIX_FMT_BGR24:
-		return IPU_DC_MAP_BGR24;
-	default:
-		return -EINVAL;
-	}
-}
-
-int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
-		u32 pixel_fmt, u32 width)
-{
-	struct ipu_dc_priv *priv = dc->priv;
-	u32 reg = 0;
-	int map;
-
-	dc->di = ipu_di_get_num(di);
-
-	map = ipu_pixfmt_to_map(pixel_fmt);
-	if (map < 0) {
-		dev_dbg(priv->dev, "IPU_DISP: No MAP\n");
-		return map;
-	}
-
-	if (interlaced) {
-		dc_link_event(dc, DC_EVT_NL, 0, 3);
-		dc_link_event(dc, DC_EVT_EOL, 0, 2);
-		dc_link_event(dc, DC_EVT_NEW_DATA, 0, 1);
-
-		/* Init template microcode */
-		dc_write_tmpl(dc, 0, WROD(0), 0, map, SYNC_WAVE, 0, 8, 1);
-	} else {
-		if (dc->di) {
-			dc_link_event(dc, DC_EVT_NL, 2, 3);
-			dc_link_event(dc, DC_EVT_EOL, 3, 2);
-			dc_link_event(dc, DC_EVT_NEW_DATA, 1, 1);
-			/* Init template microcode */
-			dc_write_tmpl(dc, 2, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1);
-			dc_write_tmpl(dc, 3, WROD(0), 0, map, SYNC_WAVE, 4, 5, 0);
-			dc_write_tmpl(dc, 4, WRG, 0, map, NULL_WAVE, 0, 0, 1);
-			dc_write_tmpl(dc, 1, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
-		} else {
-			dc_link_event(dc, DC_EVT_NL, 5, 3);
-			dc_link_event(dc, DC_EVT_EOL, 6, 2);
-			dc_link_event(dc, DC_EVT_NEW_DATA, 8, 1);
-			/* Init template microcode */
-			dc_write_tmpl(dc, 5, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1);
-			dc_write_tmpl(dc, 6, WROD(0), 0, map, SYNC_WAVE, 4, 5, 0);
-			dc_write_tmpl(dc, 7, WRG, 0, map, NULL_WAVE, 0, 0, 1);
-			dc_write_tmpl(dc, 8, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
-		}
-	}
-	dc_link_event(dc, DC_EVT_NF, 0, 0);
-	dc_link_event(dc, DC_EVT_NFIELD, 0, 0);
-	dc_link_event(dc, DC_EVT_EOF, 0, 0);
-	dc_link_event(dc, DC_EVT_EOFIELD, 0, 0);
-	dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0);
-	dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0);
-
-	reg = readl(dc->base + DC_WR_CH_CONF);
-	if (interlaced)
-		reg |= DC_WR_CH_CONF_FIELD_MODE;
-	else
-		reg &= ~DC_WR_CH_CONF_FIELD_MODE;
-	writel(reg, dc->base + DC_WR_CH_CONF);
-
-	writel(0x0, dc->base + DC_WR_CH_ADDR);
-	writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di));
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
-
-void ipu_dc_enable(struct ipu_soc *ipu)
-{
-	ipu_module_enable(ipu, IPU_CONF_DC_EN);
-}
-EXPORT_SYMBOL_GPL(ipu_dc_enable);
-
-void ipu_dc_enable_channel(struct ipu_dc *dc)
-{
-	int di;
-	u32 reg;
-
-	di = dc->di;
-
-	reg = readl(dc->base + DC_WR_CH_CONF);
-	reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL;
-	writel(reg, dc->base + DC_WR_CH_CONF);
-}
-EXPORT_SYMBOL_GPL(ipu_dc_enable_channel);
-
-static irqreturn_t dc_irq_handler(int irq, void *dev_id)
-{
-	struct ipu_dc *dc = dev_id;
-	u32 reg;
-
-	reg = readl(dc->base + DC_WR_CH_CONF);
-	reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
-	writel(reg, dc->base + DC_WR_CH_CONF);
-
-	/* The Freescale BSP kernel clears DIx_COUNTER_RELEASE here */
-
-	complete(&dc->priv->comp);
-	return IRQ_HANDLED;
-}
-
-void ipu_dc_disable_channel(struct ipu_dc *dc)
-{
-	struct ipu_dc_priv *priv = dc->priv;
-	int irq, ret;
-	u32 val;
-
-	/* TODO: Handle MEM_FG_SYNC differently from MEM_BG_SYNC */
-	if (dc->chno == 1)
-		irq = priv->dc_irq;
-	else if (dc->chno == 5)
-		irq = priv->dp_irq;
-	else
-		return;
-
-	init_completion(&priv->comp);
-	enable_irq(irq);
-	ret = wait_for_completion_timeout(&priv->comp, msecs_to_jiffies(50));
-	disable_irq(irq);
-	if (ret <= 0) {
-		dev_warn(priv->dev, "DC stop timeout after 50 ms\n");
-
-		val = readl(dc->base + DC_WR_CH_CONF);
-		val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
-		writel(val, dc->base + DC_WR_CH_CONF);
-	}
-}
-EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
-
-void ipu_dc_disable(struct ipu_soc *ipu)
-{
-	ipu_module_disable(ipu, IPU_CONF_DC_EN);
-}
-EXPORT_SYMBOL_GPL(ipu_dc_disable);
-
-static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map,
-		int byte_num, int offset, int mask)
-{
-	int ptr = map * 3 + byte_num;
-	u32 reg;
-
-	reg = readl(priv->dc_reg + DC_MAP_CONF_VAL(ptr));
-	reg &= ~(0xffff << (16 * (ptr & 0x1)));
-	reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
-	writel(reg, priv->dc_reg + DC_MAP_CONF_VAL(ptr));
-
-	reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
-	reg &= ~(0x1f << ((16 * (map & 0x1)) + (5 * byte_num)));
-	reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
-	writel(reg, priv->dc_reg + DC_MAP_CONF_PTR(map));
-}
-
-static void ipu_dc_map_clear(struct ipu_dc_priv *priv, int map)
-{
-	u32 reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
-
-	writel(reg & ~(0xffff << (16 * (map & 0x1))),
-		     priv->dc_reg + DC_MAP_CONF_PTR(map));
-}
-
-struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel)
-{
-	struct ipu_dc_priv *priv = ipu->dc_priv;
-	struct ipu_dc *dc;
-
-	if (channel >= IPU_DC_NUM_CHANNELS)
-		return ERR_PTR(-ENODEV);
-
-	dc = &priv->channels[channel];
-
-	mutex_lock(&priv->mutex);
-
-	if (dc->in_use) {
-		mutex_unlock(&priv->mutex);
-		return ERR_PTR(-EBUSY);
-	}
-
-	dc->in_use = true;
-
-	mutex_unlock(&priv->mutex);
-
-	return dc;
-}
-EXPORT_SYMBOL_GPL(ipu_dc_get);
-
-void ipu_dc_put(struct ipu_dc *dc)
-{
-	struct ipu_dc_priv *priv = dc->priv;
-
-	mutex_lock(&priv->mutex);
-	dc->in_use = false;
-	mutex_unlock(&priv->mutex);
-}
-EXPORT_SYMBOL_GPL(ipu_dc_put);
-
-int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
-		unsigned long base, unsigned long template_base)
-{
-	struct ipu_dc_priv *priv;
-	static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c,
-		0x78, 0, 0x94, 0xb4};
-	int i, ret;
-
-	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	mutex_init(&priv->mutex);
-
-	priv->dev = dev;
-	priv->ipu = ipu;
-	priv->dc_reg = devm_ioremap(dev, base, PAGE_SIZE);
-	priv->dc_tmpl_reg = devm_ioremap(dev, template_base, PAGE_SIZE);
-	if (!priv->dc_reg || !priv->dc_tmpl_reg)
-		return -ENOMEM;
-
-	for (i = 0; i < IPU_DC_NUM_CHANNELS; i++) {
-		priv->channels[i].chno = i;
-		priv->channels[i].priv = priv;
-		priv->channels[i].base = priv->dc_reg + channel_offsets[i];
-	}
-
-	priv->dc_irq = ipu_map_irq(ipu, IPU_IRQ_DC_FC_1);
-	if (!priv->dc_irq)
-		return -EINVAL;
-	ret = devm_request_irq(dev, priv->dc_irq, dc_irq_handler, 0, NULL,
-			       &priv->channels[1]);
-	if (ret < 0)
-		return ret;
-	disable_irq(priv->dc_irq);
-	priv->dp_irq = ipu_map_irq(ipu, IPU_IRQ_DP_SF_END);
-	if (!priv->dp_irq)
-		return -EINVAL;
-	ret = devm_request_irq(dev, priv->dp_irq, dc_irq_handler, 0, NULL,
-			       &priv->channels[5]);
-	if (ret < 0)
-		return ret;
-	disable_irq(priv->dp_irq);
-
-	writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) |
-			DC_WR_CH_CONF_PROG_DI_ID,
-			priv->channels[1].base + DC_WR_CH_CONF);
-	writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(0),
-			priv->channels[5].base + DC_WR_CH_CONF);
-
-	writel(DC_GEN_SYNC_1_6_SYNC | DC_GEN_SYNC_PRIORITY_1,
-		priv->dc_reg + DC_GEN);
-
-	ipu->dc_priv = priv;
-
-	dev_dbg(dev, "DC base: 0x%08lx template base: 0x%08lx\n",
-			base, template_base);
-
-	/* rgb24 */
-	ipu_dc_map_clear(priv, IPU_DC_MAP_RGB24);
-	ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 0, 7, 0xff); /* blue */
-	ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 1, 15, 0xff); /* green */
-	ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 2, 23, 0xff); /* red */
-
-	/* rgb565 */
-	ipu_dc_map_clear(priv, IPU_DC_MAP_RGB565);
-	ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 0, 4, 0xf8); /* blue */
-	ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 1, 10, 0xfc); /* green */
-	ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 2, 15, 0xf8); /* red */
-
-	/* gbr24 */
-	ipu_dc_map_clear(priv, IPU_DC_MAP_GBR24);
-	ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 2, 15, 0xff); /* green */
-	ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 1, 7, 0xff); /* blue */
-	ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 0, 23, 0xff); /* red */
-
-	/* bgr666 */
-	ipu_dc_map_clear(priv, IPU_DC_MAP_BGR666);
-	ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 0, 5, 0xfc); /* blue */
-	ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 1, 11, 0xfc); /* green */
-	ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 2, 17, 0xfc); /* red */
-
-	/* lvds666 */
-	ipu_dc_map_clear(priv, IPU_DC_MAP_LVDS666);
-	ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 0, 5, 0xfc); /* blue */
-	ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 1, 13, 0xfc); /* green */
-	ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 2, 21, 0xfc); /* red */
-
-	/* bgr24 */
-	ipu_dc_map_clear(priv, IPU_DC_MAP_BGR24);
-	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 2, 7, 0xff); /* red */
-	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
-	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
-
-	return 0;
-}
-
-void ipu_dc_exit(struct ipu_soc *ipu)
-{
-}
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-di.c b/drivers/staging/imx-drm/ipu-v3/ipu-di.c
deleted file mode 100644
index 849b3e120..0000000
--- a/drivers/staging/imx-drm/ipu-v3/ipu-di.c
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * Copyright (c) 2010 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-#include <linux/export.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-
-#include "imx-ipu-v3.h"
-#include "ipu-prv.h"
-
-struct ipu_di {
-	void __iomem *base;
-	int id;
-	u32 module;
-	struct clk *clk_di;	/* display input clock */
-	struct clk *clk_ipu;	/* IPU bus clock */
-	struct clk *clk_di_pixel; /* resulting pixel clock */
-	bool inuse;
-	struct ipu_soc *ipu;
-};
-
-static DEFINE_MUTEX(di_mutex);
-
-struct di_sync_config {
-	int run_count;
-	int run_src;
-	int offset_count;
-	int offset_src;
-	int repeat_count;
-	int cnt_clr_src;
-	int cnt_polarity_gen_en;
-	int cnt_polarity_clr_src;
-	int cnt_polarity_trigger_src;
-	int cnt_up;
-	int cnt_down;
-};
-
-enum di_pins {
-	DI_PIN11 = 0,
-	DI_PIN12 = 1,
-	DI_PIN13 = 2,
-	DI_PIN14 = 3,
-	DI_PIN15 = 4,
-	DI_PIN16 = 5,
-	DI_PIN17 = 6,
-	DI_PIN_CS = 7,
-
-	DI_PIN_SER_CLK = 0,
-	DI_PIN_SER_RS = 1,
-};
-
-enum di_sync_wave {
-	DI_SYNC_NONE = 0,
-	DI_SYNC_CLK = 1,
-	DI_SYNC_INT_HSYNC = 2,
-	DI_SYNC_HSYNC = 3,
-	DI_SYNC_VSYNC = 4,
-	DI_SYNC_DE = 6,
-};
-
-#define SYNC_WAVE 0
-
-#define DI_GENERAL		0x0000
-#define DI_BS_CLKGEN0		0x0004
-#define DI_BS_CLKGEN1		0x0008
-#define DI_SW_GEN0(gen)		(0x000c + 4 * ((gen) - 1))
-#define DI_SW_GEN1(gen)		(0x0030 + 4 * ((gen) - 1))
-#define DI_STP_REP(gen)		(0x0148 + 4 * (((gen) - 1)/2))
-#define DI_SYNC_AS_GEN		0x0054
-#define DI_DW_GEN(gen)		(0x0058 + 4 * (gen))
-#define DI_DW_SET(gen, set)	(0x0088 + 4 * ((gen) + 0xc * (set)))
-#define DI_SER_CONF		0x015c
-#define DI_SSC			0x0160
-#define DI_POL			0x0164
-#define DI_AW0			0x0168
-#define DI_AW1			0x016c
-#define DI_SCR_CONF		0x0170
-#define DI_STAT			0x0174
-
-#define DI_SW_GEN0_RUN_COUNT(x)			((x) << 19)
-#define DI_SW_GEN0_RUN_SRC(x)			((x) << 16)
-#define DI_SW_GEN0_OFFSET_COUNT(x)		((x) << 3)
-#define DI_SW_GEN0_OFFSET_SRC(x)		((x) << 0)
-
-#define DI_SW_GEN1_CNT_POL_GEN_EN(x)		((x) << 29)
-#define DI_SW_GEN1_CNT_CLR_SRC(x)		((x) << 25)
-#define DI_SW_GEN1_CNT_POL_TRIGGER_SRC(x)	((x) << 12)
-#define DI_SW_GEN1_CNT_POL_CLR_SRC(x)		((x) << 9)
-#define DI_SW_GEN1_CNT_DOWN(x)			((x) << 16)
-#define DI_SW_GEN1_CNT_UP(x)			(x)
-#define DI_SW_GEN1_AUTO_RELOAD			(0x10000000)
-
-#define DI_DW_GEN_ACCESS_SIZE_OFFSET		24
-#define DI_DW_GEN_COMPONENT_SIZE_OFFSET		16
-
-#define DI_GEN_POLARITY_1			(1 << 0)
-#define DI_GEN_POLARITY_2			(1 << 1)
-#define DI_GEN_POLARITY_3			(1 << 2)
-#define DI_GEN_POLARITY_4			(1 << 3)
-#define DI_GEN_POLARITY_5			(1 << 4)
-#define DI_GEN_POLARITY_6			(1 << 5)
-#define DI_GEN_POLARITY_7			(1 << 6)
-#define DI_GEN_POLARITY_8			(1 << 7)
-#define DI_GEN_POLARITY_DISP_CLK		(1 << 17)
-#define DI_GEN_DI_CLK_EXT			(1 << 20)
-#define DI_GEN_DI_VSYNC_EXT			(1 << 21)
-
-#define DI_POL_DRDY_DATA_POLARITY		(1 << 7)
-#define DI_POL_DRDY_POLARITY_15			(1 << 4)
-
-#define DI_VSYNC_SEL_OFFSET			13
-
-static inline u32 ipu_di_read(struct ipu_di *di, unsigned offset)
-{
-	return readl(di->base + offset);
-}
-
-static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset)
-{
-	writel(value, di->base + offset);
-}
-
-static void ipu_di_data_wave_config(struct ipu_di *di,
-				     int wave_gen,
-				     int access_size, int component_size)
-{
-	u32 reg;
-	reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
-	    (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
-	ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
-}
-
-static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin,
-		int set, int up, int down)
-{
-	u32 reg;
-
-	reg = ipu_di_read(di, DI_DW_GEN(wave_gen));
-	reg &= ~(0x3 << (di_pin * 2));
-	reg |= set << (di_pin * 2);
-	ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
-
-	ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set));
-}
-
-static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config,
-		int start, int count)
-{
-	u32 reg;
-	int i;
-
-	for (i = 0; i < count; i++) {
-		struct di_sync_config *c = &config[i];
-		int wave_gen = start + i + 1;
-
-		if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) ||
-				(c->repeat_count >= 0x1000) ||
-				(c->cnt_up >= 0x400) ||
-				(c->cnt_down >= 0x400)) {
-			dev_err(di->ipu->dev, "DI%d counters out of range.\n",
-					di->id);
-			return;
-		}
-
-		reg = DI_SW_GEN0_RUN_COUNT(c->run_count) |
-			DI_SW_GEN0_RUN_SRC(c->run_src) |
-			DI_SW_GEN0_OFFSET_COUNT(c->offset_count) |
-			DI_SW_GEN0_OFFSET_SRC(c->offset_src);
-		ipu_di_write(di, reg, DI_SW_GEN0(wave_gen));
-
-		reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) |
-			DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) |
-			DI_SW_GEN1_CNT_POL_TRIGGER_SRC(
-					c->cnt_polarity_trigger_src) |
-			DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) |
-			DI_SW_GEN1_CNT_DOWN(c->cnt_down) |
-			DI_SW_GEN1_CNT_UP(c->cnt_up);
-
-		/* Enable auto reload */
-		if (c->repeat_count == 0)
-			reg |= DI_SW_GEN1_AUTO_RELOAD;
-
-		ipu_di_write(di, reg, DI_SW_GEN1(wave_gen));
-
-		reg = ipu_di_read(di, DI_STP_REP(wave_gen));
-		reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1)));
-		reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1));
-		ipu_di_write(di, reg, DI_STP_REP(wave_gen));
-	}
-}
-
-static void ipu_di_sync_config_interlaced(struct ipu_di *di,
-		struct ipu_di_signal_cfg *sig)
-{
-	u32 h_total = sig->width + sig->h_sync_width +
-		sig->h_start_width + sig->h_end_width;
-	u32 v_total = sig->height + sig->v_sync_width +
-		sig->v_start_width + sig->v_end_width;
-	u32 reg;
-	struct di_sync_config cfg[] = {
-		{
-			.run_count = h_total / 2 - 1,
-			.run_src = DI_SYNC_CLK,
-		}, {
-			.run_count = h_total - 11,
-			.run_src = DI_SYNC_CLK,
-			.cnt_down = 4,
-		}, {
-			.run_count = v_total * 2 - 1,
-			.run_src = DI_SYNC_INT_HSYNC,
-			.offset_count = 1,
-			.offset_src = DI_SYNC_INT_HSYNC,
-			.cnt_down = 4,
-		}, {
-			.run_count = v_total / 2 - 1,
-			.run_src = DI_SYNC_HSYNC,
-			.offset_count = sig->v_start_width,
-			.offset_src = DI_SYNC_HSYNC,
-			.repeat_count = 2,
-			.cnt_clr_src = DI_SYNC_VSYNC,
-		}, {
-			.run_src = DI_SYNC_HSYNC,
-			.repeat_count = sig->height / 2,
-			.cnt_clr_src = 4,
-		}, {
-			.run_count = v_total - 1,
-			.run_src = DI_SYNC_HSYNC,
-		}, {
-			.run_count = v_total / 2 - 1,
-			.run_src = DI_SYNC_HSYNC,
-			.offset_count = 9,
-			.offset_src = DI_SYNC_HSYNC,
-			.repeat_count = 2,
-			.cnt_clr_src = DI_SYNC_VSYNC,
-		}, {
-			.run_src = DI_SYNC_CLK,
-			.offset_count = sig->h_start_width,
-			.offset_src = DI_SYNC_CLK,
-			.repeat_count = sig->width,
-			.cnt_clr_src = 5,
-		}, {
-			.run_count = v_total - 1,
-			.run_src = DI_SYNC_INT_HSYNC,
-			.offset_count = v_total / 2,
-			.offset_src = DI_SYNC_INT_HSYNC,
-			.cnt_clr_src = DI_SYNC_HSYNC,
-			.cnt_down = 4,
-		}
-	};
-
-	ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
-
-	/* set gentime select and tag sel */
-	reg = ipu_di_read(di, DI_SW_GEN1(9));
-	reg &= 0x1FFFFFFF;
-	reg |= (3 - 1) << 29 | 0x00008000;
-	ipu_di_write(di, reg, DI_SW_GEN1(9));
-
-	ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF);
-}
-
-static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
-		struct ipu_di_signal_cfg *sig, int div)
-{
-	u32 h_total = sig->width + sig->h_sync_width + sig->h_start_width +
-		sig->h_end_width;
-	u32 v_total = sig->height + sig->v_sync_width + sig->v_start_width +
-		sig->v_end_width;
-	struct di_sync_config cfg[] = {
-		{
-			/* 1: INT_HSYNC */
-			.run_count = h_total - 1,
-			.run_src = DI_SYNC_CLK,
-		} , {
-			/* PIN2: HSYNC */
-			.run_count = h_total - 1,
-			.run_src = DI_SYNC_CLK,
-			.offset_count = div * sig->v_to_h_sync,
-			.offset_src = DI_SYNC_CLK,
-			.cnt_polarity_gen_en = 1,
-			.cnt_polarity_trigger_src = DI_SYNC_CLK,
-			.cnt_down = sig->h_sync_width * 2,
-		} , {
-			/* PIN3: VSYNC */
-			.run_count = v_total - 1,
-			.run_src = DI_SYNC_INT_HSYNC,
-			.cnt_polarity_gen_en = 1,
-			.cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
-			.cnt_down = sig->v_sync_width * 2,
-		} , {
-			/* 4: Line Active */
-			.run_src = DI_SYNC_HSYNC,
-			.offset_count = sig->v_sync_width + sig->v_start_width,
-			.offset_src = DI_SYNC_HSYNC,
-			.repeat_count = sig->height,
-			.cnt_clr_src = DI_SYNC_VSYNC,
-		} , {
-			/* 5: Pixel Active, referenced by DC */
-			.run_src = DI_SYNC_CLK,
-			.offset_count = sig->h_sync_width + sig->h_start_width,
-			.offset_src = DI_SYNC_CLK,
-			.repeat_count = sig->width,
-			.cnt_clr_src = 5, /* Line Active */
-		} , {
-			/* unused */
-		} , {
-			/* unused */
-		} , {
-			/* unused */
-		} , {
-			/* unused */
-		},
-	};
-	/* can't use #7 and #8 for line active and pixel active counters */
-	struct di_sync_config cfg_vga[] = {
-		{
-			/* 1: INT_HSYNC */
-			.run_count = h_total - 1,
-			.run_src = DI_SYNC_CLK,
-		} , {
-			/* 2: VSYNC */
-			.run_count = v_total - 1,
-			.run_src = DI_SYNC_INT_HSYNC,
-		} , {
-			/* 3: Line Active */
-			.run_src = DI_SYNC_INT_HSYNC,
-			.offset_count = sig->v_sync_width + sig->v_start_width,
-			.offset_src = DI_SYNC_INT_HSYNC,
-			.repeat_count = sig->height,
-			.cnt_clr_src = 3 /* VSYNC */,
-		} , {
-			/* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */
-			.run_count = h_total - 1,
-			.run_src = DI_SYNC_CLK,
-			.offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
-			.offset_src = DI_SYNC_CLK,
-			.cnt_polarity_gen_en = 1,
-			.cnt_polarity_trigger_src = DI_SYNC_CLK,
-			.cnt_down = sig->h_sync_width * 2,
-		} , {
-			/* 5: Pixel Active signal to DC */
-			.run_src = DI_SYNC_CLK,
-			.offset_count = sig->h_sync_width + sig->h_start_width,
-			.offset_src = DI_SYNC_CLK,
-			.repeat_count = sig->width,
-			.cnt_clr_src = 4, /* Line Active */
-		} , {
-			/* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */
-			.run_count = v_total - 1,
-			.run_src = DI_SYNC_INT_HSYNC,
-			.offset_count = 1, /* magic value from Freescale TVE driver */
-			.offset_src = DI_SYNC_INT_HSYNC,
-			.cnt_polarity_gen_en = 1,
-			.cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
-			.cnt_down = sig->v_sync_width * 2,
-		} , {
-			/* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */
-			.run_count = h_total - 1,
-			.run_src = DI_SYNC_CLK,
-			.offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
-			.offset_src = DI_SYNC_CLK,
-			.cnt_polarity_gen_en = 1,
-			.cnt_polarity_trigger_src = DI_SYNC_CLK,
-			.cnt_down = sig->h_sync_width * 2,
-		} , {
-			/* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */
-			.run_count = v_total - 1,
-			.run_src = DI_SYNC_INT_HSYNC,
-			.offset_count = 1, /* magic value from Freescale TVE driver */
-			.offset_src = DI_SYNC_INT_HSYNC,
-			.cnt_polarity_gen_en = 1,
-			.cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
-			.cnt_down = sig->v_sync_width * 2,
-		} , {
-			/* unused */
-		},
-	};
-
-	ipu_di_write(di, v_total - 1, DI_SCR_CONF);
-	if (sig->hsync_pin == 2 && sig->vsync_pin == 3)
-		ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
-	else
-		ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
-}
-
-static void ipu_di_config_clock(struct ipu_di *di,
-	const struct ipu_di_signal_cfg *sig)
-{
-	struct clk *clk;
-	unsigned clkgen0;
-	uint32_t val;
-
-	if (sig->clkflags & IPU_DI_CLKMODE_EXT) {
-		/*
-		 * CLKMODE_EXT means we must use the DI clock: this is
-		 * needed for things like LVDS which needs to feed the
-		 * DI and LDB with the same pixel clock.
-		 */
-		clk = di->clk_di;
-
-		if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
-			/*
-			 * CLKMODE_SYNC means that we want the DI to be
-			 * clocked at the same rate as the parent clock.
-			 * This is needed (eg) for LDB which needs to be
-			 * fed with the same pixel clock.  We assume that
-			 * the LDB clock has already been set correctly.
-			 */
-			clkgen0 = 1 << 4;
-		} else {
-			/*
-			 * We can use the divider.  We should really have
-			 * a flag here indicating whether the bridge can
-			 * cope with a fractional divider or not.  For the
-			 * time being, let's go for simplicitly and
-			 * reliability.
-			 */
-			unsigned long in_rate;
-			unsigned div;
-
-			clk_set_rate(clk, sig->pixelclock);
-
-			in_rate = clk_get_rate(clk);
-			div = (in_rate + sig->pixelclock / 2) / sig->pixelclock;
-			if (div == 0)
-				div = 1;
-
-			clkgen0 = div << 4;
-		}
-	} else {
-		/*
-		 * For other interfaces, we can arbitarily select between
-		 * the DI specific clock and the internal IPU clock.  See
-		 * DI_GENERAL bit 20.  We select the IPU clock if it can
-		 * give us a clock rate within 1% of the requested frequency,
-		 * otherwise we use the DI clock.
-		 */
-		unsigned long rate, clkrate;
-		unsigned div, error;
-
-		clkrate = clk_get_rate(di->clk_ipu);
-		div = (clkrate + sig->pixelclock / 2) / sig->pixelclock;
-		rate = clkrate / div;
-
-		error = rate / (sig->pixelclock / 1000);
-
-		dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
-			rate, div, (signed)(error - 1000) / 10, error % 10);
-
-		/* Allow a 1% error */
-		if (error < 1010 && error >= 990) {
-			clk = di->clk_ipu;
-
-			clkgen0 = div << 4;
-		} else {
-			unsigned long in_rate;
-			unsigned div;
-
-			clk = di->clk_di;
-
-			clk_set_rate(clk, sig->pixelclock);
-
-			in_rate = clk_get_rate(clk);
-			div = (in_rate + sig->pixelclock / 2) / sig->pixelclock;
-			if (div == 0)
-				div = 1;
-
-			clkgen0 = div << 4;
-		}
-	}
-
-	di->clk_di_pixel = clk;
-
-	/* Set the divider */
-	ipu_di_write(di, clkgen0, DI_BS_CLKGEN0);
-
-	/*
-	 * Set the high/low periods.  Bits 24:16 give us the falling edge,
-	 * and bits 8:0 give the rising edge.  LSB is fraction, and is
-	 * based on the divider above.  We want a 50% duty cycle, so set
-	 * the falling edge to be half the divider.
-	 */
-	ipu_di_write(di, (clkgen0 >> 4) << 16, DI_BS_CLKGEN1);
-
-	/* Finally select the input clock */
-	val = ipu_di_read(di, DI_GENERAL) & ~DI_GEN_DI_CLK_EXT;
-	if (clk == di->clk_di)
-		val |= DI_GEN_DI_CLK_EXT;
-	ipu_di_write(di, val, DI_GENERAL);
-
-	dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
-		sig->pixelclock,
-		clk_get_rate(di->clk_ipu),
-		clk_get_rate(di->clk_di),
-		clk == di->clk_di ? "DI" : "IPU",
-		clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
-}
-
-int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
-{
-	u32 reg;
-	u32 di_gen, vsync_cnt;
-	u32 div;
-	u32 h_total, v_total;
-
-	dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
-		di->id, sig->width, sig->height);
-
-	if ((sig->v_sync_width == 0) || (sig->h_sync_width == 0))
-		return -EINVAL;
-
-	h_total = sig->width + sig->h_sync_width + sig->h_start_width +
-		sig->h_end_width;
-	v_total = sig->height + sig->v_sync_width + sig->v_start_width +
-		sig->v_end_width;
-
-	dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
-		clk_get_rate(di->clk_ipu),
-		clk_get_rate(di->clk_di),
-		sig->pixelclock);
-
-	mutex_lock(&di_mutex);
-
-	ipu_di_config_clock(di, sig);
-
-	div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
-	div = div / 16;		/* Now divider is integer portion */
-
-	/* Setup pixel clock timing */
-	/* Down time is half of period */
-	ipu_di_write(di, (div << 16), DI_BS_CLKGEN1);
-
-	ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1);
-	ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
-
-	di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT;
-	di_gen |= DI_GEN_DI_VSYNC_EXT;
-
-	if (sig->interlaced) {
-		ipu_di_sync_config_interlaced(di, sig);
-
-		/* set y_sel = 1 */
-		di_gen |= 0x10000000;
-		di_gen |= DI_GEN_POLARITY_5;
-		di_gen |= DI_GEN_POLARITY_8;
-
-		vsync_cnt = 7;
-
-		if (sig->Hsync_pol)
-			di_gen |= DI_GEN_POLARITY_3;
-		if (sig->Vsync_pol)
-			di_gen |= DI_GEN_POLARITY_2;
-	} else {
-		ipu_di_sync_config_noninterlaced(di, sig, div);
-
-		vsync_cnt = 3;
-		if (di->id == 1)
-			/*
-			 * TODO: change only for TVEv2, parallel display
-			 * uses pin 2 / 3
-			 */
-			if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3))
-				vsync_cnt = 6;
-
-		if (sig->Hsync_pol) {
-			if (sig->hsync_pin == 2)
-				di_gen |= DI_GEN_POLARITY_2;
-			else if (sig->hsync_pin == 4)
-				di_gen |= DI_GEN_POLARITY_4;
-			else if (sig->hsync_pin == 7)
-				di_gen |= DI_GEN_POLARITY_7;
-		}
-		if (sig->Vsync_pol) {
-			if (sig->vsync_pin == 3)
-				di_gen |= DI_GEN_POLARITY_3;
-			else if (sig->vsync_pin == 6)
-				di_gen |= DI_GEN_POLARITY_6;
-			else if (sig->vsync_pin == 8)
-				di_gen |= DI_GEN_POLARITY_8;
-		}
-	}
-
-	if (sig->clk_pol)
-		di_gen |= DI_GEN_POLARITY_DISP_CLK;
-
-	ipu_di_write(di, di_gen, DI_GENERAL);
-
-	ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002,
-		     DI_SYNC_AS_GEN);
-
-	reg = ipu_di_read(di, DI_POL);
-	reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
-
-	if (sig->enable_pol)
-		reg |= DI_POL_DRDY_POLARITY_15;
-	if (sig->data_pol)
-		reg |= DI_POL_DRDY_DATA_POLARITY;
-
-	ipu_di_write(di, reg, DI_POL);
-
-	mutex_unlock(&di_mutex);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);
-
-int ipu_di_enable(struct ipu_di *di)
-{
-	int ret;
-
-	WARN_ON(IS_ERR(di->clk_di_pixel));
-
-	ret = clk_prepare_enable(di->clk_di_pixel);
-	if (ret)
-		return ret;
-
-	ipu_module_enable(di->ipu, di->module);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_di_enable);
-
-int ipu_di_disable(struct ipu_di *di)
-{
-	WARN_ON(IS_ERR(di->clk_di_pixel));
-
-	ipu_module_disable(di->ipu, di->module);
-
-	clk_disable_unprepare(di->clk_di_pixel);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_di_disable);
-
-int ipu_di_get_num(struct ipu_di *di)
-{
-	return di->id;
-}
-EXPORT_SYMBOL_GPL(ipu_di_get_num);
-
-static DEFINE_MUTEX(ipu_di_lock);
-
-struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp)
-{
-	struct ipu_di *di;
-
-	if (disp > 1)
-		return ERR_PTR(-EINVAL);
-
-	di = ipu->di_priv[disp];
-
-	mutex_lock(&ipu_di_lock);
-
-	if (di->inuse) {
-		di = ERR_PTR(-EBUSY);
-		goto out;
-	}
-
-	di->inuse = true;
-out:
-	mutex_unlock(&ipu_di_lock);
-
-	return di;
-}
-EXPORT_SYMBOL_GPL(ipu_di_get);
-
-void ipu_di_put(struct ipu_di *di)
-{
-	mutex_lock(&ipu_di_lock);
-
-	di->inuse = false;
-
-	mutex_unlock(&ipu_di_lock);
-}
-EXPORT_SYMBOL_GPL(ipu_di_put);
-
-int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
-		unsigned long base,
-		u32 module, struct clk *clk_ipu)
-{
-	struct ipu_di *di;
-
-	if (id > 1)
-		return -ENODEV;
-
-	di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
-	if (!di)
-		return -ENOMEM;
-
-	ipu->di_priv[id] = di;
-
-	di->clk_di = devm_clk_get(dev, id ? "di1" : "di0");
-	if (IS_ERR(di->clk_di))
-		return PTR_ERR(di->clk_di);
-
-	di->module = module;
-	di->id = id;
-	di->clk_ipu = clk_ipu;
-	di->base = devm_ioremap(dev, base, PAGE_SIZE);
-	if (!di->base)
-		return -ENOMEM;
-
-	ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
-
-	dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
-			id, base, di->base);
-	di->inuse = false;
-	di->ipu = ipu;
-
-	return 0;
-}
-
-void ipu_di_exit(struct ipu_soc *ipu, int id)
-{
-}
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
deleted file mode 100644
index 59f182b..0000000
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright (c) 2010 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-#include <linux/export.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-
-#include "imx-ipu-v3.h"
-#include "ipu-prv.h"
-
-#define DMFC_RD_CHAN		0x0000
-#define DMFC_WR_CHAN		0x0004
-#define DMFC_WR_CHAN_DEF	0x0008
-#define DMFC_DP_CHAN		0x000c
-#define DMFC_DP_CHAN_DEF	0x0010
-#define DMFC_GENERAL1		0x0014
-#define DMFC_GENERAL2		0x0018
-#define DMFC_IC_CTRL		0x001c
-#define DMFC_WR_CHAN_ALT	0x0020
-#define DMFC_WR_CHAN_DEF_ALT	0x0024
-#define DMFC_DP_CHAN_ALT	0x0028
-#define DMFC_DP_CHAN_DEF_ALT	0x002c
-#define DMFC_GENERAL1_ALT	0x0030
-#define DMFC_STAT		0x0034
-
-#define DMFC_WR_CHAN_1_28		0
-#define DMFC_WR_CHAN_2_41		8
-#define DMFC_WR_CHAN_1C_42		16
-#define DMFC_WR_CHAN_2C_43		24
-
-#define DMFC_DP_CHAN_5B_23		0
-#define DMFC_DP_CHAN_5F_27		8
-#define DMFC_DP_CHAN_6B_24		16
-#define DMFC_DP_CHAN_6F_29		24
-
-#define DMFC_FIFO_SIZE_64		(3 << 3)
-#define DMFC_FIFO_SIZE_128		(2 << 3)
-#define DMFC_FIFO_SIZE_256		(1 << 3)
-#define DMFC_FIFO_SIZE_512		(0 << 3)
-
-#define DMFC_SEGMENT(x)			((x & 0x7) << 0)
-#define DMFC_BURSTSIZE_128		(0 << 6)
-#define DMFC_BURSTSIZE_64		(1 << 6)
-#define DMFC_BURSTSIZE_32		(2 << 6)
-#define DMFC_BURSTSIZE_16		(3 << 6)
-
-struct dmfc_channel_data {
-	int		ipu_channel;
-	unsigned long	channel_reg;
-	unsigned long	shift;
-	unsigned	eot_shift;
-	unsigned	max_fifo_lines;
-};
-
-static const struct dmfc_channel_data dmfcdata[] = {
-	{
-		.ipu_channel	= IPUV3_CHANNEL_MEM_BG_SYNC,
-		.channel_reg	= DMFC_DP_CHAN,
-		.shift		= DMFC_DP_CHAN_5B_23,
-		.eot_shift	= 20,
-		.max_fifo_lines	= 3,
-	}, {
-		.ipu_channel	= 24,
-		.channel_reg	= DMFC_DP_CHAN,
-		.shift		= DMFC_DP_CHAN_6B_24,
-		.eot_shift	= 22,
-		.max_fifo_lines	= 1,
-	}, {
-		.ipu_channel	= IPUV3_CHANNEL_MEM_FG_SYNC,
-		.channel_reg	= DMFC_DP_CHAN,
-		.shift		= DMFC_DP_CHAN_5F_27,
-		.eot_shift	= 21,
-		.max_fifo_lines	= 2,
-	}, {
-		.ipu_channel	= IPUV3_CHANNEL_MEM_DC_SYNC,
-		.channel_reg	= DMFC_WR_CHAN,
-		.shift		= DMFC_WR_CHAN_1_28,
-		.eot_shift	= 16,
-		.max_fifo_lines	= 2,
-	}, {
-		.ipu_channel	= 29,
-		.channel_reg	= DMFC_DP_CHAN,
-		.shift		= DMFC_DP_CHAN_6F_29,
-		.eot_shift	= 23,
-		.max_fifo_lines	= 1,
-	},
-};
-
-#define DMFC_NUM_CHANNELS	ARRAY_SIZE(dmfcdata)
-
-struct ipu_dmfc_priv;
-
-struct dmfc_channel {
-	unsigned			slots;
-	unsigned			slotmask;
-	unsigned			segment;
-	int				burstsize;
-	struct ipu_soc			*ipu;
-	struct ipu_dmfc_priv		*priv;
-	const struct dmfc_channel_data	*data;
-};
-
-struct ipu_dmfc_priv {
-	struct ipu_soc *ipu;
-	struct device *dev;
-	struct dmfc_channel channels[DMFC_NUM_CHANNELS];
-	struct mutex mutex;
-	unsigned long bandwidth_per_slot;
-	void __iomem *base;
-	int use_count;
-};
-
-int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
-{
-	struct ipu_dmfc_priv *priv = dmfc->priv;
-	mutex_lock(&priv->mutex);
-
-	if (!priv->use_count)
-		ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
-
-	priv->use_count++;
-
-	mutex_unlock(&priv->mutex);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
-
-static void ipu_dmfc_wait_fifos(struct ipu_dmfc_priv *priv)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-
-	while ((readl(priv->base + DMFC_STAT) & 0x02fff000) != 0x02fff000) {
-		if (time_after(jiffies, timeout)) {
-			dev_warn(priv->dev,
-				 "Timeout waiting for DMFC FIFOs to clear\n");
-			break;
-		}
-		cpu_relax();
-	}
-}
-
-void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
-{
-	struct ipu_dmfc_priv *priv = dmfc->priv;
-
-	mutex_lock(&priv->mutex);
-
-	priv->use_count--;
-
-	if (!priv->use_count) {
-		ipu_dmfc_wait_fifos(priv);
-		ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
-	}
-
-	if (priv->use_count < 0)
-		priv->use_count = 0;
-
-	mutex_unlock(&priv->mutex);
-}
-EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
-
-static int ipu_dmfc_setup_channel(struct dmfc_channel *dmfc, int slots,
-		int segment, int burstsize)
-{
-	struct ipu_dmfc_priv *priv = dmfc->priv;
-	u32 val, field;
-
-	dev_dbg(priv->dev,
-			"dmfc: using %d slots starting from segment %d for IPU channel %d\n",
-			slots, segment, dmfc->data->ipu_channel);
-
-	switch (slots) {
-	case 1:
-		field = DMFC_FIFO_SIZE_64;
-		break;
-	case 2:
-		field = DMFC_FIFO_SIZE_128;
-		break;
-	case 4:
-		field = DMFC_FIFO_SIZE_256;
-		break;
-	case 8:
-		field = DMFC_FIFO_SIZE_512;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (burstsize) {
-	case 16:
-		field |= DMFC_BURSTSIZE_16;
-		break;
-	case 32:
-		field |= DMFC_BURSTSIZE_32;
-		break;
-	case 64:
-		field |= DMFC_BURSTSIZE_64;
-		break;
-	case 128:
-		field |= DMFC_BURSTSIZE_128;
-		break;
-	}
-
-	field |= DMFC_SEGMENT(segment);
-
-	val = readl(priv->base + dmfc->data->channel_reg);
-
-	val &= ~(0xff << dmfc->data->shift);
-	val |= field << dmfc->data->shift;
-
-	writel(val, priv->base + dmfc->data->channel_reg);
-
-	dmfc->slots = slots;
-	dmfc->segment = segment;
-	dmfc->burstsize = burstsize;
-	dmfc->slotmask = ((1 << slots) - 1) << segment;
-
-	return 0;
-}
-
-static int dmfc_bandwidth_to_slots(struct ipu_dmfc_priv *priv,
-		unsigned long bandwidth)
-{
-	int slots = 1;
-
-	while (slots * priv->bandwidth_per_slot < bandwidth)
-		slots *= 2;
-
-	return slots;
-}
-
-static int dmfc_find_slots(struct ipu_dmfc_priv *priv, int slots)
-{
-	unsigned slotmask_need, slotmask_used = 0;
-	int i, segment = 0;
-
-	slotmask_need = (1 << slots) - 1;
-
-	for (i = 0; i < DMFC_NUM_CHANNELS; i++)
-		slotmask_used |= priv->channels[i].slotmask;
-
-	while (slotmask_need <= 0xff) {
-		if (!(slotmask_used & slotmask_need))
-			return segment;
-
-		slotmask_need <<= 1;
-		segment++;
-	}
-
-	return -EBUSY;
-}
-
-void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc)
-{
-	struct ipu_dmfc_priv *priv = dmfc->priv;
-	int i;
-
-	dev_dbg(priv->dev, "dmfc: freeing %d slots starting from segment %d\n",
-			dmfc->slots, dmfc->segment);
-
-	mutex_lock(&priv->mutex);
-
-	if (!dmfc->slots)
-		goto out;
-
-	dmfc->slotmask = 0;
-	dmfc->slots = 0;
-	dmfc->segment = 0;
-
-	for (i = 0; i < DMFC_NUM_CHANNELS; i++)
-		priv->channels[i].slotmask = 0;
-
-	for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
-		if (priv->channels[i].slots > 0) {
-			priv->channels[i].segment =
-				dmfc_find_slots(priv, priv->channels[i].slots);
-			priv->channels[i].slotmask =
-				((1 << priv->channels[i].slots) - 1) <<
-				priv->channels[i].segment;
-		}
-	}
-
-	for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
-		if (priv->channels[i].slots > 0)
-			ipu_dmfc_setup_channel(&priv->channels[i],
-					priv->channels[i].slots,
-					priv->channels[i].segment,
-					priv->channels[i].burstsize);
-	}
-out:
-	mutex_unlock(&priv->mutex);
-}
-EXPORT_SYMBOL_GPL(ipu_dmfc_free_bandwidth);
-
-int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
-		unsigned long bandwidth_pixel_per_second, int burstsize)
-{
-	struct ipu_dmfc_priv *priv = dmfc->priv;
-	int slots = dmfc_bandwidth_to_slots(priv, bandwidth_pixel_per_second);
-	int segment = -1, ret = 0;
-
-	dev_dbg(priv->dev, "dmfc: trying to allocate %ldMpixel/s for IPU channel %d\n",
-			bandwidth_pixel_per_second / 1000000,
-			dmfc->data->ipu_channel);
-
-	ipu_dmfc_free_bandwidth(dmfc);
-
-	mutex_lock(&priv->mutex);
-
-	if (slots > 8) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	/* For the MEM_BG channel, first try to allocate twice the slots */
-	if (dmfc->data->ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC)
-		segment = dmfc_find_slots(priv, slots * 2);
-	else if (slots < 2)
-		/* Always allocate at least 128*4 bytes (2 slots) */
-		slots = 2;
-
-	if (segment >= 0)
-		slots *= 2;
-	else
-		segment = dmfc_find_slots(priv, slots);
-	if (segment < 0) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	ipu_dmfc_setup_channel(dmfc, slots, segment, burstsize);
-
-out:
-	mutex_unlock(&priv->mutex);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(ipu_dmfc_alloc_bandwidth);
-
-int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width)
-{
-	struct ipu_dmfc_priv *priv = dmfc->priv;
-	u32 dmfc_gen1;
-
-	dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
-
-	if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
-		dmfc_gen1 |= 1 << dmfc->data->eot_shift;
-	else
-		dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
-
-	writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_dmfc_init_channel);
-
-struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
-{
-	struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
-	int i;
-
-	for (i = 0; i < DMFC_NUM_CHANNELS; i++)
-		if (dmfcdata[i].ipu_channel == ipu_channel)
-			return &priv->channels[i];
-	return ERR_PTR(-ENODEV);
-}
-EXPORT_SYMBOL_GPL(ipu_dmfc_get);
-
-void ipu_dmfc_put(struct dmfc_channel *dmfc)
-{
-	ipu_dmfc_free_bandwidth(dmfc);
-}
-EXPORT_SYMBOL_GPL(ipu_dmfc_put);
-
-int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
-		struct clk *ipu_clk)
-{
-	struct ipu_dmfc_priv *priv;
-	int i;
-
-	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	priv->base = devm_ioremap(dev, base, PAGE_SIZE);
-	if (!priv->base)
-		return -ENOMEM;
-
-	priv->dev = dev;
-	priv->ipu = ipu;
-	mutex_init(&priv->mutex);
-
-	ipu->dmfc_priv = priv;
-
-	for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
-		priv->channels[i].priv = priv;
-		priv->channels[i].ipu = ipu;
-		priv->channels[i].data = &dmfcdata[i];
-	}
-
-	writel(0x0, priv->base + DMFC_WR_CHAN);
-	writel(0x0, priv->base + DMFC_DP_CHAN);
-
-	/*
-	 * We have a total bandwidth of clkrate * 4pixel divided
-	 * into 8 slots.
-	 */
-	priv->bandwidth_per_slot = clk_get_rate(ipu_clk) * 4 / 8;
-
-	dev_dbg(dev, "dmfc: 8 slots with %ldMpixel/s bandwidth each\n",
-			priv->bandwidth_per_slot / 1000000);
-
-	writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
-	writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
-	writel(0x00000003, priv->base + DMFC_GENERAL1);
-
-	return 0;
-}
-
-void ipu_dmfc_exit(struct ipu_soc *ipu)
-{
-}
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
deleted file mode 100644
index d90f82a..0000000
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright (c) 2010 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-#include <linux/export.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/err.h>
-
-#include "imx-ipu-v3.h"
-#include "ipu-prv.h"
-
-#define DP_SYNC 0
-#define DP_ASYNC0 0x60
-#define DP_ASYNC1 0xBC
-
-#define DP_COM_CONF		0x0
-#define DP_GRAPH_WIND_CTRL	0x0004
-#define DP_FG_POS		0x0008
-#define DP_CSC_A_0		0x0044
-#define DP_CSC_A_1		0x0048
-#define DP_CSC_A_2		0x004C
-#define DP_CSC_A_3		0x0050
-#define DP_CSC_0		0x0054
-#define DP_CSC_1		0x0058
-
-#define DP_COM_CONF_FG_EN		(1 << 0)
-#define DP_COM_CONF_GWSEL		(1 << 1)
-#define DP_COM_CONF_GWAM		(1 << 2)
-#define DP_COM_CONF_GWCKE		(1 << 3)
-#define DP_COM_CONF_CSC_DEF_MASK	(3 << 8)
-#define DP_COM_CONF_CSC_DEF_OFFSET	8
-#define DP_COM_CONF_CSC_DEF_FG		(3 << 8)
-#define DP_COM_CONF_CSC_DEF_BG		(2 << 8)
-#define DP_COM_CONF_CSC_DEF_BOTH	(1 << 8)
-
-#define IPUV3_NUM_FLOWS		3
-
-struct ipu_dp_priv;
-
-struct ipu_dp {
-	u32 flow;
-	bool in_use;
-	bool foreground;
-	enum ipu_color_space in_cs;
-};
-
-struct ipu_flow {
-	struct ipu_dp foreground;
-	struct ipu_dp background;
-	enum ipu_color_space out_cs;
-	void __iomem *base;
-	struct ipu_dp_priv *priv;
-};
-
-struct ipu_dp_priv {
-	struct ipu_soc *ipu;
-	struct device *dev;
-	void __iomem *base;
-	struct ipu_flow flow[IPUV3_NUM_FLOWS];
-	struct mutex mutex;
-	int use_count;
-};
-
-static u32 ipu_dp_flow_base[] = {DP_SYNC, DP_ASYNC0, DP_ASYNC1};
-
-static inline struct ipu_flow *to_flow(struct ipu_dp *dp)
-{
-	if (dp->foreground)
-		return container_of(dp, struct ipu_flow, foreground);
-	else
-		return container_of(dp, struct ipu_flow, background);
-}
-
-int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
-		u8 alpha, bool bg_chan)
-{
-	struct ipu_flow *flow = to_flow(dp);
-	struct ipu_dp_priv *priv = flow->priv;
-	u32 reg;
-
-	mutex_lock(&priv->mutex);
-
-	reg = readl(flow->base + DP_COM_CONF);
-	if (bg_chan)
-		reg &= ~DP_COM_CONF_GWSEL;
-	else
-		reg |= DP_COM_CONF_GWSEL;
-	writel(reg, flow->base + DP_COM_CONF);
-
-	if (enable) {
-		reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & 0x00FFFFFFL;
-		writel(reg | ((u32) alpha << 24),
-			     flow->base + DP_GRAPH_WIND_CTRL);
-
-		reg = readl(flow->base + DP_COM_CONF);
-		writel(reg | DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
-	} else {
-		reg = readl(flow->base + DP_COM_CONF);
-		writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
-	}
-
-	ipu_srm_dp_sync_update(priv->ipu);
-
-	mutex_unlock(&priv->mutex);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha);
-
-int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
-{
-	struct ipu_flow *flow = to_flow(dp);
-	struct ipu_dp_priv *priv = flow->priv;
-
-	writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS);
-
-	ipu_srm_dp_sync_update(priv->ipu);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos);
-
-static void ipu_dp_csc_init(struct ipu_flow *flow,
-		enum ipu_color_space in,
-		enum ipu_color_space out,
-		u32 place)
-{
-	u32 reg;
-
-	reg = readl(flow->base + DP_COM_CONF);
-	reg &= ~DP_COM_CONF_CSC_DEF_MASK;
-
-	if (in == out) {
-		writel(reg, flow->base + DP_COM_CONF);
-		return;
-	}
-
-	if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) {
-		writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0);
-		writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1);
-		writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2);
-		writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3);
-		writel(0x3d6 | (0x0000 << 16) | (2 << 30),
-				flow->base + DP_CSC_0);
-		writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
-				flow->base + DP_CSC_1);
-	} else {
-		writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
-		writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1);
-		writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2);
-		writel(0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3);
-		writel(0x000 | (0x3e42 << 16) | (1 << 30),
-				flow->base + DP_CSC_0);
-		writel(0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30),
-				flow->base + DP_CSC_1);
-	}
-
-	reg |= place;
-
-	writel(reg, flow->base + DP_COM_CONF);
-}
-
-int ipu_dp_setup_channel(struct ipu_dp *dp,
-		enum ipu_color_space in,
-		enum ipu_color_space out)
-{
-	struct ipu_flow *flow = to_flow(dp);
-	struct ipu_dp_priv *priv = flow->priv;
-
-	mutex_lock(&priv->mutex);
-
-	dp->in_cs = in;
-
-	if (!dp->foreground)
-		flow->out_cs = out;
-
-	if (flow->foreground.in_cs == flow->background.in_cs) {
-		/*
-		 * foreground and background are of same colorspace, put
-		 * colorspace converter after combining unit.
-		 */
-		ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs,
-				DP_COM_CONF_CSC_DEF_BOTH);
-	} else {
-		if (flow->foreground.in_cs == flow->out_cs)
-			/*
-			 * foreground identical to output, apply color
-			 * conversion on background
-			 */
-			ipu_dp_csc_init(flow, flow->background.in_cs,
-					flow->out_cs, DP_COM_CONF_CSC_DEF_BG);
-		else
-			ipu_dp_csc_init(flow, flow->foreground.in_cs,
-					flow->out_cs, DP_COM_CONF_CSC_DEF_FG);
-	}
-
-	ipu_srm_dp_sync_update(priv->ipu);
-
-	mutex_unlock(&priv->mutex);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
-
-int ipu_dp_enable(struct ipu_soc *ipu)
-{
-	struct ipu_dp_priv *priv = ipu->dp_priv;
-
-	mutex_lock(&priv->mutex);
-
-	if (!priv->use_count)
-		ipu_module_enable(priv->ipu, IPU_CONF_DP_EN);
-
-	priv->use_count++;
-
-	mutex_unlock(&priv->mutex);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_dp_enable);
-
-int ipu_dp_enable_channel(struct ipu_dp *dp)
-{
-	struct ipu_flow *flow = to_flow(dp);
-	struct ipu_dp_priv *priv = flow->priv;
-	u32 reg;
-
-	if (!dp->foreground)
-		return 0;
-
-	mutex_lock(&priv->mutex);
-
-	reg = readl(flow->base + DP_COM_CONF);
-	reg |= DP_COM_CONF_FG_EN;
-	writel(reg, flow->base + DP_COM_CONF);
-
-	ipu_srm_dp_sync_update(priv->ipu);
-
-	mutex_unlock(&priv->mutex);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_dp_enable_channel);
-
-void ipu_dp_disable_channel(struct ipu_dp *dp)
-{
-	struct ipu_flow *flow = to_flow(dp);
-	struct ipu_dp_priv *priv = flow->priv;
-	u32 reg, csc;
-
-	if (!dp->foreground)
-		return;
-
-	mutex_lock(&priv->mutex);
-
-	reg = readl(flow->base + DP_COM_CONF);
-	csc = reg & DP_COM_CONF_CSC_DEF_MASK;
-	if (csc == DP_COM_CONF_CSC_DEF_FG)
-		reg &= ~DP_COM_CONF_CSC_DEF_MASK;
-
-	reg &= ~DP_COM_CONF_FG_EN;
-	writel(reg, flow->base + DP_COM_CONF);
-
-	writel(0, flow->base + DP_FG_POS);
-	ipu_srm_dp_sync_update(priv->ipu);
-
-	if (ipu_idmac_channel_busy(priv->ipu, IPUV3_CHANNEL_MEM_BG_SYNC))
-		ipu_wait_interrupt(priv->ipu, IPU_IRQ_DP_SF_END, 50);
-
-	mutex_unlock(&priv->mutex);
-}
-EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
-
-void ipu_dp_disable(struct ipu_soc *ipu)
-{
-	struct ipu_dp_priv *priv = ipu->dp_priv;
-
-	mutex_lock(&priv->mutex);
-
-	priv->use_count--;
-
-	if (!priv->use_count)
-		ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
-
-	if (priv->use_count < 0)
-		priv->use_count = 0;
-
-	mutex_unlock(&priv->mutex);
-}
-EXPORT_SYMBOL_GPL(ipu_dp_disable);
-
-struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
-{
-	struct ipu_dp_priv *priv = ipu->dp_priv;
-	struct ipu_dp *dp;
-
-	if ((flow >> 1) >= IPUV3_NUM_FLOWS)
-		return ERR_PTR(-EINVAL);
-
-	if (flow & 1)
-		dp = &priv->flow[flow >> 1].foreground;
-	else
-		dp = &priv->flow[flow >> 1].background;
-
-	if (dp->in_use)
-		return ERR_PTR(-EBUSY);
-
-	dp->in_use = true;
-
-	return dp;
-}
-EXPORT_SYMBOL_GPL(ipu_dp_get);
-
-void ipu_dp_put(struct ipu_dp *dp)
-{
-	dp->in_use = false;
-}
-EXPORT_SYMBOL_GPL(ipu_dp_put);
-
-int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
-{
-	struct ipu_dp_priv *priv;
-	int i;
-
-	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-	priv->dev = dev;
-	priv->ipu = ipu;
-
-	ipu->dp_priv = priv;
-
-	priv->base = devm_ioremap(dev, base, PAGE_SIZE);
-	if (!priv->base)
-		return -ENOMEM;
-
-	mutex_init(&priv->mutex);
-
-	for (i = 0; i < IPUV3_NUM_FLOWS; i++) {
-		priv->flow[i].foreground.foreground = true;
-		priv->flow[i].base = priv->base + ipu_dp_flow_base[i];
-		priv->flow[i].priv = priv;
-	}
-
-	return 0;
-}
-
-void ipu_dp_exit(struct ipu_soc *ipu)
-{
-}
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-prv.h b/drivers/staging/imx-drm/ipu-v3/ipu-prv.h
deleted file mode 100644
index bfc1b33..0000000
--- a/drivers/staging/imx-drm/ipu-v3/ipu-prv.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (c) 2010 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-#ifndef __IPU_PRV_H__
-#define __IPU_PRV_H__
-
-struct ipu_soc;
-
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-
-#include "imx-ipu-v3.h"
-
-#define IPUV3_CHANNEL_CSI0			 0
-#define IPUV3_CHANNEL_CSI1			 1
-#define IPUV3_CHANNEL_CSI2			 2
-#define IPUV3_CHANNEL_CSI3			 3
-#define IPUV3_CHANNEL_MEM_BG_SYNC		23
-#define IPUV3_CHANNEL_MEM_FG_SYNC		27
-#define IPUV3_CHANNEL_MEM_DC_SYNC		28
-#define IPUV3_CHANNEL_MEM_FG_SYNC_ALPHA		31
-#define IPUV3_CHANNEL_MEM_DC_ASYNC		41
-#define IPUV3_CHANNEL_ROT_ENC_MEM		45
-#define IPUV3_CHANNEL_ROT_VF_MEM		46
-#define IPUV3_CHANNEL_ROT_PP_MEM		47
-#define IPUV3_CHANNEL_ROT_ENC_MEM_OUT		48
-#define IPUV3_CHANNEL_ROT_VF_MEM_OUT		49
-#define IPUV3_CHANNEL_ROT_PP_MEM_OUT		50
-#define IPUV3_CHANNEL_MEM_BG_SYNC_ALPHA		51
-
-#define IPU_MCU_T_DEFAULT	8
-#define IPU_CM_IDMAC_REG_OFS	0x00008000
-#define IPU_CM_IC_REG_OFS	0x00020000
-#define IPU_CM_IRT_REG_OFS	0x00028000
-#define IPU_CM_CSI0_REG_OFS	0x00030000
-#define IPU_CM_CSI1_REG_OFS	0x00038000
-#define IPU_CM_SMFC_REG_OFS	0x00050000
-#define IPU_CM_DC_REG_OFS	0x00058000
-#define IPU_CM_DMFC_REG_OFS	0x00060000
-
-/* Register addresses */
-/* IPU Common registers */
-#define IPU_CM_REG(offset)	(offset)
-
-#define IPU_CONF			IPU_CM_REG(0)
-
-#define IPU_SRM_PRI1			IPU_CM_REG(0x00a0)
-#define IPU_SRM_PRI2			IPU_CM_REG(0x00a4)
-#define IPU_FS_PROC_FLOW1		IPU_CM_REG(0x00a8)
-#define IPU_FS_PROC_FLOW2		IPU_CM_REG(0x00ac)
-#define IPU_FS_PROC_FLOW3		IPU_CM_REG(0x00b0)
-#define IPU_FS_DISP_FLOW1		IPU_CM_REG(0x00b4)
-#define IPU_FS_DISP_FLOW2		IPU_CM_REG(0x00b8)
-#define IPU_SKIP			IPU_CM_REG(0x00bc)
-#define IPU_DISP_ALT_CONF		IPU_CM_REG(0x00c0)
-#define IPU_DISP_GEN			IPU_CM_REG(0x00c4)
-#define IPU_DISP_ALT1			IPU_CM_REG(0x00c8)
-#define IPU_DISP_ALT2			IPU_CM_REG(0x00cc)
-#define IPU_DISP_ALT3			IPU_CM_REG(0x00d0)
-#define IPU_DISP_ALT4			IPU_CM_REG(0x00d4)
-#define IPU_SNOOP			IPU_CM_REG(0x00d8)
-#define IPU_MEM_RST			IPU_CM_REG(0x00dc)
-#define IPU_PM				IPU_CM_REG(0x00e0)
-#define IPU_GPR				IPU_CM_REG(0x00e4)
-#define IPU_CHA_DB_MODE_SEL(ch)		IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
-#define IPU_ALT_CHA_DB_MODE_SEL(ch)	IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
-#define IPU_CHA_CUR_BUF(ch)		IPU_CM_REG(0x023C + 4 * ((ch) / 32))
-#define IPU_ALT_CUR_BUF0		IPU_CM_REG(0x0244)
-#define IPU_ALT_CUR_BUF1		IPU_CM_REG(0x0248)
-#define IPU_SRM_STAT			IPU_CM_REG(0x024C)
-#define IPU_PROC_TASK_STAT		IPU_CM_REG(0x0250)
-#define IPU_DISP_TASK_STAT		IPU_CM_REG(0x0254)
-#define IPU_CHA_BUF0_RDY(ch)		IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
-#define IPU_CHA_BUF1_RDY(ch)		IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
-#define IPU_ALT_CHA_BUF0_RDY(ch)	IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
-#define IPU_ALT_CHA_BUF1_RDY(ch)	IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
-
-#define IPU_INT_CTRL(n)		IPU_CM_REG(0x003C + 4 * (n))
-#define IPU_INT_STAT(n)		IPU_CM_REG(0x0200 + 4 * (n))
-
-#define IPU_DI0_COUNTER_RELEASE			(1 << 24)
-#define IPU_DI1_COUNTER_RELEASE			(1 << 25)
-
-#define IPU_IDMAC_REG(offset)	(offset)
-
-#define IDMAC_CONF			IPU_IDMAC_REG(0x0000)
-#define IDMAC_CHA_EN(ch)		IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
-#define IDMAC_SEP_ALPHA			IPU_IDMAC_REG(0x000c)
-#define IDMAC_ALT_SEP_ALPHA		IPU_IDMAC_REG(0x0010)
-#define IDMAC_CHA_PRI(ch)		IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
-#define IDMAC_WM_EN(ch)			IPU_IDMAC_REG(0x001c + 4 * ((ch) / 32))
-#define IDMAC_CH_LOCK_EN_1		IPU_IDMAC_REG(0x0024)
-#define IDMAC_CH_LOCK_EN_2		IPU_IDMAC_REG(0x0028)
-#define IDMAC_SUB_ADDR_0		IPU_IDMAC_REG(0x002c)
-#define IDMAC_SUB_ADDR_1		IPU_IDMAC_REG(0x0030)
-#define IDMAC_SUB_ADDR_2		IPU_IDMAC_REG(0x0034)
-#define IDMAC_BAND_EN(ch)		IPU_IDMAC_REG(0x0040 + 4 * ((ch) / 32))
-#define IDMAC_CHA_BUSY(ch)		IPU_IDMAC_REG(0x0100 + 4 * ((ch) / 32))
-
-#define IPU_NUM_IRQS	(32 * 15)
-
-enum ipu_modules {
-	IPU_CONF_CSI0_EN		= (1 << 0),
-	IPU_CONF_CSI1_EN		= (1 << 1),
-	IPU_CONF_IC_EN			= (1 << 2),
-	IPU_CONF_ROT_EN			= (1 << 3),
-	IPU_CONF_ISP_EN			= (1 << 4),
-	IPU_CONF_DP_EN			= (1 << 5),
-	IPU_CONF_DI0_EN			= (1 << 6),
-	IPU_CONF_DI1_EN			= (1 << 7),
-	IPU_CONF_SMFC_EN		= (1 << 8),
-	IPU_CONF_DC_EN			= (1 << 9),
-	IPU_CONF_DMFC_EN		= (1 << 10),
-
-	IPU_CONF_VDI_EN			= (1 << 12),
-
-	IPU_CONF_IDMAC_DIS		= (1 << 22),
-
-	IPU_CONF_IC_DMFC_SEL		= (1 << 25),
-	IPU_CONF_IC_DMFC_SYNC		= (1 << 26),
-	IPU_CONF_VDI_DMFC_SYNC		= (1 << 27),
-
-	IPU_CONF_CSI0_DATA_SOURCE	= (1 << 28),
-	IPU_CONF_CSI1_DATA_SOURCE	= (1 << 29),
-	IPU_CONF_IC_INPUT		= (1 << 30),
-	IPU_CONF_CSI_SEL		= (1 << 31),
-};
-
-struct ipuv3_channel {
-	unsigned int num;
-
-	bool enabled;
-	bool busy;
-
-	struct ipu_soc *ipu;
-};
-
-struct ipu_dc_priv;
-struct ipu_dmfc_priv;
-struct ipu_di;
-struct ipu_devtype;
-
-struct ipu_soc {
-	struct device		*dev;
-	const struct ipu_devtype	*devtype;
-	enum ipuv3_type		ipu_type;
-	spinlock_t		lock;
-	struct mutex		channel_lock;
-
-	void __iomem		*cm_reg;
-	void __iomem		*idmac_reg;
-	struct ipu_ch_param __iomem	*cpmem_base;
-
-	int			usecount;
-
-	struct clk		*clk;
-
-	struct ipuv3_channel	channel[64];
-
-	int			irq_sync;
-	int			irq_err;
-	struct irq_domain	*domain;
-
-	struct ipu_dc_priv	*dc_priv;
-	struct ipu_dp_priv	*dp_priv;
-	struct ipu_dmfc_priv	*dmfc_priv;
-	struct ipu_di		*di_priv[2];
-};
-
-void ipu_srm_dp_sync_update(struct ipu_soc *ipu);
-
-int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
-int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
-
-bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
-int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms);
-
-int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
-		unsigned long base, u32 module, struct clk *ipu_clk);
-void ipu_di_exit(struct ipu_soc *ipu, int id);
-
-int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
-		struct clk *ipu_clk);
-void ipu_dmfc_exit(struct ipu_soc *ipu);
-
-int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
-void ipu_dp_exit(struct ipu_soc *ipu);
-
-int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
-		unsigned long template_base);
-void ipu_dc_exit(struct ipu_soc *ipu);
-
-int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
-void ipu_cpmem_exit(struct ipu_soc *ipu);
-
-#endif				/* __IPU_PRV_H__ */
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index 47bec5e..720868b 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -30,7 +30,7 @@
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 
-#include "ipu-v3/imx-ipu-v3.h"
+#include <video/imx-ipu-v3.h>
 #include "imx-drm.h"
 #include "ipuv3-plane.h"
 
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c
index 5697e59..6f393a1 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -17,7 +17,7 @@
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 
-#include "ipu-v3/imx-ipu-v3.h"
+#include "video/imx-ipu-v3.h"
 #include "ipuv3-plane.h"
 
 #define to_ipu_plane(x)	container_of(x, struct ipu_plane, base)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index c7b4f0f..8bf495f 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -20,6 +20,7 @@ source "drivers/char/agp/Kconfig"
 source "drivers/gpu/vga/Kconfig"
 
 source "drivers/gpu/host1x/Kconfig"
+source "drivers/gpu/ipu-v3/Kconfig"
 
 menu "Direct Rendering Manager"
 source "drivers/gpu/drm/Kconfig"
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
new file mode 100644
index 0000000..c2c6fab
--- /dev/null
+++ b/include/video/imx-ipu-v3.h
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU Lesser General
+ * Public License.  You may obtain a copy of the GNU Lesser General
+ * Public License Version 2.1 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/lgpl-license.html
+ * http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#ifndef __DRM_IPU_H__
+#define __DRM_IPU_H__
+
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <linux/bitmap.h>
+#include <linux/fb.h>
+
+struct ipu_soc;
+
+enum ipuv3_type {
+	IPUV3EX,
+	IPUV3M,
+	IPUV3H,
+};
+
+#define IPU_PIX_FMT_GBR24	v4l2_fourcc('G', 'B', 'R', '3')
+
+/*
+ * Bitfield of Display Interface signal polarities.
+ */
+struct ipu_di_signal_cfg {
+	unsigned datamask_en:1;
+	unsigned interlaced:1;
+	unsigned odd_field_first:1;
+	unsigned clksel_en:1;
+	unsigned clkidle_en:1;
+	unsigned data_pol:1;	/* true = inverted */
+	unsigned clk_pol:1;	/* true = rising edge */
+	unsigned enable_pol:1;
+	unsigned Hsync_pol:1;	/* true = active high */
+	unsigned Vsync_pol:1;
+
+	u16 width;
+	u16 height;
+	u32 pixel_fmt;
+	u16 h_start_width;
+	u16 h_sync_width;
+	u16 h_end_width;
+	u16 v_start_width;
+	u16 v_sync_width;
+	u16 v_end_width;
+	u32 v_to_h_sync;
+	unsigned long pixelclock;
+#define IPU_DI_CLKMODE_SYNC	(1 << 0)
+#define IPU_DI_CLKMODE_EXT	(1 << 1)
+	unsigned long clkflags;
+
+	u8 hsync_pin;
+	u8 vsync_pin;
+};
+
+enum ipu_color_space {
+	IPUV3_COLORSPACE_RGB,
+	IPUV3_COLORSPACE_YUV,
+	IPUV3_COLORSPACE_UNKNOWN,
+};
+
+struct ipuv3_channel;
+
+enum ipu_channel_irq {
+	IPU_IRQ_EOF = 0,
+	IPU_IRQ_NFACK = 64,
+	IPU_IRQ_NFB4EOF = 128,
+	IPU_IRQ_EOS = 192,
+};
+
+int ipu_map_irq(struct ipu_soc *ipu, int irq);
+int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
+		enum ipu_channel_irq irq);
+
+#define IPU_IRQ_DP_SF_START		(448 + 2)
+#define IPU_IRQ_DP_SF_END		(448 + 3)
+#define IPU_IRQ_BG_SF_END		IPU_IRQ_DP_SF_END,
+#define IPU_IRQ_DC_FC_0			(448 + 8)
+#define IPU_IRQ_DC_FC_1			(448 + 9)
+#define IPU_IRQ_DC_FC_2			(448 + 10)
+#define IPU_IRQ_DC_FC_3			(448 + 11)
+#define IPU_IRQ_DC_FC_4			(448 + 12)
+#define IPU_IRQ_DC_FC_6			(448 + 13)
+#define IPU_IRQ_VSYNC_PRE_0		(448 + 14)
+#define IPU_IRQ_VSYNC_PRE_1		(448 + 15)
+
+/*
+ * IPU Image DMA Controller (idmac) functions
+ */
+struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned channel);
+void ipu_idmac_put(struct ipuv3_channel *);
+
+int ipu_idmac_enable_channel(struct ipuv3_channel *channel);
+int ipu_idmac_disable_channel(struct ipuv3_channel *channel);
+int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms);
+
+void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
+		bool doublebuffer);
+void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num);
+
+/*
+ * IPU Display Controller (dc) functions
+ */
+struct ipu_dc;
+struct ipu_di;
+struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel);
+void ipu_dc_put(struct ipu_dc *dc);
+int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
+		u32 pixel_fmt, u32 width);
+void ipu_dc_enable(struct ipu_soc *ipu);
+void ipu_dc_enable_channel(struct ipu_dc *dc);
+void ipu_dc_disable_channel(struct ipu_dc *dc);
+void ipu_dc_disable(struct ipu_soc *ipu);
+
+/*
+ * IPU Display Interface (di) functions
+ */
+struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp);
+void ipu_di_put(struct ipu_di *);
+int ipu_di_disable(struct ipu_di *);
+int ipu_di_enable(struct ipu_di *);
+int ipu_di_get_num(struct ipu_di *);
+int ipu_di_init_sync_panel(struct ipu_di *, struct ipu_di_signal_cfg *sig);
+
+/*
+ * IPU Display Multi FIFO Controller (dmfc) functions
+ */
+struct dmfc_channel;
+int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc);
+void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc);
+int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
+		unsigned long bandwidth_mbs, int burstsize);
+void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc);
+int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width);
+struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipuv3_channel);
+void ipu_dmfc_put(struct dmfc_channel *dmfc);
+
+/*
+ * IPU Display Processor (dp) functions
+ */
+#define IPU_DP_FLOW_SYNC_BG	0
+#define IPU_DP_FLOW_SYNC_FG	1
+#define IPU_DP_FLOW_ASYNC0_BG	2
+#define IPU_DP_FLOW_ASYNC0_FG	3
+#define IPU_DP_FLOW_ASYNC1_BG	4
+#define IPU_DP_FLOW_ASYNC1_FG	5
+
+struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow);
+void ipu_dp_put(struct ipu_dp *);
+int ipu_dp_enable(struct ipu_soc *ipu);
+int ipu_dp_enable_channel(struct ipu_dp *dp);
+void ipu_dp_disable_channel(struct ipu_dp *dp);
+void ipu_dp_disable(struct ipu_soc *ipu);
+int ipu_dp_setup_channel(struct ipu_dp *dp,
+		enum ipu_color_space in, enum ipu_color_space out);
+int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos);
+int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha,
+		bool bg_chan);
+
+#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
+
+#define IPU_FIELD_UBO		IPU_CPMEM_WORD(0, 46, 22)
+#define IPU_FIELD_VBO		IPU_CPMEM_WORD(0, 68, 22)
+#define IPU_FIELD_IOX		IPU_CPMEM_WORD(0, 90, 4)
+#define IPU_FIELD_RDRW		IPU_CPMEM_WORD(0, 94, 1)
+#define IPU_FIELD_SO		IPU_CPMEM_WORD(0, 113, 1)
+#define IPU_FIELD_SLY		IPU_CPMEM_WORD(1, 102, 14)
+#define IPU_FIELD_SLUV		IPU_CPMEM_WORD(1, 128, 14)
+
+#define IPU_FIELD_XV		IPU_CPMEM_WORD(0, 0, 10)
+#define IPU_FIELD_YV		IPU_CPMEM_WORD(0, 10, 9)
+#define IPU_FIELD_XB		IPU_CPMEM_WORD(0, 19, 13)
+#define IPU_FIELD_YB		IPU_CPMEM_WORD(0, 32, 12)
+#define IPU_FIELD_NSB_B		IPU_CPMEM_WORD(0, 44, 1)
+#define IPU_FIELD_CF		IPU_CPMEM_WORD(0, 45, 1)
+#define IPU_FIELD_SX		IPU_CPMEM_WORD(0, 46, 12)
+#define IPU_FIELD_SY		IPU_CPMEM_WORD(0, 58, 11)
+#define IPU_FIELD_NS		IPU_CPMEM_WORD(0, 69, 10)
+#define IPU_FIELD_SDX		IPU_CPMEM_WORD(0, 79, 7)
+#define IPU_FIELD_SM		IPU_CPMEM_WORD(0, 86, 10)
+#define IPU_FIELD_SCC		IPU_CPMEM_WORD(0, 96, 1)
+#define IPU_FIELD_SCE		IPU_CPMEM_WORD(0, 97, 1)
+#define IPU_FIELD_SDY		IPU_CPMEM_WORD(0, 98, 7)
+#define IPU_FIELD_SDRX		IPU_CPMEM_WORD(0, 105, 1)
+#define IPU_FIELD_SDRY		IPU_CPMEM_WORD(0, 106, 1)
+#define IPU_FIELD_BPP		IPU_CPMEM_WORD(0, 107, 3)
+#define IPU_FIELD_DEC_SEL	IPU_CPMEM_WORD(0, 110, 2)
+#define IPU_FIELD_DIM		IPU_CPMEM_WORD(0, 112, 1)
+#define IPU_FIELD_BNDM		IPU_CPMEM_WORD(0, 114, 3)
+#define IPU_FIELD_BM		IPU_CPMEM_WORD(0, 117, 2)
+#define IPU_FIELD_ROT		IPU_CPMEM_WORD(0, 119, 1)
+#define IPU_FIELD_HF		IPU_CPMEM_WORD(0, 120, 1)
+#define IPU_FIELD_VF		IPU_CPMEM_WORD(0, 121, 1)
+#define IPU_FIELD_THE		IPU_CPMEM_WORD(0, 122, 1)
+#define IPU_FIELD_CAP		IPU_CPMEM_WORD(0, 123, 1)
+#define IPU_FIELD_CAE		IPU_CPMEM_WORD(0, 124, 1)
+#define IPU_FIELD_FW		IPU_CPMEM_WORD(0, 125, 13)
+#define IPU_FIELD_FH		IPU_CPMEM_WORD(0, 138, 12)
+#define IPU_FIELD_EBA0		IPU_CPMEM_WORD(1, 0, 29)
+#define IPU_FIELD_EBA1		IPU_CPMEM_WORD(1, 29, 29)
+#define IPU_FIELD_ILO		IPU_CPMEM_WORD(1, 58, 20)
+#define IPU_FIELD_NPB		IPU_CPMEM_WORD(1, 78, 7)
+#define IPU_FIELD_PFS		IPU_CPMEM_WORD(1, 85, 4)
+#define IPU_FIELD_ALU		IPU_CPMEM_WORD(1, 89, 1)
+#define IPU_FIELD_ALBM		IPU_CPMEM_WORD(1, 90, 3)
+#define IPU_FIELD_ID		IPU_CPMEM_WORD(1, 93, 2)
+#define IPU_FIELD_TH		IPU_CPMEM_WORD(1, 95, 7)
+#define IPU_FIELD_SL		IPU_CPMEM_WORD(1, 102, 14)
+#define IPU_FIELD_WID0		IPU_CPMEM_WORD(1, 116, 3)
+#define IPU_FIELD_WID1		IPU_CPMEM_WORD(1, 119, 3)
+#define IPU_FIELD_WID2		IPU_CPMEM_WORD(1, 122, 3)
+#define IPU_FIELD_WID3		IPU_CPMEM_WORD(1, 125, 3)
+#define IPU_FIELD_OFS0		IPU_CPMEM_WORD(1, 128, 5)
+#define IPU_FIELD_OFS1		IPU_CPMEM_WORD(1, 133, 5)
+#define IPU_FIELD_OFS2		IPU_CPMEM_WORD(1, 138, 5)
+#define IPU_FIELD_OFS3		IPU_CPMEM_WORD(1, 143, 5)
+#define IPU_FIELD_SXYS		IPU_CPMEM_WORD(1, 148, 1)
+#define IPU_FIELD_CRE		IPU_CPMEM_WORD(1, 149, 1)
+#define IPU_FIELD_DEC_SEL2	IPU_CPMEM_WORD(1, 150, 1)
+
+struct ipu_cpmem_word {
+	u32 data[5];
+	u32 res[3];
+};
+
+struct ipu_ch_param {
+	struct ipu_cpmem_word word[2];
+};
+
+void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 v);
+u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs);
+struct ipu_ch_param __iomem *ipu_get_cpmem(struct ipuv3_channel *channel);
+void ipu_ch_param_dump(struct ipu_ch_param __iomem *p);
+
+static inline void ipu_ch_param_zero(struct ipu_ch_param __iomem *p)
+{
+	int i;
+	void __iomem *base = p;
+
+	for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
+		writel(0, base + i * sizeof(u32));
+}
+
+static inline void ipu_cpmem_set_buffer(struct ipu_ch_param __iomem *p,
+		int bufnum, dma_addr_t buf)
+{
+	if (bufnum)
+		ipu_ch_param_write_field(p, IPU_FIELD_EBA1, buf >> 3);
+	else
+		ipu_ch_param_write_field(p, IPU_FIELD_EBA0, buf >> 3);
+}
+
+static inline void ipu_cpmem_set_resolution(struct ipu_ch_param __iomem *p,
+		int xres, int yres)
+{
+	ipu_ch_param_write_field(p, IPU_FIELD_FW, xres - 1);
+	ipu_ch_param_write_field(p, IPU_FIELD_FH, yres - 1);
+}
+
+static inline void ipu_cpmem_set_stride(struct ipu_ch_param __iomem *p,
+		int stride)
+{
+	ipu_ch_param_write_field(p, IPU_FIELD_SLY, stride - 1);
+}
+
+void ipu_cpmem_set_high_priority(struct ipuv3_channel *channel);
+
+struct ipu_rgb {
+	struct fb_bitfield	red;
+	struct fb_bitfield	green;
+	struct fb_bitfield	blue;
+	struct fb_bitfield	transp;
+	int			bits_per_pixel;
+};
+
+struct ipu_image {
+	struct v4l2_pix_format pix;
+	struct v4l2_rect rect;
+	dma_addr_t phys;
+};
+
+int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p,
+		int width);
+
+int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *,
+		const struct ipu_rgb *rgb);
+
+static inline void ipu_cpmem_interlaced_scan(struct ipu_ch_param *p,
+		int stride)
+{
+	ipu_ch_param_write_field(p, IPU_FIELD_SO, 1);
+	ipu_ch_param_write_field(p, IPU_FIELD_ILO, stride / 8);
+	ipu_ch_param_write_field(p, IPU_FIELD_SLY, (stride * 2) - 1);
+};
+
+void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format,
+			int stride, int height);
+void ipu_cpmem_set_yuv_interleaved(struct ipu_ch_param __iomem *p,
+				   u32 pixel_format);
+void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p,
+		u32 pixel_format, int stride, int u_offset, int v_offset);
+int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat);
+int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem,
+		struct ipu_image *image);
+
+enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc);
+enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat);
+
+static inline void ipu_cpmem_set_burstsize(struct ipu_ch_param __iomem *p,
+		int burstsize)
+{
+	ipu_ch_param_write_field(p, IPU_FIELD_NPB, burstsize - 1);
+};
+
+struct ipu_client_platformdata {
+	int di;
+	int dc;
+	int dp;
+	int dmfc;
+	int dma[2];
+};
+
+#endif /* __DRM_IPU_H__ */
-- 
2.0.0.rc2


_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel




[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux