All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/11] i.MX RGB565, plane and PRIME support
@ 2013-10-10 14:18 Philipp Zabel
  2013-10-10 14:18 ` [PATCH 01/11] staging: drm/imx: also allow to allocate only 2 DMFC slots for DP full plane Philipp Zabel
                   ` (11 more replies)
  0 siblings, 12 replies; 14+ messages in thread
From: Philipp Zabel @ 2013-10-10 14:18 UTC (permalink / raw)
  To: dri-devel
  Cc: devel, Fabio Estevam, David Airlie, Greg Kroah-Hartman, kernel,
	Shawn Guo

Hi,

This series fixes DMFC allocation for small displays and pageflip events
during device close, clarifies the RGB memory formats, adds support for the
RGB565 format and KMS planes, and enables DRM PRIME using the CMA helpers.

In the next step, I would like to move the code
from drivers/staging/imx-drm/ipu-v3 to drivers/gpu/ipu-v3 (right next to
host1x), as these parts provide an internal API for the IPU modules to be
used by both DRM and V4L2 drivers.

regards
Philipp

---
 drivers/staging/imx-drm/Makefile            |   2 +-
 drivers/staging/imx-drm/TODO                |   1 -
 drivers/staging/imx-drm/imx-drm-core.c      |  29 ++-
 drivers/staging/imx-drm/imx-drm.h           |   2 +
 drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h |   4 +-
 drivers/staging/imx-drm/ipu-v3/ipu-common.c | 169 ++++++++++---
 drivers/staging/imx-drm/ipu-v3/ipu-dc.c     |   9 +
 drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c   |   8 +-
 drivers/staging/imx-drm/ipuv3-crtc.c        | 209 ++++------------
 drivers/staging/imx-drm/ipuv3-plane.c       | 375 ++++++++++++++++++++++++++++
 drivers/staging/imx-drm/ipuv3-plane.h       |  55 ++++
 11 files changed, 655 insertions(+), 208 deletions(-)

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 01/11] staging: drm/imx: also allow to allocate only 2 DMFC slots for DP full plane
  2013-10-10 14:18 [PATCH 0/11] i.MX RGB565, plane and PRIME support Philipp Zabel
@ 2013-10-10 14:18 ` Philipp Zabel
  2013-10-11  7:12   ` Liu Ying
  2013-10-10 14:18 ` [PATCH 02/11] staging: drm/imx: make struct ipu_rgb format definitions const Philipp Zabel
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 14+ messages in thread
From: Philipp Zabel @ 2013-10-10 14:18 UTC (permalink / raw)
  To: dri-devel
  Cc: devel, Fabio Estevam, Philipp Zabel, David Airlie,
	Greg Kroah-Hartman, kernel, Shawn Guo

Connecting a 320x240 parallel display on i.MX6 resulted in an invalid DRDY
signal because the DC would not receive NL/EOL events on every line.
Reducing the allocated DMFC space from 4 slots (256 * 128-bit) to 2 slots
(128 * 128-bit) solved the problem.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
index 2e97c33..98070dd 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
@@ -307,13 +307,13 @@ int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
 		goto out;
 	}
 
-	/* Always allocate at least 128*4 bytes (2 slots) */
-	if (slots < 2)
-		slots = 2;
-
 	/* 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
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 02/11] staging: drm/imx: make struct ipu_rgb format definitions const
  2013-10-10 14:18 [PATCH 0/11] i.MX RGB565, plane and PRIME support Philipp Zabel
  2013-10-10 14:18 ` [PATCH 01/11] staging: drm/imx: also allow to allocate only 2 DMFC slots for DP full plane Philipp Zabel
@ 2013-10-10 14:18 ` Philipp Zabel
  2013-10-10 14:18 ` [PATCH 03/11] staging: drm/imx: fix RGB formats, make ipu_cpmem_set_fmt take a drm_fourcc Philipp Zabel
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Philipp Zabel @ 2013-10-10 14:18 UTC (permalink / raw)
  To: dri-devel
  Cc: devel, Fabio Estevam, Philipp Zabel, David Airlie,
	Greg Kroah-Hartman, kernel, Shawn Guo

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h |  2 +-
 drivers/staging/imx-drm/ipu-v3/ipu-common.c | 12 ++++++------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
index 74c022e..872cf62 100644
--- a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
+++ b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
@@ -283,7 +283,7 @@ 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 *,
-		struct ipu_rgb *rgb);
+		const struct ipu_rgb *rgb);
 
 static inline void ipu_cpmem_interlaced_scan(struct ipu_ch_param *p,
 		int stride)
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
index ba464e5..8abd215 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
@@ -139,7 +139,7 @@ u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs)
 EXPORT_SYMBOL_GPL(ipu_ch_param_read_field);
 
 int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *p,
-		struct ipu_rgb *rgb)
+		const struct ipu_rgb *rgb)
 {
 	int bpp = 0, npb = 0, ro, go, bo, to;
 
@@ -282,7 +282,7 @@ void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format,
 }
 EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar);
 
-static struct ipu_rgb def_rgb_32 = {
+static const struct ipu_rgb def_rgb_32 = {
 	.red	= { .offset = 16, .length = 8, },
 	.green	= { .offset =  8, .length = 8, },
 	.blue	= { .offset =  0, .length = 8, },
@@ -290,7 +290,7 @@ static struct ipu_rgb def_rgb_32 = {
 	.bits_per_pixel = 32,
 };
 
-static struct ipu_rgb def_bgr_32 = {
+static const struct ipu_rgb def_bgr_32 = {
 	.red	= { .offset = 16, .length = 8, },
 	.green	= { .offset =  8, .length = 8, },
 	.blue	= { .offset =  0, .length = 8, },
@@ -298,7 +298,7 @@ static struct ipu_rgb def_bgr_32 = {
 	.bits_per_pixel = 32,
 };
 
-static struct ipu_rgb def_rgb_24 = {
+static const struct ipu_rgb def_rgb_24 = {
 	.red	= { .offset =  0, .length = 8, },
 	.green	= { .offset =  8, .length = 8, },
 	.blue	= { .offset = 16, .length = 8, },
@@ -306,7 +306,7 @@ static struct ipu_rgb def_rgb_24 = {
 	.bits_per_pixel = 24,
 };
 
-static struct ipu_rgb def_bgr_24 = {
+static const struct ipu_rgb def_bgr_24 = {
 	.red	= { .offset = 16, .length = 8, },
 	.green	= { .offset =  8, .length = 8, },
 	.blue	= { .offset =  0, .length = 8, },
@@ -314,7 +314,7 @@ static struct ipu_rgb def_bgr_24 = {
 	.bits_per_pixel = 24,
 };
 
-static struct ipu_rgb def_rgb_16 = {
+static const struct ipu_rgb def_rgb_16 = {
 	.red	= { .offset = 11, .length = 5, },
 	.green	= { .offset =  5, .length = 6, },
 	.blue	= { .offset =  0, .length = 5, },
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 03/11] staging: drm/imx: fix RGB formats, make ipu_cpmem_set_fmt take a drm_fourcc
  2013-10-10 14:18 [PATCH 0/11] i.MX RGB565, plane and PRIME support Philipp Zabel
  2013-10-10 14:18 ` [PATCH 01/11] staging: drm/imx: also allow to allocate only 2 DMFC slots for DP full plane Philipp Zabel
  2013-10-10 14:18 ` [PATCH 02/11] staging: drm/imx: make struct ipu_rgb format definitions const Philipp Zabel
@ 2013-10-10 14:18 ` Philipp Zabel
  2013-10-10 14:18 ` [PATCH 04/11] staging: drm/imx: add BGR565 format Philipp Zabel
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Philipp Zabel @ 2013-10-10 14:18 UTC (permalink / raw)
  To: dri-devel
  Cc: devel, Fabio Estevam, Philipp Zabel, David Airlie,
	Greg Kroah-Hartman, kernel, Shawn Guo

The drm fourccs define formats not available as video4linux pixel formats,
such as DRM_FORMAT_BGR565, or the DRM_FORMAT_RGBX/BGRX variants.
Also, contrary to the v4l2 formats, the drm formats are well defined.

This patch also fixes the BGRA32 and RGB/RGB24 internal formats to use a
common internal representation.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h |   1 +
 drivers/staging/imx-drm/ipu-v3/ipu-common.c | 121 +++++++++++++++++++++++-----
 2 files changed, 100 insertions(+), 22 deletions(-)

diff --git a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
index 872cf62..9bee640 100644
--- a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
+++ b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
@@ -303,6 +303,7 @@ 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,
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
index 8abd215..54466df 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
@@ -30,6 +30,8 @@
 #include <linux/irqdomain.h>
 #include <linux/of_device.h>
 
+#include <drm/drm_fourcc.h>
+
 #include "imx-ipu-v3.h"
 #include "ipu-prv.h"
 
@@ -291,25 +293,25 @@ static const struct ipu_rgb def_rgb_32 = {
 };
 
 static const struct ipu_rgb def_bgr_32 = {
-	.red	= { .offset = 16, .length = 8, },
+	.red	= { .offset =  0, .length = 8, },
 	.green	= { .offset =  8, .length = 8, },
-	.blue	= { .offset =  0, .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 =  0, .length = 8, },
+	.red	= { .offset = 16, .length = 8, },
 	.green	= { .offset =  8, .length = 8, },
-	.blue	= { .offset = 16, .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 = 16, .length = 8, },
+	.red	= { .offset =  0, .length = 8, },
 	.green	= { .offset =  8, .length = 8, },
-	.blue	= { .offset =  0, .length = 8, },
+	.blue	= { .offset = 16, .length = 8, },
 	.transp = { .offset =  0, .length = 0, },
 	.bits_per_pixel = 24,
 };
@@ -329,17 +331,17 @@ static const struct ipu_rgb def_rgb_16 = {
 					(pix->width * pix->height / 4) + \
 					(pix->width * (y) / 4) + (x) / 2)
 
-int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat)
+int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 drm_fourcc)
 {
-	switch (pixelformat) {
-	case V4L2_PIX_FMT_YUV420:
-	case V4L2_PIX_FMT_YVU420:
+	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 V4L2_PIX_FMT_UYVY:
+	case DRM_FORMAT_UYVY:
 		/* bits/pixel */
 		ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3);
 		/* pix format */
@@ -347,7 +349,7 @@ int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat)
 		/* burst size */
 		ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31);
 		break;
-	case V4L2_PIX_FMT_YUYV:
+	case DRM_FORMAT_YUYV:
 		/* bits/pixel */
 		ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3);
 		/* pix format */
@@ -355,20 +357,22 @@ int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat)
 		/* burst size */
 		ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31);
 		break;
-	case V4L2_PIX_FMT_RGB32:
-		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32);
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_XBGR8888:
+		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_32);
 		break;
-	case V4L2_PIX_FMT_RGB565:
-		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_16);
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XRGB8888:
+		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32);
 		break;
-	case V4L2_PIX_FMT_BGR32:
-		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_32);
+	case DRM_FORMAT_BGR888:
+		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_24);
 		break;
-	case V4L2_PIX_FMT_RGB24:
+	case DRM_FORMAT_RGB888:
 		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_24);
 		break;
-	case V4L2_PIX_FMT_BGR24:
-		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_24);
+	case DRM_FORMAT_RGB565:
+		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_16);
 		break;
 	default:
 		return -EINVAL;
@@ -378,6 +382,79 @@ int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat)
 }
 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)
 {
@@ -392,7 +469,7 @@ int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem,
 			image->rect.height);
 	ipu_cpmem_set_stride(cpmem, pix->bytesperline);
 
-	ipu_cpmem_set_fmt(cpmem, pix->pixelformat);
+	ipu_cpmem_set_fmt(cpmem, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
 
 	switch (pix->pixelformat) {
 	case V4L2_PIX_FMT_YUV420:
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 04/11] staging: drm/imx: add BGR565 format
  2013-10-10 14:18 [PATCH 0/11] i.MX RGB565, plane and PRIME support Philipp Zabel
                   ` (2 preceding siblings ...)
  2013-10-10 14:18 ` [PATCH 03/11] staging: drm/imx: fix RGB formats, make ipu_cpmem_set_fmt take a drm_fourcc Philipp Zabel
@ 2013-10-10 14:18 ` Philipp Zabel
  2013-10-10 14:18 ` [PATCH 05/11] staging: drm/imx: Add 24-bit BGR support to DC Philipp Zabel
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Philipp Zabel @ 2013-10-10 14:18 UTC (permalink / raw)
  To: dri-devel
  Cc: devel, Fabio Estevam, Philipp Zabel, David Airlie,
	Greg Kroah-Hartman, kernel, Shawn Guo

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/staging/imx-drm/ipu-v3/ipu-common.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
index 54466df..f90bdb4 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
@@ -324,6 +324,14 @@ static const struct ipu_rgb def_rgb_16 = {
 	.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)
@@ -374,6 +382,9 @@ int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 drm_fourcc)
 	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;
 	}
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 05/11] staging: drm/imx: Add 24-bit BGR support to DC
  2013-10-10 14:18 [PATCH 0/11] i.MX RGB565, plane and PRIME support Philipp Zabel
                   ` (3 preceding siblings ...)
  2013-10-10 14:18 ` [PATCH 04/11] staging: drm/imx: add BGR565 format Philipp Zabel
@ 2013-10-10 14:18 ` Philipp Zabel
  2013-10-10 14:18 ` [PATCH 06/11] staging: drm/imx: make waiting for idle channel optional Philipp Zabel
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Philipp Zabel @ 2013-10-10 14:18 UTC (permalink / raw)
  To: dri-devel
  Cc: devel, Fabio Estevam, Philipp Zabel, David Airlie,
	Greg Kroah-Hartman, kernel, Shawn Guo

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/staging/imx-drm/ipu-v3/ipu-dc.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
index 21bf1c8..1a6e06d 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
@@ -91,6 +91,7 @@ enum ipu_dc_map {
 	IPU_DC_MAP_RGB565,
 	IPU_DC_MAP_GBR24, /* TVEv2 */
 	IPU_DC_MAP_BGR666,
+	IPU_DC_MAP_BGR24,
 };
 
 struct ipu_dc {
@@ -152,6 +153,8 @@ static int ipu_pixfmt_to_map(u32 fmt)
 		return IPU_DC_MAP_GBR24;
 	case V4L2_PIX_FMT_BGR666:
 		return IPU_DC_MAP_BGR666;
+	case V4L2_PIX_FMT_BGR24:
+		return IPU_DC_MAP_BGR24;
 	default:
 		return -EINVAL;
 	}
@@ -395,6 +398,12 @@ int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
 	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 */
 
+	/* 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;
 }
 
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 06/11] staging: drm/imx: make waiting for idle channel optional
  2013-10-10 14:18 [PATCH 0/11] i.MX RGB565, plane and PRIME support Philipp Zabel
                   ` (4 preceding siblings ...)
  2013-10-10 14:18 ` [PATCH 05/11] staging: drm/imx: Add 24-bit BGR support to DC Philipp Zabel
@ 2013-10-10 14:18 ` Philipp Zabel
  2013-10-10 14:18 ` [PATCH 07/11] staging: drm-imx: add DRM_FORMAT_BGR888 to ipu crtc driver Philipp Zabel
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Philipp Zabel @ 2013-10-10 14:18 UTC (permalink / raw)
  To: dri-devel
  Cc: devel, Fabio Estevam, Philipp Zabel, David Airlie,
	Greg Kroah-Hartman, Sascha Hauer, kernel, Shawn Guo

From: Sascha Hauer <s.hauer@pengutronix.de>

Currently we wait for a channel until it's idle before actually
disabling it. This is not needed for all channels though, so make
waiting for idle a separate function and call it where necessary.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h |  1 +
 drivers/staging/imx-drm/ipu-v3/ipu-common.c | 23 ++++++++++++++---------
 drivers/staging/imx-drm/ipuv3-crtc.c        |  1 +
 3 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
index 9bee640..4826b5c 100644
--- a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
+++ b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
@@ -97,6 +97,7 @@ 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);
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
index f90bdb4..5ca42f0 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
@@ -698,24 +698,29 @@ int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
 }
 EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
 
-int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
+int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
 {
 	struct ipu_soc *ipu = channel->ipu;
-	u32 val;
-	unsigned long flags;
 	unsigned long timeout;
 
-	timeout = jiffies + msecs_to_jiffies(50);
+	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)) {
-			dev_warn(ipu->dev, "disabling busy idmac channel %d\n",
-					channel->num);
-			break;
-		}
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
 		cpu_relax();
 	}
 
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
+
+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) */
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index 6fd37a7..574633b 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -102,6 +102,7 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
 	if (ipu_crtc->dp)
 		ipu_dp_disable_channel(ipu_crtc->dp);
 	ipu_dc_disable_channel(ipu_crtc->dc);
+	ipu_idmac_wait_busy(ipu_crtc->ipu_ch, 50);
 	ipu_idmac_disable_channel(ipu_crtc->ipu_ch);
 	ipu_dmfc_disable_channel(ipu_crtc->dmfc);
 	ipu_di_disable(ipu_crtc->di);
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 07/11] staging: drm-imx: add DRM_FORMAT_BGR888 to ipu crtc driver
  2013-10-10 14:18 [PATCH 0/11] i.MX RGB565, plane and PRIME support Philipp Zabel
                   ` (5 preceding siblings ...)
  2013-10-10 14:18 ` [PATCH 06/11] staging: drm/imx: make waiting for idle channel optional Philipp Zabel
@ 2013-10-10 14:18 ` Philipp Zabel
  2013-10-10 14:18 ` [PATCH 08/11] staging: drm/imx: ipuv3-crtc: remove unused struct ipu_framebuffer Philipp Zabel
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Philipp Zabel @ 2013-10-10 14:18 UTC (permalink / raw)
  To: dri-devel
  Cc: devel, Fabio Estevam, Philipp Zabel, David Airlie,
	Greg Kroah-Hartman, kernel, Shawn Guo

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/staging/imx-drm/ipuv3-crtc.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index 574633b..f63931b 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -223,6 +223,10 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
 		v4l2_fmt = V4L2_PIX_FMT_RGB24;
 		bpp = 24;
 		break;
+	case DRM_FORMAT_BGR888:
+		v4l2_fmt = V4L2_PIX_FMT_BGR24;
+		bpp = 24;
+		break;
 	default:
 		dev_err(ipu_crtc->dev, "unsupported pixel format 0x%08x\n",
 				fb->pixel_format);
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 08/11] staging: drm/imx: ipuv3-crtc: remove unused struct ipu_framebuffer
  2013-10-10 14:18 [PATCH 0/11] i.MX RGB565, plane and PRIME support Philipp Zabel
                   ` (6 preceding siblings ...)
  2013-10-10 14:18 ` [PATCH 07/11] staging: drm-imx: add DRM_FORMAT_BGR888 to ipu crtc driver Philipp Zabel
@ 2013-10-10 14:18 ` Philipp Zabel
  2013-10-10 14:18 ` [PATCH 09/11] staging: drm/imx: fix pageflip events during device close Philipp Zabel
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Philipp Zabel @ 2013-10-10 14:18 UTC (permalink / raw)
  To: dri-devel
  Cc: devel, Fabio Estevam, Philipp Zabel, David Airlie,
	Greg Kroah-Hartman, kernel, Shawn Guo

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/staging/imx-drm/ipuv3-crtc.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index f63931b..292abea 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -33,13 +33,6 @@
 
 #define DRIVER_DESC		"i.MX IPUv3 Graphics"
 
-struct ipu_framebuffer {
-	struct drm_framebuffer	base;
-	void			*virt;
-	dma_addr_t		phys;
-	size_t			len;
-};
-
 struct ipu_crtc {
 	struct device		*dev;
 	struct drm_crtc		base;
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 09/11] staging: drm/imx: fix pageflip events during device close
  2013-10-10 14:18 [PATCH 0/11] i.MX RGB565, plane and PRIME support Philipp Zabel
                   ` (7 preceding siblings ...)
  2013-10-10 14:18 ` [PATCH 08/11] staging: drm/imx: ipuv3-crtc: remove unused struct ipu_framebuffer Philipp Zabel
@ 2013-10-10 14:18 ` Philipp Zabel
  2013-10-10 14:18 ` [PATCH 10/11] staging: drm/imx: add drm plane support Philipp Zabel
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Philipp Zabel @ 2013-10-10 14:18 UTC (permalink / raw)
  To: dri-devel
  Cc: devel, Fabio Estevam, Philipp Zabel, David Airlie,
	Greg Kroah-Hartman, Sascha Hauer, kernel, Shawn Guo

From: Sascha Hauer <s.hauer@pengutronix.de>

During a device close the drm core frees all pending events in
drm_events_release(). If at that time a pageflip is pending the
interrupt handler will try to complete the now unitialized
event resulting in a NULL pointer exception. Seen on imx-drm
when userspace is killed during a page flip.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/staging/imx-drm/imx-drm-core.c | 13 +++++++++++++
 drivers/staging/imx-drm/ipuv3-crtc.c   |  9 ++-------
 2 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index a2e52a0..c77f9eb 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -191,6 +191,18 @@ static void imx_drm_disable_vblank(struct drm_device *drm, int crtc)
 	imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc);
 }
 
+static void imx_drm_driver_preclose(struct drm_device *drm,
+		struct drm_file *file)
+{
+	int i;
+
+	if (!file->is_master)
+		return;
+
+	for (i = 0; i < 4; i++)
+		imx_drm_disable_vblank(drm , i);
+}
+
 static const struct file_operations imx_drm_driver_fops = {
 	.owner = THIS_MODULE,
 	.open = drm_open,
@@ -778,6 +790,7 @@ static struct drm_driver imx_drm_driver = {
 	.load			= imx_drm_driver_load,
 	.unload			= imx_drm_driver_unload,
 	.lastclose		= imx_drm_driver_lastclose,
+	.preclose		= imx_drm_driver_preclose,
 	.gem_free_object	= drm_gem_cma_free_object,
 	.gem_vm_ops		= &drm_gem_cma_vm_ops,
 	.dumb_create		= drm_gem_cma_dumb_create,
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index 292abea..ae50dd4 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -368,10 +368,6 @@ static struct drm_crtc_helper_funcs ipu_helper_funcs = {
 
 static int ipu_enable_vblank(struct drm_crtc *crtc)
 {
-	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
-
-	enable_irq(ipu_crtc->irq);
-
 	return 0;
 }
 
@@ -379,7 +375,8 @@ static void ipu_disable_vblank(struct drm_crtc *crtc)
 {
 	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
 
-	disable_irq(ipu_crtc->irq);
+	ipu_crtc->page_flip_event = NULL;
+	ipu_crtc->newfb = NULL;
 }
 
 static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
@@ -502,8 +499,6 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
 		goto err_put_resources;
 	}
 
-	disable_irq(ipu_crtc->irq);
-
 	return 0;
 
 err_put_resources:
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 10/11] staging: drm/imx: add drm plane support
  2013-10-10 14:18 [PATCH 0/11] i.MX RGB565, plane and PRIME support Philipp Zabel
                   ` (8 preceding siblings ...)
  2013-10-10 14:18 ` [PATCH 09/11] staging: drm/imx: fix pageflip events during device close Philipp Zabel
@ 2013-10-10 14:18 ` Philipp Zabel
  2013-10-10 14:18 ` [PATCH 11/11] staging: drm/imx: Enable DRM PRIME support Philipp Zabel
  2013-10-11 22:30 ` [PATCH 0/11] i.MX RGB565, plane and " Greg Kroah-Hartman
  11 siblings, 0 replies; 14+ messages in thread
From: Philipp Zabel @ 2013-10-10 14:18 UTC (permalink / raw)
  To: dri-devel
  Cc: devel, Fabio Estevam, Philipp Zabel, David Airlie,
	Greg Kroah-Hartman, kernel, Shawn Guo

This patch adds support for a drm overlay plane on DI0 using the DP.
In principle, the overlay plane could also be used on DI1, but to switch
the overlay plane between display interfaces, the base planes would have
to be exchanged transparently while both display interfaces are inactive.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/staging/imx-drm/Makefile            |   2 +-
 drivers/staging/imx-drm/TODO                |   1 -
 drivers/staging/imx-drm/imx-drm-core.c      |   5 +
 drivers/staging/imx-drm/imx-drm.h           |   2 +
 drivers/staging/imx-drm/ipu-v3/ipu-common.c |   2 +-
 drivers/staging/imx-drm/ipuv3-crtc.c        | 198 ++++-----------
 drivers/staging/imx-drm/ipuv3-plane.c       | 375 ++++++++++++++++++++++++++++
 drivers/staging/imx-drm/ipuv3-plane.h       |  55 ++++
 8 files changed, 484 insertions(+), 156 deletions(-)
 create mode 100644 drivers/staging/imx-drm/ipuv3-plane.c
 create mode 100644 drivers/staging/imx-drm/ipuv3-plane.h

diff --git a/drivers/staging/imx-drm/Makefile b/drivers/staging/imx-drm/Makefile
index bfaf693..2c3a9e1 100644
--- a/drivers/staging/imx-drm/Makefile
+++ b/drivers/staging/imx-drm/Makefile
@@ -8,4 +8,4 @@ obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o
 obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
 obj-$(CONFIG_DRM_IMX_FB_HELPER) += imx-fbdev.o
 obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += ipu-v3/
-obj-$(CONFIG_DRM_IMX_IPUV3)	+= ipuv3-crtc.o
+obj-$(CONFIG_DRM_IMX_IPUV3)	+= ipuv3-crtc.o ipuv3-plane.o
diff --git a/drivers/staging/imx-drm/TODO b/drivers/staging/imx-drm/TODO
index 9cfa2a7..6a9da94 100644
--- a/drivers/staging/imx-drm/TODO
+++ b/drivers/staging/imx-drm/TODO
@@ -9,7 +9,6 @@ TODO:
 
 Missing features (not necessarily for moving out of staging):
 
-- Add KMS plane support for CRTC driver
 - Add i.MX6 HDMI support
 - Add support for IC (Image converter)
 - Add support for CSI (CMOS Sensor interface)
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index c77f9eb..f931c62 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -68,6 +68,11 @@ struct imx_drm_connector {
 	struct module				*owner;
 };
 
+int imx_drm_crtc_id(struct imx_drm_crtc *crtc)
+{
+	return crtc->pipe;
+}
+
 static void imx_drm_driver_lastclose(struct drm_device *drm)
 {
 	struct imx_drm_device *imxdrm = drm->dev_private;
diff --git a/drivers/staging/imx-drm/imx-drm.h b/drivers/staging/imx-drm/imx-drm.h
index f2aac91..ae90c9c 100644
--- a/drivers/staging/imx-drm/imx-drm.h
+++ b/drivers/staging/imx-drm/imx-drm.h
@@ -14,6 +14,8 @@ struct drm_fbdev_cma;
 struct drm_framebuffer;
 struct platform_device;
 
+int imx_drm_crtc_id(struct imx_drm_crtc *crtc);
+
 struct imx_drm_crtc_helper_funcs {
 	int (*enable_vblank)(struct drm_crtc *crtc);
 	void (*disable_vblank)(struct drm_crtc *crtc);
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
index 5ca42f0..a0e7fc2 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
@@ -981,7 +981,7 @@ static const struct ipu_platform_reg client_reg[] = {
 			.dc = 5,
 			.dp = IPU_DP_FLOW_SYNC_BG,
 			.dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
-			.dma[1] = -EINVAL,
+			.dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
 		},
 		.name = "imx-ipuv3-crtc",
 	}, {
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index ae50dd4..f1112df 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -25,11 +25,13 @@
 #include <drm/drm_crtc_helper.h>
 #include <linux/fb.h>
 #include <linux/clk.h>
+#include <linux/errno.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 
 #include "ipu-v3/imx-ipu-v3.h"
 #include "imx-drm.h"
+#include "ipuv3-plane.h"
 
 #define DRIVER_DESC		"i.MX IPUv3 Graphics"
 
@@ -37,10 +39,11 @@ struct ipu_crtc {
 	struct device		*dev;
 	struct drm_crtc		base;
 	struct imx_drm_crtc	*imx_crtc;
-	struct ipuv3_channel	*ipu_ch;
+
+	/* plane[0] is the full plane, plane[1] is the partial plane */
+	struct ipu_plane	*plane[2];
+
 	struct ipu_dc		*dc;
-	struct ipu_dp		*dp;
-	struct dmfc_channel	*dmfc;
 	struct ipu_di		*di;
 	int			enabled;
 	struct drm_pending_vblank_event *page_flip_event;
@@ -54,35 +57,14 @@ struct ipu_crtc {
 
 #define to_ipu_crtc(x) container_of(x, struct ipu_crtc, base)
 
-static int calc_vref(struct drm_display_mode *mode)
-{
-	unsigned long htotal, vtotal;
-
-	htotal = mode->htotal;
-	vtotal = mode->vtotal;
-
-	if (!htotal || !vtotal)
-		return 60;
-
-	return mode->clock * 1000 / vtotal / htotal;
-}
-
-static int calc_bandwidth(struct drm_display_mode *mode, unsigned int vref)
-{
-	return mode->hdisplay * mode->vdisplay * vref;
-}
-
 static void ipu_fb_enable(struct ipu_crtc *ipu_crtc)
 {
 	if (ipu_crtc->enabled)
 		return;
 
 	ipu_di_enable(ipu_crtc->di);
-	ipu_dmfc_enable_channel(ipu_crtc->dmfc);
-	ipu_idmac_enable_channel(ipu_crtc->ipu_ch);
 	ipu_dc_enable_channel(ipu_crtc->dc);
-	if (ipu_crtc->dp)
-		ipu_dp_enable_channel(ipu_crtc->dp);
+	ipu_plane_enable(ipu_crtc->plane[0]);
 
 	ipu_crtc->enabled = 1;
 }
@@ -92,12 +74,8 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
 	if (!ipu_crtc->enabled)
 		return;
 
-	if (ipu_crtc->dp)
-		ipu_dp_disable_channel(ipu_crtc->dp);
+	ipu_plane_disable(ipu_crtc->plane[0]);
 	ipu_dc_disable_channel(ipu_crtc->dc);
-	ipu_idmac_wait_busy(ipu_crtc->ipu_ch, 50);
-	ipu_idmac_disable_channel(ipu_crtc->ipu_ch);
-	ipu_dmfc_disable_channel(ipu_crtc->dmfc);
 	ipu_di_disable(ipu_crtc->di);
 
 	ipu_crtc->enabled = 0;
@@ -153,33 +131,6 @@ static const struct drm_crtc_funcs ipu_crtc_funcs = {
 	.page_flip = ipu_page_flip,
 };
 
-static int ipu_drm_set_base(struct drm_crtc *crtc, int x, int y)
-{
-	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
-	struct drm_gem_cma_object *cma_obj;
-	struct drm_framebuffer *fb = crtc->fb;
-	unsigned long phys;
-
-	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-	if (!cma_obj) {
-		DRM_LOG_KMS("entry is null.\n");
-		return -EFAULT;
-	}
-
-	phys = cma_obj->paddr;
-	phys += x * (fb->bits_per_pixel >> 3);
-	phys += y * fb->pitches[0];
-
-	dev_dbg(ipu_crtc->dev, "%s: phys: 0x%lx\n", __func__, phys);
-	dev_dbg(ipu_crtc->dev, "%s: xy: %dx%d\n", __func__, x, y);
-
-	ipu_cpmem_set_stride(ipu_get_cpmem(ipu_crtc->ipu_ch), fb->pitches[0]);
-	ipu_cpmem_set_buffer(ipu_get_cpmem(ipu_crtc->ipu_ch),
-			  0, phys);
-
-	return 0;
-}
-
 static int ipu_crtc_mode_set(struct drm_crtc *crtc,
 			       struct drm_display_mode *orig_mode,
 			       struct drm_display_mode *mode,
@@ -187,45 +138,15 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
 			       struct drm_framebuffer *old_fb)
 {
 	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
-	struct drm_framebuffer *fb = ipu_crtc->base.fb;
 	int ret;
 	struct ipu_di_signal_cfg sig_cfg = {};
 	u32 out_pixel_fmt;
-	struct ipu_ch_param __iomem *cpmem = ipu_get_cpmem(ipu_crtc->ipu_ch);
-	int bpp;
-	u32 v4l2_fmt;
 
 	dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
 			mode->hdisplay);
 	dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__,
 			mode->vdisplay);
 
-	ipu_ch_param_zero(cpmem);
-
-	switch (fb->pixel_format) {
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_ARGB8888:
-		v4l2_fmt = V4L2_PIX_FMT_RGB32;
-		bpp = 32;
-		break;
-	case DRM_FORMAT_RGB565:
-		v4l2_fmt = V4L2_PIX_FMT_RGB565;
-		bpp = 16;
-		break;
-	case DRM_FORMAT_RGB888:
-		v4l2_fmt = V4L2_PIX_FMT_RGB24;
-		bpp = 24;
-		break;
-	case DRM_FORMAT_BGR888:
-		v4l2_fmt = V4L2_PIX_FMT_BGR24;
-		bpp = 24;
-		break;
-	default:
-		dev_err(ipu_crtc->dev, "unsupported pixel format 0x%08x\n",
-				fb->pixel_format);
-		return -EINVAL;
-	}
-
 	out_pixel_fmt = ipu_crtc->interface_pix_fmt;
 
 	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
@@ -255,18 +176,6 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
 	sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin;
 	sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin;
 
-	if (ipu_crtc->dp) {
-		ret = ipu_dp_setup_channel(ipu_crtc->dp, IPUV3_COLORSPACE_RGB,
-				IPUV3_COLORSPACE_RGB);
-		if (ret) {
-			dev_err(ipu_crtc->dev,
-				"initializing display processor failed with %d\n",
-				ret);
-			return ret;
-		}
-		ipu_dp_set_global_alpha(ipu_crtc->dp, 1, 0, 1);
-	}
-
 	ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, sig_cfg.interlaced,
 			out_pixel_fmt, mode->hdisplay);
 	if (ret) {
@@ -283,30 +192,9 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
 		return ret;
 	}
 
-	ipu_cpmem_set_resolution(cpmem, mode->hdisplay, mode->vdisplay);
-	ipu_cpmem_set_fmt(cpmem, v4l2_fmt);
-	ipu_cpmem_set_high_priority(ipu_crtc->ipu_ch);
-
-	ret = ipu_dmfc_init_channel(ipu_crtc->dmfc, mode->hdisplay);
-	if (ret) {
-		dev_err(ipu_crtc->dev,
-				"initializing dmfc channel failed with %d\n",
-				ret);
-		return ret;
-	}
-
-	ret = ipu_dmfc_alloc_bandwidth(ipu_crtc->dmfc,
-			calc_bandwidth(mode, calc_vref(mode)), 64);
-	if (ret) {
-		dev_err(ipu_crtc->dev,
-				"allocating dmfc bandwidth failed with %d\n",
-				ret);
-		return ret;
-	}
-
-	ipu_drm_set_base(crtc, x, y);
-
-	return 0;
+	return ipu_plane_mode_set(ipu_crtc->plane[0], crtc, mode, crtc->fb,
+				  0, 0, mode->hdisplay, mode->vdisplay,
+				  x, y, mode->hdisplay, mode->vdisplay);
 }
 
 static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc)
@@ -330,7 +218,7 @@ static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
 
 	if (ipu_crtc->newfb) {
 		ipu_crtc->newfb = NULL;
-		ipu_drm_set_base(&ipu_crtc->base, 0, 0);
+		ipu_plane_set_base(ipu_crtc->plane[0], ipu_crtc->base.fb, 0, 0);
 		ipu_crtc_handle_pageflip(ipu_crtc);
 	}
 
@@ -413,12 +301,8 @@ static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = {
 
 static void ipu_put_resources(struct ipu_crtc *ipu_crtc)
 {
-	if (!IS_ERR_OR_NULL(ipu_crtc->ipu_ch))
-		ipu_idmac_put(ipu_crtc->ipu_ch);
-	if (!IS_ERR_OR_NULL(ipu_crtc->dmfc))
-		ipu_dmfc_put(ipu_crtc->dmfc);
-	if (!IS_ERR_OR_NULL(ipu_crtc->dp))
-		ipu_dp_put(ipu_crtc->dp);
+	if (!IS_ERR_OR_NULL(ipu_crtc->dc))
+		ipu_dc_put(ipu_crtc->dc);
 	if (!IS_ERR_OR_NULL(ipu_crtc->di))
 		ipu_di_put(ipu_crtc->di);
 }
@@ -429,32 +313,12 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
 	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
 	int ret;
 
-	ipu_crtc->ipu_ch = ipu_idmac_get(ipu, pdata->dma[0]);
-	if (IS_ERR(ipu_crtc->ipu_ch)) {
-		ret = PTR_ERR(ipu_crtc->ipu_ch);
-		goto err_out;
-	}
-
 	ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc);
 	if (IS_ERR(ipu_crtc->dc)) {
 		ret = PTR_ERR(ipu_crtc->dc);
 		goto err_out;
 	}
 
-	ipu_crtc->dmfc = ipu_dmfc_get(ipu, pdata->dma[0]);
-	if (IS_ERR(ipu_crtc->dmfc)) {
-		ret = PTR_ERR(ipu_crtc->dmfc);
-		goto err_out;
-	}
-
-	if (pdata->dp >= 0) {
-		ipu_crtc->dp = ipu_dp_get(ipu, pdata->dp);
-		if (IS_ERR(ipu_crtc->dp)) {
-			ret = PTR_ERR(ipu_crtc->dp);
-			goto err_out;
-		}
-	}
-
 	ipu_crtc->di = ipu_di_get(ipu, pdata->di);
 	if (IS_ERR(ipu_crtc->di)) {
 		ret = PTR_ERR(ipu_crtc->di);
@@ -472,7 +336,9 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
 		struct ipu_client_platformdata *pdata)
 {
 	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
+	int dp = -EINVAL;
 	int ret;
+	int id;
 
 	ret = ipu_get_resources(ipu_crtc, pdata);
 	if (ret) {
@@ -490,17 +356,42 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
 		goto err_put_resources;
 	}
 
-	ipu_crtc->irq = ipu_idmac_channel_irq(ipu, ipu_crtc->ipu_ch,
-			IPU_IRQ_EOF);
+	if (pdata->dp >= 0)
+		dp = IPU_DP_FLOW_SYNC_BG;
+	id = imx_drm_crtc_id(ipu_crtc->imx_crtc);
+	ipu_crtc->plane[0] = ipu_plane_init(ipu_crtc->base.dev, ipu,
+					    pdata->dma[0], dp, BIT(id), true);
+	ret = ipu_plane_get_resources(ipu_crtc->plane[0]);
+	if (ret) {
+		dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n",
+			ret);
+		goto err_remove_crtc;
+	}
+
+	/* If this crtc is using the DP, add an overlay plane */
+	if (pdata->dp >= 0 && pdata->dma[1] > 0) {
+		ipu_crtc->plane[1] = ipu_plane_init(ipu_crtc->base.dev, ipu,
+						    pdata->dma[1],
+						    IPU_DP_FLOW_SYNC_FG,
+						    BIT(id), false);
+		if (IS_ERR(ipu_crtc->plane[1]))
+			ipu_crtc->plane[1] = NULL;
+	}
+
+	ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]);
 	ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0,
 			"imx_drm", ipu_crtc);
 	if (ret < 0) {
 		dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
-		goto err_put_resources;
+		goto err_put_plane_res;
 	}
 
 	return 0;
 
+err_put_plane_res:
+	ipu_plane_put_resources(ipu_crtc->plane[0]);
+err_remove_crtc:
+	imx_drm_remove_crtc(ipu_crtc->imx_crtc);
 err_put_resources:
 	ipu_put_resources(ipu_crtc);
 
@@ -539,6 +430,7 @@ static int ipu_drm_remove(struct platform_device *pdev)
 
 	imx_drm_remove_crtc(ipu_crtc->imx_crtc);
 
+	ipu_plane_put_resources(ipu_crtc->plane[0]);
 	ipu_put_resources(ipu_crtc);
 
 	return 0;
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c
new file mode 100644
index 0000000..d97454a
--- /dev/null
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -0,0 +1,375 @@
+/*
+ * i.MX IPUv3 DP Overlay Planes
+ *
+ * Copyright (C) 2013 Philipp Zabel, Pengutronix
+ *
+ * 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 <drm/drmP.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include "ipu-v3/imx-ipu-v3.h"
+#include "ipuv3-plane.h"
+
+#define to_ipu_plane(x)	container_of(x, struct ipu_plane, base)
+
+static const uint32_t ipu_plane_formats[] = {
+	DRM_FORMAT_XRGB1555,
+	DRM_FORMAT_XBGR1555,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_YUV420,
+	DRM_FORMAT_YVU420,
+};
+
+int ipu_plane_irq(struct ipu_plane *ipu_plane)
+{
+	return ipu_idmac_channel_irq(ipu_plane->ipu, ipu_plane->ipu_ch,
+				     IPU_IRQ_EOF);
+}
+
+static int calc_vref(struct drm_display_mode *mode)
+{
+	unsigned long htotal, vtotal;
+
+	htotal = mode->htotal;
+	vtotal = mode->vtotal;
+
+	if (!htotal || !vtotal)
+		return 60;
+
+	return DIV_ROUND_UP(mode->clock * 1000, vtotal * htotal);
+}
+
+static inline int calc_bandwidth(int width, int height, unsigned int vref)
+{
+	return width * height * vref;
+}
+
+int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
+		       int x, int y)
+{
+	struct ipu_ch_param __iomem *cpmem;
+	struct drm_gem_cma_object *cma_obj;
+
+	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+	if (!cma_obj) {
+		DRM_LOG_KMS("entry is null.\n");
+		return -EFAULT;
+	}
+
+	dev_dbg(ipu_plane->base.dev->dev, "phys = 0x%x, x = %d, y = %d",
+		cma_obj->paddr, x, y);
+
+	cpmem = ipu_get_cpmem(ipu_plane->ipu_ch);
+	ipu_cpmem_set_stride(cpmem, fb->pitches[0]);
+	ipu_cpmem_set_buffer(cpmem, 0, cma_obj->paddr + fb->offsets[0] +
+			     fb->pitches[0] * y + x);
+
+	return 0;
+}
+
+int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
+		       struct drm_display_mode *mode,
+		       struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+		       unsigned int crtc_w, unsigned int crtc_h,
+		       uint32_t src_x, uint32_t src_y,
+		       uint32_t src_w, uint32_t src_h)
+{
+	struct ipu_ch_param __iomem *cpmem;
+	struct device *dev = ipu_plane->base.dev->dev;
+	int ret;
+
+	/* no scaling */
+	if (src_w != crtc_w || src_h != crtc_h)
+		return -EINVAL;
+
+	/* clip to crtc bounds */
+	if (crtc_x < 0) {
+		if (-crtc_x > crtc_w)
+			return -EINVAL;
+		src_x += -crtc_x;
+		src_w -= -crtc_x;
+		crtc_w -= -crtc_x;
+		crtc_x = 0;
+	}
+	if (crtc_y < 0) {
+		if (-crtc_y > crtc_h)
+			return -EINVAL;
+		src_y += -crtc_y;
+		src_h -= -crtc_y;
+		crtc_h -= -crtc_y;
+		crtc_y = 0;
+	}
+	if (crtc_x + crtc_w > mode->hdisplay) {
+		if (crtc_x > mode->hdisplay)
+			return -EINVAL;
+		crtc_w = mode->hdisplay - crtc_x;
+		src_w = crtc_w;
+	}
+	if (crtc_y + crtc_h > mode->vdisplay) {
+		if (crtc_y > mode->vdisplay)
+			return -EINVAL;
+		crtc_h = mode->vdisplay - crtc_y;
+		src_h = crtc_h;
+	}
+	/* full plane minimum width is 13 pixels */
+	if (crtc_w < 13 && (ipu_plane->dp_flow != IPU_DP_FLOW_SYNC_FG))
+		return -EINVAL;
+	if (crtc_h < 2)
+		return -EINVAL;
+
+	switch (ipu_plane->dp_flow) {
+	case IPU_DP_FLOW_SYNC_BG:
+		ret = ipu_dp_setup_channel(ipu_plane->dp,
+				IPUV3_COLORSPACE_RGB,
+				IPUV3_COLORSPACE_RGB);
+		if (ret) {
+			dev_err(dev,
+				"initializing display processor failed with %d\n",
+				ret);
+			return ret;
+		}
+		ipu_dp_set_global_alpha(ipu_plane->dp, 1, 0, 1);
+		break;
+	case IPU_DP_FLOW_SYNC_FG:
+		ipu_dp_setup_channel(ipu_plane->dp,
+				ipu_drm_fourcc_to_colorspace(fb->pixel_format),
+				IPUV3_COLORSPACE_UNKNOWN);
+		ipu_dp_set_window_pos(ipu_plane->dp, crtc_x, crtc_y);
+		break;
+	}
+
+	ret = ipu_dmfc_init_channel(ipu_plane->dmfc, crtc_w);
+	if (ret) {
+		dev_err(dev, "initializing dmfc channel failed with %d\n", ret);
+		return ret;
+	}
+
+	ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc,
+			calc_bandwidth(crtc_w, crtc_h,
+				       calc_vref(mode)), 64);
+	if (ret) {
+		dev_err(dev, "allocating dmfc bandwidth failed with %d\n", ret);
+		return ret;
+	}
+
+	cpmem = ipu_get_cpmem(ipu_plane->ipu_ch);
+	ipu_ch_param_zero(cpmem);
+	ipu_cpmem_set_resolution(cpmem, src_w, src_h);
+	ret = ipu_cpmem_set_fmt(cpmem, fb->pixel_format);
+	if (ret < 0) {
+		dev_err(dev, "unsupported pixel format 0x%08x\n",
+			fb->pixel_format);
+		return ret;
+	}
+	ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
+
+	ret = ipu_plane_set_base(ipu_plane, fb, src_x, src_y);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
+{
+	if (!IS_ERR_OR_NULL(ipu_plane->dp))
+		ipu_dp_put(ipu_plane->dp);
+	if (!IS_ERR_OR_NULL(ipu_plane->dmfc))
+		ipu_dmfc_put(ipu_plane->dmfc);
+	if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch))
+		ipu_idmac_put(ipu_plane->ipu_ch);
+}
+
+int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
+{
+	int ret;
+
+	ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma);
+	if (IS_ERR(ipu_plane->ipu_ch)) {
+		ret = PTR_ERR(ipu_plane->ipu_ch);
+		DRM_ERROR("failed to get idmac channel: %d\n", ret);
+		return ret;
+	}
+
+	ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma);
+	if (IS_ERR(ipu_plane->dmfc)) {
+		ret = PTR_ERR(ipu_plane->dmfc);
+		DRM_ERROR("failed to get dmfc: ret %d\n", ret);
+		goto err_out;
+	}
+
+	if (ipu_plane->dp_flow >= 0) {
+		ipu_plane->dp = ipu_dp_get(ipu_plane->ipu, ipu_plane->dp_flow);
+		if (IS_ERR(ipu_plane->dp)) {
+			ret = PTR_ERR(ipu_plane->dp);
+			DRM_ERROR("failed to get dp flow: %d\n", ret);
+			goto err_out;
+		}
+	}
+
+	return 0;
+err_out:
+	ipu_plane_put_resources(ipu_plane);
+
+	return ret;
+}
+
+void ipu_plane_enable(struct ipu_plane *ipu_plane)
+{
+	ipu_dmfc_enable_channel(ipu_plane->dmfc);
+	ipu_idmac_enable_channel(ipu_plane->ipu_ch);
+	if (ipu_plane->dp)
+		ipu_dp_enable_channel(ipu_plane->dp);
+
+	ipu_plane->enabled = true;
+}
+
+void ipu_plane_disable(struct ipu_plane *ipu_plane)
+{
+	ipu_plane->enabled = false;
+
+	ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50);
+
+	if (ipu_plane->dp)
+		ipu_dp_disable_channel(ipu_plane->dp);
+	ipu_idmac_disable_channel(ipu_plane->ipu_ch);
+	ipu_dmfc_disable_channel(ipu_plane->dmfc);
+}
+
+static void ipu_plane_dpms(struct ipu_plane *ipu_plane, int mode)
+{
+	bool enable;
+
+	DRM_DEBUG_KMS("mode = %d", mode);
+
+	enable = (mode == DRM_MODE_DPMS_ON);
+
+	if (enable == ipu_plane->enabled)
+		return;
+
+	if (enable) {
+		ipu_plane_enable(ipu_plane);
+	} else {
+		ipu_plane_disable(ipu_plane);
+
+		ipu_idmac_put(ipu_plane->ipu_ch);
+		ipu_dmfc_put(ipu_plane->dmfc);
+		ipu_dp_put(ipu_plane->dp);
+	}
+}
+
+/*
+ * drm_plane API
+ */
+
+static int ipu_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+			    struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+			    unsigned int crtc_w, unsigned int crtc_h,
+			    uint32_t src_x, uint32_t src_y,
+			    uint32_t src_w, uint32_t src_h)
+{
+	struct ipu_plane *ipu_plane = to_ipu_plane(plane);
+	int ret = 0;
+
+	DRM_DEBUG_KMS("plane - %p\n", plane);
+
+	if (!ipu_plane->enabled)
+		ret = ipu_plane_get_resources(ipu_plane);
+	if (ret < 0)
+		return ret;
+
+	ret = ipu_plane_mode_set(ipu_plane, crtc, &crtc->hwmode, fb,
+			crtc_x, crtc_y, crtc_w, crtc_h,
+			src_x >> 16, src_y >> 16, src_w >> 16, src_h >> 16);
+	if (ret < 0) {
+		ipu_plane_put_resources(ipu_plane);
+		return ret;
+	}
+
+	if (crtc != plane->crtc)
+		dev_info(plane->dev->dev, "crtc change: %p -> %p\n",
+				plane->crtc, crtc);
+	plane->crtc = crtc;
+
+	ipu_plane_dpms(ipu_plane, DRM_MODE_DPMS_ON);
+
+	return 0;
+}
+
+static int ipu_disable_plane(struct drm_plane *plane)
+{
+	struct ipu_plane *ipu_plane = to_ipu_plane(plane);
+
+	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
+
+	ipu_plane_dpms(ipu_plane, DRM_MODE_DPMS_OFF);
+
+	ipu_plane_put_resources(ipu_plane);
+
+	return 0;
+}
+
+static void ipu_plane_destroy(struct drm_plane *plane)
+{
+	struct ipu_plane *ipu_plane = to_ipu_plane(plane);
+
+	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
+
+	ipu_disable_plane(plane);
+	drm_plane_cleanup(plane);
+	kfree(ipu_plane);
+}
+
+static struct drm_plane_funcs ipu_plane_funcs = {
+	.update_plane	= ipu_update_plane,
+	.disable_plane	= ipu_disable_plane,
+	.destroy	= ipu_plane_destroy,
+};
+
+struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
+				 int dma, int dp, unsigned int possible_crtcs,
+				 bool priv)
+{
+	struct ipu_plane *ipu_plane;
+	int ret;
+
+	DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
+		      dma, dp, possible_crtcs);
+
+	ipu_plane = kzalloc(sizeof(*ipu_plane), GFP_KERNEL);
+	if (!ipu_plane) {
+		DRM_ERROR("failed to allocate plane\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ipu_plane->ipu = ipu;
+	ipu_plane->dma = dma;
+	ipu_plane->dp_flow = dp;
+
+	ret = drm_plane_init(dev, &ipu_plane->base, possible_crtcs,
+			     &ipu_plane_funcs, ipu_plane_formats,
+			     ARRAY_SIZE(ipu_plane_formats),
+			     priv);
+	if (ret) {
+		DRM_ERROR("failed to initialize plane\n");
+		kfree(ipu_plane);
+		return ERR_PTR(ret);
+	}
+
+	return ipu_plane;
+}
diff --git a/drivers/staging/imx-drm/ipuv3-plane.h b/drivers/staging/imx-drm/ipuv3-plane.h
new file mode 100644
index 0000000..c0aae5b
--- /dev/null
+++ b/drivers/staging/imx-drm/ipuv3-plane.h
@@ -0,0 +1,55 @@
+#ifndef __IPUV3_PLANE_H__
+#define __IPUV3_PLANE_H__
+
+#include <drm/drm_crtc.h> /* drm_plane */
+
+struct drm_plane;
+struct drm_device;
+struct ipu_soc;
+struct drm_crtc;
+struct drm_framebuffer;
+
+struct ipuv3_channel;
+struct dmfc_channel;
+struct ipu_dp;
+
+struct ipu_plane {
+	struct drm_plane	base;
+
+	struct ipu_soc		*ipu;
+	struct ipuv3_channel	*ipu_ch;
+	struct dmfc_channel	*dmfc;
+	struct ipu_dp		*dp;
+
+	int			dma;
+	int			dp_flow;
+
+	int			x;
+	int			y;
+
+	bool			enabled;
+};
+
+struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
+				 int dma, int dp, unsigned int possible_crtcs,
+				 bool priv);
+
+/* Init IDMAC, DMFC, DP */
+int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc,
+		       struct drm_display_mode *mode,
+		       struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+		       unsigned int crtc_w, unsigned int crtc_h,
+		       uint32_t src_x, uint32_t src_y, uint32_t src_w,
+		       uint32_t src_h);
+
+void ipu_plane_enable(struct ipu_plane *plane);
+void ipu_plane_disable(struct ipu_plane *plane);
+int ipu_plane_set_base(struct ipu_plane *plane, struct drm_framebuffer *fb,
+		       int x, int y);
+
+int ipu_plane_get_resources(struct ipu_plane *plane);
+void ipu_plane_put_resources(struct ipu_plane *plane);
+
+int ipu_plane_irq(struct ipu_plane *plane);
+
+#endif
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 11/11] staging: drm/imx: Enable DRM PRIME support
  2013-10-10 14:18 [PATCH 0/11] i.MX RGB565, plane and PRIME support Philipp Zabel
                   ` (9 preceding siblings ...)
  2013-10-10 14:18 ` [PATCH 10/11] staging: drm/imx: add drm plane support Philipp Zabel
@ 2013-10-10 14:18 ` Philipp Zabel
  2013-10-11 22:30 ` [PATCH 0/11] i.MX RGB565, plane and " Greg Kroah-Hartman
  11 siblings, 0 replies; 14+ messages in thread
From: Philipp Zabel @ 2013-10-10 14:18 UTC (permalink / raw)
  To: dri-devel
  Cc: devel, Fabio Estevam, Philipp Zabel, David Airlie,
	Greg Kroah-Hartman, kernel, Shawn Guo

Lets the IPU driver make use of the PRIME functionality introduced
by the "drm: GEM CMA: Add DRM PRIME support" patch.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/staging/imx-drm/imx-drm-core.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index f931c62..7b25181 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -791,7 +791,7 @@ static const struct drm_ioctl_desc imx_drm_ioctls[] = {
 };
 
 static struct drm_driver imx_drm_driver = {
-	.driver_features	= DRIVER_MODESET | DRIVER_GEM,
+	.driver_features	= DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
 	.load			= imx_drm_driver_load,
 	.unload			= imx_drm_driver_unload,
 	.lastclose		= imx_drm_driver_lastclose,
@@ -802,6 +802,15 @@ static struct drm_driver imx_drm_driver = {
 	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
 	.dumb_destroy		= drm_gem_dumb_destroy,
 
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
+	.gem_prime_import	= drm_gem_prime_import,
+	.gem_prime_export	= drm_gem_prime_export,
+	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
 	.get_vblank_counter	= drm_vblank_count,
 	.enable_vblank		= imx_drm_enable_vblank,
 	.disable_vblank		= imx_drm_disable_vblank,
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 01/11] staging: drm/imx: also allow to allocate only 2 DMFC slots for DP full plane
  2013-10-10 14:18 ` [PATCH 01/11] staging: drm/imx: also allow to allocate only 2 DMFC slots for DP full plane Philipp Zabel
@ 2013-10-11  7:12   ` Liu Ying
  0 siblings, 0 replies; 14+ messages in thread
From: Liu Ying @ 2013-10-11  7:12 UTC (permalink / raw)
  To: Philipp Zabel; +Cc: devel, Fabio Estevam, kernel, dri-devel, Greg Kroah-Hartman

Hi Philipp,

On 10/10/2013 10:18 PM, Philipp Zabel wrote:
> Connecting a 320x240 parallel display on i.MX6 resulted in an invalid DRDY
> signal because the DC would not receive NL/EOL events on every line.
> Reducing the allocated DMFC space from 4 slots (256 * 128-bit) to 2 slots
> (128 * 128-bit) solved the problem.
> 
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> ---
>  drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
> index 2e97c33..98070dd 100644
> --- a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
> +++ b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
> @@ -307,13 +307,13 @@ int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
>  		goto out;
>  	}
>  
> -	/* Always allocate at least 128*4 bytes (2 slots) */
> -	if (slots < 2)
> -		slots = 2;
> -
>  	/* 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) */

The commit message mentions that the size of 2 slots is 128*128-bit, that is, 128*16-byte.
This contradicts the above annotation(128*4 bytes (2 slots)).

> +		slots = 2;
> +
>  	if (segment >= 0)
>  		slots *= 2;
>  	else
> 

Regards,
Liu Ying

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/11] i.MX RGB565, plane and PRIME support
  2013-10-10 14:18 [PATCH 0/11] i.MX RGB565, plane and PRIME support Philipp Zabel
                   ` (10 preceding siblings ...)
  2013-10-10 14:18 ` [PATCH 11/11] staging: drm/imx: Enable DRM PRIME support Philipp Zabel
@ 2013-10-11 22:30 ` Greg Kroah-Hartman
  11 siblings, 0 replies; 14+ messages in thread
From: Greg Kroah-Hartman @ 2013-10-11 22:30 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: devel, Fabio Estevam, David Airlie, dri-devel, kernel, Shawn Guo

On Thu, Oct 10, 2013 at 04:18:35PM +0200, Philipp Zabel wrote:
> Hi,
> 
> This series fixes DMFC allocation for small displays and pageflip events
> during device close, clarifies the RGB memory formats, adds support for the
> RGB565 format and KMS planes, and enables DRM PRIME using the CMA helpers.
> 
> In the next step, I would like to move the code
> from drivers/staging/imx-drm/ipu-v3 to drivers/gpu/ipu-v3 (right next to
> host1x), as these parts provide an internal API for the IPU modules to be
> used by both DRM and V4L2 drivers.

I would like to see this happen as well, I really don't like new
features being added to staging drivers as they should be primarily
worked on to clean the code up and get merged to the proper place
instead.

I'll take this series, but after that, please work to move it to
drivers/gpu/

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2013-10-11 22:30 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-10 14:18 [PATCH 0/11] i.MX RGB565, plane and PRIME support Philipp Zabel
2013-10-10 14:18 ` [PATCH 01/11] staging: drm/imx: also allow to allocate only 2 DMFC slots for DP full plane Philipp Zabel
2013-10-11  7:12   ` Liu Ying
2013-10-10 14:18 ` [PATCH 02/11] staging: drm/imx: make struct ipu_rgb format definitions const Philipp Zabel
2013-10-10 14:18 ` [PATCH 03/11] staging: drm/imx: fix RGB formats, make ipu_cpmem_set_fmt take a drm_fourcc Philipp Zabel
2013-10-10 14:18 ` [PATCH 04/11] staging: drm/imx: add BGR565 format Philipp Zabel
2013-10-10 14:18 ` [PATCH 05/11] staging: drm/imx: Add 24-bit BGR support to DC Philipp Zabel
2013-10-10 14:18 ` [PATCH 06/11] staging: drm/imx: make waiting for idle channel optional Philipp Zabel
2013-10-10 14:18 ` [PATCH 07/11] staging: drm-imx: add DRM_FORMAT_BGR888 to ipu crtc driver Philipp Zabel
2013-10-10 14:18 ` [PATCH 08/11] staging: drm/imx: ipuv3-crtc: remove unused struct ipu_framebuffer Philipp Zabel
2013-10-10 14:18 ` [PATCH 09/11] staging: drm/imx: fix pageflip events during device close Philipp Zabel
2013-10-10 14:18 ` [PATCH 10/11] staging: drm/imx: add drm plane support Philipp Zabel
2013-10-10 14:18 ` [PATCH 11/11] staging: drm/imx: Enable DRM PRIME support Philipp Zabel
2013-10-11 22:30 ` [PATCH 0/11] i.MX RGB565, plane and " Greg Kroah-Hartman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.