All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2
@ 2015-02-03 19:14 Gustavo Padovan
  2015-02-03 19:14 ` [PATCH 01/14] drm/exynos: track vblank events on a per crtc basis Gustavo Padovan
                   ` (14 more replies)
  0 siblings, 15 replies; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: jy0922.shim, inki.dae, dri-devel, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

Hi,

This series clean ups a few more paths from exynos-drm with the most important
being the removal of the global page flip queue and the removal in driver
internal data (struct *_win_data) that was replicating plane data.

Following these patches comes the first step torwards atomic modesetting
support on exynos.

This series is applied on top of 3 patches[0][1][2] that were sent recently to
dri-devel.

	Gustavo

---
[0] http://www.spinics.net/lists/linux-samsung-soc/msg41867.html
[1] http://lists.freedesktop.org/archives/dri-devel/2015-January/076504.html
[2] http://lists.freedesktop.org/archives/dri-devel/2015-January/076505.html


Daniel Kurtz (1):
  drm/exynos: do not copy adjusted mode into mode during crtc mode_set

Gustavo Padovan (12):
  drm/exynos: Remove exynos_plane_dpms() call with no effect
  drm/exynos: remove leftover functions declarations
  drm/exynos: remove struct *_win_data abstraction on planes
  drm/exynos: atomic phase 1: use drm_plane_helper_update()
  drm/exynos: atomic phase 1: use drm_plane_helper_disable()
  drm/exynos: atomic phase 1: add atomic_begin()/atomic_flush()
  drm/exynos: atomic phase 1: add .mode_set_nofb() callback
  drm/exynos: atomic phase 2: wire up state reset(), duplicate() and
    destroy()
  drm/exynos: atomic phase 2: keep track of framebuffer pointer
  drm/exynos: make exynos_plane_mode_set() static
  drm/exynos: use correct pipe number on vblank event
  drm/exynos: remove exynos_disable_plane()

Mandeep Singh Baines (1):
  drm/exynos: track vblank events on a per crtc basis

 drivers/gpu/drm/bridge/ptn3460.c              |   4 +
 drivers/gpu/drm/exynos/exynos_dp_core.c       |   4 +
 drivers/gpu/drm/exynos/exynos_drm_connector.c |   4 +
 drivers/gpu/drm/exynos/exynos_drm_crtc.c      | 203 +++++++++++-----------
 drivers/gpu/drm/exynos/exynos_drm_crtc.h      |   7 +-
 drivers/gpu/drm/exynos/exynos_drm_dpi.c       |   4 +
 drivers/gpu/drm/exynos/exynos_drm_drv.c       |  29 +---
 drivers/gpu/drm/exynos/exynos_drm_drv.h       |  15 +-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c       |   4 +
 drivers/gpu/drm/exynos/exynos_drm_fb.c        |   2 +-
 drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 235 ++++++++++++--------------
 drivers/gpu/drm/exynos/exynos_drm_plane.c     |  99 ++++++-----
 drivers/gpu/drm/exynos/exynos_drm_plane.h     |  13 +-
 drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 127 ++++----------
 drivers/gpu/drm/exynos/exynos_hdmi.c          |   4 +
 drivers/gpu/drm/exynos/exynos_mixer.c         | 212 ++++++++---------------
 16 files changed, 408 insertions(+), 558 deletions(-)

-- 
1.9.3

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

* [PATCH 01/14] drm/exynos: track vblank events on a per crtc basis
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-03 19:14 ` [PATCH 02/14] drm/exynos: Remove exynos_plane_dpms() call with no effect Gustavo Padovan
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: jy0922.shim, inki.dae, dri-devel, Mandeep Singh Baines

From: Mandeep Singh Baines <msb@chromium.org>

The goal of the change is to make sure we send the vblank event on the
current vblank. My hope is to fix any races that might be causing flicker.
After this change I only see a flicker in the transition plymouth and
X11.

Simplified the code by tracking vblank events on a per-crtc basis. This
allowed me to remove all error paths from the callback. It also allowed
me to remove the vblank wait from the callback.

Signed-off-by: Mandeep Singh Baines <msb@chromium.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_crtc.c | 92 +++++++++++++++-----------------
 drivers/gpu/drm/exynos/exynos_drm_drv.c  | 13 -----
 drivers/gpu/drm/exynos/exynos_drm_drv.h  |  6 +--
 3 files changed, 44 insertions(+), 67 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index a85c451..b2a4b84 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -34,9 +34,8 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
 	if (mode > DRM_MODE_DPMS_ON) {
 		/* wait for the completion of page flip. */
 		if (!wait_event_timeout(exynos_crtc->pending_flip_queue,
-				!atomic_read(&exynos_crtc->pending_flip),
-				HZ/20))
-			atomic_set(&exynos_crtc->pending_flip, 0);
+				(exynos_crtc->event == NULL), HZ/20))
+			exynos_crtc->event = NULL;
 		drm_crtc_vblank_off(crtc);
 	}
 
@@ -166,11 +165,10 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
 				     uint32_t page_flip_flags)
 {
 	struct drm_device *dev = crtc->dev;
-	struct exynos_drm_private *dev_priv = dev->dev_private;
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 	struct drm_framebuffer *old_fb = crtc->primary->fb;
 	unsigned int crtc_w, crtc_h;
-	int ret = -EINVAL;
+	int ret;
 
 	/* when the page flip is requested, crtc's dpms should be on */
 	if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
@@ -178,48 +176,49 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
 		return -EINVAL;
 	}
 
-	mutex_lock(&dev->struct_mutex);
+	if (!event)
+		return -EINVAL;
 
-	if (event) {
-		/*
-		 * the pipe from user always is 0 so we can set pipe number
-		 * of current owner to event.
-		 */
-		event->pipe = exynos_crtc->pipe;
+	spin_lock_irq(&dev->event_lock);
+	if (exynos_crtc->event) {
+		ret = -EBUSY;
+		goto out;
+	}
 
-		ret = drm_vblank_get(dev, exynos_crtc->pipe);
-		if (ret) {
-			DRM_DEBUG("failed to acquire vblank counter\n");
+	ret = drm_vblank_get(dev, exynos_crtc->pipe);
+	if (ret) {
+		DRM_DEBUG("failed to acquire vblank counter\n");
+		goto out;
+	}
 
-			goto out;
-		}
+	exynos_crtc->event = event;
+	spin_unlock_irq(&dev->event_lock);
 
+	/*
+	 * the pipe from user always is 0 so we can set pipe number
+	 * of current owner to event.
+	 */
+	event->pipe = exynos_crtc->pipe;
+
+	crtc->primary->fb = fb;
+	crtc_w = fb->width - crtc->x;
+	crtc_h = fb->height - crtc->y;
+	ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
+				  crtc_w, crtc_h, crtc->x, crtc->y,
+				  crtc_w, crtc_h);
+	if (ret) {
+		crtc->primary->fb = old_fb;
 		spin_lock_irq(&dev->event_lock);
-		list_add_tail(&event->base.link,
-				&dev_priv->pageflip_event_list);
-		atomic_set(&exynos_crtc->pending_flip, 1);
+		exynos_crtc->event = NULL;
+		drm_vblank_put(dev, exynos_crtc->pipe);
 		spin_unlock_irq(&dev->event_lock);
-
-		crtc->primary->fb = fb;
-		crtc_w = fb->width - crtc->x;
-		crtc_h = fb->height - crtc->y;
-		ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
-					  crtc_w, crtc_h, crtc->x, crtc->y,
-					  crtc_w, crtc_h);
-		if (ret) {
-			crtc->primary->fb = old_fb;
-
-			spin_lock_irq(&dev->event_lock);
-			drm_vblank_put(dev, exynos_crtc->pipe);
-			list_del(&event->base.link);
-			atomic_set(&exynos_crtc->pending_flip, 0);
-			spin_unlock_irq(&dev->event_lock);
-
-			goto out;
-		}
+		return ret;
 	}
+
+	return 0;
+
 out:
-	mutex_unlock(&dev->struct_mutex);
+	spin_unlock_irq(&dev->event_lock);
 	return ret;
 }
 
@@ -315,7 +314,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
 		return ERR_PTR(-ENOMEM);
 
 	init_waitqueue_head(&exynos_crtc->pending_flip_queue);
-	atomic_set(&exynos_crtc->pending_flip, 0);
 
 	exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
 	exynos_crtc->pipe = pipe;
@@ -382,26 +380,20 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
 void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
 {
 	struct exynos_drm_private *dev_priv = dev->dev_private;
-	struct drm_pending_vblank_event *e, *t;
 	struct drm_crtc *drm_crtc = dev_priv->crtc[pipe];
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc);
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->event_lock, flags);
+	if (exynos_crtc->event) {
 
-	list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
-			base.link) {
-		/* if event's pipe isn't same as crtc then ignore it. */
-		if (pipe != e->pipe)
-			continue;
-
-		list_del(&e->base.link);
-		drm_send_vblank_event(dev, -1, e);
+		drm_send_vblank_event(dev, -1, exynos_crtc->event);
 		drm_vblank_put(dev, pipe);
-		atomic_set(&exynos_crtc->pending_flip, 0);
 		wake_up(&exynos_crtc->pending_flip_queue);
+
 	}
 
+	exynos_crtc->event = NULL;
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 1bcbe07..737164d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -61,7 +61,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 	if (!private)
 		return -ENOMEM;
 
-	INIT_LIST_HEAD(&private->pageflip_event_list);
 	dev_set_drvdata(dev->dev, dev);
 	dev->dev_private = (void *)private;
 
@@ -237,25 +236,13 @@ static void exynos_drm_preclose(struct drm_device *dev,
 
 static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
 {
-	struct exynos_drm_private *private = dev->dev_private;
-	struct drm_pending_vblank_event *v, *vt;
 	struct drm_pending_event *e, *et;
 	unsigned long flags;
 
 	if (!file->driver_priv)
 		return;
 
-	/* Release all events not unhandled by page flip handler. */
 	spin_lock_irqsave(&dev->event_lock, flags);
-	list_for_each_entry_safe(v, vt, &private->pageflip_event_list,
-			base.link) {
-		if (v->base.file_priv == file) {
-			list_del(&v->base.link);
-			drm_vblank_put(dev, v->pipe);
-			v->base.destroy(&v->base);
-		}
-	}
-
 	/* Release all events handled by page flip handler but not freed. */
 	list_for_each_entry_safe(e, et, &file->event_list, link) {
 		list_del(&e->link);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index d490b49..7411af2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -216,6 +216,7 @@ enum exynos_crtc_mode {
  *	this pipe value.
  * @dpms: store the crtc dpms value
  * @mode: store the crtc mode value
+ * @event: vblank event that is currently queued for flip
  * @ops: pointer to callbacks for exynos drm specific functionality
  * @ctx: A pointer to the crtc's implementation specific context
  */
@@ -226,7 +227,7 @@ struct exynos_drm_crtc {
 	unsigned int			dpms;
 	enum exynos_crtc_mode		mode;
 	wait_queue_head_t		pending_flip_queue;
-	atomic_t			pending_flip;
+	struct drm_pending_vblank_event	*event;
 	struct exynos_drm_crtc_ops	*ops;
 	void				*ctx;
 };
@@ -256,9 +257,6 @@ struct drm_exynos_file_private {
 struct exynos_drm_private {
 	struct drm_fb_helper *fb_helper;
 
-	/* list head for new event to be added. */
-	struct list_head pageflip_event_list;
-
 	/*
 	 * created crtc object would be contained at this array and
 	 * this array is used to be aware of which crtc did it request vblank.
-- 
1.9.3

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

* [PATCH 02/14] drm/exynos: Remove exynos_plane_dpms() call with no effect
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
  2015-02-03 19:14 ` [PATCH 01/14] drm/exynos: track vblank events on a per crtc basis Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-04  7:42   ` Joonyoung Shim
  2015-02-03 19:14 ` [PATCH 03/14] drm/exynos: remove leftover functions declarations Gustavo Padovan
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: jy0922.shim, inki.dae, dri-devel, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

exynos_plane_dpms(DRM_MODE_DPMS_ON) calls the win_enable()'s callback
from the underlying layer. However neither one of these layers implement
win_enable() - FIMD, Mixer and VIDI. Thus the call to exynos_plane_dpms()
is pointless.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_crtc.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index b2a4b84..ad675fb 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -65,8 +65,6 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
 
 	if (exynos_crtc->ops->commit)
 		exynos_crtc->ops->commit(exynos_crtc);
-
-	exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON);
 }
 
 static bool
-- 
1.9.3

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

* [PATCH 03/14] drm/exynos: remove leftover functions declarations
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
  2015-02-03 19:14 ` [PATCH 01/14] drm/exynos: track vblank events on a per crtc basis Gustavo Padovan
  2015-02-03 19:14 ` [PATCH 02/14] drm/exynos: Remove exynos_plane_dpms() call with no effect Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-03 19:14 ` [PATCH 04/14] drm/exynos: remove struct *_win_data abstraction on planes Gustavo Padovan
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: Gustavo Padovan, dri-devel

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

These functions were already removed by previous cleanup work, but these
ones were left behind.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Acked-by: Joonyoung Shim <jy0922.shim@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_crtc.h | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index 6258b80..628b787 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -27,12 +27,6 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe);
 void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe);
 void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);
 
-void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
-			struct exynos_drm_plane *plane);
-void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos);
-void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos);
-void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos);
-
 /* This function gets pipe value to crtc device matched with out_type. */
 int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
 					unsigned int out_type);
-- 
1.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 04/14] drm/exynos: remove struct *_win_data abstraction on planes
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
                   ` (2 preceding siblings ...)
  2015-02-03 19:14 ` [PATCH 03/14] drm/exynos: remove leftover functions declarations Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-04  7:44   ` Joonyoung Shim
  2015-02-03 19:14 ` [PATCH 05/14] drm/exynos: do not copy adjusted mode into mode during crtc mode_set Gustavo Padovan
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: jy0922.shim, inki.dae, dri-devel, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

struct {fimd,mixer,vidi}_win_data was just keeping the same data
as struct exynos_drm_plane thus get ride of it and use exynos_drm_plane
directly.

It changes how planes are created and remove .win_mode_set() callback
that was only filling all *_win_data structs.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_crtc.c  |   9 +-
 drivers/gpu/drm/exynos/exynos_drm_crtc.h  |   1 +
 drivers/gpu/drm/exynos/exynos_drm_drv.c   |  14 --
 drivers/gpu/drm/exynos/exynos_drm_drv.h   |   5 +-
 drivers/gpu/drm/exynos/exynos_drm_fimd.c  | 182 ++++++++++---------------
 drivers/gpu/drm/exynos/exynos_drm_plane.c |  20 +--
 drivers/gpu/drm/exynos/exynos_drm_plane.h |   6 +-
 drivers/gpu/drm/exynos/exynos_drm_vidi.c  | 123 +++++------------
 drivers/gpu/drm/exynos/exynos_mixer.c     | 212 +++++++++++-------------------
 9 files changed, 183 insertions(+), 389 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index ad675fb..d504f0b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -296,13 +296,13 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
 }
 
 struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
+					       struct drm_plane *plane,
 					       int pipe,
 					       enum exynos_drm_output_type type,
 					       struct exynos_drm_crtc_ops *ops,
 					       void *ctx)
 {
 	struct exynos_drm_crtc *exynos_crtc;
-	struct drm_plane *plane;
 	struct exynos_drm_private *private = drm_dev->dev_private;
 	struct drm_crtc *crtc;
 	int ret;
@@ -318,12 +318,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
 	exynos_crtc->type = type;
 	exynos_crtc->ops = ops;
 	exynos_crtc->ctx = ctx;
-	plane = exynos_plane_init(drm_dev, 1 << pipe,
-				  DRM_PLANE_TYPE_PRIMARY);
-	if (IS_ERR(plane)) {
-		ret = PTR_ERR(plane);
-		goto err_plane;
-	}
 
 	crtc = &exynos_crtc->base;
 
@@ -342,7 +336,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
 
 err_crtc:
 	plane->funcs->destroy(plane);
-err_plane:
 	kfree(exynos_crtc);
 	return ERR_PTR(ret);
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index 628b787..0ecd8fc 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -18,6 +18,7 @@
 #include "exynos_drm_drv.h"
 
 struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
+					       struct drm_plane *plane,
 					       int pipe,
 					       enum exynos_drm_output_type type,
 					       struct exynos_drm_crtc_ops *ops,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 737164d..778c91e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -55,7 +55,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 {
 	struct exynos_drm_private *private;
 	int ret;
-	int nr;
 
 	private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
 	if (!private)
@@ -80,19 +79,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 
 	exynos_drm_mode_config_init(dev);
 
-	for (nr = 0; nr < MAX_PLANE; nr++) {
-		struct drm_plane *plane;
-		unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;
-
-		plane = exynos_plane_init(dev, possible_crtcs,
-					  DRM_PLANE_TYPE_OVERLAY);
-		if (!IS_ERR(plane))
-			continue;
-
-		ret = PTR_ERR(plane);
-		goto err_mode_config_cleanup;
-	}
-
 	/* setup possible_clones. */
 	exynos_drm_encoder_setup(dev);
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 7411af2..cad54e7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -78,6 +78,7 @@ enum exynos_drm_output_type {
  * @transparency: transparency on or off.
  * @activated: activated or not.
  * @enabled: enabled or not.
+ * @resume: to resume or not.
  *
  * this structure is common to exynos SoC and its contents would be copied
  * to hardware specific overlay info.
@@ -112,6 +113,7 @@ struct exynos_drm_plane {
 	bool transparency:1;
 	bool activated:1;
 	bool enabled:1;
+	bool resume:1;
 };
 
 /*
@@ -172,7 +174,6 @@ struct exynos_drm_display {
  * @disable_vblank: specific driver callback for disabling vblank interrupt.
  * @wait_for_vblank: wait for vblank interrupt to make sure that
  *	hardware overlay is updated.
- * @win_mode_set: copy drm overlay info to hw specific overlay info.
  * @win_commit: apply hardware specific overlay data to registers.
  * @win_enable: enable hardware specific overlay.
  * @win_disable: disable hardware specific overlay.
@@ -189,8 +190,6 @@ struct exynos_drm_crtc_ops {
 	int (*enable_vblank)(struct exynos_drm_crtc *crtc);
 	void (*disable_vblank)(struct exynos_drm_crtc *crtc);
 	void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
-	void (*win_mode_set)(struct exynos_drm_crtc *crtc,
-				struct exynos_drm_plane *plane);
 	void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos);
 	void (*win_enable)(struct exynos_drm_crtc *crtc, int zpos);
 	void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 925fc69..ebb4cdc 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -31,6 +31,7 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fbdev.h"
 #include "exynos_drm_crtc.h"
+#include "exynos_drm_plane.h"
 #include "exynos_drm_iommu.h"
 
 /*
@@ -140,31 +141,15 @@ static struct fimd_driver_data exynos5_fimd_driver_data = {
 	.has_vtsel = 1,
 };
 
-struct fimd_win_data {
-	unsigned int		offset_x;
-	unsigned int		offset_y;
-	unsigned int		ovl_width;
-	unsigned int		ovl_height;
-	unsigned int		fb_width;
-	unsigned int		fb_height;
-	unsigned int		bpp;
-	unsigned int		pixel_format;
-	dma_addr_t		dma_addr;
-	unsigned int		buf_offsize;
-	unsigned int		line_size;	/* bytes */
-	bool			enabled;
-	bool			resume;
-};
-
 struct fimd_context {
 	struct device			*dev;
 	struct drm_device		*drm_dev;
 	struct exynos_drm_crtc		*crtc;
+	struct exynos_drm_plane		planes[WINDOWS_NR];
 	struct clk			*bus_clk;
 	struct clk			*lcd_clk;
 	void __iomem			*regs;
 	struct regmap			*sysreg;
-	struct fimd_win_data		win_data[WINDOWS_NR];
 	unsigned int			default_win;
 	unsigned long			irq_flags;
 	u32				vidcon0;
@@ -506,58 +491,9 @@ static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
 	}
 }
 
-static void fimd_win_mode_set(struct exynos_drm_crtc *crtc,
-			struct exynos_drm_plane *plane)
-{
-	struct fimd_context *ctx = crtc->ctx;
-	struct fimd_win_data *win_data;
-	int win;
-	unsigned long offset;
-
-	if (!plane) {
-		DRM_ERROR("plane is NULL\n");
-		return;
-	}
-
-	win = plane->zpos;
-	if (win == DEFAULT_ZPOS)
-		win = ctx->default_win;
-
-	if (win < 0 || win >= WINDOWS_NR)
-		return;
-
-	offset = plane->fb_x * (plane->bpp >> 3);
-	offset += plane->fb_y * plane->pitch;
-
-	DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
-
-	win_data = &ctx->win_data[win];
-
-	win_data->offset_x = plane->crtc_x;
-	win_data->offset_y = plane->crtc_y;
-	win_data->ovl_width = plane->crtc_width;
-	win_data->ovl_height = plane->crtc_height;
-	win_data->fb_width = plane->fb_width;
-	win_data->fb_height = plane->fb_height;
-	win_data->dma_addr = plane->dma_addr[0] + offset;
-	win_data->bpp = plane->bpp;
-	win_data->pixel_format = plane->pixel_format;
-	win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
-				(plane->bpp >> 3);
-	win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
-
-	DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
-			win_data->offset_x, win_data->offset_y);
-	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
-			win_data->ovl_width, win_data->ovl_height);
-	DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
-	DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
-			plane->fb_width, plane->crtc_width);
-}
-
 static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
 {
-	struct fimd_win_data *win_data = &ctx->win_data[win];
+	struct exynos_drm_plane *plane = &ctx->planes[win];
 	unsigned long val;
 
 	val = WINCONx_ENWIN;
@@ -567,11 +503,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
 	 * So the request format is ARGB8888 then change it to XRGB8888.
 	 */
 	if (ctx->driver_data->has_limited_fmt && !win) {
-		if (win_data->pixel_format == DRM_FORMAT_ARGB8888)
-			win_data->pixel_format = DRM_FORMAT_XRGB8888;
+		if (plane->pixel_format == DRM_FORMAT_ARGB8888)
+			plane->pixel_format = DRM_FORMAT_XRGB8888;
 	}
 
-	switch (win_data->pixel_format) {
+	switch (plane->pixel_format) {
 	case DRM_FORMAT_C8:
 		val |= WINCON0_BPPMODE_8BPP_PALETTE;
 		val |= WINCONx_BURSTLEN_8WORD;
@@ -607,7 +543,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
 		break;
 	}
 
-	DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
+	DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);
 
 	/*
 	 * In case of exynos, setting dma-burst to 16Word causes permanent
@@ -617,7 +553,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
 	 * movement causes unstable DMA which results into iommu crash/tear.
 	 */
 
-	if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
+	if (plane->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
 		val &= ~WINCONx_BURSTLEN_MASK;
 		val |= WINCONx_BURSTLEN_4WORD;
 	}
@@ -668,11 +604,11 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
 static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 {
 	struct fimd_context *ctx = crtc->ctx;
-	struct fimd_win_data *win_data;
+	struct exynos_drm_plane *plane;
 	int win = zpos;
-	unsigned long val, alpha, size;
-	unsigned int last_x;
-	unsigned int last_y;
+	dma_addr_t dma_addr;
+	unsigned long val, alpha, size, offset;
+	unsigned int last_x, last_y, buf_offsize, line_size;
 
 	if (ctx->suspended)
 		return;
@@ -683,11 +619,11 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 	if (win < 0 || win >= WINDOWS_NR)
 		return;
 
-	win_data = &ctx->win_data[win];
+	plane = &ctx->planes[win];
 
 	/* If suspended, enable this on resume */
 	if (ctx->suspended) {
-		win_data->resume = true;
+		plane->resume = true;
 		return;
 	}
 
@@ -704,38 +640,45 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 	/* protect windows */
 	fimd_shadow_protect_win(ctx, win, true);
 
+
+	offset = plane->fb_x * (plane->bpp >> 3);
+	offset += plane->fb_y * plane->pitch;
+
 	/* buffer start address */
-	val = (unsigned long)win_data->dma_addr;
+	dma_addr = plane->dma_addr[0] + offset;
+	val = (unsigned long)dma_addr;
 	writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
 
 	/* buffer end address */
-	size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
-	val = (unsigned long)(win_data->dma_addr + size);
+	size = plane->fb_width * plane->crtc_height * (plane->bpp >> 3);
+	val = (unsigned long)(dma_addr + size);
 	writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
 
 	DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
-			(unsigned long)win_data->dma_addr, val, size);
+			(unsigned long)dma_addr, val, size);
 	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
-			win_data->ovl_width, win_data->ovl_height);
+			plane->crtc_width, plane->crtc_height);
 
 	/* buffer size */
-	val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
-		VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size) |
-		VIDW_BUF_SIZE_OFFSET_E(win_data->buf_offsize) |
-		VIDW_BUF_SIZE_PAGEWIDTH_E(win_data->line_size);
+	buf_offsize = (plane->fb_width - plane->crtc_width) * (plane->bpp >> 3);
+	line_size = plane->crtc_width * (plane->bpp >> 3);
+	val = VIDW_BUF_SIZE_OFFSET(buf_offsize) |
+		VIDW_BUF_SIZE_PAGEWIDTH(line_size) |
+		VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
+		VIDW_BUF_SIZE_PAGEWIDTH_E(line_size);
 	writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
 
 	/* OSD position */
-	val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
-		VIDOSDxA_TOPLEFT_Y(win_data->offset_y) |
-		VIDOSDxA_TOPLEFT_X_E(win_data->offset_x) |
-		VIDOSDxA_TOPLEFT_Y_E(win_data->offset_y);
+	val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
+		VIDOSDxA_TOPLEFT_Y(plane->crtc_y) |
+		VIDOSDxA_TOPLEFT_X_E(plane->crtc_x) |
+		VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y);
 	writel(val, ctx->regs + VIDOSD_A(win));
 
-	last_x = win_data->offset_x + win_data->ovl_width;
+	last_x = plane->crtc_x + plane->crtc_width;
 	if (last_x)
 		last_x--;
-	last_y = win_data->offset_y + win_data->ovl_height;
+	last_y = plane->crtc_y + plane->crtc_height;
 	if (last_y)
 		last_y--;
 
@@ -745,7 +688,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 	writel(val, ctx->regs + VIDOSD_B(win));
 
 	DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
-			win_data->offset_x, win_data->offset_y, last_x, last_y);
+			plane->crtc_x, plane->crtc_y, last_x, last_y);
 
 	/* hardware window 0 doesn't support alpha channel. */
 	if (win != 0) {
@@ -762,7 +705,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 		u32 offset = VIDOSD_D(win);
 		if (win == 0)
 			offset = VIDOSD_C(win);
-		val = win_data->ovl_width * win_data->ovl_height;
+		val = plane->crtc_width * plane->crtc_height;
 		writel(val, ctx->regs + offset);
 
 		DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
@@ -782,7 +725,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 	/* Enable DMA channel and unprotect windows */
 	fimd_shadow_protect_win(ctx, win, false);
 
-	win_data->enabled = true;
+	plane->enabled = true;
 
 	if (ctx->i80_if)
 		atomic_set(&ctx->win_updated, 1);
@@ -791,7 +734,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
 {
 	struct fimd_context *ctx = crtc->ctx;
-	struct fimd_win_data *win_data;
+	struct exynos_drm_plane *plane;
 	int win = zpos;
 
 	if (win == DEFAULT_ZPOS)
@@ -800,11 +743,11 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
 	if (win < 0 || win >= WINDOWS_NR)
 		return;
 
-	win_data = &ctx->win_data[win];
+	plane = &ctx->planes[win];
 
 	if (ctx->suspended) {
 		/* do not resume this window*/
-		win_data->resume = false;
+		plane->resume = false;
 		return;
 	}
 
@@ -819,42 +762,42 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
 	/* unprotect windows */
 	fimd_shadow_protect_win(ctx, win, false);
 
-	win_data->enabled = false;
+	plane->enabled = false;
 }
 
 static void fimd_window_suspend(struct fimd_context *ctx)
 {
-	struct fimd_win_data *win_data;
+	struct exynos_drm_plane *plane;
 	int i;
 
 	for (i = 0; i < WINDOWS_NR; i++) {
-		win_data = &ctx->win_data[i];
-		win_data->resume = win_data->enabled;
-		if (win_data->enabled)
+		plane = &ctx->planes[i];
+		plane->resume = plane->enabled;
+		if (plane->enabled)
 			fimd_win_disable(ctx->crtc, i);
 	}
 }
 
 static void fimd_window_resume(struct fimd_context *ctx)
 {
-	struct fimd_win_data *win_data;
+	struct exynos_drm_plane *plane;
 	int i;
 
 	for (i = 0; i < WINDOWS_NR; i++) {
-		win_data = &ctx->win_data[i];
-		win_data->enabled = win_data->resume;
-		win_data->resume = false;
+		plane = &ctx->planes[i];
+		plane->enabled = plane->resume;
+		plane->resume = false;
 	}
 }
 
 static void fimd_apply(struct fimd_context *ctx)
 {
-	struct fimd_win_data *win_data;
+	struct exynos_drm_plane *plane;
 	int i;
 
 	for (i = 0; i < WINDOWS_NR; i++) {
-		win_data = &ctx->win_data[i];
-		if (win_data->enabled)
+		plane = &ctx->planes[i];
+		if (plane->enabled)
 			fimd_win_commit(ctx->crtc, i);
 		else
 			fimd_win_disable(ctx->crtc, i);
@@ -1011,7 +954,6 @@ static struct exynos_drm_crtc_ops fimd_crtc_ops = {
 	.enable_vblank = fimd_enable_vblank,
 	.disable_vblank = fimd_disable_vblank,
 	.wait_for_vblank = fimd_wait_for_vblank,
-	.win_mode_set = fimd_win_mode_set,
 	.win_commit = fimd_win_commit,
 	.win_disable = fimd_win_disable,
 	.te_handler = fimd_te_handler,
@@ -1056,7 +998,16 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
 {
 	struct fimd_context *ctx = dev_get_drvdata(dev);
 	struct drm_device *drm_dev = data;
-	int ret;
+	struct exynos_drm_plane *exynos_plane;
+	enum drm_plane_type type;
+	int i, ret;
+
+	for (i = 0; i < WINDOWS_NR; i++) {
+		type = (i == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
+						DRM_PLANE_TYPE_OVERLAY;
+		exynos_plane_init(drm_dev, &ctx->planes[i], 1 << ctx->pipe,
+				  type);
+	}
 
 	ret = fimd_ctx_initialize(ctx, drm_dev);
 	if (ret) {
@@ -1064,8 +1015,9 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
 		return ret;
 	}
 
-	ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
-					   EXYNOS_DISPLAY_TYPE_LCD,
+	exynos_plane = &ctx->planes[ctx->default_win];
+	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
+					   ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
 					   &fimd_crtc_ops, ctx);
 	if (IS_ERR(ctx->crtc)) {
 		fimd_ctx_remove(ctx);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 358cff6..dc13621 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -93,7 +93,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
 			  uint32_t src_w, uint32_t src_h)
 {
 	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
-	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 	unsigned int actual_w;
 	unsigned int actual_h;
 
@@ -140,9 +139,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
 			exynos_plane->crtc_width, exynos_plane->crtc_height);
 
 	plane->crtc = crtc;
-
-	if (exynos_crtc->ops->win_mode_set)
-		exynos_crtc->ops->win_mode_set(exynos_crtc, exynos_plane);
 }
 
 void exynos_plane_dpms(struct drm_plane *plane, int mode)
@@ -255,24 +251,18 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
 	drm_object_attach_property(&plane->base, prop, 0);
 }
 
-struct drm_plane *exynos_plane_init(struct drm_device *dev,
-				    unsigned long possible_crtcs,
-				    enum drm_plane_type type)
+int exynos_plane_init(struct drm_device *dev,
+		      struct exynos_drm_plane *exynos_plane,
+		      unsigned long possible_crtcs, enum drm_plane_type type)
 {
-	struct exynos_drm_plane *exynos_plane;
 	int err;
 
-	exynos_plane = kzalloc(sizeof(struct exynos_drm_plane), GFP_KERNEL);
-	if (!exynos_plane)
-		return ERR_PTR(-ENOMEM);
-
 	err = drm_universal_plane_init(dev, &exynos_plane->base, possible_crtcs,
 				       &exynos_plane_funcs, formats,
 				       ARRAY_SIZE(formats), type);
 	if (err) {
 		DRM_ERROR("failed to initialize plane\n");
-		kfree(exynos_plane);
-		return ERR_PTR(err);
+		return err;
 	}
 
 	if (type == DRM_PLANE_TYPE_PRIMARY)
@@ -280,5 +270,5 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
 	else
 		exynos_plane_attach_zpos_property(&exynos_plane->base);
 
-	return &exynos_plane->base;
+	return 0;
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index 59d4075..100ca5e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -21,6 +21,6 @@ int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 			uint32_t src_x, uint32_t src_y,
 			uint32_t src_w, uint32_t src_h);
 void exynos_plane_dpms(struct drm_plane *plane, int mode);
-struct drm_plane *exynos_plane_init(struct drm_device *dev,
-				    unsigned long possible_crtcs,
-				    enum drm_plane_type type);
+int exynos_plane_init(struct drm_device *dev,
+		      struct exynos_drm_plane *exynos_plane,
+		      unsigned long possible_crtcs, enum drm_plane_type type);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index b886972..08c7a1e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -23,6 +23,7 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
+#include "exynos_drm_plane.h"
 #include "exynos_drm_encoder.h"
 #include "exynos_drm_vidi.h"
 
@@ -32,20 +33,6 @@
 #define ctx_from_connector(c)	container_of(c, struct vidi_context, \
 					connector)
 
-struct vidi_win_data {
-	unsigned int		offset_x;
-	unsigned int		offset_y;
-	unsigned int		ovl_width;
-	unsigned int		ovl_height;
-	unsigned int		fb_width;
-	unsigned int		fb_height;
-	unsigned int		bpp;
-	dma_addr_t		dma_addr;
-	unsigned int		buf_offsize;
-	unsigned int		line_size;	/* bytes */
-	bool			enabled;
-};
-
 struct vidi_context {
 	struct exynos_drm_display	display;
 	struct platform_device		*pdev;
@@ -53,7 +40,7 @@ struct vidi_context {
 	struct exynos_drm_crtc		*crtc;
 	struct drm_encoder		*encoder;
 	struct drm_connector		connector;
-	struct vidi_win_data		win_data[WINDOWS_NR];
+	struct exynos_drm_plane		planes[WINDOWS_NR];
 	struct edid			*raw_edid;
 	unsigned int			clkdiv;
 	unsigned int			default_win;
@@ -97,19 +84,6 @@ static const char fake_edid_info[] = {
 	0x00, 0x00, 0x00, 0x06
 };
 
-static void vidi_apply(struct vidi_context *ctx)
-{
-	struct exynos_drm_crtc_ops *crtc_ops = ctx->crtc->ops;
-	struct vidi_win_data *win_data;
-	int i;
-
-	for (i = 0; i < WINDOWS_NR; i++) {
-		win_data = &ctx->win_data[i];
-		if (win_data->enabled && (crtc_ops && crtc_ops->win_commit))
-			crtc_ops->win_commit(ctx->crtc, i);
-	}
-}
-
 static int vidi_enable_vblank(struct exynos_drm_crtc *crtc)
 {
 	struct vidi_context *ctx = crtc->ctx;
@@ -143,63 +117,10 @@ static void vidi_disable_vblank(struct exynos_drm_crtc *crtc)
 		ctx->vblank_on = false;
 }
 
-static void vidi_win_mode_set(struct exynos_drm_crtc *crtc,
-			struct exynos_drm_plane *plane)
-{
-	struct vidi_context *ctx = crtc->ctx;
-	struct vidi_win_data *win_data;
-	int win;
-	unsigned long offset;
-
-	if (!plane) {
-		DRM_ERROR("plane is NULL\n");
-		return;
-	}
-
-	win = plane->zpos;
-	if (win == DEFAULT_ZPOS)
-		win = ctx->default_win;
-
-	if (win < 0 || win >= WINDOWS_NR)
-		return;
-
-	offset = plane->fb_x * (plane->bpp >> 3);
-	offset += plane->fb_y * plane->pitch;
-
-	DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
-
-	win_data = &ctx->win_data[win];
-
-	win_data->offset_x = plane->crtc_x;
-	win_data->offset_y = plane->crtc_y;
-	win_data->ovl_width = plane->crtc_width;
-	win_data->ovl_height = plane->crtc_height;
-	win_data->fb_width = plane->fb_width;
-	win_data->fb_height = plane->fb_height;
-	win_data->dma_addr = plane->dma_addr[0] + offset;
-	win_data->bpp = plane->bpp;
-	win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
-				(plane->bpp >> 3);
-	win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
-
-	/*
-	 * some parts of win_data should be transferred to user side
-	 * through specific ioctl.
-	 */
-
-	DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
-			win_data->offset_x, win_data->offset_y);
-	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
-			win_data->ovl_width, win_data->ovl_height);
-	DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
-	DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
-			plane->fb_width, plane->crtc_width);
-}
-
 static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 {
 	struct vidi_context *ctx = crtc->ctx;
-	struct vidi_win_data *win_data;
+	struct exynos_drm_plane *plane;
 	int win = zpos;
 
 	if (ctx->suspended)
@@ -211,11 +132,11 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 	if (win < 0 || win >= WINDOWS_NR)
 		return;
 
-	win_data = &ctx->win_data[win];
+	plane = &ctx->planes[win];
 
-	win_data->enabled = true;
+	plane->enabled = true;
 
-	DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data->dma_addr);
+	DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
 
 	if (ctx->vblank_on)
 		schedule_work(&ctx->work);
@@ -224,7 +145,7 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
 {
 	struct vidi_context *ctx = crtc->ctx;
-	struct vidi_win_data *win_data;
+	struct exynos_drm_plane *plane;
 	int win = zpos;
 
 	if (win == DEFAULT_ZPOS)
@@ -233,14 +154,17 @@ static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
 	if (win < 0 || win >= WINDOWS_NR)
 		return;
 
-	win_data = &ctx->win_data[win];
-	win_data->enabled = false;
+	plane = &ctx->planes[win];
+	plane->enabled = false;
 
 	/* TODO. */
 }
 
 static int vidi_power_on(struct vidi_context *ctx, bool enable)
 {
+	struct exynos_drm_plane *plane;
+	int i;
+
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
 	if (enable != false && enable != true)
@@ -253,7 +177,11 @@ static int vidi_power_on(struct vidi_context *ctx, bool enable)
 		if (test_and_clear_bit(0, &ctx->irq_flags))
 			vidi_enable_vblank(ctx->crtc);
 
-		vidi_apply(ctx);
+		for (i = 0; i < WINDOWS_NR; i++) {
+			plane = &ctx->planes[i];
+			if (plane->enabled)
+				vidi_win_commit(ctx->crtc, i);
+		}
 	} else {
 		ctx->suspended = true;
 	}
@@ -301,7 +229,6 @@ static struct exynos_drm_crtc_ops vidi_crtc_ops = {
 	.dpms = vidi_dpms,
 	.enable_vblank = vidi_enable_vblank,
 	.disable_vblank = vidi_disable_vblank,
-	.win_mode_set = vidi_win_mode_set,
 	.win_commit = vidi_win_commit,
 	.win_disable = vidi_win_disable,
 };
@@ -543,12 +470,22 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
 {
 	struct vidi_context *ctx = dev_get_drvdata(dev);
 	struct drm_device *drm_dev = data;
-	int ret;
+	struct exynos_drm_plane *exynos_plane;
+	enum drm_plane_type type;
+	int i, ret;
+
+	for (i = 0; i < WINDOWS_NR; i++) {
+		type = (i == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
+						DRM_PLANE_TYPE_OVERLAY;
+		exynos_plane_init(drm_dev, &ctx->planes[i], 1 << ctx->pipe,
+				  type);
+	}
 
 	vidi_ctx_initialize(ctx, drm_dev);
 
-	ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
-					   EXYNOS_DISPLAY_TYPE_VIDI,
+	exynos_plane = &ctx->planes[ctx->default_win];
+	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
+					   ctx->pipe, EXYNOS_DISPLAY_TYPE_VIDI,
 					   &vidi_crtc_ops, ctx);
 	if (IS_ERR(ctx->crtc)) {
 		DRM_ERROR("failed to create crtc.\n");
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 736269a..d6864e6 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -37,34 +37,13 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
+#include "exynos_drm_plane.h"
 #include "exynos_drm_iommu.h"
 #include "exynos_mixer.h"
 
 #define MIXER_WIN_NR		3
 #define MIXER_DEFAULT_WIN	0
 
-struct hdmi_win_data {
-	dma_addr_t		dma_addr;
-	dma_addr_t		chroma_dma_addr;
-	uint32_t		pixel_format;
-	unsigned int		bpp;
-	unsigned int		crtc_x;
-	unsigned int		crtc_y;
-	unsigned int		crtc_width;
-	unsigned int		crtc_height;
-	unsigned int		fb_x;
-	unsigned int		fb_y;
-	unsigned int		fb_width;
-	unsigned int		fb_height;
-	unsigned int		src_width;
-	unsigned int		src_height;
-	unsigned int		mode_width;
-	unsigned int		mode_height;
-	unsigned int		scan_flags;
-	bool			enabled;
-	bool			resume;
-};
-
 struct mixer_resources {
 	int			irq;
 	void __iomem		*mixer_regs;
@@ -88,6 +67,7 @@ struct mixer_context {
 	struct device		*dev;
 	struct drm_device	*drm_dev;
 	struct exynos_drm_crtc	*crtc;
+	struct exynos_drm_plane	planes[MIXER_WIN_NR];
 	int			pipe;
 	bool			interlace;
 	bool			powered;
@@ -97,7 +77,6 @@ struct mixer_context {
 
 	struct mutex		mixer_mutex;
 	struct mixer_resources	mixer_res;
-	struct hdmi_win_data	win_data[MIXER_WIN_NR];
 	enum mixer_version_id	mxr_ver;
 	wait_queue_head_t	wait_vsync_queue;
 	atomic_t		wait_vsync_event;
@@ -401,7 +380,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
 {
 	struct mixer_resources *res = &ctx->mixer_res;
 	unsigned long flags;
-	struct hdmi_win_data *win_data;
+	struct exynos_drm_plane *plane;
 	unsigned int x_ratio, y_ratio;
 	unsigned int buf_num = 1;
 	dma_addr_t luma_addr[2], chroma_addr[2];
@@ -409,9 +388,9 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
 	bool crcb_mode = false;
 	u32 val;
 
-	win_data = &ctx->win_data[win];
+	plane = &ctx->planes[win];
 
-	switch (win_data->pixel_format) {
+	switch (plane->pixel_format) {
 	case DRM_FORMAT_NV12MT:
 		tiled_mode = true;
 	case DRM_FORMAT_NV12:
@@ -421,35 +400,35 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
 	/* TODO: single buffer format NV12, NV21 */
 	default:
 		/* ignore pixel format at disable time */
-		if (!win_data->dma_addr)
+		if (!plane->dma_addr[0])
 			break;
 
 		DRM_ERROR("pixel format for vp is wrong [%d].\n",
-				win_data->pixel_format);
+				plane->pixel_format);
 		return;
 	}
 
 	/* scaling feature: (src << 16) / dst */
-	x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
-	y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
+	x_ratio = (plane->src_width << 16) / plane->crtc_width;
+	y_ratio = (plane->src_height << 16) / plane->crtc_height;
 
 	if (buf_num == 2) {
-		luma_addr[0] = win_data->dma_addr;
-		chroma_addr[0] = win_data->chroma_dma_addr;
+		luma_addr[0] = plane->dma_addr[0];
+		chroma_addr[0] = plane->dma_addr[1];
 	} else {
-		luma_addr[0] = win_data->dma_addr;
-		chroma_addr[0] = win_data->dma_addr
-			+ (win_data->fb_width * win_data->fb_height);
+		luma_addr[0] = plane->dma_addr[0];
+		chroma_addr[0] = plane->dma_addr[0]
+			+ (plane->fb_width * plane->fb_height);
 	}
 
-	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
+	if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) {
 		ctx->interlace = true;
 		if (tiled_mode) {
 			luma_addr[1] = luma_addr[0] + 0x40;
 			chroma_addr[1] = chroma_addr[0] + 0x40;
 		} else {
-			luma_addr[1] = luma_addr[0] + win_data->fb_width;
-			chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
+			luma_addr[1] = luma_addr[0] + plane->fb_width;
+			chroma_addr[1] = chroma_addr[0] + plane->fb_width;
 		}
 	} else {
 		ctx->interlace = false;
@@ -470,26 +449,26 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
 	vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
 
 	/* setting size of input image */
-	vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
-		VP_IMG_VSIZE(win_data->fb_height));
+	vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->fb_width) |
+		VP_IMG_VSIZE(plane->fb_height));
 	/* chroma height has to reduced by 2 to avoid chroma distorions */
-	vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
-		VP_IMG_VSIZE(win_data->fb_height / 2));
+	vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->fb_width) |
+		VP_IMG_VSIZE(plane->fb_height / 2));
 
-	vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
-	vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
+	vp_reg_write(res, VP_SRC_WIDTH, plane->src_width);
+	vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height);
 	vp_reg_write(res, VP_SRC_H_POSITION,
-			VP_SRC_H_POSITION_VAL(win_data->fb_x));
-	vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
+			VP_SRC_H_POSITION_VAL(plane->fb_x));
+	vp_reg_write(res, VP_SRC_V_POSITION, plane->fb_y);
 
-	vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
-	vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
+	vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width);
+	vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
 	if (ctx->interlace) {
-		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
-		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
+		vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2);
+		vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
 	} else {
-		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
-		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
+		vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height);
+		vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
 	}
 
 	vp_reg_write(res, VP_H_RATIO, x_ratio);
@@ -503,8 +482,8 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
 	vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
 	vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
 
-	mixer_cfg_scan(ctx, win_data->mode_height);
-	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
+	mixer_cfg_scan(ctx, plane->mode_height);
+	mixer_cfg_rgb_fmt(ctx, plane->mode_height);
 	mixer_cfg_layer(ctx, win, true);
 	mixer_run(ctx);
 
@@ -525,21 +504,21 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
 {
 	struct mixer_resources *res = &ctx->mixer_res;
 	unsigned long flags;
-	struct hdmi_win_data *win_data;
+	struct exynos_drm_plane *plane;
 	unsigned int x_ratio, y_ratio;
 	unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
 	dma_addr_t dma_addr;
 	unsigned int fmt;
 	u32 val;
 
-	win_data = &ctx->win_data[win];
+	plane = &ctx->planes[win];
 
 	#define RGB565 4
 	#define ARGB1555 5
 	#define ARGB4444 6
 	#define ARGB8888 7
 
-	switch (win_data->bpp) {
+	switch (plane->bpp) {
 	case 16:
 		fmt = ARGB4444;
 		break;
@@ -554,17 +533,17 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
 	x_ratio = 0;
 	y_ratio = 0;
 
-	dst_x_offset = win_data->crtc_x;
-	dst_y_offset = win_data->crtc_y;
+	dst_x_offset = plane->crtc_x;
+	dst_y_offset = plane->crtc_y;
 
 	/* converting dma address base and source offset */
-	dma_addr = win_data->dma_addr
-		+ (win_data->fb_x * win_data->bpp >> 3)
-		+ (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
+	dma_addr = plane->dma_addr[0]
+		+ (plane->fb_x * plane->bpp >> 3)
+		+ (plane->fb_y * plane->fb_width * plane->bpp >> 3);
 	src_x_offset = 0;
 	src_y_offset = 0;
 
-	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
+	if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE)
 		ctx->interlace = true;
 	else
 		ctx->interlace = false;
@@ -577,18 +556,18 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
 		MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
 
 	/* setup geometry */
-	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
+	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), plane->fb_width);
 
 	/* setup display size */
 	if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
 		win == MIXER_DEFAULT_WIN) {
-		val  = MXR_MXR_RES_HEIGHT(win_data->fb_height);
-		val |= MXR_MXR_RES_WIDTH(win_data->fb_width);
+		val  = MXR_MXR_RES_HEIGHT(plane->fb_height);
+		val |= MXR_MXR_RES_WIDTH(plane->fb_width);
 		mixer_reg_write(res, MXR_RESOLUTION, val);
 	}
 
-	val  = MXR_GRP_WH_WIDTH(win_data->crtc_width);
-	val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
+	val  = MXR_GRP_WH_WIDTH(plane->crtc_width);
+	val |= MXR_GRP_WH_HEIGHT(plane->crtc_height);
 	val |= MXR_GRP_WH_H_SCALE(x_ratio);
 	val |= MXR_GRP_WH_V_SCALE(y_ratio);
 	mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
@@ -606,8 +585,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
 	/* set buffer address to mixer */
 	mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
 
-	mixer_cfg_scan(ctx, win_data->mode_height);
-	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
+	mixer_cfg_scan(ctx, plane->mode_height);
+	mixer_cfg_rgb_fmt(ctx, plane->mode_height);
 	mixer_cfg_layer(ctx, win, true);
 
 	/* layer update mandatory for mixer 16.0.33.0 */
@@ -913,58 +892,6 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
 	mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 }
 
-static void mixer_win_mode_set(struct exynos_drm_crtc *crtc,
-			struct exynos_drm_plane *plane)
-{
-	struct mixer_context *mixer_ctx = crtc->ctx;
-	struct hdmi_win_data *win_data;
-	int win;
-
-	if (!plane) {
-		DRM_ERROR("plane is NULL\n");
-		return;
-	}
-
-	DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
-				 plane->fb_width, plane->fb_height,
-				 plane->fb_x, plane->fb_y,
-				 plane->crtc_width, plane->crtc_height,
-				 plane->crtc_x, plane->crtc_y);
-
-	win = plane->zpos;
-	if (win == DEFAULT_ZPOS)
-		win = MIXER_DEFAULT_WIN;
-
-	if (win < 0 || win >= MIXER_WIN_NR) {
-		DRM_ERROR("mixer window[%d] is wrong\n", win);
-		return;
-	}
-
-	win_data = &mixer_ctx->win_data[win];
-
-	win_data->dma_addr = plane->dma_addr[0];
-	win_data->chroma_dma_addr = plane->dma_addr[1];
-	win_data->pixel_format = plane->pixel_format;
-	win_data->bpp = plane->bpp;
-
-	win_data->crtc_x = plane->crtc_x;
-	win_data->crtc_y = plane->crtc_y;
-	win_data->crtc_width = plane->crtc_width;
-	win_data->crtc_height = plane->crtc_height;
-
-	win_data->fb_x = plane->fb_x;
-	win_data->fb_y = plane->fb_y;
-	win_data->fb_width = plane->fb_width;
-	win_data->fb_height = plane->fb_height;
-	win_data->src_width = plane->src_width;
-	win_data->src_height = plane->src_height;
-
-	win_data->mode_width = plane->mode_width;
-	win_data->mode_height = plane->mode_height;
-
-	win_data->scan_flags = plane->scan_flag;
-}
-
 static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 {
 	struct mixer_context *mixer_ctx = crtc->ctx;
@@ -984,7 +911,7 @@ static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 	else
 		mixer_graph_buffer(mixer_ctx, win);
 
-	mixer_ctx->win_data[win].enabled = true;
+	mixer_ctx->planes[win].enabled = true;
 }
 
 static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
@@ -999,7 +926,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
 	mutex_lock(&mixer_ctx->mixer_mutex);
 	if (!mixer_ctx->powered) {
 		mutex_unlock(&mixer_ctx->mixer_mutex);
-		mixer_ctx->win_data[win].resume = false;
+		mixer_ctx->planes[win].resume = false;
 		return;
 	}
 	mutex_unlock(&mixer_ctx->mixer_mutex);
@@ -1012,7 +939,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
 	mixer_vsync_set_update(mixer_ctx, true);
 	spin_unlock_irqrestore(&res->reg_slock, flags);
 
-	mixer_ctx->win_data[win].enabled = false;
+	mixer_ctx->planes[win].enabled = false;
 }
 
 static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
@@ -1049,12 +976,12 @@ static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
 
 static void mixer_window_suspend(struct mixer_context *ctx)
 {
-	struct hdmi_win_data *win_data;
+	struct exynos_drm_plane *plane;
 	int i;
 
 	for (i = 0; i < MIXER_WIN_NR; i++) {
-		win_data = &ctx->win_data[i];
-		win_data->resume = win_data->enabled;
+		plane = &ctx->planes[i];
+		plane->resume = plane->enabled;
 		mixer_win_disable(ctx->crtc, i);
 	}
 	mixer_wait_for_vblank(ctx->crtc);
@@ -1062,14 +989,14 @@ static void mixer_window_suspend(struct mixer_context *ctx)
 
 static void mixer_window_resume(struct mixer_context *ctx)
 {
-	struct hdmi_win_data *win_data;
+	struct exynos_drm_plane *plane;
 	int i;
 
 	for (i = 0; i < MIXER_WIN_NR; i++) {
-		win_data = &ctx->win_data[i];
-		win_data->enabled = win_data->resume;
-		win_data->resume = false;
-		if (win_data->enabled)
+		plane = &ctx->planes[i];
+		plane->enabled = plane->resume;
+		plane->resume = false;
+		if (plane->enabled)
 			mixer_win_commit(ctx->crtc, i);
 	}
 }
@@ -1179,7 +1106,6 @@ static struct exynos_drm_crtc_ops mixer_crtc_ops = {
 	.enable_vblank		= mixer_enable_vblank,
 	.disable_vblank		= mixer_disable_vblank,
 	.wait_for_vblank	= mixer_wait_for_vblank,
-	.win_mode_set		= mixer_win_mode_set,
 	.win_commit		= mixer_win_commit,
 	.win_disable		= mixer_win_disable,
 };
@@ -1243,15 +1169,25 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
 {
 	struct mixer_context *ctx = dev_get_drvdata(dev);
 	struct drm_device *drm_dev = data;
-	int ret;
+	struct exynos_drm_plane *exynos_plane;
+	enum drm_plane_type type;
+	int i, ret;
+
+	for (i = 0; i < MIXER_WIN_NR; i++) {
+		type = (i == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
+						DRM_PLANE_TYPE_OVERLAY;
+		exynos_plane_init(drm_dev, &ctx->planes[i], 1 << ctx->pipe,
+				  type);
+	}
 
 	ret = mixer_initialize(ctx, drm_dev);
 	if (ret)
 		return ret;
 
-	ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
-				     EXYNOS_DISPLAY_TYPE_HDMI,
-				     &mixer_crtc_ops, ctx);
+	exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
+	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
+					   ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
+					   &mixer_crtc_ops, ctx);
 	if (IS_ERR(ctx->crtc)) {
 		mixer_ctx_remove(ctx);
 		ret = PTR_ERR(ctx->crtc);
-- 
1.9.3

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

* [PATCH 05/14] drm/exynos: do not copy adjusted mode into mode during crtc mode_set
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
                   ` (3 preceding siblings ...)
  2015-02-03 19:14 ` [PATCH 04/14] drm/exynos: remove struct *_win_data abstraction on planes Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-03 19:14 ` [PATCH 06/14] drm/exynos: atomic phase 1: use drm_plane_helper_update() Gustavo Padovan
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: dri-devel

From: Daniel Kurtz <djkurtz@chromium.org>

The 'mode' is the modeline information which specifies the ideal mode
requested by the mode set initiator (usually userspace).
The 'adjusted_mode' is the actual hardware mode after all the crtcs
and encoders have had a chance to "fix it up".

The adjusted_mode starts as a duplicate of the mode in
drm_crtc_helper_set_mode(), and gets modified as required.  There is no
reason to touch the original requested mode.

In fact, doing so will cause us to think a new mode is being requested
whenever userspace tries to establish a new framebuffer with
drmModeSetCrtc(), since userspace will still be using the ideal mode, but
the crtc will be incorrectly comparing it against the adjusted_mode.

Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_crtc.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index d504f0b..ecbcade 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -91,12 +91,6 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	unsigned int crtc_h;
 	int ret;
 
-	/*
-	 * copy the mode data adjusted by mode_fixup() into crtc->mode
-	 * so that hardware can be seet to proper mode.
-	 */
-	memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
-
 	ret = exynos_check_plane(crtc->primary, fb);
 	if (ret < 0)
 		return ret;
-- 
1.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 06/14] drm/exynos: atomic phase 1: use drm_plane_helper_update()
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
                   ` (4 preceding siblings ...)
  2015-02-03 19:14 ` [PATCH 05/14] drm/exynos: do not copy adjusted mode into mode during crtc mode_set Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-03 19:14 ` [PATCH 07/14] drm/exynos: atomic phase 1: use drm_plane_helper_disable() Gustavo Padovan
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: Gustavo Padovan, dri-devel

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

Rip out the check from exynos_update_plane() and create
exynos_check_plane() for the check phase enabling use to use
the atomic helpers to call our check and update phases when updating
planes.

Update all users of exynos_update_plane() accordingly to call
exynos_check_plane() before.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_crtc.c  | 29 ++++++++++++------------
 drivers/gpu/drm/exynos/exynos_drm_plane.c | 37 ++++++++++++++++++++++---------
 drivers/gpu/drm/exynos/exynos_drm_plane.h |  2 +-
 3 files changed, 43 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index ecbcade..09d4780 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -110,6 +110,7 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 	struct drm_framebuffer *fb = crtc->primary->fb;
 	unsigned int crtc_w;
 	unsigned int crtc_h;
+	int ret;
 
 	/* when framebuffer changing is requested, crtc's dpms should be on */
 	if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
@@ -117,11 +118,16 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 		return -EPERM;
 	}
 
+	ret = exynos_check_plane(crtc->primary, fb);
+	if (ret)
+		return ret;
+
 	crtc_w = fb->width - x;
 	crtc_h = fb->height - y;
+	exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
+			    crtc_w, crtc_h, x, y, crtc_w, crtc_h);
 
-	return exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
-				   crtc_w, crtc_h, x, y, crtc_w, crtc_h);
+	return 0;
 }
 
 static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
@@ -158,7 +164,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
-	struct drm_framebuffer *old_fb = crtc->primary->fb;
 	unsigned int crtc_w, crtc_h;
 	int ret;
 
@@ -177,6 +182,10 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
 		goto out;
 	}
 
+	ret = exynos_check_plane(crtc->primary, fb);
+	if (ret)
+		goto out;
+
 	ret = drm_vblank_get(dev, exynos_crtc->pipe);
 	if (ret) {
 		DRM_DEBUG("failed to acquire vblank counter\n");
@@ -195,17 +204,9 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
 	crtc->primary->fb = fb;
 	crtc_w = fb->width - crtc->x;
 	crtc_h = fb->height - crtc->y;
-	ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
-				  crtc_w, crtc_h, crtc->x, crtc->y,
-				  crtc_w, crtc_h);
-	if (ret) {
-		crtc->primary->fb = old_fb;
-		spin_lock_irq(&dev->event_lock);
-		exynos_crtc->event = NULL;
-		drm_vblank_put(dev, exynos_crtc->pipe);
-		spin_unlock_irq(&dev->event_lock);
-		return ret;
-	}
+	exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
+			    crtc_w, crtc_h, crtc->x, crtc->y,
+			    crtc_w, crtc_h);
 
 	return 0;
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index dc13621..2c356b9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -167,21 +167,15 @@ void exynos_plane_dpms(struct drm_plane *plane, int mode)
 	}
 }
 
-int
+void
 exynos_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 exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
-	int ret;
-
-	ret = exynos_check_plane(plane, fb);
-	if (ret < 0)
-		return ret;
 
 	exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y,
 			      crtc_w, crtc_h, src_x >> 16, src_y >> 16,
@@ -189,8 +183,6 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 
 	if (exynos_crtc->ops->win_commit)
 		exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);
-
-	return 0;
 }
 
 static int exynos_disable_plane(struct drm_plane *plane)
@@ -226,12 +218,35 @@ static int exynos_plane_set_property(struct drm_plane *plane,
 }
 
 static struct drm_plane_funcs exynos_plane_funcs = {
-	.update_plane	= exynos_update_plane,
+	.update_plane	= drm_plane_helper_update,
 	.disable_plane	= exynos_disable_plane,
 	.destroy	= exynos_plane_destroy,
 	.set_property	= exynos_plane_set_property,
 };
 
+static int exynos_plane_atomic_check(struct drm_plane *plane,
+				     struct drm_plane_state *state)
+{
+	return exynos_check_plane(plane, state->fb);
+}
+
+static void exynos_plane_atomic_update(struct drm_plane *plane,
+				       struct drm_plane_state *old_state)
+{
+	struct drm_plane_state *state = plane->state;
+
+	exynos_update_plane(plane, state->crtc, state->fb,
+			    state->crtc_x, state->crtc_y,
+			    state->crtc_w, state->crtc_h,
+			    state->src_x >> 16, state->src_y >> 16,
+			    state->src_w >> 16, state->src_h >> 16);
+}
+
+static const struct drm_plane_helper_funcs plane_helper_funcs = {
+	.atomic_check = exynos_plane_atomic_check,
+	.atomic_update = exynos_plane_atomic_update,
+};
+
 static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
 {
 	struct drm_device *dev = plane->dev;
@@ -265,6 +280,8 @@ int exynos_plane_init(struct drm_device *dev,
 		return err;
 	}
 
+	drm_plane_helper_add(&exynos_plane->base, &plane_helper_funcs);
+
 	if (type == DRM_PLANE_TYPE_PRIMARY)
 		exynos_plane->zpos = DEFAULT_ZPOS;
 	else
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index 100ca5e..8361606 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -15,7 +15,7 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
 			   unsigned int crtc_w, unsigned int crtc_h,
 			   uint32_t src_x, uint32_t src_y,
 			   uint32_t src_w, uint32_t src_h);
-int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+void exynos_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,
-- 
1.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 07/14] drm/exynos: atomic phase 1: use drm_plane_helper_disable()
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
                   ` (5 preceding siblings ...)
  2015-02-03 19:14 ` [PATCH 06/14] drm/exynos: atomic phase 1: use drm_plane_helper_update() Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-04  7:47   ` Joonyoung Shim
  2015-02-03 19:14 ` [PATCH 08/14] drm/exynos: atomic phase 1: add atomic_begin()/atomic_flush() Gustavo Padovan
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: jy0922.shim, inki.dae, dri-devel, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

The atomic helper to disable planes also uses the optional
.atomic_disable() helper. The unique operation it does is calling
.win_disable()

exynos_drm_fb_get_buf_cnt() needs a fb check too to avoid a null pointer.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_fb.c    |  2 +-
 drivers/gpu/drm/exynos/exynos_drm_plane.c | 14 +++++++++++++-
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index d346d1e..470456d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -136,7 +136,7 @@ unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb)
 
 	exynos_fb = to_exynos_fb(fb);
 
-	return exynos_fb->buf_cnt;
+	return exynos_fb ? exynos_fb->buf_cnt : 0;
 }
 
 struct drm_framebuffer *
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 2c356b9..a3b0687 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -219,7 +219,7 @@ static int exynos_plane_set_property(struct drm_plane *plane,
 
 static struct drm_plane_funcs exynos_plane_funcs = {
 	.update_plane	= drm_plane_helper_update,
-	.disable_plane	= exynos_disable_plane,
+	.disable_plane	= drm_plane_helper_disable,
 	.destroy	= exynos_plane_destroy,
 	.set_property	= exynos_plane_set_property,
 };
@@ -242,9 +242,21 @@ static void exynos_plane_atomic_update(struct drm_plane *plane,
 			    state->src_w >> 16, state->src_h >> 16);
 }
 
+static void exynos_plane_atomic_disable(struct drm_plane *plane,
+				        struct drm_plane_state *old_state)
+{
+	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(old_state->crtc);
+
+	if (exynos_crtc->ops->win_disable)
+		exynos_crtc->ops->win_disable(exynos_crtc,
+					      exynos_plane->zpos);
+}
+
 static const struct drm_plane_helper_funcs plane_helper_funcs = {
 	.atomic_check = exynos_plane_atomic_check,
 	.atomic_update = exynos_plane_atomic_update,
+	.atomic_disable = exynos_plane_atomic_disable,
 };
 
 static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
-- 
1.9.3

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

* [PATCH 08/14] drm/exynos: atomic phase 1: add atomic_begin()/atomic_flush()
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
                   ` (6 preceding siblings ...)
  2015-02-03 19:14 ` [PATCH 07/14] drm/exynos: atomic phase 1: use drm_plane_helper_disable() Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-04  7:49   ` Joonyoung Shim
  2015-02-03 19:14 ` [PATCH 09/14] drm/exynos: atomic phase 1: add .mode_set_nofb() callback Gustavo Padovan
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: Gustavo Padovan, dri-devel

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

Add CRTC callbacks .atomic_begin() .atomic_flush(). On exynos they
unprotect the windows before the commit and protects it after based on
a plane mask tha store which plane will be updated.

For that we create two new exynos_crtc callbacks: .win_protect() and
.win_unprotect(). The only driver that implement those now is FIMD.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_crtc.c  | 34 ++++++++++++++++++
 drivers/gpu/drm/exynos/exynos_drm_drv.h   |  4 +++
 drivers/gpu/drm/exynos/exynos_drm_fimd.c  | 57 ++++++++++++++++++++++---------
 drivers/gpu/drm/exynos/exynos_drm_plane.c |  4 +++
 4 files changed, 82 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 09d4780..be36cca 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -147,6 +147,38 @@ static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
 	}
 }
 
+static void exynos_crtc_atomic_begin(struct drm_crtc *crtc)
+{
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct drm_plane *plane;
+	int index = 0;
+
+	list_for_each_entry(plane, &crtc->dev->mode_config.plane_list, head) {
+		if (exynos_crtc->ops->win_protect &&
+		    exynos_crtc->plane_mask & (0x01 << index))
+			exynos_crtc->ops->win_protect(exynos_crtc, index);
+
+		index++;
+	}
+}
+
+static void exynos_crtc_atomic_flush(struct drm_crtc *crtc)
+{
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct drm_plane *plane;
+	int index = 0;
+
+	list_for_each_entry(plane, &crtc->dev->mode_config.plane_list, head) {
+		if (exynos_crtc->ops->win_unprotect &&
+		    exynos_crtc->plane_mask & (0x01 << index))
+			exynos_crtc->ops->win_unprotect(exynos_crtc, index);
+
+		index++;
+	}
+
+	exynos_crtc->plane_mask = 0;
+}
+
 static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
 	.dpms		= exynos_drm_crtc_dpms,
 	.prepare	= exynos_drm_crtc_prepare,
@@ -155,6 +187,8 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
 	.mode_set	= exynos_drm_crtc_mode_set,
 	.mode_set_base	= exynos_drm_crtc_mode_set_base,
 	.disable	= exynos_drm_crtc_disable,
+	.atomic_begin	= exynos_crtc_atomic_begin,
+	.atomic_flush	= exynos_crtc_atomic_flush,
 };
 
 static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index cad54e7..43efd9f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -194,6 +194,8 @@ struct exynos_drm_crtc_ops {
 	void (*win_enable)(struct exynos_drm_crtc *crtc, int zpos);
 	void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
 	void (*te_handler)(struct exynos_drm_crtc *crtc);
+	void (*win_protect)(struct exynos_drm_crtc *crtc, int zpos);
+	void (*win_unprotect)(struct exynos_drm_crtc *crtc, int zpos);
 };
 
 enum exynos_crtc_mode {
@@ -214,6 +216,7 @@ enum exynos_crtc_mode {
  *	we can refer to the crtc to current hardware interrupt occurred through
  *	this pipe value.
  * @dpms: store the crtc dpms value
+ * @plane_mask: store planes to be updated on atomic modesetting
  * @mode: store the crtc mode value
  * @event: vblank event that is currently queued for flip
  * @ops: pointer to callbacks for exynos drm specific functionality
@@ -224,6 +227,7 @@ struct exynos_drm_crtc {
 	enum exynos_drm_output_type	type;
 	unsigned int			pipe;
 	unsigned int			dpms;
+	unsigned int			plane_mask;
 	enum exynos_crtc_mode		mode;
 	wait_queue_head_t		pending_flip_queue;
 	struct drm_pending_vblank_event	*event;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index ebb4cdc..f498d86 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -585,6 +585,16 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
 {
 	u32 reg, bits, val;
 
+	/*
+	 * SHADOWCON/PRTCON register is used for enabling timing.
+	 *
+	 * for example, once only width value of a register is set,
+	 * if the dma is started then fimd hardware could malfunction so
+	 * with protect window setting, the register fields with prefix '_F'
+	 * wouldn't be updated at vsync also but updated once unprotect window
+	 * is set.
+	 */
+
 	if (ctx->driver_data->has_shadowcon) {
 		reg = SHADOWCON;
 		bits = SHADOWCON_WINx_PROTECT(win);
@@ -627,20 +637,6 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 		return;
 	}
 
-	/*
-	 * SHADOWCON/PRTCON register is used for enabling timing.
-	 *
-	 * for example, once only width value of a register is set,
-	 * if the dma is started then fimd hardware could malfunction so
-	 * with protect window setting, the register fields with prefix '_F'
-	 * wouldn't be updated at vsync also but updated once unprotect window
-	 * is set.
-	 */
-
-	/* protect windows */
-	fimd_shadow_protect_win(ctx, win, true);
-
-
 	offset = plane->fb_x * (plane->bpp >> 3);
 	offset += plane->fb_y * plane->pitch;
 
@@ -722,9 +718,6 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 	if (ctx->driver_data->has_shadowcon)
 		fimd_enable_shadow_channel_path(ctx, win, true);
 
-	/* Enable DMA channel and unprotect windows */
-	fimd_shadow_protect_win(ctx, win, false);
-
 	plane->enabled = true;
 
 	if (ctx->i80_if)
@@ -947,6 +940,34 @@ static void fimd_te_handler(struct exynos_drm_crtc *crtc)
 		drm_handle_vblank(ctx->drm_dev, ctx->pipe);
 }
 
+static void fimd_win_protect(struct exynos_drm_crtc *crtc, int zpos)
+{
+	struct fimd_context *ctx = crtc->ctx;
+	int win = zpos;
+
+	if (win == DEFAULT_ZPOS)
+		win = ctx->default_win;
+
+	if (win < 0 || win >= WINDOWS_NR)
+		return;
+
+	fimd_shadow_protect_win(ctx, win, true);
+}
+
+static void fimd_win_unprotect(struct exynos_drm_crtc *crtc, int zpos)
+{
+	struct fimd_context *ctx = crtc->ctx;
+	int win = zpos;
+
+	if (win == DEFAULT_ZPOS)
+		win = ctx->default_win;
+
+	if (win < 0 || win >= WINDOWS_NR)
+		return;
+
+	fimd_shadow_protect_win(ctx, win, false);
+}
+
 static struct exynos_drm_crtc_ops fimd_crtc_ops = {
 	.dpms = fimd_dpms,
 	.mode_fixup = fimd_mode_fixup,
@@ -957,6 +978,8 @@ static struct exynos_drm_crtc_ops fimd_crtc_ops = {
 	.win_commit = fimd_win_commit,
 	.win_disable = fimd_win_disable,
 	.te_handler = fimd_te_handler,
+	.win_protect = fimd_win_protect,
+	.win_unprotect = fimd_win_unprotect,
 };
 
 static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index a3b0687..363d59d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -65,6 +65,7 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last)
 int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb)
 {
 	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(plane->crtc);
 	int nr;
 	int i;
 
@@ -83,6 +84,9 @@ int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb)
 				i, (unsigned long)exynos_plane->dma_addr[i]);
 	}
 
+	if (exynos_crtc)
+		exynos_crtc->plane_mask += 1 << exynos_plane->zpos;
+
 	return 0;
 }
 
-- 
1.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 09/14] drm/exynos: atomic phase 1: add .mode_set_nofb() callback
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
                   ` (7 preceding siblings ...)
  2015-02-03 19:14 ` [PATCH 08/14] drm/exynos: atomic phase 1: add atomic_begin()/atomic_flush() Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-04  7:51   ` Joonyoung Shim
  2015-02-03 19:14 ` [PATCH 10/14] drm/exynos: atomic phase 2: wire up state reset(), duplicate() and destroy() Gustavo Padovan
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: Gustavo Padovan, dri-devel

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

The new atomic infrastructure needs the .mode_set_nofb() callback to
update CRTC timings before setting any plane.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

Conflicts:
	drivers/gpu/drm/exynos/exynos_drm_crtc.c
---
 drivers/gpu/drm/exynos/exynos_drm_crtc.c | 55 +++++++-------------------------
 1 file changed, 11 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index be36cca..17b64f8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -81,53 +81,19 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
 	return true;
 }
 
-static int
-exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
-			  struct drm_display_mode *adjusted_mode, int x, int y,
-			  struct drm_framebuffer *old_fb)
-{
-	struct drm_framebuffer *fb = crtc->primary->fb;
-	unsigned int crtc_w;
-	unsigned int crtc_h;
-	int ret;
-
-	ret = exynos_check_plane(crtc->primary, fb);
-	if (ret < 0)
-		return ret;
-
-	crtc_w = fb->width - x;
-	crtc_h = fb->height - y;
-	exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0,
-			      crtc_w, crtc_h, x, y, crtc_w, crtc_h);
-
-	return 0;
-}
-
-static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
-					  struct drm_framebuffer *old_fb)
+static void
+exynos_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
-	struct drm_framebuffer *fb = crtc->primary->fb;
-	unsigned int crtc_w;
-	unsigned int crtc_h;
-	int ret;
+	struct drm_display_mode *adjusted_mode;
 
-	/* when framebuffer changing is requested, crtc's dpms should be on */
-	if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
-		DRM_ERROR("failed framebuffer changing request.\n");
-		return -EPERM;
-	}
-
-	ret = exynos_check_plane(crtc->primary, fb);
-	if (ret)
-		return ret;
+	if (WARN_ON(!crtc->state))
+		return;
 
-	crtc_w = fb->width - x;
-	crtc_h = fb->height - y;
-	exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
-			    crtc_w, crtc_h, x, y, crtc_w, crtc_h);
+	adjusted_mode = &crtc->state->adjusted_mode;
 
-	return 0;
+	if (exynos_crtc->ops->commit)
+		exynos_crtc->ops->commit(exynos_crtc);
 }
 
 static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
@@ -184,8 +150,9 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
 	.prepare	= exynos_drm_crtc_prepare,
 	.commit		= exynos_drm_crtc_commit,
 	.mode_fixup	= exynos_drm_crtc_mode_fixup,
-	.mode_set	= exynos_drm_crtc_mode_set,
-	.mode_set_base	= exynos_drm_crtc_mode_set_base,
+	.mode_set	= drm_helper_crtc_mode_set,
+	.mode_set_nofb	= exynos_drm_crtc_mode_set_nofb,
+	.mode_set_base	= drm_helper_crtc_mode_set_base,
 	.disable	= exynos_drm_crtc_disable,
 	.atomic_begin	= exynos_crtc_atomic_begin,
 	.atomic_flush	= exynos_crtc_atomic_flush,
-- 
1.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 10/14] drm/exynos: atomic phase 2: wire up state reset(), duplicate() and destroy()
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
                   ` (8 preceding siblings ...)
  2015-02-03 19:14 ` [PATCH 09/14] drm/exynos: atomic phase 1: add .mode_set_nofb() callback Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-03 19:14 ` [PATCH 11/14] drm/exynos: atomic phase 2: keep track of framebuffer pointer Gustavo Padovan
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: jy0922.shim, inki.dae, dri-devel, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

Set CRTC, planes and connectors to use the default implementations from
the atomic helper library. The helpers will work to keep track of state
for each DRM object.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/bridge/ptn3460.c              | 4 ++++
 drivers/gpu/drm/exynos/exynos_dp_core.c       | 4 ++++
 drivers/gpu/drm/exynos/exynos_drm_connector.c | 4 ++++
 drivers/gpu/drm/exynos/exynos_drm_crtc.c      | 5 +++++
 drivers/gpu/drm/exynos/exynos_drm_dpi.c       | 4 ++++
 drivers/gpu/drm/exynos/exynos_drm_drv.c       | 2 ++
 drivers/gpu/drm/exynos/exynos_drm_dsi.c       | 4 ++++
 drivers/gpu/drm/exynos/exynos_drm_plane.c     | 4 ++++
 drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 4 ++++
 drivers/gpu/drm/exynos/exynos_hdmi.c          | 4 ++++
 10 files changed, 39 insertions(+)

diff --git a/drivers/gpu/drm/bridge/ptn3460.c b/drivers/gpu/drm/bridge/ptn3460.c
index 826833e..30da10c 100644
--- a/drivers/gpu/drm/bridge/ptn3460.c
+++ b/drivers/gpu/drm/bridge/ptn3460.c
@@ -27,6 +27,7 @@
 
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
+#include "drm_atomic_helper.h"
 #include "drm_edid.h"
 #include "drmP.h"
 
@@ -263,6 +264,9 @@ static struct drm_connector_funcs ptn3460_connector_funcs = {
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = ptn3460_detect,
 	.destroy = ptn3460_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 int ptn3460_bridge_attach(struct drm_bridge *bridge)
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
index bf17a60..6704d5c 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.c
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
@@ -28,6 +28,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_panel.h>
 #include <drm/bridge/ptn3460.h>
 
@@ -952,6 +953,9 @@ static struct drm_connector_funcs exynos_dp_connector_funcs = {
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = exynos_dp_detect,
 	.destroy = exynos_dp_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static int exynos_dp_get_modes(struct drm_connector *connector)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index ba9b3d5..980b085 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -13,6 +13,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
 
 #include <drm/exynos_drm.h>
 #include "exynos_drm_drv.h"
@@ -182,6 +183,9 @@ static struct drm_connector_funcs exynos_connector_funcs = {
 	.fill_modes	= exynos_drm_connector_fill_modes,
 	.detect		= exynos_drm_connector_detect,
 	.destroy	= exynos_drm_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 17b64f8..660ad64 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -14,6 +14,8 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_drv.h"
@@ -265,6 +267,9 @@ static struct drm_crtc_funcs exynos_crtc_funcs = {
 	.page_flip	= exynos_drm_crtc_page_flip,
 	.destroy	= exynos_drm_crtc_destroy,
 	.set_property	= exynos_drm_crtc_set_property,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 };
 
 static const struct drm_prop_enum_list mode_names[] = {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
index 37678cf..ced5c23 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
@@ -13,6 +13,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_atomic_helper.h>
 
 #include <linux/regulator/consumer.h>
 
@@ -63,6 +64,9 @@ static struct drm_connector_funcs exynos_dpi_connector_funcs = {
 	.detect = exynos_dpi_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = exynos_dpi_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static int exynos_dpi_get_modes(struct drm_connector *connector)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 778c91e..0b76a42 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -98,6 +98,8 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 	if (ret)
 		goto err_cleanup_vblank;
 
+	drm_mode_config_reset(dev);
+
 	/*
 	 * enable drm irq mode.
 	 * - with irq_enabled = true, we can use the vblank feature.
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 05fe93d..6e9c2c3 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -14,6 +14,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_atomic_helper.h>
 
 #include <linux/clk.h>
 #include <linux/gpio/consumer.h>
@@ -1461,6 +1462,9 @@ static struct drm_connector_funcs exynos_dsi_connector_funcs = {
 	.detect = exynos_dsi_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = exynos_dsi_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static int exynos_dsi_get_modes(struct drm_connector *connector)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 363d59d..0980c84 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -13,6 +13,7 @@
 
 #include <drm/exynos_drm.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic_helper.h>
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_fb.h"
@@ -226,6 +227,9 @@ static struct drm_plane_funcs exynos_plane_funcs = {
 	.disable_plane	= drm_plane_helper_disable,
 	.destroy	= exynos_plane_destroy,
 	.set_property	= exynos_plane_set_property,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
 };
 
 static int exynos_plane_atomic_check(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 08c7a1e..a42af1d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -20,6 +20,7 @@
 
 #include <drm/drm_edid.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
@@ -396,6 +397,9 @@ static struct drm_connector_funcs vidi_connector_funcs = {
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = vidi_detect,
 	.destroy = vidi_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static int vidi_get_modes(struct drm_connector *connector)
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 229b361..5b597bc 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -17,6 +17,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
 
 #include "regs-hdmi.h"
 
@@ -1054,6 +1055,9 @@ static struct drm_connector_funcs hdmi_connector_funcs = {
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = hdmi_detect,
 	.destroy = hdmi_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static int hdmi_get_modes(struct drm_connector *connector)
-- 
1.9.3

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

* [PATCH 11/14] drm/exynos: atomic phase 2: keep track of framebuffer pointer
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
                   ` (9 preceding siblings ...)
  2015-02-03 19:14 ` [PATCH 10/14] drm/exynos: atomic phase 2: wire up state reset(), duplicate() and destroy() Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-04  7:53   ` Joonyoung Shim
  2015-02-03 19:14 ` [PATCH 12/14] drm/exynos: make exynos_plane_mode_set() static Gustavo Padovan
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: jy0922.shim, inki.dae, dri-devel, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

Use drm_atomic_set_fb_for_plane() in the legacy page_flip path to keep
track of the framebuffer pointer and reference.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_crtc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 660ad64..2edc73c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -211,6 +211,9 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
 			    crtc_w, crtc_h, crtc->x, crtc->y,
 			    crtc_w, crtc_h);
 
+	if (crtc->primary->state)
+		drm_atomic_set_fb_for_plane(crtc->primary->state, fb);
+
 	return 0;
 
 out:
-- 
1.9.3

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

* [PATCH 12/14] drm/exynos: make exynos_plane_mode_set() static
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
                   ` (10 preceding siblings ...)
  2015-02-03 19:14 ` [PATCH 11/14] drm/exynos: atomic phase 2: keep track of framebuffer pointer Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-03 19:14 ` [PATCH 13/14] drm/exynos: use correct pipe number on vblank event Gustavo Padovan
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: jy0922.shim, inki.dae, dri-devel, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

It is not used outside of the plane scope anymore.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_plane.c | 11 ++++++-----
 drivers/gpu/drm/exynos/exynos_drm_plane.h |  5 -----
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 0980c84..c0c53d6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -91,11 +91,12 @@ int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb)
 	return 0;
 }
 
-void exynos_plane_mode_set(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)
+static void exynos_plane_mode_set(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 exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
 	unsigned int actual_w;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index 8361606..8cdca0d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -10,11 +10,6 @@
  */
 
 int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb);
-void exynos_plane_mode_set(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);
 void exynos_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,
-- 
1.9.3

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

* [PATCH 13/14] drm/exynos: use correct pipe number on vblank event
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
                   ` (11 preceding siblings ...)
  2015-02-03 19:14 ` [PATCH 12/14] drm/exynos: make exynos_plane_mode_set() static Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-03 19:14 ` [PATCH 14/14] drm/exynos: remove exynos_disable_plane() Gustavo Padovan
  2015-02-04  7:37 ` [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Joonyoung Shim
  14 siblings, 0 replies; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: jy0922.shim, inki.dae, dri-devel, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

Use the pipe var received instead of using always -1 as pipe value.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_crtc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 2edc73c..0f2b789 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -382,7 +382,7 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
 	spin_lock_irqsave(&dev->event_lock, flags);
 	if (exynos_crtc->event) {
 
-		drm_send_vblank_event(dev, -1, exynos_crtc->event);
+		drm_send_vblank_event(dev, pipe, exynos_crtc->event);
 		drm_vblank_put(dev, pipe);
 		wake_up(&exynos_crtc->pending_flip_queue);
 
-- 
1.9.3

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

* [PATCH 14/14] drm/exynos: remove exynos_disable_plane()
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
                   ` (12 preceding siblings ...)
  2015-02-03 19:14 ` [PATCH 13/14] drm/exynos: use correct pipe number on vblank event Gustavo Padovan
@ 2015-02-03 19:14 ` Gustavo Padovan
  2015-02-04  7:37 ` [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Joonyoung Shim
  14 siblings, 0 replies; 37+ messages in thread
From: Gustavo Padovan @ 2015-02-03 19:14 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: Gustavo Padovan, dri-devel

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

exynos_disable_plane() is used only once now thus remove it and call
exynos_plane_dpms() directly.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/gpu/drm/exynos/exynos_drm_plane.c | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index c0c53d6..34dcf17b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -191,18 +191,11 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);
 }
 
-static int exynos_disable_plane(struct drm_plane *plane)
-{
-	exynos_plane_dpms(plane, DRM_MODE_DPMS_OFF);
-
-	return 0;
-}
-
 static void exynos_plane_destroy(struct drm_plane *plane)
 {
 	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
 
-	exynos_disable_plane(plane);
+	exynos_plane_dpms(plane, DRM_MODE_DPMS_OFF);
 	drm_plane_cleanup(plane);
 	kfree(exynos_plane);
 }
-- 
1.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2
  2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
                   ` (13 preceding siblings ...)
  2015-02-03 19:14 ` [PATCH 14/14] drm/exynos: remove exynos_disable_plane() Gustavo Padovan
@ 2015-02-04  7:37 ` Joonyoung Shim
  2015-02-04 14:35   ` Daniel Vetter
  14 siblings, 1 reply; 37+ messages in thread
From: Joonyoung Shim @ 2015-02-04  7:37 UTC (permalink / raw)
  To: Gustavo Padovan, linux-samsung-soc; +Cc: Gustavo Padovan, dri-devel

Hi,

On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> 
> Hi,
> 
> This series clean ups a few more paths from exynos-drm with the most important
> being the removal of the global page flip queue and the removal in driver
> internal data (struct *_win_data) that was replicating plane data.
> 
> Following these patches comes the first step torwards atomic modesetting
> support on exynos.
> 

It's better to split cleanup and atomic support, not one patchset.

Thanks.

> This series is applied on top of 3 patches[0][1][2] that were sent recently to
> dri-devel.
> 
> 	Gustavo
> 
> ---
> [0] http://www.spinics.net/lists/linux-samsung-soc/msg41867.html
> [1] http://lists.freedesktop.org/archives/dri-devel/2015-January/076504.html
> [2] http://lists.freedesktop.org/archives/dri-devel/2015-January/076505.html
> 
> 
> Daniel Kurtz (1):
>   drm/exynos: do not copy adjusted mode into mode during crtc mode_set
> 
> Gustavo Padovan (12):
>   drm/exynos: Remove exynos_plane_dpms() call with no effect
>   drm/exynos: remove leftover functions declarations
>   drm/exynos: remove struct *_win_data abstraction on planes
>   drm/exynos: atomic phase 1: use drm_plane_helper_update()
>   drm/exynos: atomic phase 1: use drm_plane_helper_disable()
>   drm/exynos: atomic phase 1: add atomic_begin()/atomic_flush()
>   drm/exynos: atomic phase 1: add .mode_set_nofb() callback
>   drm/exynos: atomic phase 2: wire up state reset(), duplicate() and
>     destroy()
>   drm/exynos: atomic phase 2: keep track of framebuffer pointer
>   drm/exynos: make exynos_plane_mode_set() static
>   drm/exynos: use correct pipe number on vblank event
>   drm/exynos: remove exynos_disable_plane()
> 
> Mandeep Singh Baines (1):
>   drm/exynos: track vblank events on a per crtc basis
> 
>  drivers/gpu/drm/bridge/ptn3460.c              |   4 +
>  drivers/gpu/drm/exynos/exynos_dp_core.c       |   4 +
>  drivers/gpu/drm/exynos/exynos_drm_connector.c |   4 +
>  drivers/gpu/drm/exynos/exynos_drm_crtc.c      | 203 +++++++++++-----------
>  drivers/gpu/drm/exynos/exynos_drm_crtc.h      |   7 +-
>  drivers/gpu/drm/exynos/exynos_drm_dpi.c       |   4 +
>  drivers/gpu/drm/exynos/exynos_drm_drv.c       |  29 +---
>  drivers/gpu/drm/exynos/exynos_drm_drv.h       |  15 +-
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c       |   4 +
>  drivers/gpu/drm/exynos/exynos_drm_fb.c        |   2 +-
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 235 ++++++++++++--------------
>  drivers/gpu/drm/exynos/exynos_drm_plane.c     |  99 ++++++-----
>  drivers/gpu/drm/exynos/exynos_drm_plane.h     |  13 +-
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 127 ++++----------
>  drivers/gpu/drm/exynos/exynos_hdmi.c          |   4 +
>  drivers/gpu/drm/exynos/exynos_mixer.c         | 212 ++++++++---------------
>  16 files changed, 408 insertions(+), 558 deletions(-)
> 

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 02/14] drm/exynos: Remove exynos_plane_dpms() call with no effect
  2015-02-03 19:14 ` [PATCH 02/14] drm/exynos: Remove exynos_plane_dpms() call with no effect Gustavo Padovan
@ 2015-02-04  7:42   ` Joonyoung Shim
  2015-02-04 14:16     ` Daniel Vetter
  0 siblings, 1 reply; 37+ messages in thread
From: Joonyoung Shim @ 2015-02-04  7:42 UTC (permalink / raw)
  To: Gustavo Padovan, linux-samsung-soc; +Cc: Gustavo Padovan, dri-devel

Hi,

On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> 
> exynos_plane_dpms(DRM_MODE_DPMS_ON) calls the win_enable()'s callback
> from the underlying layer. However neither one of these layers implement
> win_enable() - FIMD, Mixer and VIDI. Thus the call to exynos_plane_dpms()
> is pointless.
> 
> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_crtc.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> index b2a4b84..ad675fb 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> @@ -65,8 +65,6 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
>  
>  	if (exynos_crtc->ops->commit)
>  		exynos_crtc->ops->commit(exynos_crtc);
> -
> -	exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON);

As i said, this needs to keep pair enabled flag of struct
exynos_drm_plane.

Thanks.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 04/14] drm/exynos: remove struct *_win_data abstraction on planes
  2015-02-03 19:14 ` [PATCH 04/14] drm/exynos: remove struct *_win_data abstraction on planes Gustavo Padovan
@ 2015-02-04  7:44   ` Joonyoung Shim
  2015-02-04 14:28     ` Daniel Vetter
  0 siblings, 1 reply; 37+ messages in thread
From: Joonyoung Shim @ 2015-02-04  7:44 UTC (permalink / raw)
  To: Gustavo Padovan, linux-samsung-soc; +Cc: Gustavo Padovan, dri-devel

Hi,

On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> 
> struct {fimd,mixer,vidi}_win_data was just keeping the same data
> as struct exynos_drm_plane thus get ride of it and use exynos_drm_plane
> directly.
> 
> It changes how planes are created and remove .win_mode_set() callback
> that was only filling all *_win_data structs.
> 

I commented already on prior patch.

Thanks.

> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_crtc.c  |   9 +-
>  drivers/gpu/drm/exynos/exynos_drm_crtc.h  |   1 +
>  drivers/gpu/drm/exynos/exynos_drm_drv.c   |  14 --
>  drivers/gpu/drm/exynos/exynos_drm_drv.h   |   5 +-
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c  | 182 ++++++++++---------------
>  drivers/gpu/drm/exynos/exynos_drm_plane.c |  20 +--
>  drivers/gpu/drm/exynos/exynos_drm_plane.h |   6 +-
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c  | 123 +++++------------
>  drivers/gpu/drm/exynos/exynos_mixer.c     | 212 +++++++++++-------------------
>  9 files changed, 183 insertions(+), 389 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> index ad675fb..d504f0b 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> @@ -296,13 +296,13 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
>  }
>  
>  struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
> +					       struct drm_plane *plane,
>  					       int pipe,
>  					       enum exynos_drm_output_type type,
>  					       struct exynos_drm_crtc_ops *ops,
>  					       void *ctx)
>  {
>  	struct exynos_drm_crtc *exynos_crtc;
> -	struct drm_plane *plane;
>  	struct exynos_drm_private *private = drm_dev->dev_private;
>  	struct drm_crtc *crtc;
>  	int ret;
> @@ -318,12 +318,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
>  	exynos_crtc->type = type;
>  	exynos_crtc->ops = ops;
>  	exynos_crtc->ctx = ctx;
> -	plane = exynos_plane_init(drm_dev, 1 << pipe,
> -				  DRM_PLANE_TYPE_PRIMARY);
> -	if (IS_ERR(plane)) {
> -		ret = PTR_ERR(plane);
> -		goto err_plane;
> -	}
>  
>  	crtc = &exynos_crtc->base;
>  
> @@ -342,7 +336,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
>  
>  err_crtc:
>  	plane->funcs->destroy(plane);
> -err_plane:
>  	kfree(exynos_crtc);
>  	return ERR_PTR(ret);
>  }
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
> index 628b787..0ecd8fc 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
> +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
> @@ -18,6 +18,7 @@
>  #include "exynos_drm_drv.h"
>  
>  struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
> +					       struct drm_plane *plane,
>  					       int pipe,
>  					       enum exynos_drm_output_type type,
>  					       struct exynos_drm_crtc_ops *ops,
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> index 737164d..778c91e 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> @@ -55,7 +55,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
>  {
>  	struct exynos_drm_private *private;
>  	int ret;
> -	int nr;
>  
>  	private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
>  	if (!private)
> @@ -80,19 +79,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
>  
>  	exynos_drm_mode_config_init(dev);
>  
> -	for (nr = 0; nr < MAX_PLANE; nr++) {
> -		struct drm_plane *plane;
> -		unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;
> -
> -		plane = exynos_plane_init(dev, possible_crtcs,
> -					  DRM_PLANE_TYPE_OVERLAY);
> -		if (!IS_ERR(plane))
> -			continue;
> -
> -		ret = PTR_ERR(plane);
> -		goto err_mode_config_cleanup;
> -	}
> -
>  	/* setup possible_clones. */
>  	exynos_drm_encoder_setup(dev);
>  
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> index 7411af2..cad54e7 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> @@ -78,6 +78,7 @@ enum exynos_drm_output_type {
>   * @transparency: transparency on or off.
>   * @activated: activated or not.
>   * @enabled: enabled or not.
> + * @resume: to resume or not.
>   *
>   * this structure is common to exynos SoC and its contents would be copied
>   * to hardware specific overlay info.
> @@ -112,6 +113,7 @@ struct exynos_drm_plane {
>  	bool transparency:1;
>  	bool activated:1;
>  	bool enabled:1;
> +	bool resume:1;
>  };
>  
>  /*
> @@ -172,7 +174,6 @@ struct exynos_drm_display {
>   * @disable_vblank: specific driver callback for disabling vblank interrupt.
>   * @wait_for_vblank: wait for vblank interrupt to make sure that
>   *	hardware overlay is updated.
> - * @win_mode_set: copy drm overlay info to hw specific overlay info.
>   * @win_commit: apply hardware specific overlay data to registers.
>   * @win_enable: enable hardware specific overlay.
>   * @win_disable: disable hardware specific overlay.
> @@ -189,8 +190,6 @@ struct exynos_drm_crtc_ops {
>  	int (*enable_vblank)(struct exynos_drm_crtc *crtc);
>  	void (*disable_vblank)(struct exynos_drm_crtc *crtc);
>  	void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
> -	void (*win_mode_set)(struct exynos_drm_crtc *crtc,
> -				struct exynos_drm_plane *plane);
>  	void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos);
>  	void (*win_enable)(struct exynos_drm_crtc *crtc, int zpos);
>  	void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> index 925fc69..ebb4cdc 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> @@ -31,6 +31,7 @@
>  #include "exynos_drm_drv.h"
>  #include "exynos_drm_fbdev.h"
>  #include "exynos_drm_crtc.h"
> +#include "exynos_drm_plane.h"
>  #include "exynos_drm_iommu.h"
>  
>  /*
> @@ -140,31 +141,15 @@ static struct fimd_driver_data exynos5_fimd_driver_data = {
>  	.has_vtsel = 1,
>  };
>  
> -struct fimd_win_data {
> -	unsigned int		offset_x;
> -	unsigned int		offset_y;
> -	unsigned int		ovl_width;
> -	unsigned int		ovl_height;
> -	unsigned int		fb_width;
> -	unsigned int		fb_height;
> -	unsigned int		bpp;
> -	unsigned int		pixel_format;
> -	dma_addr_t		dma_addr;
> -	unsigned int		buf_offsize;
> -	unsigned int		line_size;	/* bytes */
> -	bool			enabled;
> -	bool			resume;
> -};
> -
>  struct fimd_context {
>  	struct device			*dev;
>  	struct drm_device		*drm_dev;
>  	struct exynos_drm_crtc		*crtc;
> +	struct exynos_drm_plane		planes[WINDOWS_NR];
>  	struct clk			*bus_clk;
>  	struct clk			*lcd_clk;
>  	void __iomem			*regs;
>  	struct regmap			*sysreg;
> -	struct fimd_win_data		win_data[WINDOWS_NR];
>  	unsigned int			default_win;
>  	unsigned long			irq_flags;
>  	u32				vidcon0;
> @@ -506,58 +491,9 @@ static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
>  	}
>  }
>  
> -static void fimd_win_mode_set(struct exynos_drm_crtc *crtc,
> -			struct exynos_drm_plane *plane)
> -{
> -	struct fimd_context *ctx = crtc->ctx;
> -	struct fimd_win_data *win_data;
> -	int win;
> -	unsigned long offset;
> -
> -	if (!plane) {
> -		DRM_ERROR("plane is NULL\n");
> -		return;
> -	}
> -
> -	win = plane->zpos;
> -	if (win == DEFAULT_ZPOS)
> -		win = ctx->default_win;
> -
> -	if (win < 0 || win >= WINDOWS_NR)
> -		return;
> -
> -	offset = plane->fb_x * (plane->bpp >> 3);
> -	offset += plane->fb_y * plane->pitch;
> -
> -	DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
> -
> -	win_data = &ctx->win_data[win];
> -
> -	win_data->offset_x = plane->crtc_x;
> -	win_data->offset_y = plane->crtc_y;
> -	win_data->ovl_width = plane->crtc_width;
> -	win_data->ovl_height = plane->crtc_height;
> -	win_data->fb_width = plane->fb_width;
> -	win_data->fb_height = plane->fb_height;
> -	win_data->dma_addr = plane->dma_addr[0] + offset;
> -	win_data->bpp = plane->bpp;
> -	win_data->pixel_format = plane->pixel_format;
> -	win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
> -				(plane->bpp >> 3);
> -	win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
> -
> -	DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
> -			win_data->offset_x, win_data->offset_y);
> -	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
> -			win_data->ovl_width, win_data->ovl_height);
> -	DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
> -	DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
> -			plane->fb_width, plane->crtc_width);
> -}
> -
>  static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
>  {
> -	struct fimd_win_data *win_data = &ctx->win_data[win];
> +	struct exynos_drm_plane *plane = &ctx->planes[win];
>  	unsigned long val;
>  
>  	val = WINCONx_ENWIN;
> @@ -567,11 +503,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
>  	 * So the request format is ARGB8888 then change it to XRGB8888.
>  	 */
>  	if (ctx->driver_data->has_limited_fmt && !win) {
> -		if (win_data->pixel_format == DRM_FORMAT_ARGB8888)
> -			win_data->pixel_format = DRM_FORMAT_XRGB8888;
> +		if (plane->pixel_format == DRM_FORMAT_ARGB8888)
> +			plane->pixel_format = DRM_FORMAT_XRGB8888;
>  	}
>  
> -	switch (win_data->pixel_format) {
> +	switch (plane->pixel_format) {
>  	case DRM_FORMAT_C8:
>  		val |= WINCON0_BPPMODE_8BPP_PALETTE;
>  		val |= WINCONx_BURSTLEN_8WORD;
> @@ -607,7 +543,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
>  		break;
>  	}
>  
> -	DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
> +	DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);
>  
>  	/*
>  	 * In case of exynos, setting dma-burst to 16Word causes permanent
> @@ -617,7 +553,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
>  	 * movement causes unstable DMA which results into iommu crash/tear.
>  	 */
>  
> -	if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
> +	if (plane->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
>  		val &= ~WINCONx_BURSTLEN_MASK;
>  		val |= WINCONx_BURSTLEN_4WORD;
>  	}
> @@ -668,11 +604,11 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
>  static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  {
>  	struct fimd_context *ctx = crtc->ctx;
> -	struct fimd_win_data *win_data;
> +	struct exynos_drm_plane *plane;
>  	int win = zpos;
> -	unsigned long val, alpha, size;
> -	unsigned int last_x;
> -	unsigned int last_y;
> +	dma_addr_t dma_addr;
> +	unsigned long val, alpha, size, offset;
> +	unsigned int last_x, last_y, buf_offsize, line_size;
>  
>  	if (ctx->suspended)
>  		return;
> @@ -683,11 +619,11 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  	if (win < 0 || win >= WINDOWS_NR)
>  		return;
>  
> -	win_data = &ctx->win_data[win];
> +	plane = &ctx->planes[win];
>  
>  	/* If suspended, enable this on resume */
>  	if (ctx->suspended) {
> -		win_data->resume = true;
> +		plane->resume = true;
>  		return;
>  	}
>  
> @@ -704,38 +640,45 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  	/* protect windows */
>  	fimd_shadow_protect_win(ctx, win, true);
>  
> +
> +	offset = plane->fb_x * (plane->bpp >> 3);
> +	offset += plane->fb_y * plane->pitch;
> +
>  	/* buffer start address */
> -	val = (unsigned long)win_data->dma_addr;
> +	dma_addr = plane->dma_addr[0] + offset;
> +	val = (unsigned long)dma_addr;
>  	writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
>  
>  	/* buffer end address */
> -	size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
> -	val = (unsigned long)(win_data->dma_addr + size);
> +	size = plane->fb_width * plane->crtc_height * (plane->bpp >> 3);
> +	val = (unsigned long)(dma_addr + size);
>  	writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
>  
>  	DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
> -			(unsigned long)win_data->dma_addr, val, size);
> +			(unsigned long)dma_addr, val, size);
>  	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
> -			win_data->ovl_width, win_data->ovl_height);
> +			plane->crtc_width, plane->crtc_height);
>  
>  	/* buffer size */
> -	val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
> -		VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size) |
> -		VIDW_BUF_SIZE_OFFSET_E(win_data->buf_offsize) |
> -		VIDW_BUF_SIZE_PAGEWIDTH_E(win_data->line_size);
> +	buf_offsize = (plane->fb_width - plane->crtc_width) * (plane->bpp >> 3);
> +	line_size = plane->crtc_width * (plane->bpp >> 3);
> +	val = VIDW_BUF_SIZE_OFFSET(buf_offsize) |
> +		VIDW_BUF_SIZE_PAGEWIDTH(line_size) |
> +		VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
> +		VIDW_BUF_SIZE_PAGEWIDTH_E(line_size);
>  	writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
>  
>  	/* OSD position */
> -	val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
> -		VIDOSDxA_TOPLEFT_Y(win_data->offset_y) |
> -		VIDOSDxA_TOPLEFT_X_E(win_data->offset_x) |
> -		VIDOSDxA_TOPLEFT_Y_E(win_data->offset_y);
> +	val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
> +		VIDOSDxA_TOPLEFT_Y(plane->crtc_y) |
> +		VIDOSDxA_TOPLEFT_X_E(plane->crtc_x) |
> +		VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y);
>  	writel(val, ctx->regs + VIDOSD_A(win));
>  
> -	last_x = win_data->offset_x + win_data->ovl_width;
> +	last_x = plane->crtc_x + plane->crtc_width;
>  	if (last_x)
>  		last_x--;
> -	last_y = win_data->offset_y + win_data->ovl_height;
> +	last_y = plane->crtc_y + plane->crtc_height;
>  	if (last_y)
>  		last_y--;
>  
> @@ -745,7 +688,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  	writel(val, ctx->regs + VIDOSD_B(win));
>  
>  	DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
> -			win_data->offset_x, win_data->offset_y, last_x, last_y);
> +			plane->crtc_x, plane->crtc_y, last_x, last_y);
>  
>  	/* hardware window 0 doesn't support alpha channel. */
>  	if (win != 0) {
> @@ -762,7 +705,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  		u32 offset = VIDOSD_D(win);
>  		if (win == 0)
>  			offset = VIDOSD_C(win);
> -		val = win_data->ovl_width * win_data->ovl_height;
> +		val = plane->crtc_width * plane->crtc_height;
>  		writel(val, ctx->regs + offset);
>  
>  		DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
> @@ -782,7 +725,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  	/* Enable DMA channel and unprotect windows */
>  	fimd_shadow_protect_win(ctx, win, false);
>  
> -	win_data->enabled = true;
> +	plane->enabled = true;
>  
>  	if (ctx->i80_if)
>  		atomic_set(&ctx->win_updated, 1);
> @@ -791,7 +734,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>  {
>  	struct fimd_context *ctx = crtc->ctx;
> -	struct fimd_win_data *win_data;
> +	struct exynos_drm_plane *plane;
>  	int win = zpos;
>  
>  	if (win == DEFAULT_ZPOS)
> @@ -800,11 +743,11 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>  	if (win < 0 || win >= WINDOWS_NR)
>  		return;
>  
> -	win_data = &ctx->win_data[win];
> +	plane = &ctx->planes[win];
>  
>  	if (ctx->suspended) {
>  		/* do not resume this window*/
> -		win_data->resume = false;
> +		plane->resume = false;
>  		return;
>  	}
>  
> @@ -819,42 +762,42 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>  	/* unprotect windows */
>  	fimd_shadow_protect_win(ctx, win, false);
>  
> -	win_data->enabled = false;
> +	plane->enabled = false;
>  }
>  
>  static void fimd_window_suspend(struct fimd_context *ctx)
>  {
> -	struct fimd_win_data *win_data;
> +	struct exynos_drm_plane *plane;
>  	int i;
>  
>  	for (i = 0; i < WINDOWS_NR; i++) {
> -		win_data = &ctx->win_data[i];
> -		win_data->resume = win_data->enabled;
> -		if (win_data->enabled)
> +		plane = &ctx->planes[i];
> +		plane->resume = plane->enabled;
> +		if (plane->enabled)
>  			fimd_win_disable(ctx->crtc, i);
>  	}
>  }
>  
>  static void fimd_window_resume(struct fimd_context *ctx)
>  {
> -	struct fimd_win_data *win_data;
> +	struct exynos_drm_plane *plane;
>  	int i;
>  
>  	for (i = 0; i < WINDOWS_NR; i++) {
> -		win_data = &ctx->win_data[i];
> -		win_data->enabled = win_data->resume;
> -		win_data->resume = false;
> +		plane = &ctx->planes[i];
> +		plane->enabled = plane->resume;
> +		plane->resume = false;
>  	}
>  }
>  
>  static void fimd_apply(struct fimd_context *ctx)
>  {
> -	struct fimd_win_data *win_data;
> +	struct exynos_drm_plane *plane;
>  	int i;
>  
>  	for (i = 0; i < WINDOWS_NR; i++) {
> -		win_data = &ctx->win_data[i];
> -		if (win_data->enabled)
> +		plane = &ctx->planes[i];
> +		if (plane->enabled)
>  			fimd_win_commit(ctx->crtc, i);
>  		else
>  			fimd_win_disable(ctx->crtc, i);
> @@ -1011,7 +954,6 @@ static struct exynos_drm_crtc_ops fimd_crtc_ops = {
>  	.enable_vblank = fimd_enable_vblank,
>  	.disable_vblank = fimd_disable_vblank,
>  	.wait_for_vblank = fimd_wait_for_vblank,
> -	.win_mode_set = fimd_win_mode_set,
>  	.win_commit = fimd_win_commit,
>  	.win_disable = fimd_win_disable,
>  	.te_handler = fimd_te_handler,
> @@ -1056,7 +998,16 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
>  {
>  	struct fimd_context *ctx = dev_get_drvdata(dev);
>  	struct drm_device *drm_dev = data;
> -	int ret;
> +	struct exynos_drm_plane *exynos_plane;
> +	enum drm_plane_type type;
> +	int i, ret;
> +
> +	for (i = 0; i < WINDOWS_NR; i++) {
> +		type = (i == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
> +						DRM_PLANE_TYPE_OVERLAY;
> +		exynos_plane_init(drm_dev, &ctx->planes[i], 1 << ctx->pipe,
> +				  type);
> +	}
>  
>  	ret = fimd_ctx_initialize(ctx, drm_dev);
>  	if (ret) {
> @@ -1064,8 +1015,9 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
>  		return ret;
>  	}
>  
> -	ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
> -					   EXYNOS_DISPLAY_TYPE_LCD,
> +	exynos_plane = &ctx->planes[ctx->default_win];
> +	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
> +					   ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
>  					   &fimd_crtc_ops, ctx);
>  	if (IS_ERR(ctx->crtc)) {
>  		fimd_ctx_remove(ctx);
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
> index 358cff6..dc13621 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
> @@ -93,7 +93,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
>  			  uint32_t src_w, uint32_t src_h)
>  {
>  	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
> -	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
>  	unsigned int actual_w;
>  	unsigned int actual_h;
>  
> @@ -140,9 +139,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
>  			exynos_plane->crtc_width, exynos_plane->crtc_height);
>  
>  	plane->crtc = crtc;
> -
> -	if (exynos_crtc->ops->win_mode_set)
> -		exynos_crtc->ops->win_mode_set(exynos_crtc, exynos_plane);
>  }
>  
>  void exynos_plane_dpms(struct drm_plane *plane, int mode)
> @@ -255,24 +251,18 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
>  	drm_object_attach_property(&plane->base, prop, 0);
>  }
>  
> -struct drm_plane *exynos_plane_init(struct drm_device *dev,
> -				    unsigned long possible_crtcs,
> -				    enum drm_plane_type type)
> +int exynos_plane_init(struct drm_device *dev,
> +		      struct exynos_drm_plane *exynos_plane,
> +		      unsigned long possible_crtcs, enum drm_plane_type type)
>  {
> -	struct exynos_drm_plane *exynos_plane;
>  	int err;
>  
> -	exynos_plane = kzalloc(sizeof(struct exynos_drm_plane), GFP_KERNEL);
> -	if (!exynos_plane)
> -		return ERR_PTR(-ENOMEM);
> -
>  	err = drm_universal_plane_init(dev, &exynos_plane->base, possible_crtcs,
>  				       &exynos_plane_funcs, formats,
>  				       ARRAY_SIZE(formats), type);
>  	if (err) {
>  		DRM_ERROR("failed to initialize plane\n");
> -		kfree(exynos_plane);
> -		return ERR_PTR(err);
> +		return err;
>  	}
>  
>  	if (type == DRM_PLANE_TYPE_PRIMARY)
> @@ -280,5 +270,5 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
>  	else
>  		exynos_plane_attach_zpos_property(&exynos_plane->base);
>  
> -	return &exynos_plane->base;
> +	return 0;
>  }
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
> index 59d4075..100ca5e 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
> +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
> @@ -21,6 +21,6 @@ int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  			uint32_t src_x, uint32_t src_y,
>  			uint32_t src_w, uint32_t src_h);
>  void exynos_plane_dpms(struct drm_plane *plane, int mode);
> -struct drm_plane *exynos_plane_init(struct drm_device *dev,
> -				    unsigned long possible_crtcs,
> -				    enum drm_plane_type type);
> +int exynos_plane_init(struct drm_device *dev,
> +		      struct exynos_drm_plane *exynos_plane,
> +		      unsigned long possible_crtcs, enum drm_plane_type type);
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> index b886972..08c7a1e 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> @@ -23,6 +23,7 @@
>  
>  #include "exynos_drm_drv.h"
>  #include "exynos_drm_crtc.h"
> +#include "exynos_drm_plane.h"
>  #include "exynos_drm_encoder.h"
>  #include "exynos_drm_vidi.h"
>  
> @@ -32,20 +33,6 @@
>  #define ctx_from_connector(c)	container_of(c, struct vidi_context, \
>  					connector)
>  
> -struct vidi_win_data {
> -	unsigned int		offset_x;
> -	unsigned int		offset_y;
> -	unsigned int		ovl_width;
> -	unsigned int		ovl_height;
> -	unsigned int		fb_width;
> -	unsigned int		fb_height;
> -	unsigned int		bpp;
> -	dma_addr_t		dma_addr;
> -	unsigned int		buf_offsize;
> -	unsigned int		line_size;	/* bytes */
> -	bool			enabled;
> -};
> -
>  struct vidi_context {
>  	struct exynos_drm_display	display;
>  	struct platform_device		*pdev;
> @@ -53,7 +40,7 @@ struct vidi_context {
>  	struct exynos_drm_crtc		*crtc;
>  	struct drm_encoder		*encoder;
>  	struct drm_connector		connector;
> -	struct vidi_win_data		win_data[WINDOWS_NR];
> +	struct exynos_drm_plane		planes[WINDOWS_NR];
>  	struct edid			*raw_edid;
>  	unsigned int			clkdiv;
>  	unsigned int			default_win;
> @@ -97,19 +84,6 @@ static const char fake_edid_info[] = {
>  	0x00, 0x00, 0x00, 0x06
>  };
>  
> -static void vidi_apply(struct vidi_context *ctx)
> -{
> -	struct exynos_drm_crtc_ops *crtc_ops = ctx->crtc->ops;
> -	struct vidi_win_data *win_data;
> -	int i;
> -
> -	for (i = 0; i < WINDOWS_NR; i++) {
> -		win_data = &ctx->win_data[i];
> -		if (win_data->enabled && (crtc_ops && crtc_ops->win_commit))
> -			crtc_ops->win_commit(ctx->crtc, i);
> -	}
> -}
> -
>  static int vidi_enable_vblank(struct exynos_drm_crtc *crtc)
>  {
>  	struct vidi_context *ctx = crtc->ctx;
> @@ -143,63 +117,10 @@ static void vidi_disable_vblank(struct exynos_drm_crtc *crtc)
>  		ctx->vblank_on = false;
>  }
>  
> -static void vidi_win_mode_set(struct exynos_drm_crtc *crtc,
> -			struct exynos_drm_plane *plane)
> -{
> -	struct vidi_context *ctx = crtc->ctx;
> -	struct vidi_win_data *win_data;
> -	int win;
> -	unsigned long offset;
> -
> -	if (!plane) {
> -		DRM_ERROR("plane is NULL\n");
> -		return;
> -	}
> -
> -	win = plane->zpos;
> -	if (win == DEFAULT_ZPOS)
> -		win = ctx->default_win;
> -
> -	if (win < 0 || win >= WINDOWS_NR)
> -		return;
> -
> -	offset = plane->fb_x * (plane->bpp >> 3);
> -	offset += plane->fb_y * plane->pitch;
> -
> -	DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
> -
> -	win_data = &ctx->win_data[win];
> -
> -	win_data->offset_x = plane->crtc_x;
> -	win_data->offset_y = plane->crtc_y;
> -	win_data->ovl_width = plane->crtc_width;
> -	win_data->ovl_height = plane->crtc_height;
> -	win_data->fb_width = plane->fb_width;
> -	win_data->fb_height = plane->fb_height;
> -	win_data->dma_addr = plane->dma_addr[0] + offset;
> -	win_data->bpp = plane->bpp;
> -	win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
> -				(plane->bpp >> 3);
> -	win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
> -
> -	/*
> -	 * some parts of win_data should be transferred to user side
> -	 * through specific ioctl.
> -	 */
> -
> -	DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
> -			win_data->offset_x, win_data->offset_y);
> -	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
> -			win_data->ovl_width, win_data->ovl_height);
> -	DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
> -	DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
> -			plane->fb_width, plane->crtc_width);
> -}
> -
>  static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  {
>  	struct vidi_context *ctx = crtc->ctx;
> -	struct vidi_win_data *win_data;
> +	struct exynos_drm_plane *plane;
>  	int win = zpos;
>  
>  	if (ctx->suspended)
> @@ -211,11 +132,11 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  	if (win < 0 || win >= WINDOWS_NR)
>  		return;
>  
> -	win_data = &ctx->win_data[win];
> +	plane = &ctx->planes[win];
>  
> -	win_data->enabled = true;
> +	plane->enabled = true;
>  
> -	DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data->dma_addr);
> +	DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
>  
>  	if (ctx->vblank_on)
>  		schedule_work(&ctx->work);
> @@ -224,7 +145,7 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>  {
>  	struct vidi_context *ctx = crtc->ctx;
> -	struct vidi_win_data *win_data;
> +	struct exynos_drm_plane *plane;
>  	int win = zpos;
>  
>  	if (win == DEFAULT_ZPOS)
> @@ -233,14 +154,17 @@ static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>  	if (win < 0 || win >= WINDOWS_NR)
>  		return;
>  
> -	win_data = &ctx->win_data[win];
> -	win_data->enabled = false;
> +	plane = &ctx->planes[win];
> +	plane->enabled = false;
>  
>  	/* TODO. */
>  }
>  
>  static int vidi_power_on(struct vidi_context *ctx, bool enable)
>  {
> +	struct exynos_drm_plane *plane;
> +	int i;
> +
>  	DRM_DEBUG_KMS("%s\n", __FILE__);
>  
>  	if (enable != false && enable != true)
> @@ -253,7 +177,11 @@ static int vidi_power_on(struct vidi_context *ctx, bool enable)
>  		if (test_and_clear_bit(0, &ctx->irq_flags))
>  			vidi_enable_vblank(ctx->crtc);
>  
> -		vidi_apply(ctx);
> +		for (i = 0; i < WINDOWS_NR; i++) {
> +			plane = &ctx->planes[i];
> +			if (plane->enabled)
> +				vidi_win_commit(ctx->crtc, i);
> +		}
>  	} else {
>  		ctx->suspended = true;
>  	}
> @@ -301,7 +229,6 @@ static struct exynos_drm_crtc_ops vidi_crtc_ops = {
>  	.dpms = vidi_dpms,
>  	.enable_vblank = vidi_enable_vblank,
>  	.disable_vblank = vidi_disable_vblank,
> -	.win_mode_set = vidi_win_mode_set,
>  	.win_commit = vidi_win_commit,
>  	.win_disable = vidi_win_disable,
>  };
> @@ -543,12 +470,22 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
>  {
>  	struct vidi_context *ctx = dev_get_drvdata(dev);
>  	struct drm_device *drm_dev = data;
> -	int ret;
> +	struct exynos_drm_plane *exynos_plane;
> +	enum drm_plane_type type;
> +	int i, ret;
> +
> +	for (i = 0; i < WINDOWS_NR; i++) {
> +		type = (i == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
> +						DRM_PLANE_TYPE_OVERLAY;
> +		exynos_plane_init(drm_dev, &ctx->planes[i], 1 << ctx->pipe,
> +				  type);
> +	}
>  
>  	vidi_ctx_initialize(ctx, drm_dev);
>  
> -	ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
> -					   EXYNOS_DISPLAY_TYPE_VIDI,
> +	exynos_plane = &ctx->planes[ctx->default_win];
> +	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
> +					   ctx->pipe, EXYNOS_DISPLAY_TYPE_VIDI,
>  					   &vidi_crtc_ops, ctx);
>  	if (IS_ERR(ctx->crtc)) {
>  		DRM_ERROR("failed to create crtc.\n");
> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
> index 736269a..d6864e6 100644
> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
> @@ -37,34 +37,13 @@
>  
>  #include "exynos_drm_drv.h"
>  #include "exynos_drm_crtc.h"
> +#include "exynos_drm_plane.h"
>  #include "exynos_drm_iommu.h"
>  #include "exynos_mixer.h"
>  
>  #define MIXER_WIN_NR		3
>  #define MIXER_DEFAULT_WIN	0
>  
> -struct hdmi_win_data {
> -	dma_addr_t		dma_addr;
> -	dma_addr_t		chroma_dma_addr;
> -	uint32_t		pixel_format;
> -	unsigned int		bpp;
> -	unsigned int		crtc_x;
> -	unsigned int		crtc_y;
> -	unsigned int		crtc_width;
> -	unsigned int		crtc_height;
> -	unsigned int		fb_x;
> -	unsigned int		fb_y;
> -	unsigned int		fb_width;
> -	unsigned int		fb_height;
> -	unsigned int		src_width;
> -	unsigned int		src_height;
> -	unsigned int		mode_width;
> -	unsigned int		mode_height;
> -	unsigned int		scan_flags;
> -	bool			enabled;
> -	bool			resume;
> -};
> -
>  struct mixer_resources {
>  	int			irq;
>  	void __iomem		*mixer_regs;
> @@ -88,6 +67,7 @@ struct mixer_context {
>  	struct device		*dev;
>  	struct drm_device	*drm_dev;
>  	struct exynos_drm_crtc	*crtc;
> +	struct exynos_drm_plane	planes[MIXER_WIN_NR];
>  	int			pipe;
>  	bool			interlace;
>  	bool			powered;
> @@ -97,7 +77,6 @@ struct mixer_context {
>  
>  	struct mutex		mixer_mutex;
>  	struct mixer_resources	mixer_res;
> -	struct hdmi_win_data	win_data[MIXER_WIN_NR];
>  	enum mixer_version_id	mxr_ver;
>  	wait_queue_head_t	wait_vsync_queue;
>  	atomic_t		wait_vsync_event;
> @@ -401,7 +380,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
>  {
>  	struct mixer_resources *res = &ctx->mixer_res;
>  	unsigned long flags;
> -	struct hdmi_win_data *win_data;
> +	struct exynos_drm_plane *plane;
>  	unsigned int x_ratio, y_ratio;
>  	unsigned int buf_num = 1;
>  	dma_addr_t luma_addr[2], chroma_addr[2];
> @@ -409,9 +388,9 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
>  	bool crcb_mode = false;
>  	u32 val;
>  
> -	win_data = &ctx->win_data[win];
> +	plane = &ctx->planes[win];
>  
> -	switch (win_data->pixel_format) {
> +	switch (plane->pixel_format) {
>  	case DRM_FORMAT_NV12MT:
>  		tiled_mode = true;
>  	case DRM_FORMAT_NV12:
> @@ -421,35 +400,35 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
>  	/* TODO: single buffer format NV12, NV21 */
>  	default:
>  		/* ignore pixel format at disable time */
> -		if (!win_data->dma_addr)
> +		if (!plane->dma_addr[0])
>  			break;
>  
>  		DRM_ERROR("pixel format for vp is wrong [%d].\n",
> -				win_data->pixel_format);
> +				plane->pixel_format);
>  		return;
>  	}
>  
>  	/* scaling feature: (src << 16) / dst */
> -	x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
> -	y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
> +	x_ratio = (plane->src_width << 16) / plane->crtc_width;
> +	y_ratio = (plane->src_height << 16) / plane->crtc_height;
>  
>  	if (buf_num == 2) {
> -		luma_addr[0] = win_data->dma_addr;
> -		chroma_addr[0] = win_data->chroma_dma_addr;
> +		luma_addr[0] = plane->dma_addr[0];
> +		chroma_addr[0] = plane->dma_addr[1];
>  	} else {
> -		luma_addr[0] = win_data->dma_addr;
> -		chroma_addr[0] = win_data->dma_addr
> -			+ (win_data->fb_width * win_data->fb_height);
> +		luma_addr[0] = plane->dma_addr[0];
> +		chroma_addr[0] = plane->dma_addr[0]
> +			+ (plane->fb_width * plane->fb_height);
>  	}
>  
> -	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
> +	if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) {
>  		ctx->interlace = true;
>  		if (tiled_mode) {
>  			luma_addr[1] = luma_addr[0] + 0x40;
>  			chroma_addr[1] = chroma_addr[0] + 0x40;
>  		} else {
> -			luma_addr[1] = luma_addr[0] + win_data->fb_width;
> -			chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
> +			luma_addr[1] = luma_addr[0] + plane->fb_width;
> +			chroma_addr[1] = chroma_addr[0] + plane->fb_width;
>  		}
>  	} else {
>  		ctx->interlace = false;
> @@ -470,26 +449,26 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
>  	vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
>  
>  	/* setting size of input image */
> -	vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
> -		VP_IMG_VSIZE(win_data->fb_height));
> +	vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->fb_width) |
> +		VP_IMG_VSIZE(plane->fb_height));
>  	/* chroma height has to reduced by 2 to avoid chroma distorions */
> -	vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
> -		VP_IMG_VSIZE(win_data->fb_height / 2));
> +	vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->fb_width) |
> +		VP_IMG_VSIZE(plane->fb_height / 2));
>  
> -	vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
> -	vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
> +	vp_reg_write(res, VP_SRC_WIDTH, plane->src_width);
> +	vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height);
>  	vp_reg_write(res, VP_SRC_H_POSITION,
> -			VP_SRC_H_POSITION_VAL(win_data->fb_x));
> -	vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
> +			VP_SRC_H_POSITION_VAL(plane->fb_x));
> +	vp_reg_write(res, VP_SRC_V_POSITION, plane->fb_y);
>  
> -	vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
> -	vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
> +	vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width);
> +	vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
>  	if (ctx->interlace) {
> -		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
> -		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
> +		vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2);
> +		vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
>  	} else {
> -		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
> -		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
> +		vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height);
> +		vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
>  	}
>  
>  	vp_reg_write(res, VP_H_RATIO, x_ratio);
> @@ -503,8 +482,8 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
>  	vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
>  	vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
>  
> -	mixer_cfg_scan(ctx, win_data->mode_height);
> -	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
> +	mixer_cfg_scan(ctx, plane->mode_height);
> +	mixer_cfg_rgb_fmt(ctx, plane->mode_height);
>  	mixer_cfg_layer(ctx, win, true);
>  	mixer_run(ctx);
>  
> @@ -525,21 +504,21 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
>  {
>  	struct mixer_resources *res = &ctx->mixer_res;
>  	unsigned long flags;
> -	struct hdmi_win_data *win_data;
> +	struct exynos_drm_plane *plane;
>  	unsigned int x_ratio, y_ratio;
>  	unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
>  	dma_addr_t dma_addr;
>  	unsigned int fmt;
>  	u32 val;
>  
> -	win_data = &ctx->win_data[win];
> +	plane = &ctx->planes[win];
>  
>  	#define RGB565 4
>  	#define ARGB1555 5
>  	#define ARGB4444 6
>  	#define ARGB8888 7
>  
> -	switch (win_data->bpp) {
> +	switch (plane->bpp) {
>  	case 16:
>  		fmt = ARGB4444;
>  		break;
> @@ -554,17 +533,17 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
>  	x_ratio = 0;
>  	y_ratio = 0;
>  
> -	dst_x_offset = win_data->crtc_x;
> -	dst_y_offset = win_data->crtc_y;
> +	dst_x_offset = plane->crtc_x;
> +	dst_y_offset = plane->crtc_y;
>  
>  	/* converting dma address base and source offset */
> -	dma_addr = win_data->dma_addr
> -		+ (win_data->fb_x * win_data->bpp >> 3)
> -		+ (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
> +	dma_addr = plane->dma_addr[0]
> +		+ (plane->fb_x * plane->bpp >> 3)
> +		+ (plane->fb_y * plane->fb_width * plane->bpp >> 3);
>  	src_x_offset = 0;
>  	src_y_offset = 0;
>  
> -	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
> +	if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE)
>  		ctx->interlace = true;
>  	else
>  		ctx->interlace = false;
> @@ -577,18 +556,18 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
>  		MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
>  
>  	/* setup geometry */
> -	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
> +	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), plane->fb_width);
>  
>  	/* setup display size */
>  	if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
>  		win == MIXER_DEFAULT_WIN) {
> -		val  = MXR_MXR_RES_HEIGHT(win_data->fb_height);
> -		val |= MXR_MXR_RES_WIDTH(win_data->fb_width);
> +		val  = MXR_MXR_RES_HEIGHT(plane->fb_height);
> +		val |= MXR_MXR_RES_WIDTH(plane->fb_width);
>  		mixer_reg_write(res, MXR_RESOLUTION, val);
>  	}
>  
> -	val  = MXR_GRP_WH_WIDTH(win_data->crtc_width);
> -	val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
> +	val  = MXR_GRP_WH_WIDTH(plane->crtc_width);
> +	val |= MXR_GRP_WH_HEIGHT(plane->crtc_height);
>  	val |= MXR_GRP_WH_H_SCALE(x_ratio);
>  	val |= MXR_GRP_WH_V_SCALE(y_ratio);
>  	mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
> @@ -606,8 +585,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
>  	/* set buffer address to mixer */
>  	mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
>  
> -	mixer_cfg_scan(ctx, win_data->mode_height);
> -	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
> +	mixer_cfg_scan(ctx, plane->mode_height);
> +	mixer_cfg_rgb_fmt(ctx, plane->mode_height);
>  	mixer_cfg_layer(ctx, win, true);
>  
>  	/* layer update mandatory for mixer 16.0.33.0 */
> @@ -913,58 +892,6 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
>  	mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
>  }
>  
> -static void mixer_win_mode_set(struct exynos_drm_crtc *crtc,
> -			struct exynos_drm_plane *plane)
> -{
> -	struct mixer_context *mixer_ctx = crtc->ctx;
> -	struct hdmi_win_data *win_data;
> -	int win;
> -
> -	if (!plane) {
> -		DRM_ERROR("plane is NULL\n");
> -		return;
> -	}
> -
> -	DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
> -				 plane->fb_width, plane->fb_height,
> -				 plane->fb_x, plane->fb_y,
> -				 plane->crtc_width, plane->crtc_height,
> -				 plane->crtc_x, plane->crtc_y);
> -
> -	win = plane->zpos;
> -	if (win == DEFAULT_ZPOS)
> -		win = MIXER_DEFAULT_WIN;
> -
> -	if (win < 0 || win >= MIXER_WIN_NR) {
> -		DRM_ERROR("mixer window[%d] is wrong\n", win);
> -		return;
> -	}
> -
> -	win_data = &mixer_ctx->win_data[win];
> -
> -	win_data->dma_addr = plane->dma_addr[0];
> -	win_data->chroma_dma_addr = plane->dma_addr[1];
> -	win_data->pixel_format = plane->pixel_format;
> -	win_data->bpp = plane->bpp;
> -
> -	win_data->crtc_x = plane->crtc_x;
> -	win_data->crtc_y = plane->crtc_y;
> -	win_data->crtc_width = plane->crtc_width;
> -	win_data->crtc_height = plane->crtc_height;
> -
> -	win_data->fb_x = plane->fb_x;
> -	win_data->fb_y = plane->fb_y;
> -	win_data->fb_width = plane->fb_width;
> -	win_data->fb_height = plane->fb_height;
> -	win_data->src_width = plane->src_width;
> -	win_data->src_height = plane->src_height;
> -
> -	win_data->mode_width = plane->mode_width;
> -	win_data->mode_height = plane->mode_height;
> -
> -	win_data->scan_flags = plane->scan_flag;
> -}
> -
>  static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  {
>  	struct mixer_context *mixer_ctx = crtc->ctx;
> @@ -984,7 +911,7 @@ static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  	else
>  		mixer_graph_buffer(mixer_ctx, win);
>  
> -	mixer_ctx->win_data[win].enabled = true;
> +	mixer_ctx->planes[win].enabled = true;
>  }
>  
>  static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
> @@ -999,7 +926,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>  	mutex_lock(&mixer_ctx->mixer_mutex);
>  	if (!mixer_ctx->powered) {
>  		mutex_unlock(&mixer_ctx->mixer_mutex);
> -		mixer_ctx->win_data[win].resume = false;
> +		mixer_ctx->planes[win].resume = false;
>  		return;
>  	}
>  	mutex_unlock(&mixer_ctx->mixer_mutex);
> @@ -1012,7 +939,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>  	mixer_vsync_set_update(mixer_ctx, true);
>  	spin_unlock_irqrestore(&res->reg_slock, flags);
>  
> -	mixer_ctx->win_data[win].enabled = false;
> +	mixer_ctx->planes[win].enabled = false;
>  }
>  
>  static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
> @@ -1049,12 +976,12 @@ static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
>  
>  static void mixer_window_suspend(struct mixer_context *ctx)
>  {
> -	struct hdmi_win_data *win_data;
> +	struct exynos_drm_plane *plane;
>  	int i;
>  
>  	for (i = 0; i < MIXER_WIN_NR; i++) {
> -		win_data = &ctx->win_data[i];
> -		win_data->resume = win_data->enabled;
> +		plane = &ctx->planes[i];
> +		plane->resume = plane->enabled;
>  		mixer_win_disable(ctx->crtc, i);
>  	}
>  	mixer_wait_for_vblank(ctx->crtc);
> @@ -1062,14 +989,14 @@ static void mixer_window_suspend(struct mixer_context *ctx)
>  
>  static void mixer_window_resume(struct mixer_context *ctx)
>  {
> -	struct hdmi_win_data *win_data;
> +	struct exynos_drm_plane *plane;
>  	int i;
>  
>  	for (i = 0; i < MIXER_WIN_NR; i++) {
> -		win_data = &ctx->win_data[i];
> -		win_data->enabled = win_data->resume;
> -		win_data->resume = false;
> -		if (win_data->enabled)
> +		plane = &ctx->planes[i];
> +		plane->enabled = plane->resume;
> +		plane->resume = false;
> +		if (plane->enabled)
>  			mixer_win_commit(ctx->crtc, i);
>  	}
>  }
> @@ -1179,7 +1106,6 @@ static struct exynos_drm_crtc_ops mixer_crtc_ops = {
>  	.enable_vblank		= mixer_enable_vblank,
>  	.disable_vblank		= mixer_disable_vblank,
>  	.wait_for_vblank	= mixer_wait_for_vblank,
> -	.win_mode_set		= mixer_win_mode_set,
>  	.win_commit		= mixer_win_commit,
>  	.win_disable		= mixer_win_disable,
>  };
> @@ -1243,15 +1169,25 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
>  {
>  	struct mixer_context *ctx = dev_get_drvdata(dev);
>  	struct drm_device *drm_dev = data;
> -	int ret;
> +	struct exynos_drm_plane *exynos_plane;
> +	enum drm_plane_type type;
> +	int i, ret;
> +
> +	for (i = 0; i < MIXER_WIN_NR; i++) {
> +		type = (i == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
> +						DRM_PLANE_TYPE_OVERLAY;
> +		exynos_plane_init(drm_dev, &ctx->planes[i], 1 << ctx->pipe,
> +				  type);
> +	}
>  
>  	ret = mixer_initialize(ctx, drm_dev);
>  	if (ret)
>  		return ret;
>  
> -	ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
> -				     EXYNOS_DISPLAY_TYPE_HDMI,
> -				     &mixer_crtc_ops, ctx);
> +	exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
> +	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
> +					   ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
> +					   &mixer_crtc_ops, ctx);
>  	if (IS_ERR(ctx->crtc)) {
>  		mixer_ctx_remove(ctx);
>  		ret = PTR_ERR(ctx->crtc);
> 

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 07/14] drm/exynos: atomic phase 1: use drm_plane_helper_disable()
  2015-02-03 19:14 ` [PATCH 07/14] drm/exynos: atomic phase 1: use drm_plane_helper_disable() Gustavo Padovan
@ 2015-02-04  7:47   ` Joonyoung Shim
  0 siblings, 0 replies; 37+ messages in thread
From: Joonyoung Shim @ 2015-02-04  7:47 UTC (permalink / raw)
  To: Gustavo Padovan, linux-samsung-soc; +Cc: Gustavo Padovan, dri-devel

Hi,

On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> 
> The atomic helper to disable planes also uses the optional
> .atomic_disable() helper. The unique operation it does is calling
> .win_disable()
> 

Is there any reason to split this patch from patch 06/14?

> exynos_drm_fb_get_buf_cnt() needs a fb check too to avoid a null pointer.
> 

This is not related with this patch purpose.

> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_fb.c    |  2 +-
>  drivers/gpu/drm/exynos/exynos_drm_plane.c | 14 +++++++++++++-
>  2 files changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
> index d346d1e..470456d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
> @@ -136,7 +136,7 @@ unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb)
>  
>  	exynos_fb = to_exynos_fb(fb);
>  
> -	return exynos_fb->buf_cnt;
> +	return exynos_fb ? exynos_fb->buf_cnt : 0;

I don't think exynos_fb can be NULL.

Thanks.

>  }
>  
>  struct drm_framebuffer *
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
> index 2c356b9..a3b0687 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
> @@ -219,7 +219,7 @@ static int exynos_plane_set_property(struct drm_plane *plane,
>  
>  static struct drm_plane_funcs exynos_plane_funcs = {
>  	.update_plane	= drm_plane_helper_update,
> -	.disable_plane	= exynos_disable_plane,
> +	.disable_plane	= drm_plane_helper_disable,
>  	.destroy	= exynos_plane_destroy,
>  	.set_property	= exynos_plane_set_property,
>  };
> @@ -242,9 +242,21 @@ static void exynos_plane_atomic_update(struct drm_plane *plane,
>  			    state->src_w >> 16, state->src_h >> 16);
>  }
>  
> +static void exynos_plane_atomic_disable(struct drm_plane *plane,
> +				        struct drm_plane_state *old_state)
> +{
> +	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
> +	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(old_state->crtc);
> +
> +	if (exynos_crtc->ops->win_disable)
> +		exynos_crtc->ops->win_disable(exynos_crtc,
> +					      exynos_plane->zpos);
> +}
> +
>  static const struct drm_plane_helper_funcs plane_helper_funcs = {
>  	.atomic_check = exynos_plane_atomic_check,
>  	.atomic_update = exynos_plane_atomic_update,
> +	.atomic_disable = exynos_plane_atomic_disable,
>  };
>  
>  static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
> 

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 08/14] drm/exynos: atomic phase 1: add atomic_begin()/atomic_flush()
  2015-02-03 19:14 ` [PATCH 08/14] drm/exynos: atomic phase 1: add atomic_begin()/atomic_flush() Gustavo Padovan
@ 2015-02-04  7:49   ` Joonyoung Shim
  2015-02-04 14:30     ` Daniel Vetter
  0 siblings, 1 reply; 37+ messages in thread
From: Joonyoung Shim @ 2015-02-04  7:49 UTC (permalink / raw)
  To: Gustavo Padovan, linux-samsung-soc; +Cc: inki.dae, dri-devel, Gustavo Padovan

Hi,

On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> 
> Add CRTC callbacks .atomic_begin() .atomic_flush(). On exynos they
> unprotect the windows before the commit and protects it after based on
> a plane mask tha store which plane will be updated.
> 

I don't think they need now.

Thanks.

> For that we create two new exynos_crtc callbacks: .win_protect() and
> .win_unprotect(). The only driver that implement those now is FIMD.
> 
> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_crtc.c  | 34 ++++++++++++++++++
>  drivers/gpu/drm/exynos/exynos_drm_drv.h   |  4 +++
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c  | 57 ++++++++++++++++++++++---------
>  drivers/gpu/drm/exynos/exynos_drm_plane.c |  4 +++
>  4 files changed, 82 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> index 09d4780..be36cca 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> @@ -147,6 +147,38 @@ static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
>  	}
>  }
>  
> +static void exynos_crtc_atomic_begin(struct drm_crtc *crtc)
> +{
> +	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
> +	struct drm_plane *plane;
> +	int index = 0;
> +
> +	list_for_each_entry(plane, &crtc->dev->mode_config.plane_list, head) {
> +		if (exynos_crtc->ops->win_protect &&
> +		    exynos_crtc->plane_mask & (0x01 << index))
> +			exynos_crtc->ops->win_protect(exynos_crtc, index);
> +
> +		index++;
> +	}
> +}
> +
> +static void exynos_crtc_atomic_flush(struct drm_crtc *crtc)
> +{
> +	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
> +	struct drm_plane *plane;
> +	int index = 0;
> +
> +	list_for_each_entry(plane, &crtc->dev->mode_config.plane_list, head) {
> +		if (exynos_crtc->ops->win_unprotect &&
> +		    exynos_crtc->plane_mask & (0x01 << index))
> +			exynos_crtc->ops->win_unprotect(exynos_crtc, index);
> +
> +		index++;
> +	}
> +
> +	exynos_crtc->plane_mask = 0;
> +}
> +
>  static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
>  	.dpms		= exynos_drm_crtc_dpms,
>  	.prepare	= exynos_drm_crtc_prepare,
> @@ -155,6 +187,8 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
>  	.mode_set	= exynos_drm_crtc_mode_set,
>  	.mode_set_base	= exynos_drm_crtc_mode_set_base,
>  	.disable	= exynos_drm_crtc_disable,
> +	.atomic_begin	= exynos_crtc_atomic_begin,
> +	.atomic_flush	= exynos_crtc_atomic_flush,
>  };
>  
>  static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> index cad54e7..43efd9f 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> @@ -194,6 +194,8 @@ struct exynos_drm_crtc_ops {
>  	void (*win_enable)(struct exynos_drm_crtc *crtc, int zpos);
>  	void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
>  	void (*te_handler)(struct exynos_drm_crtc *crtc);
> +	void (*win_protect)(struct exynos_drm_crtc *crtc, int zpos);
> +	void (*win_unprotect)(struct exynos_drm_crtc *crtc, int zpos);
>  };
>  
>  enum exynos_crtc_mode {
> @@ -214,6 +216,7 @@ enum exynos_crtc_mode {
>   *	we can refer to the crtc to current hardware interrupt occurred through
>   *	this pipe value.
>   * @dpms: store the crtc dpms value
> + * @plane_mask: store planes to be updated on atomic modesetting
>   * @mode: store the crtc mode value
>   * @event: vblank event that is currently queued for flip
>   * @ops: pointer to callbacks for exynos drm specific functionality
> @@ -224,6 +227,7 @@ struct exynos_drm_crtc {
>  	enum exynos_drm_output_type	type;
>  	unsigned int			pipe;
>  	unsigned int			dpms;
> +	unsigned int			plane_mask;
>  	enum exynos_crtc_mode		mode;
>  	wait_queue_head_t		pending_flip_queue;
>  	struct drm_pending_vblank_event	*event;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> index ebb4cdc..f498d86 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> @@ -585,6 +585,16 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
>  {
>  	u32 reg, bits, val;
>  
> +	/*
> +	 * SHADOWCON/PRTCON register is used for enabling timing.
> +	 *
> +	 * for example, once only width value of a register is set,
> +	 * if the dma is started then fimd hardware could malfunction so
> +	 * with protect window setting, the register fields with prefix '_F'
> +	 * wouldn't be updated at vsync also but updated once unprotect window
> +	 * is set.
> +	 */
> +
>  	if (ctx->driver_data->has_shadowcon) {
>  		reg = SHADOWCON;
>  		bits = SHADOWCON_WINx_PROTECT(win);
> @@ -627,20 +637,6 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  		return;
>  	}
>  
> -	/*
> -	 * SHADOWCON/PRTCON register is used for enabling timing.
> -	 *
> -	 * for example, once only width value of a register is set,
> -	 * if the dma is started then fimd hardware could malfunction so
> -	 * with protect window setting, the register fields with prefix '_F'
> -	 * wouldn't be updated at vsync also but updated once unprotect window
> -	 * is set.
> -	 */
> -
> -	/* protect windows */
> -	fimd_shadow_protect_win(ctx, win, true);
> -
> -
>  	offset = plane->fb_x * (plane->bpp >> 3);
>  	offset += plane->fb_y * plane->pitch;
>  
> @@ -722,9 +718,6 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>  	if (ctx->driver_data->has_shadowcon)
>  		fimd_enable_shadow_channel_path(ctx, win, true);
>  
> -	/* Enable DMA channel and unprotect windows */
> -	fimd_shadow_protect_win(ctx, win, false);
> -
>  	plane->enabled = true;
>  
>  	if (ctx->i80_if)
> @@ -947,6 +940,34 @@ static void fimd_te_handler(struct exynos_drm_crtc *crtc)
>  		drm_handle_vblank(ctx->drm_dev, ctx->pipe);
>  }
>  
> +static void fimd_win_protect(struct exynos_drm_crtc *crtc, int zpos)
> +{
> +	struct fimd_context *ctx = crtc->ctx;
> +	int win = zpos;
> +
> +	if (win == DEFAULT_ZPOS)
> +		win = ctx->default_win;
> +
> +	if (win < 0 || win >= WINDOWS_NR)
> +		return;
> +
> +	fimd_shadow_protect_win(ctx, win, true);
> +}
> +
> +static void fimd_win_unprotect(struct exynos_drm_crtc *crtc, int zpos)
> +{
> +	struct fimd_context *ctx = crtc->ctx;
> +	int win = zpos;
> +
> +	if (win == DEFAULT_ZPOS)
> +		win = ctx->default_win;
> +
> +	if (win < 0 || win >= WINDOWS_NR)
> +		return;
> +
> +	fimd_shadow_protect_win(ctx, win, false);
> +}
> +
>  static struct exynos_drm_crtc_ops fimd_crtc_ops = {
>  	.dpms = fimd_dpms,
>  	.mode_fixup = fimd_mode_fixup,
> @@ -957,6 +978,8 @@ static struct exynos_drm_crtc_ops fimd_crtc_ops = {
>  	.win_commit = fimd_win_commit,
>  	.win_disable = fimd_win_disable,
>  	.te_handler = fimd_te_handler,
> +	.win_protect = fimd_win_protect,
> +	.win_unprotect = fimd_win_unprotect,
>  };
>  
>  static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
> index a3b0687..363d59d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
> @@ -65,6 +65,7 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last)
>  int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb)
>  {
>  	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
> +	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(plane->crtc);
>  	int nr;
>  	int i;
>  
> @@ -83,6 +84,9 @@ int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb)
>  				i, (unsigned long)exynos_plane->dma_addr[i]);
>  	}
>  
> +	if (exynos_crtc)
> +		exynos_crtc->plane_mask += 1 << exynos_plane->zpos;
> +
>  	return 0;
>  }
>  
> 

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

* Re: [PATCH 09/14] drm/exynos: atomic phase 1: add .mode_set_nofb() callback
  2015-02-03 19:14 ` [PATCH 09/14] drm/exynos: atomic phase 1: add .mode_set_nofb() callback Gustavo Padovan
@ 2015-02-04  7:51   ` Joonyoung Shim
  0 siblings, 0 replies; 37+ messages in thread
From: Joonyoung Shim @ 2015-02-04  7:51 UTC (permalink / raw)
  To: Gustavo Padovan, linux-samsung-soc; +Cc: Gustavo Padovan, dri-devel

Hi,

On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> 
> The new atomic infrastructure needs the .mode_set_nofb() callback to
> update CRTC timings before setting any plane.
> 
> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> 
> Conflicts:
> 	drivers/gpu/drm/exynos/exynos_drm_crtc.c
> ---
>  drivers/gpu/drm/exynos/exynos_drm_crtc.c | 55 +++++++-------------------------
>  1 file changed, 11 insertions(+), 44 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> index be36cca..17b64f8 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> @@ -81,53 +81,19 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
>  	return true;
>  }
>  
> -static int
> -exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
> -			  struct drm_display_mode *adjusted_mode, int x, int y,
> -			  struct drm_framebuffer *old_fb)
> -{
> -	struct drm_framebuffer *fb = crtc->primary->fb;
> -	unsigned int crtc_w;
> -	unsigned int crtc_h;
> -	int ret;
> -
> -	ret = exynos_check_plane(crtc->primary, fb);
> -	if (ret < 0)
> -		return ret;
> -
> -	crtc_w = fb->width - x;
> -	crtc_h = fb->height - y;
> -	exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0,
> -			      crtc_w, crtc_h, x, y, crtc_w, crtc_h);
> -
> -	return 0;
> -}
> -
> -static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> -					  struct drm_framebuffer *old_fb)
> +static void
> +exynos_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
>  {
>  	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
> -	struct drm_framebuffer *fb = crtc->primary->fb;
> -	unsigned int crtc_w;
> -	unsigned int crtc_h;
> -	int ret;
> +	struct drm_display_mode *adjusted_mode;
>  
> -	/* when framebuffer changing is requested, crtc's dpms should be on */
> -	if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
> -		DRM_ERROR("failed framebuffer changing request.\n");
> -		return -EPERM;
> -	}
> -
> -	ret = exynos_check_plane(crtc->primary, fb);
> -	if (ret)
> -		return ret;
> +	if (WARN_ON(!crtc->state))
> +		return;
>  
> -	crtc_w = fb->width - x;
> -	crtc_h = fb->height - y;
> -	exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
> -			    crtc_w, crtc_h, x, y, crtc_w, crtc_h);
> +	adjusted_mode = &crtc->state->adjusted_mode;
>  
> -	return 0;
> +	if (exynos_crtc->ops->commit)
> +		exynos_crtc->ops->commit(exynos_crtc);

This already should be executed by .commit of struct
drm_crtc_helper_funcs, not here.

Thanks.

>  }
>  
>  static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
> @@ -184,8 +150,9 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
>  	.prepare	= exynos_drm_crtc_prepare,
>  	.commit		= exynos_drm_crtc_commit,
>  	.mode_fixup	= exynos_drm_crtc_mode_fixup,
> -	.mode_set	= exynos_drm_crtc_mode_set,
> -	.mode_set_base	= exynos_drm_crtc_mode_set_base,
> +	.mode_set	= drm_helper_crtc_mode_set,
> +	.mode_set_nofb	= exynos_drm_crtc_mode_set_nofb,
> +	.mode_set_base	= drm_helper_crtc_mode_set_base,
>  	.disable	= exynos_drm_crtc_disable,
>  	.atomic_begin	= exynos_crtc_atomic_begin,
>  	.atomic_flush	= exynos_crtc_atomic_flush,
> 

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 11/14] drm/exynos: atomic phase 2: keep track of framebuffer pointer
  2015-02-03 19:14 ` [PATCH 11/14] drm/exynos: atomic phase 2: keep track of framebuffer pointer Gustavo Padovan
@ 2015-02-04  7:53   ` Joonyoung Shim
  2015-02-04 14:33     ` Daniel Vetter
  0 siblings, 1 reply; 37+ messages in thread
From: Joonyoung Shim @ 2015-02-04  7:53 UTC (permalink / raw)
  To: Gustavo Padovan, linux-samsung-soc; +Cc: Gustavo Padovan, dri-devel

Hi,

On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> 
> Use drm_atomic_set_fb_for_plane() in the legacy page_flip path to keep
> track of the framebuffer pointer and reference.
> 
> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_crtc.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> index 660ad64..2edc73c 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> @@ -211,6 +211,9 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
>  			    crtc_w, crtc_h, crtc->x, crtc->y,
>  			    crtc_w, crtc_h);
>  
> +	if (crtc->primary->state)
> +		drm_atomic_set_fb_for_plane(crtc->primary->state, fb);
> +

I'm not sure whether this needs, how about go to
drm_atomic_helper_page_flip?

Thanks.

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 02/14] drm/exynos: Remove exynos_plane_dpms() call with no effect
  2015-02-04  7:42   ` Joonyoung Shim
@ 2015-02-04 14:16     ` Daniel Vetter
  2015-02-05  1:05       ` Joonyoung Shim
  0 siblings, 1 reply; 37+ messages in thread
From: Daniel Vetter @ 2015-02-04 14:16 UTC (permalink / raw)
  To: Joonyoung Shim
  Cc: Gustavo Padovan, linux-samsung-soc, Gustavo Padovan, dri-devel

On Wed, Feb 04, 2015 at 04:42:57PM +0900, Joonyoung Shim wrote:
> Hi,
> 
> On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> > From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> > 
> > exynos_plane_dpms(DRM_MODE_DPMS_ON) calls the win_enable()'s callback
> > from the underlying layer. However neither one of these layers implement
> > win_enable() - FIMD, Mixer and VIDI. Thus the call to exynos_plane_dpms()
> > is pointless.
> > 
> > Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> > ---
> >  drivers/gpu/drm/exynos/exynos_drm_crtc.c | 2 --
> >  1 file changed, 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> > index b2a4b84..ad675fb 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> > @@ -65,8 +65,6 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
> >  
> >  	if (exynos_crtc->ops->commit)
> >  		exynos_crtc->ops->commit(exynos_crtc);
> > -
> > -	exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON);
> 
> As i said, this needs to keep pair enabled flag of struct
> exynos_drm_plane.

The reason exynos needs that exynos_plane->enable is because it has its
own per-plane dpms state. There's two problems with that:
- It's highyl non-standard, the drm kms way is to just disable the plane
  and not have some additional knob on top.
- The atomic helpers will not be able to handle this. They assume that
  there's only one dpms knob for the entire display pipeline, and
  per-plane enable/disable is handled by setting plane->state->crtc, which
  must be set iff plane->state->fb is set right now.

I recommend we rip this all out if we can adjust existing userspace to
stop using the "mode" property on planes and crtcs.

And with that non-standard exynos plane mode thing gone we can indeed rip
out exynos_plane_dpms and exynos_plane->enabled and just directly call
manager->ops->win_enable/disble. And then rip out the win_enable since
it's unused.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 04/14] drm/exynos: remove struct *_win_data abstraction on planes
  2015-02-04  7:44   ` Joonyoung Shim
@ 2015-02-04 14:28     ` Daniel Vetter
  2015-02-05  2:37       ` Joonyoung Shim
  0 siblings, 1 reply; 37+ messages in thread
From: Daniel Vetter @ 2015-02-04 14:28 UTC (permalink / raw)
  To: Joonyoung Shim
  Cc: Gustavo Padovan, linux-samsung-soc, Gustavo Padovan, dri-devel

On Wed, Feb 04, 2015 at 04:44:12PM +0900, Joonyoung Shim wrote:
> Hi,
> 
> On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> > From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> > 
> > struct {fimd,mixer,vidi}_win_data was just keeping the same data
> > as struct exynos_drm_plane thus get ride of it and use exynos_drm_plane
> > directly.
> > 
> > It changes how planes are created and remove .win_mode_set() callback
> > that was only filling all *_win_data structs.
> > 
> 
> I commented already on prior patch.

I think you don't quite understand how this primary/overlay plane stuff
works in drm core. The entire point of the drm core primary plane is to
work _exactly_ like an overlay plane and allow userspace to mangle the
primary plane configuration through the overlay plane. The only reason we
have primary planes is so that old userspace keeps working.

When I've done the testconversion with exynos to validate my atomic
helpers I've noticed that exynos makes a mess here, and on a quick look
Padovan seems to fix this up here. Not a detailed review, but this has my
Ack.
-Daniel

> 
> Thanks.
> 
> > Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> > ---
> >  drivers/gpu/drm/exynos/exynos_drm_crtc.c  |   9 +-
> >  drivers/gpu/drm/exynos/exynos_drm_crtc.h  |   1 +
> >  drivers/gpu/drm/exynos/exynos_drm_drv.c   |  14 --
> >  drivers/gpu/drm/exynos/exynos_drm_drv.h   |   5 +-
> >  drivers/gpu/drm/exynos/exynos_drm_fimd.c  | 182 ++++++++++---------------
> >  drivers/gpu/drm/exynos/exynos_drm_plane.c |  20 +--
> >  drivers/gpu/drm/exynos/exynos_drm_plane.h |   6 +-
> >  drivers/gpu/drm/exynos/exynos_drm_vidi.c  | 123 +++++------------
> >  drivers/gpu/drm/exynos/exynos_mixer.c     | 212 +++++++++++-------------------
> >  9 files changed, 183 insertions(+), 389 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> > index ad675fb..d504f0b 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> > @@ -296,13 +296,13 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
> >  }
> >  
> >  struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
> > +					       struct drm_plane *plane,
> >  					       int pipe,
> >  					       enum exynos_drm_output_type type,
> >  					       struct exynos_drm_crtc_ops *ops,
> >  					       void *ctx)
> >  {
> >  	struct exynos_drm_crtc *exynos_crtc;
> > -	struct drm_plane *plane;
> >  	struct exynos_drm_private *private = drm_dev->dev_private;
> >  	struct drm_crtc *crtc;
> >  	int ret;
> > @@ -318,12 +318,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
> >  	exynos_crtc->type = type;
> >  	exynos_crtc->ops = ops;
> >  	exynos_crtc->ctx = ctx;
> > -	plane = exynos_plane_init(drm_dev, 1 << pipe,
> > -				  DRM_PLANE_TYPE_PRIMARY);
> > -	if (IS_ERR(plane)) {
> > -		ret = PTR_ERR(plane);
> > -		goto err_plane;
> > -	}
> >  
> >  	crtc = &exynos_crtc->base;
> >  
> > @@ -342,7 +336,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
> >  
> >  err_crtc:
> >  	plane->funcs->destroy(plane);
> > -err_plane:
> >  	kfree(exynos_crtc);
> >  	return ERR_PTR(ret);
> >  }
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
> > index 628b787..0ecd8fc 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
> > @@ -18,6 +18,7 @@
> >  #include "exynos_drm_drv.h"
> >  
> >  struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
> > +					       struct drm_plane *plane,
> >  					       int pipe,
> >  					       enum exynos_drm_output_type type,
> >  					       struct exynos_drm_crtc_ops *ops,
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> > index 737164d..778c91e 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> > @@ -55,7 +55,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
> >  {
> >  	struct exynos_drm_private *private;
> >  	int ret;
> > -	int nr;
> >  
> >  	private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
> >  	if (!private)
> > @@ -80,19 +79,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
> >  
> >  	exynos_drm_mode_config_init(dev);
> >  
> > -	for (nr = 0; nr < MAX_PLANE; nr++) {
> > -		struct drm_plane *plane;
> > -		unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;
> > -
> > -		plane = exynos_plane_init(dev, possible_crtcs,
> > -					  DRM_PLANE_TYPE_OVERLAY);
> > -		if (!IS_ERR(plane))
> > -			continue;
> > -
> > -		ret = PTR_ERR(plane);
> > -		goto err_mode_config_cleanup;
> > -	}
> > -
> >  	/* setup possible_clones. */
> >  	exynos_drm_encoder_setup(dev);
> >  
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> > index 7411af2..cad54e7 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> > @@ -78,6 +78,7 @@ enum exynos_drm_output_type {
> >   * @transparency: transparency on or off.
> >   * @activated: activated or not.
> >   * @enabled: enabled or not.
> > + * @resume: to resume or not.
> >   *
> >   * this structure is common to exynos SoC and its contents would be copied
> >   * to hardware specific overlay info.
> > @@ -112,6 +113,7 @@ struct exynos_drm_plane {
> >  	bool transparency:1;
> >  	bool activated:1;
> >  	bool enabled:1;
> > +	bool resume:1;
> >  };
> >  
> >  /*
> > @@ -172,7 +174,6 @@ struct exynos_drm_display {
> >   * @disable_vblank: specific driver callback for disabling vblank interrupt.
> >   * @wait_for_vblank: wait for vblank interrupt to make sure that
> >   *	hardware overlay is updated.
> > - * @win_mode_set: copy drm overlay info to hw specific overlay info.
> >   * @win_commit: apply hardware specific overlay data to registers.
> >   * @win_enable: enable hardware specific overlay.
> >   * @win_disable: disable hardware specific overlay.
> > @@ -189,8 +190,6 @@ struct exynos_drm_crtc_ops {
> >  	int (*enable_vblank)(struct exynos_drm_crtc *crtc);
> >  	void (*disable_vblank)(struct exynos_drm_crtc *crtc);
> >  	void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
> > -	void (*win_mode_set)(struct exynos_drm_crtc *crtc,
> > -				struct exynos_drm_plane *plane);
> >  	void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos);
> >  	void (*win_enable)(struct exynos_drm_crtc *crtc, int zpos);
> >  	void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> > index 925fc69..ebb4cdc 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> > @@ -31,6 +31,7 @@
> >  #include "exynos_drm_drv.h"
> >  #include "exynos_drm_fbdev.h"
> >  #include "exynos_drm_crtc.h"
> > +#include "exynos_drm_plane.h"
> >  #include "exynos_drm_iommu.h"
> >  
> >  /*
> > @@ -140,31 +141,15 @@ static struct fimd_driver_data exynos5_fimd_driver_data = {
> >  	.has_vtsel = 1,
> >  };
> >  
> > -struct fimd_win_data {
> > -	unsigned int		offset_x;
> > -	unsigned int		offset_y;
> > -	unsigned int		ovl_width;
> > -	unsigned int		ovl_height;
> > -	unsigned int		fb_width;
> > -	unsigned int		fb_height;
> > -	unsigned int		bpp;
> > -	unsigned int		pixel_format;
> > -	dma_addr_t		dma_addr;
> > -	unsigned int		buf_offsize;
> > -	unsigned int		line_size;	/* bytes */
> > -	bool			enabled;
> > -	bool			resume;
> > -};
> > -
> >  struct fimd_context {
> >  	struct device			*dev;
> >  	struct drm_device		*drm_dev;
> >  	struct exynos_drm_crtc		*crtc;
> > +	struct exynos_drm_plane		planes[WINDOWS_NR];
> >  	struct clk			*bus_clk;
> >  	struct clk			*lcd_clk;
> >  	void __iomem			*regs;
> >  	struct regmap			*sysreg;
> > -	struct fimd_win_data		win_data[WINDOWS_NR];
> >  	unsigned int			default_win;
> >  	unsigned long			irq_flags;
> >  	u32				vidcon0;
> > @@ -506,58 +491,9 @@ static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
> >  	}
> >  }
> >  
> > -static void fimd_win_mode_set(struct exynos_drm_crtc *crtc,
> > -			struct exynos_drm_plane *plane)
> > -{
> > -	struct fimd_context *ctx = crtc->ctx;
> > -	struct fimd_win_data *win_data;
> > -	int win;
> > -	unsigned long offset;
> > -
> > -	if (!plane) {
> > -		DRM_ERROR("plane is NULL\n");
> > -		return;
> > -	}
> > -
> > -	win = plane->zpos;
> > -	if (win == DEFAULT_ZPOS)
> > -		win = ctx->default_win;
> > -
> > -	if (win < 0 || win >= WINDOWS_NR)
> > -		return;
> > -
> > -	offset = plane->fb_x * (plane->bpp >> 3);
> > -	offset += plane->fb_y * plane->pitch;
> > -
> > -	DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
> > -
> > -	win_data = &ctx->win_data[win];
> > -
> > -	win_data->offset_x = plane->crtc_x;
> > -	win_data->offset_y = plane->crtc_y;
> > -	win_data->ovl_width = plane->crtc_width;
> > -	win_data->ovl_height = plane->crtc_height;
> > -	win_data->fb_width = plane->fb_width;
> > -	win_data->fb_height = plane->fb_height;
> > -	win_data->dma_addr = plane->dma_addr[0] + offset;
> > -	win_data->bpp = plane->bpp;
> > -	win_data->pixel_format = plane->pixel_format;
> > -	win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
> > -				(plane->bpp >> 3);
> > -	win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
> > -
> > -	DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
> > -			win_data->offset_x, win_data->offset_y);
> > -	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
> > -			win_data->ovl_width, win_data->ovl_height);
> > -	DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
> > -	DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
> > -			plane->fb_width, plane->crtc_width);
> > -}
> > -
> >  static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
> >  {
> > -	struct fimd_win_data *win_data = &ctx->win_data[win];
> > +	struct exynos_drm_plane *plane = &ctx->planes[win];
> >  	unsigned long val;
> >  
> >  	val = WINCONx_ENWIN;
> > @@ -567,11 +503,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
> >  	 * So the request format is ARGB8888 then change it to XRGB8888.
> >  	 */
> >  	if (ctx->driver_data->has_limited_fmt && !win) {
> > -		if (win_data->pixel_format == DRM_FORMAT_ARGB8888)
> > -			win_data->pixel_format = DRM_FORMAT_XRGB8888;
> > +		if (plane->pixel_format == DRM_FORMAT_ARGB8888)
> > +			plane->pixel_format = DRM_FORMAT_XRGB8888;
> >  	}
> >  
> > -	switch (win_data->pixel_format) {
> > +	switch (plane->pixel_format) {
> >  	case DRM_FORMAT_C8:
> >  		val |= WINCON0_BPPMODE_8BPP_PALETTE;
> >  		val |= WINCONx_BURSTLEN_8WORD;
> > @@ -607,7 +543,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
> >  		break;
> >  	}
> >  
> > -	DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
> > +	DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);
> >  
> >  	/*
> >  	 * In case of exynos, setting dma-burst to 16Word causes permanent
> > @@ -617,7 +553,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
> >  	 * movement causes unstable DMA which results into iommu crash/tear.
> >  	 */
> >  
> > -	if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
> > +	if (plane->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
> >  		val &= ~WINCONx_BURSTLEN_MASK;
> >  		val |= WINCONx_BURSTLEN_4WORD;
> >  	}
> > @@ -668,11 +604,11 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
> >  static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  {
> >  	struct fimd_context *ctx = crtc->ctx;
> > -	struct fimd_win_data *win_data;
> > +	struct exynos_drm_plane *plane;
> >  	int win = zpos;
> > -	unsigned long val, alpha, size;
> > -	unsigned int last_x;
> > -	unsigned int last_y;
> > +	dma_addr_t dma_addr;
> > +	unsigned long val, alpha, size, offset;
> > +	unsigned int last_x, last_y, buf_offsize, line_size;
> >  
> >  	if (ctx->suspended)
> >  		return;
> > @@ -683,11 +619,11 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  	if (win < 0 || win >= WINDOWS_NR)
> >  		return;
> >  
> > -	win_data = &ctx->win_data[win];
> > +	plane = &ctx->planes[win];
> >  
> >  	/* If suspended, enable this on resume */
> >  	if (ctx->suspended) {
> > -		win_data->resume = true;
> > +		plane->resume = true;
> >  		return;
> >  	}
> >  
> > @@ -704,38 +640,45 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  	/* protect windows */
> >  	fimd_shadow_protect_win(ctx, win, true);
> >  
> > +
> > +	offset = plane->fb_x * (plane->bpp >> 3);
> > +	offset += plane->fb_y * plane->pitch;
> > +
> >  	/* buffer start address */
> > -	val = (unsigned long)win_data->dma_addr;
> > +	dma_addr = plane->dma_addr[0] + offset;
> > +	val = (unsigned long)dma_addr;
> >  	writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
> >  
> >  	/* buffer end address */
> > -	size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
> > -	val = (unsigned long)(win_data->dma_addr + size);
> > +	size = plane->fb_width * plane->crtc_height * (plane->bpp >> 3);
> > +	val = (unsigned long)(dma_addr + size);
> >  	writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
> >  
> >  	DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
> > -			(unsigned long)win_data->dma_addr, val, size);
> > +			(unsigned long)dma_addr, val, size);
> >  	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
> > -			win_data->ovl_width, win_data->ovl_height);
> > +			plane->crtc_width, plane->crtc_height);
> >  
> >  	/* buffer size */
> > -	val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
> > -		VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size) |
> > -		VIDW_BUF_SIZE_OFFSET_E(win_data->buf_offsize) |
> > -		VIDW_BUF_SIZE_PAGEWIDTH_E(win_data->line_size);
> > +	buf_offsize = (plane->fb_width - plane->crtc_width) * (plane->bpp >> 3);
> > +	line_size = plane->crtc_width * (plane->bpp >> 3);
> > +	val = VIDW_BUF_SIZE_OFFSET(buf_offsize) |
> > +		VIDW_BUF_SIZE_PAGEWIDTH(line_size) |
> > +		VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
> > +		VIDW_BUF_SIZE_PAGEWIDTH_E(line_size);
> >  	writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
> >  
> >  	/* OSD position */
> > -	val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
> > -		VIDOSDxA_TOPLEFT_Y(win_data->offset_y) |
> > -		VIDOSDxA_TOPLEFT_X_E(win_data->offset_x) |
> > -		VIDOSDxA_TOPLEFT_Y_E(win_data->offset_y);
> > +	val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
> > +		VIDOSDxA_TOPLEFT_Y(plane->crtc_y) |
> > +		VIDOSDxA_TOPLEFT_X_E(plane->crtc_x) |
> > +		VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y);
> >  	writel(val, ctx->regs + VIDOSD_A(win));
> >  
> > -	last_x = win_data->offset_x + win_data->ovl_width;
> > +	last_x = plane->crtc_x + plane->crtc_width;
> >  	if (last_x)
> >  		last_x--;
> > -	last_y = win_data->offset_y + win_data->ovl_height;
> > +	last_y = plane->crtc_y + plane->crtc_height;
> >  	if (last_y)
> >  		last_y--;
> >  
> > @@ -745,7 +688,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  	writel(val, ctx->regs + VIDOSD_B(win));
> >  
> >  	DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
> > -			win_data->offset_x, win_data->offset_y, last_x, last_y);
> > +			plane->crtc_x, plane->crtc_y, last_x, last_y);
> >  
> >  	/* hardware window 0 doesn't support alpha channel. */
> >  	if (win != 0) {
> > @@ -762,7 +705,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  		u32 offset = VIDOSD_D(win);
> >  		if (win == 0)
> >  			offset = VIDOSD_C(win);
> > -		val = win_data->ovl_width * win_data->ovl_height;
> > +		val = plane->crtc_width * plane->crtc_height;
> >  		writel(val, ctx->regs + offset);
> >  
> >  		DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
> > @@ -782,7 +725,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  	/* Enable DMA channel and unprotect windows */
> >  	fimd_shadow_protect_win(ctx, win, false);
> >  
> > -	win_data->enabled = true;
> > +	plane->enabled = true;
> >  
> >  	if (ctx->i80_if)
> >  		atomic_set(&ctx->win_updated, 1);
> > @@ -791,7 +734,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
> >  {
> >  	struct fimd_context *ctx = crtc->ctx;
> > -	struct fimd_win_data *win_data;
> > +	struct exynos_drm_plane *plane;
> >  	int win = zpos;
> >  
> >  	if (win == DEFAULT_ZPOS)
> > @@ -800,11 +743,11 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
> >  	if (win < 0 || win >= WINDOWS_NR)
> >  		return;
> >  
> > -	win_data = &ctx->win_data[win];
> > +	plane = &ctx->planes[win];
> >  
> >  	if (ctx->suspended) {
> >  		/* do not resume this window*/
> > -		win_data->resume = false;
> > +		plane->resume = false;
> >  		return;
> >  	}
> >  
> > @@ -819,42 +762,42 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
> >  	/* unprotect windows */
> >  	fimd_shadow_protect_win(ctx, win, false);
> >  
> > -	win_data->enabled = false;
> > +	plane->enabled = false;
> >  }
> >  
> >  static void fimd_window_suspend(struct fimd_context *ctx)
> >  {
> > -	struct fimd_win_data *win_data;
> > +	struct exynos_drm_plane *plane;
> >  	int i;
> >  
> >  	for (i = 0; i < WINDOWS_NR; i++) {
> > -		win_data = &ctx->win_data[i];
> > -		win_data->resume = win_data->enabled;
> > -		if (win_data->enabled)
> > +		plane = &ctx->planes[i];
> > +		plane->resume = plane->enabled;
> > +		if (plane->enabled)
> >  			fimd_win_disable(ctx->crtc, i);
> >  	}
> >  }
> >  
> >  static void fimd_window_resume(struct fimd_context *ctx)
> >  {
> > -	struct fimd_win_data *win_data;
> > +	struct exynos_drm_plane *plane;
> >  	int i;
> >  
> >  	for (i = 0; i < WINDOWS_NR; i++) {
> > -		win_data = &ctx->win_data[i];
> > -		win_data->enabled = win_data->resume;
> > -		win_data->resume = false;
> > +		plane = &ctx->planes[i];
> > +		plane->enabled = plane->resume;
> > +		plane->resume = false;
> >  	}
> >  }
> >  
> >  static void fimd_apply(struct fimd_context *ctx)
> >  {
> > -	struct fimd_win_data *win_data;
> > +	struct exynos_drm_plane *plane;
> >  	int i;
> >  
> >  	for (i = 0; i < WINDOWS_NR; i++) {
> > -		win_data = &ctx->win_data[i];
> > -		if (win_data->enabled)
> > +		plane = &ctx->planes[i];
> > +		if (plane->enabled)
> >  			fimd_win_commit(ctx->crtc, i);
> >  		else
> >  			fimd_win_disable(ctx->crtc, i);
> > @@ -1011,7 +954,6 @@ static struct exynos_drm_crtc_ops fimd_crtc_ops = {
> >  	.enable_vblank = fimd_enable_vblank,
> >  	.disable_vblank = fimd_disable_vblank,
> >  	.wait_for_vblank = fimd_wait_for_vblank,
> > -	.win_mode_set = fimd_win_mode_set,
> >  	.win_commit = fimd_win_commit,
> >  	.win_disable = fimd_win_disable,
> >  	.te_handler = fimd_te_handler,
> > @@ -1056,7 +998,16 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
> >  {
> >  	struct fimd_context *ctx = dev_get_drvdata(dev);
> >  	struct drm_device *drm_dev = data;
> > -	int ret;
> > +	struct exynos_drm_plane *exynos_plane;
> > +	enum drm_plane_type type;
> > +	int i, ret;
> > +
> > +	for (i = 0; i < WINDOWS_NR; i++) {
> > +		type = (i == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
> > +						DRM_PLANE_TYPE_OVERLAY;
> > +		exynos_plane_init(drm_dev, &ctx->planes[i], 1 << ctx->pipe,
> > +				  type);
> > +	}
> >  
> >  	ret = fimd_ctx_initialize(ctx, drm_dev);
> >  	if (ret) {
> > @@ -1064,8 +1015,9 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
> >  		return ret;
> >  	}
> >  
> > -	ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
> > -					   EXYNOS_DISPLAY_TYPE_LCD,
> > +	exynos_plane = &ctx->planes[ctx->default_win];
> > +	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
> > +					   ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
> >  					   &fimd_crtc_ops, ctx);
> >  	if (IS_ERR(ctx->crtc)) {
> >  		fimd_ctx_remove(ctx);
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
> > index 358cff6..dc13621 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
> > @@ -93,7 +93,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
> >  			  uint32_t src_w, uint32_t src_h)
> >  {
> >  	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
> > -	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
> >  	unsigned int actual_w;
> >  	unsigned int actual_h;
> >  
> > @@ -140,9 +139,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
> >  			exynos_plane->crtc_width, exynos_plane->crtc_height);
> >  
> >  	plane->crtc = crtc;
> > -
> > -	if (exynos_crtc->ops->win_mode_set)
> > -		exynos_crtc->ops->win_mode_set(exynos_crtc, exynos_plane);
> >  }
> >  
> >  void exynos_plane_dpms(struct drm_plane *plane, int mode)
> > @@ -255,24 +251,18 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
> >  	drm_object_attach_property(&plane->base, prop, 0);
> >  }
> >  
> > -struct drm_plane *exynos_plane_init(struct drm_device *dev,
> > -				    unsigned long possible_crtcs,
> > -				    enum drm_plane_type type)
> > +int exynos_plane_init(struct drm_device *dev,
> > +		      struct exynos_drm_plane *exynos_plane,
> > +		      unsigned long possible_crtcs, enum drm_plane_type type)
> >  {
> > -	struct exynos_drm_plane *exynos_plane;
> >  	int err;
> >  
> > -	exynos_plane = kzalloc(sizeof(struct exynos_drm_plane), GFP_KERNEL);
> > -	if (!exynos_plane)
> > -		return ERR_PTR(-ENOMEM);
> > -
> >  	err = drm_universal_plane_init(dev, &exynos_plane->base, possible_crtcs,
> >  				       &exynos_plane_funcs, formats,
> >  				       ARRAY_SIZE(formats), type);
> >  	if (err) {
> >  		DRM_ERROR("failed to initialize plane\n");
> > -		kfree(exynos_plane);
> > -		return ERR_PTR(err);
> > +		return err;
> >  	}
> >  
> >  	if (type == DRM_PLANE_TYPE_PRIMARY)
> > @@ -280,5 +270,5 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
> >  	else
> >  		exynos_plane_attach_zpos_property(&exynos_plane->base);
> >  
> > -	return &exynos_plane->base;
> > +	return 0;
> >  }
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
> > index 59d4075..100ca5e 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
> > @@ -21,6 +21,6 @@ int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> >  			uint32_t src_x, uint32_t src_y,
> >  			uint32_t src_w, uint32_t src_h);
> >  void exynos_plane_dpms(struct drm_plane *plane, int mode);
> > -struct drm_plane *exynos_plane_init(struct drm_device *dev,
> > -				    unsigned long possible_crtcs,
> > -				    enum drm_plane_type type);
> > +int exynos_plane_init(struct drm_device *dev,
> > +		      struct exynos_drm_plane *exynos_plane,
> > +		      unsigned long possible_crtcs, enum drm_plane_type type);
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> > index b886972..08c7a1e 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> > @@ -23,6 +23,7 @@
> >  
> >  #include "exynos_drm_drv.h"
> >  #include "exynos_drm_crtc.h"
> > +#include "exynos_drm_plane.h"
> >  #include "exynos_drm_encoder.h"
> >  #include "exynos_drm_vidi.h"
> >  
> > @@ -32,20 +33,6 @@
> >  #define ctx_from_connector(c)	container_of(c, struct vidi_context, \
> >  					connector)
> >  
> > -struct vidi_win_data {
> > -	unsigned int		offset_x;
> > -	unsigned int		offset_y;
> > -	unsigned int		ovl_width;
> > -	unsigned int		ovl_height;
> > -	unsigned int		fb_width;
> > -	unsigned int		fb_height;
> > -	unsigned int		bpp;
> > -	dma_addr_t		dma_addr;
> > -	unsigned int		buf_offsize;
> > -	unsigned int		line_size;	/* bytes */
> > -	bool			enabled;
> > -};
> > -
> >  struct vidi_context {
> >  	struct exynos_drm_display	display;
> >  	struct platform_device		*pdev;
> > @@ -53,7 +40,7 @@ struct vidi_context {
> >  	struct exynos_drm_crtc		*crtc;
> >  	struct drm_encoder		*encoder;
> >  	struct drm_connector		connector;
> > -	struct vidi_win_data		win_data[WINDOWS_NR];
> > +	struct exynos_drm_plane		planes[WINDOWS_NR];
> >  	struct edid			*raw_edid;
> >  	unsigned int			clkdiv;
> >  	unsigned int			default_win;
> > @@ -97,19 +84,6 @@ static const char fake_edid_info[] = {
> >  	0x00, 0x00, 0x00, 0x06
> >  };
> >  
> > -static void vidi_apply(struct vidi_context *ctx)
> > -{
> > -	struct exynos_drm_crtc_ops *crtc_ops = ctx->crtc->ops;
> > -	struct vidi_win_data *win_data;
> > -	int i;
> > -
> > -	for (i = 0; i < WINDOWS_NR; i++) {
> > -		win_data = &ctx->win_data[i];
> > -		if (win_data->enabled && (crtc_ops && crtc_ops->win_commit))
> > -			crtc_ops->win_commit(ctx->crtc, i);
> > -	}
> > -}
> > -
> >  static int vidi_enable_vblank(struct exynos_drm_crtc *crtc)
> >  {
> >  	struct vidi_context *ctx = crtc->ctx;
> > @@ -143,63 +117,10 @@ static void vidi_disable_vblank(struct exynos_drm_crtc *crtc)
> >  		ctx->vblank_on = false;
> >  }
> >  
> > -static void vidi_win_mode_set(struct exynos_drm_crtc *crtc,
> > -			struct exynos_drm_plane *plane)
> > -{
> > -	struct vidi_context *ctx = crtc->ctx;
> > -	struct vidi_win_data *win_data;
> > -	int win;
> > -	unsigned long offset;
> > -
> > -	if (!plane) {
> > -		DRM_ERROR("plane is NULL\n");
> > -		return;
> > -	}
> > -
> > -	win = plane->zpos;
> > -	if (win == DEFAULT_ZPOS)
> > -		win = ctx->default_win;
> > -
> > -	if (win < 0 || win >= WINDOWS_NR)
> > -		return;
> > -
> > -	offset = plane->fb_x * (plane->bpp >> 3);
> > -	offset += plane->fb_y * plane->pitch;
> > -
> > -	DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
> > -
> > -	win_data = &ctx->win_data[win];
> > -
> > -	win_data->offset_x = plane->crtc_x;
> > -	win_data->offset_y = plane->crtc_y;
> > -	win_data->ovl_width = plane->crtc_width;
> > -	win_data->ovl_height = plane->crtc_height;
> > -	win_data->fb_width = plane->fb_width;
> > -	win_data->fb_height = plane->fb_height;
> > -	win_data->dma_addr = plane->dma_addr[0] + offset;
> > -	win_data->bpp = plane->bpp;
> > -	win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
> > -				(plane->bpp >> 3);
> > -	win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
> > -
> > -	/*
> > -	 * some parts of win_data should be transferred to user side
> > -	 * through specific ioctl.
> > -	 */
> > -
> > -	DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
> > -			win_data->offset_x, win_data->offset_y);
> > -	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
> > -			win_data->ovl_width, win_data->ovl_height);
> > -	DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
> > -	DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
> > -			plane->fb_width, plane->crtc_width);
> > -}
> > -
> >  static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  {
> >  	struct vidi_context *ctx = crtc->ctx;
> > -	struct vidi_win_data *win_data;
> > +	struct exynos_drm_plane *plane;
> >  	int win = zpos;
> >  
> >  	if (ctx->suspended)
> > @@ -211,11 +132,11 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  	if (win < 0 || win >= WINDOWS_NR)
> >  		return;
> >  
> > -	win_data = &ctx->win_data[win];
> > +	plane = &ctx->planes[win];
> >  
> > -	win_data->enabled = true;
> > +	plane->enabled = true;
> >  
> > -	DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data->dma_addr);
> > +	DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
> >  
> >  	if (ctx->vblank_on)
> >  		schedule_work(&ctx->work);
> > @@ -224,7 +145,7 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
> >  {
> >  	struct vidi_context *ctx = crtc->ctx;
> > -	struct vidi_win_data *win_data;
> > +	struct exynos_drm_plane *plane;
> >  	int win = zpos;
> >  
> >  	if (win == DEFAULT_ZPOS)
> > @@ -233,14 +154,17 @@ static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
> >  	if (win < 0 || win >= WINDOWS_NR)
> >  		return;
> >  
> > -	win_data = &ctx->win_data[win];
> > -	win_data->enabled = false;
> > +	plane = &ctx->planes[win];
> > +	plane->enabled = false;
> >  
> >  	/* TODO. */
> >  }
> >  
> >  static int vidi_power_on(struct vidi_context *ctx, bool enable)
> >  {
> > +	struct exynos_drm_plane *plane;
> > +	int i;
> > +
> >  	DRM_DEBUG_KMS("%s\n", __FILE__);
> >  
> >  	if (enable != false && enable != true)
> > @@ -253,7 +177,11 @@ static int vidi_power_on(struct vidi_context *ctx, bool enable)
> >  		if (test_and_clear_bit(0, &ctx->irq_flags))
> >  			vidi_enable_vblank(ctx->crtc);
> >  
> > -		vidi_apply(ctx);
> > +		for (i = 0; i < WINDOWS_NR; i++) {
> > +			plane = &ctx->planes[i];
> > +			if (plane->enabled)
> > +				vidi_win_commit(ctx->crtc, i);
> > +		}
> >  	} else {
> >  		ctx->suspended = true;
> >  	}
> > @@ -301,7 +229,6 @@ static struct exynos_drm_crtc_ops vidi_crtc_ops = {
> >  	.dpms = vidi_dpms,
> >  	.enable_vblank = vidi_enable_vblank,
> >  	.disable_vblank = vidi_disable_vblank,
> > -	.win_mode_set = vidi_win_mode_set,
> >  	.win_commit = vidi_win_commit,
> >  	.win_disable = vidi_win_disable,
> >  };
> > @@ -543,12 +470,22 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
> >  {
> >  	struct vidi_context *ctx = dev_get_drvdata(dev);
> >  	struct drm_device *drm_dev = data;
> > -	int ret;
> > +	struct exynos_drm_plane *exynos_plane;
> > +	enum drm_plane_type type;
> > +	int i, ret;
> > +
> > +	for (i = 0; i < WINDOWS_NR; i++) {
> > +		type = (i == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
> > +						DRM_PLANE_TYPE_OVERLAY;
> > +		exynos_plane_init(drm_dev, &ctx->planes[i], 1 << ctx->pipe,
> > +				  type);
> > +	}
> >  
> >  	vidi_ctx_initialize(ctx, drm_dev);
> >  
> > -	ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
> > -					   EXYNOS_DISPLAY_TYPE_VIDI,
> > +	exynos_plane = &ctx->planes[ctx->default_win];
> > +	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
> > +					   ctx->pipe, EXYNOS_DISPLAY_TYPE_VIDI,
> >  					   &vidi_crtc_ops, ctx);
> >  	if (IS_ERR(ctx->crtc)) {
> >  		DRM_ERROR("failed to create crtc.\n");
> > diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
> > index 736269a..d6864e6 100644
> > --- a/drivers/gpu/drm/exynos/exynos_mixer.c
> > +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
> > @@ -37,34 +37,13 @@
> >  
> >  #include "exynos_drm_drv.h"
> >  #include "exynos_drm_crtc.h"
> > +#include "exynos_drm_plane.h"
> >  #include "exynos_drm_iommu.h"
> >  #include "exynos_mixer.h"
> >  
> >  #define MIXER_WIN_NR		3
> >  #define MIXER_DEFAULT_WIN	0
> >  
> > -struct hdmi_win_data {
> > -	dma_addr_t		dma_addr;
> > -	dma_addr_t		chroma_dma_addr;
> > -	uint32_t		pixel_format;
> > -	unsigned int		bpp;
> > -	unsigned int		crtc_x;
> > -	unsigned int		crtc_y;
> > -	unsigned int		crtc_width;
> > -	unsigned int		crtc_height;
> > -	unsigned int		fb_x;
> > -	unsigned int		fb_y;
> > -	unsigned int		fb_width;
> > -	unsigned int		fb_height;
> > -	unsigned int		src_width;
> > -	unsigned int		src_height;
> > -	unsigned int		mode_width;
> > -	unsigned int		mode_height;
> > -	unsigned int		scan_flags;
> > -	bool			enabled;
> > -	bool			resume;
> > -};
> > -
> >  struct mixer_resources {
> >  	int			irq;
> >  	void __iomem		*mixer_regs;
> > @@ -88,6 +67,7 @@ struct mixer_context {
> >  	struct device		*dev;
> >  	struct drm_device	*drm_dev;
> >  	struct exynos_drm_crtc	*crtc;
> > +	struct exynos_drm_plane	planes[MIXER_WIN_NR];
> >  	int			pipe;
> >  	bool			interlace;
> >  	bool			powered;
> > @@ -97,7 +77,6 @@ struct mixer_context {
> >  
> >  	struct mutex		mixer_mutex;
> >  	struct mixer_resources	mixer_res;
> > -	struct hdmi_win_data	win_data[MIXER_WIN_NR];
> >  	enum mixer_version_id	mxr_ver;
> >  	wait_queue_head_t	wait_vsync_queue;
> >  	atomic_t		wait_vsync_event;
> > @@ -401,7 +380,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
> >  {
> >  	struct mixer_resources *res = &ctx->mixer_res;
> >  	unsigned long flags;
> > -	struct hdmi_win_data *win_data;
> > +	struct exynos_drm_plane *plane;
> >  	unsigned int x_ratio, y_ratio;
> >  	unsigned int buf_num = 1;
> >  	dma_addr_t luma_addr[2], chroma_addr[2];
> > @@ -409,9 +388,9 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
> >  	bool crcb_mode = false;
> >  	u32 val;
> >  
> > -	win_data = &ctx->win_data[win];
> > +	plane = &ctx->planes[win];
> >  
> > -	switch (win_data->pixel_format) {
> > +	switch (plane->pixel_format) {
> >  	case DRM_FORMAT_NV12MT:
> >  		tiled_mode = true;
> >  	case DRM_FORMAT_NV12:
> > @@ -421,35 +400,35 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
> >  	/* TODO: single buffer format NV12, NV21 */
> >  	default:
> >  		/* ignore pixel format at disable time */
> > -		if (!win_data->dma_addr)
> > +		if (!plane->dma_addr[0])
> >  			break;
> >  
> >  		DRM_ERROR("pixel format for vp is wrong [%d].\n",
> > -				win_data->pixel_format);
> > +				plane->pixel_format);
> >  		return;
> >  	}
> >  
> >  	/* scaling feature: (src << 16) / dst */
> > -	x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
> > -	y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
> > +	x_ratio = (plane->src_width << 16) / plane->crtc_width;
> > +	y_ratio = (plane->src_height << 16) / plane->crtc_height;
> >  
> >  	if (buf_num == 2) {
> > -		luma_addr[0] = win_data->dma_addr;
> > -		chroma_addr[0] = win_data->chroma_dma_addr;
> > +		luma_addr[0] = plane->dma_addr[0];
> > +		chroma_addr[0] = plane->dma_addr[1];
> >  	} else {
> > -		luma_addr[0] = win_data->dma_addr;
> > -		chroma_addr[0] = win_data->dma_addr
> > -			+ (win_data->fb_width * win_data->fb_height);
> > +		luma_addr[0] = plane->dma_addr[0];
> > +		chroma_addr[0] = plane->dma_addr[0]
> > +			+ (plane->fb_width * plane->fb_height);
> >  	}
> >  
> > -	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
> > +	if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) {
> >  		ctx->interlace = true;
> >  		if (tiled_mode) {
> >  			luma_addr[1] = luma_addr[0] + 0x40;
> >  			chroma_addr[1] = chroma_addr[0] + 0x40;
> >  		} else {
> > -			luma_addr[1] = luma_addr[0] + win_data->fb_width;
> > -			chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
> > +			luma_addr[1] = luma_addr[0] + plane->fb_width;
> > +			chroma_addr[1] = chroma_addr[0] + plane->fb_width;
> >  		}
> >  	} else {
> >  		ctx->interlace = false;
> > @@ -470,26 +449,26 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
> >  	vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
> >  
> >  	/* setting size of input image */
> > -	vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
> > -		VP_IMG_VSIZE(win_data->fb_height));
> > +	vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->fb_width) |
> > +		VP_IMG_VSIZE(plane->fb_height));
> >  	/* chroma height has to reduced by 2 to avoid chroma distorions */
> > -	vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
> > -		VP_IMG_VSIZE(win_data->fb_height / 2));
> > +	vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->fb_width) |
> > +		VP_IMG_VSIZE(plane->fb_height / 2));
> >  
> > -	vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
> > -	vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
> > +	vp_reg_write(res, VP_SRC_WIDTH, plane->src_width);
> > +	vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height);
> >  	vp_reg_write(res, VP_SRC_H_POSITION,
> > -			VP_SRC_H_POSITION_VAL(win_data->fb_x));
> > -	vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
> > +			VP_SRC_H_POSITION_VAL(plane->fb_x));
> > +	vp_reg_write(res, VP_SRC_V_POSITION, plane->fb_y);
> >  
> > -	vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
> > -	vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
> > +	vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width);
> > +	vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
> >  	if (ctx->interlace) {
> > -		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
> > -		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
> > +		vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2);
> > +		vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
> >  	} else {
> > -		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
> > -		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
> > +		vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height);
> > +		vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
> >  	}
> >  
> >  	vp_reg_write(res, VP_H_RATIO, x_ratio);
> > @@ -503,8 +482,8 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
> >  	vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
> >  	vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
> >  
> > -	mixer_cfg_scan(ctx, win_data->mode_height);
> > -	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
> > +	mixer_cfg_scan(ctx, plane->mode_height);
> > +	mixer_cfg_rgb_fmt(ctx, plane->mode_height);
> >  	mixer_cfg_layer(ctx, win, true);
> >  	mixer_run(ctx);
> >  
> > @@ -525,21 +504,21 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
> >  {
> >  	struct mixer_resources *res = &ctx->mixer_res;
> >  	unsigned long flags;
> > -	struct hdmi_win_data *win_data;
> > +	struct exynos_drm_plane *plane;
> >  	unsigned int x_ratio, y_ratio;
> >  	unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
> >  	dma_addr_t dma_addr;
> >  	unsigned int fmt;
> >  	u32 val;
> >  
> > -	win_data = &ctx->win_data[win];
> > +	plane = &ctx->planes[win];
> >  
> >  	#define RGB565 4
> >  	#define ARGB1555 5
> >  	#define ARGB4444 6
> >  	#define ARGB8888 7
> >  
> > -	switch (win_data->bpp) {
> > +	switch (plane->bpp) {
> >  	case 16:
> >  		fmt = ARGB4444;
> >  		break;
> > @@ -554,17 +533,17 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
> >  	x_ratio = 0;
> >  	y_ratio = 0;
> >  
> > -	dst_x_offset = win_data->crtc_x;
> > -	dst_y_offset = win_data->crtc_y;
> > +	dst_x_offset = plane->crtc_x;
> > +	dst_y_offset = plane->crtc_y;
> >  
> >  	/* converting dma address base and source offset */
> > -	dma_addr = win_data->dma_addr
> > -		+ (win_data->fb_x * win_data->bpp >> 3)
> > -		+ (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
> > +	dma_addr = plane->dma_addr[0]
> > +		+ (plane->fb_x * plane->bpp >> 3)
> > +		+ (plane->fb_y * plane->fb_width * plane->bpp >> 3);
> >  	src_x_offset = 0;
> >  	src_y_offset = 0;
> >  
> > -	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
> > +	if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE)
> >  		ctx->interlace = true;
> >  	else
> >  		ctx->interlace = false;
> > @@ -577,18 +556,18 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
> >  		MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
> >  
> >  	/* setup geometry */
> > -	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
> > +	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), plane->fb_width);
> >  
> >  	/* setup display size */
> >  	if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
> >  		win == MIXER_DEFAULT_WIN) {
> > -		val  = MXR_MXR_RES_HEIGHT(win_data->fb_height);
> > -		val |= MXR_MXR_RES_WIDTH(win_data->fb_width);
> > +		val  = MXR_MXR_RES_HEIGHT(plane->fb_height);
> > +		val |= MXR_MXR_RES_WIDTH(plane->fb_width);
> >  		mixer_reg_write(res, MXR_RESOLUTION, val);
> >  	}
> >  
> > -	val  = MXR_GRP_WH_WIDTH(win_data->crtc_width);
> > -	val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
> > +	val  = MXR_GRP_WH_WIDTH(plane->crtc_width);
> > +	val |= MXR_GRP_WH_HEIGHT(plane->crtc_height);
> >  	val |= MXR_GRP_WH_H_SCALE(x_ratio);
> >  	val |= MXR_GRP_WH_V_SCALE(y_ratio);
> >  	mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
> > @@ -606,8 +585,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
> >  	/* set buffer address to mixer */
> >  	mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
> >  
> > -	mixer_cfg_scan(ctx, win_data->mode_height);
> > -	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
> > +	mixer_cfg_scan(ctx, plane->mode_height);
> > +	mixer_cfg_rgb_fmt(ctx, plane->mode_height);
> >  	mixer_cfg_layer(ctx, win, true);
> >  
> >  	/* layer update mandatory for mixer 16.0.33.0 */
> > @@ -913,58 +892,6 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
> >  	mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
> >  }
> >  
> > -static void mixer_win_mode_set(struct exynos_drm_crtc *crtc,
> > -			struct exynos_drm_plane *plane)
> > -{
> > -	struct mixer_context *mixer_ctx = crtc->ctx;
> > -	struct hdmi_win_data *win_data;
> > -	int win;
> > -
> > -	if (!plane) {
> > -		DRM_ERROR("plane is NULL\n");
> > -		return;
> > -	}
> > -
> > -	DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
> > -				 plane->fb_width, plane->fb_height,
> > -				 plane->fb_x, plane->fb_y,
> > -				 plane->crtc_width, plane->crtc_height,
> > -				 plane->crtc_x, plane->crtc_y);
> > -
> > -	win = plane->zpos;
> > -	if (win == DEFAULT_ZPOS)
> > -		win = MIXER_DEFAULT_WIN;
> > -
> > -	if (win < 0 || win >= MIXER_WIN_NR) {
> > -		DRM_ERROR("mixer window[%d] is wrong\n", win);
> > -		return;
> > -	}
> > -
> > -	win_data = &mixer_ctx->win_data[win];
> > -
> > -	win_data->dma_addr = plane->dma_addr[0];
> > -	win_data->chroma_dma_addr = plane->dma_addr[1];
> > -	win_data->pixel_format = plane->pixel_format;
> > -	win_data->bpp = plane->bpp;
> > -
> > -	win_data->crtc_x = plane->crtc_x;
> > -	win_data->crtc_y = plane->crtc_y;
> > -	win_data->crtc_width = plane->crtc_width;
> > -	win_data->crtc_height = plane->crtc_height;
> > -
> > -	win_data->fb_x = plane->fb_x;
> > -	win_data->fb_y = plane->fb_y;
> > -	win_data->fb_width = plane->fb_width;
> > -	win_data->fb_height = plane->fb_height;
> > -	win_data->src_width = plane->src_width;
> > -	win_data->src_height = plane->src_height;
> > -
> > -	win_data->mode_width = plane->mode_width;
> > -	win_data->mode_height = plane->mode_height;
> > -
> > -	win_data->scan_flags = plane->scan_flag;
> > -}
> > -
> >  static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  {
> >  	struct mixer_context *mixer_ctx = crtc->ctx;
> > @@ -984,7 +911,7 @@ static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  	else
> >  		mixer_graph_buffer(mixer_ctx, win);
> >  
> > -	mixer_ctx->win_data[win].enabled = true;
> > +	mixer_ctx->planes[win].enabled = true;
> >  }
> >  
> >  static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
> > @@ -999,7 +926,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
> >  	mutex_lock(&mixer_ctx->mixer_mutex);
> >  	if (!mixer_ctx->powered) {
> >  		mutex_unlock(&mixer_ctx->mixer_mutex);
> > -		mixer_ctx->win_data[win].resume = false;
> > +		mixer_ctx->planes[win].resume = false;
> >  		return;
> >  	}
> >  	mutex_unlock(&mixer_ctx->mixer_mutex);
> > @@ -1012,7 +939,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
> >  	mixer_vsync_set_update(mixer_ctx, true);
> >  	spin_unlock_irqrestore(&res->reg_slock, flags);
> >  
> > -	mixer_ctx->win_data[win].enabled = false;
> > +	mixer_ctx->planes[win].enabled = false;
> >  }
> >  
> >  static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
> > @@ -1049,12 +976,12 @@ static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
> >  
> >  static void mixer_window_suspend(struct mixer_context *ctx)
> >  {
> > -	struct hdmi_win_data *win_data;
> > +	struct exynos_drm_plane *plane;
> >  	int i;
> >  
> >  	for (i = 0; i < MIXER_WIN_NR; i++) {
> > -		win_data = &ctx->win_data[i];
> > -		win_data->resume = win_data->enabled;
> > +		plane = &ctx->planes[i];
> > +		plane->resume = plane->enabled;
> >  		mixer_win_disable(ctx->crtc, i);
> >  	}
> >  	mixer_wait_for_vblank(ctx->crtc);
> > @@ -1062,14 +989,14 @@ static void mixer_window_suspend(struct mixer_context *ctx)
> >  
> >  static void mixer_window_resume(struct mixer_context *ctx)
> >  {
> > -	struct hdmi_win_data *win_data;
> > +	struct exynos_drm_plane *plane;
> >  	int i;
> >  
> >  	for (i = 0; i < MIXER_WIN_NR; i++) {
> > -		win_data = &ctx->win_data[i];
> > -		win_data->enabled = win_data->resume;
> > -		win_data->resume = false;
> > -		if (win_data->enabled)
> > +		plane = &ctx->planes[i];
> > +		plane->enabled = plane->resume;
> > +		plane->resume = false;
> > +		if (plane->enabled)
> >  			mixer_win_commit(ctx->crtc, i);
> >  	}
> >  }
> > @@ -1179,7 +1106,6 @@ static struct exynos_drm_crtc_ops mixer_crtc_ops = {
> >  	.enable_vblank		= mixer_enable_vblank,
> >  	.disable_vblank		= mixer_disable_vblank,
> >  	.wait_for_vblank	= mixer_wait_for_vblank,
> > -	.win_mode_set		= mixer_win_mode_set,
> >  	.win_commit		= mixer_win_commit,
> >  	.win_disable		= mixer_win_disable,
> >  };
> > @@ -1243,15 +1169,25 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
> >  {
> >  	struct mixer_context *ctx = dev_get_drvdata(dev);
> >  	struct drm_device *drm_dev = data;
> > -	int ret;
> > +	struct exynos_drm_plane *exynos_plane;
> > +	enum drm_plane_type type;
> > +	int i, ret;
> > +
> > +	for (i = 0; i < MIXER_WIN_NR; i++) {
> > +		type = (i == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
> > +						DRM_PLANE_TYPE_OVERLAY;
> > +		exynos_plane_init(drm_dev, &ctx->planes[i], 1 << ctx->pipe,
> > +				  type);
> > +	}
> >  
> >  	ret = mixer_initialize(ctx, drm_dev);
> >  	if (ret)
> >  		return ret;
> >  
> > -	ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
> > -				     EXYNOS_DISPLAY_TYPE_HDMI,
> > -				     &mixer_crtc_ops, ctx);
> > +	exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
> > +	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
> > +					   ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
> > +					   &mixer_crtc_ops, ctx);
> >  	if (IS_ERR(ctx->crtc)) {
> >  		mixer_ctx_remove(ctx);
> >  		ret = PTR_ERR(ctx->crtc);
> > 
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 08/14] drm/exynos: atomic phase 1: add atomic_begin()/atomic_flush()
  2015-02-04  7:49   ` Joonyoung Shim
@ 2015-02-04 14:30     ` Daniel Vetter
  2015-02-05  2:48       ` Joonyoung Shim
  0 siblings, 1 reply; 37+ messages in thread
From: Daniel Vetter @ 2015-02-04 14:30 UTC (permalink / raw)
  To: Joonyoung Shim; +Cc: linux-samsung-soc, Gustavo Padovan, dri-devel

On Wed, Feb 04, 2015 at 04:49:25PM +0900, Joonyoung Shim wrote:
> Hi,
> 
> On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> > From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> > 
> > Add CRTC callbacks .atomic_begin() .atomic_flush(). On exynos they
> > unprotect the windows before the commit and protects it after based on
> > a plane mask tha store which plane will be updated.
> > 
> 
> I don't think they need now.

This does exactly what I wanted to do in my atomic poc but couldn't
because of the massive layer hell that was still around in atomic. Haven't
looked into the patch in details, so no full r-b but good enough for an

Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Aside: If you think something doesn't need to be done please explain what
you mean or at least ask about what you don't understand in a patch. As-is
your review is pretty much unactionable.

Cheers, Daniel

> 
> Thanks.
> 
> > For that we create two new exynos_crtc callbacks: .win_protect() and
> > .win_unprotect(). The only driver that implement those now is FIMD.
> > 
> > Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> > ---
> >  drivers/gpu/drm/exynos/exynos_drm_crtc.c  | 34 ++++++++++++++++++
> >  drivers/gpu/drm/exynos/exynos_drm_drv.h   |  4 +++
> >  drivers/gpu/drm/exynos/exynos_drm_fimd.c  | 57 ++++++++++++++++++++++---------
> >  drivers/gpu/drm/exynos/exynos_drm_plane.c |  4 +++
> >  4 files changed, 82 insertions(+), 17 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> > index 09d4780..be36cca 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> > @@ -147,6 +147,38 @@ static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
> >  	}
> >  }
> >  
> > +static void exynos_crtc_atomic_begin(struct drm_crtc *crtc)
> > +{
> > +	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
> > +	struct drm_plane *plane;
> > +	int index = 0;
> > +
> > +	list_for_each_entry(plane, &crtc->dev->mode_config.plane_list, head) {
> > +		if (exynos_crtc->ops->win_protect &&
> > +		    exynos_crtc->plane_mask & (0x01 << index))
> > +			exynos_crtc->ops->win_protect(exynos_crtc, index);
> > +
> > +		index++;
> > +	}
> > +}
> > +
> > +static void exynos_crtc_atomic_flush(struct drm_crtc *crtc)
> > +{
> > +	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
> > +	struct drm_plane *plane;
> > +	int index = 0;
> > +
> > +	list_for_each_entry(plane, &crtc->dev->mode_config.plane_list, head) {
> > +		if (exynos_crtc->ops->win_unprotect &&
> > +		    exynos_crtc->plane_mask & (0x01 << index))
> > +			exynos_crtc->ops->win_unprotect(exynos_crtc, index);
> > +
> > +		index++;
> > +	}
> > +
> > +	exynos_crtc->plane_mask = 0;
> > +}
> > +
> >  static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
> >  	.dpms		= exynos_drm_crtc_dpms,
> >  	.prepare	= exynos_drm_crtc_prepare,
> > @@ -155,6 +187,8 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
> >  	.mode_set	= exynos_drm_crtc_mode_set,
> >  	.mode_set_base	= exynos_drm_crtc_mode_set_base,
> >  	.disable	= exynos_drm_crtc_disable,
> > +	.atomic_begin	= exynos_crtc_atomic_begin,
> > +	.atomic_flush	= exynos_crtc_atomic_flush,
> >  };
> >  
> >  static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> > index cad54e7..43efd9f 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> > @@ -194,6 +194,8 @@ struct exynos_drm_crtc_ops {
> >  	void (*win_enable)(struct exynos_drm_crtc *crtc, int zpos);
> >  	void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
> >  	void (*te_handler)(struct exynos_drm_crtc *crtc);
> > +	void (*win_protect)(struct exynos_drm_crtc *crtc, int zpos);
> > +	void (*win_unprotect)(struct exynos_drm_crtc *crtc, int zpos);
> >  };
> >  
> >  enum exynos_crtc_mode {
> > @@ -214,6 +216,7 @@ enum exynos_crtc_mode {
> >   *	we can refer to the crtc to current hardware interrupt occurred through
> >   *	this pipe value.
> >   * @dpms: store the crtc dpms value
> > + * @plane_mask: store planes to be updated on atomic modesetting
> >   * @mode: store the crtc mode value
> >   * @event: vblank event that is currently queued for flip
> >   * @ops: pointer to callbacks for exynos drm specific functionality
> > @@ -224,6 +227,7 @@ struct exynos_drm_crtc {
> >  	enum exynos_drm_output_type	type;
> >  	unsigned int			pipe;
> >  	unsigned int			dpms;
> > +	unsigned int			plane_mask;
> >  	enum exynos_crtc_mode		mode;
> >  	wait_queue_head_t		pending_flip_queue;
> >  	struct drm_pending_vblank_event	*event;
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> > index ebb4cdc..f498d86 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> > @@ -585,6 +585,16 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
> >  {
> >  	u32 reg, bits, val;
> >  
> > +	/*
> > +	 * SHADOWCON/PRTCON register is used for enabling timing.
> > +	 *
> > +	 * for example, once only width value of a register is set,
> > +	 * if the dma is started then fimd hardware could malfunction so
> > +	 * with protect window setting, the register fields with prefix '_F'
> > +	 * wouldn't be updated at vsync also but updated once unprotect window
> > +	 * is set.
> > +	 */
> > +
> >  	if (ctx->driver_data->has_shadowcon) {
> >  		reg = SHADOWCON;
> >  		bits = SHADOWCON_WINx_PROTECT(win);
> > @@ -627,20 +637,6 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  		return;
> >  	}
> >  
> > -	/*
> > -	 * SHADOWCON/PRTCON register is used for enabling timing.
> > -	 *
> > -	 * for example, once only width value of a register is set,
> > -	 * if the dma is started then fimd hardware could malfunction so
> > -	 * with protect window setting, the register fields with prefix '_F'
> > -	 * wouldn't be updated at vsync also but updated once unprotect window
> > -	 * is set.
> > -	 */
> > -
> > -	/* protect windows */
> > -	fimd_shadow_protect_win(ctx, win, true);
> > -
> > -
> >  	offset = plane->fb_x * (plane->bpp >> 3);
> >  	offset += plane->fb_y * plane->pitch;
> >  
> > @@ -722,9 +718,6 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
> >  	if (ctx->driver_data->has_shadowcon)
> >  		fimd_enable_shadow_channel_path(ctx, win, true);
> >  
> > -	/* Enable DMA channel and unprotect windows */
> > -	fimd_shadow_protect_win(ctx, win, false);
> > -
> >  	plane->enabled = true;
> >  
> >  	if (ctx->i80_if)
> > @@ -947,6 +940,34 @@ static void fimd_te_handler(struct exynos_drm_crtc *crtc)
> >  		drm_handle_vblank(ctx->drm_dev, ctx->pipe);
> >  }
> >  
> > +static void fimd_win_protect(struct exynos_drm_crtc *crtc, int zpos)
> > +{
> > +	struct fimd_context *ctx = crtc->ctx;
> > +	int win = zpos;
> > +
> > +	if (win == DEFAULT_ZPOS)
> > +		win = ctx->default_win;
> > +
> > +	if (win < 0 || win >= WINDOWS_NR)
> > +		return;
> > +
> > +	fimd_shadow_protect_win(ctx, win, true);
> > +}
> > +
> > +static void fimd_win_unprotect(struct exynos_drm_crtc *crtc, int zpos)
> > +{
> > +	struct fimd_context *ctx = crtc->ctx;
> > +	int win = zpos;
> > +
> > +	if (win == DEFAULT_ZPOS)
> > +		win = ctx->default_win;
> > +
> > +	if (win < 0 || win >= WINDOWS_NR)
> > +		return;
> > +
> > +	fimd_shadow_protect_win(ctx, win, false);
> > +}
> > +
> >  static struct exynos_drm_crtc_ops fimd_crtc_ops = {
> >  	.dpms = fimd_dpms,
> >  	.mode_fixup = fimd_mode_fixup,
> > @@ -957,6 +978,8 @@ static struct exynos_drm_crtc_ops fimd_crtc_ops = {
> >  	.win_commit = fimd_win_commit,
> >  	.win_disable = fimd_win_disable,
> >  	.te_handler = fimd_te_handler,
> > +	.win_protect = fimd_win_protect,
> > +	.win_unprotect = fimd_win_unprotect,
> >  };
> >  
> >  static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
> > index a3b0687..363d59d 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
> > @@ -65,6 +65,7 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last)
> >  int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb)
> >  {
> >  	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
> > +	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(plane->crtc);
> >  	int nr;
> >  	int i;
> >  
> > @@ -83,6 +84,9 @@ int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb)
> >  				i, (unsigned long)exynos_plane->dma_addr[i]);
> >  	}
> >  
> > +	if (exynos_crtc)
> > +		exynos_crtc->plane_mask += 1 << exynos_plane->zpos;
> > +
> >  	return 0;
> >  }
> >  
> > 
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 11/14] drm/exynos: atomic phase 2: keep track of framebuffer pointer
  2015-02-04  7:53   ` Joonyoung Shim
@ 2015-02-04 14:33     ` Daniel Vetter
  0 siblings, 0 replies; 37+ messages in thread
From: Daniel Vetter @ 2015-02-04 14:33 UTC (permalink / raw)
  To: Joonyoung Shim
  Cc: Gustavo Padovan, linux-samsung-soc, Gustavo Padovan, dri-devel

On Wed, Feb 04, 2015 at 04:53:12PM +0900, Joonyoung Shim wrote:
> Hi,
> 
> On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> > From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> > 
> > Use drm_atomic_set_fb_for_plane() in the legacy page_flip path to keep
> > track of the framebuffer pointer and reference.
> > 
> > Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> > ---
> >  drivers/gpu/drm/exynos/exynos_drm_crtc.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> > index 660ad64..2edc73c 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> > @@ -211,6 +211,9 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
> >  			    crtc_w, crtc_h, crtc->x, crtc->y,
> >  			    crtc_w, crtc_h);
> >  
> > +	if (crtc->primary->state)
> > +		drm_atomic_set_fb_for_plane(crtc->primary->state, fb);
> > +
> 
> I'm not sure whether this needs, how about go to
> drm_atomic_helper_page_flip?

You can only do that once you have full async atomic commit support, which
is done in phase 3. Until that's the case you need to keep this little bit
of temporary fixup code around.

I've had the same in my exynos branch, we have the same now in i915 (well
it looks a bit different since we dont use all the helpers but roll some
things ourselves).

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> 
> Thanks.
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2
  2015-02-04  7:37 ` [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Joonyoung Shim
@ 2015-02-04 14:35   ` Daniel Vetter
  0 siblings, 0 replies; 37+ messages in thread
From: Daniel Vetter @ 2015-02-04 14:35 UTC (permalink / raw)
  To: Joonyoung Shim
  Cc: Gustavo Padovan, linux-samsung-soc, Gustavo Padovan, dri-devel

Hi all,

I've gone through some of the contentions point in this patch review. With
my community guy hat on I really want to make drm atomic a success, exynos
atomic is important for that.

On Wed, Feb 04, 2015 at 04:37:04PM +0900, Joonyoung Shim wrote:
> Hi,
> 
> On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> > From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> > 
> > Hi,
> > 
> > This series clean ups a few more paths from exynos-drm with the most important
> > being the removal of the global page flip queue and the removal in driver
> > internal data (struct *_win_data) that was replicating plane data.
> > 
> > Following these patches comes the first step torwards atomic modesetting
> > support on exynos.
> > 
> 
> It's better to split cleanup and atomic support, not one patchset.

Imo the cleanups make perfect sense as prep work for atomic. They're
definitely needed afaict from what I've seen reading exynos code and these
patches here before we can implement atomic.

Personally I'd have delayered even more aggressively before going into the
atomic stuff. But in the end I guess Padovan wants to be able to ship
exynos atomic preferrably sooner than later.

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 02/14] drm/exynos: Remove exynos_plane_dpms() call with no effect
  2015-02-04 14:16     ` Daniel Vetter
@ 2015-02-05  1:05       ` Joonyoung Shim
  2015-02-05  9:03         ` Daniel Vetter
  0 siblings, 1 reply; 37+ messages in thread
From: Joonyoung Shim @ 2015-02-05  1:05 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Gustavo Padovan, linux-samsung-soc, Gustavo Padovan, dri-devel

Hi Daniel,

On 02/04/2015 11:16 PM, Daniel Vetter wrote:
> On Wed, Feb 04, 2015 at 04:42:57PM +0900, Joonyoung Shim wrote:
>> Hi,
>>
>> On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
>>> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>>>
>>> exynos_plane_dpms(DRM_MODE_DPMS_ON) calls the win_enable()'s callback
>>> from the underlying layer. However neither one of these layers implement
>>> win_enable() - FIMD, Mixer and VIDI. Thus the call to exynos_plane_dpms()
>>> is pointless.
>>>
>>> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>>> ---
>>>  drivers/gpu/drm/exynos/exynos_drm_crtc.c | 2 --
>>>  1 file changed, 2 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
>>> index b2a4b84..ad675fb 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
>>> @@ -65,8 +65,6 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
>>>  
>>>  	if (exynos_crtc->ops->commit)
>>>  		exynos_crtc->ops->commit(exynos_crtc);
>>> -
>>> -	exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON);
>>
>> As i said, this needs to keep pair enabled flag of struct
>> exynos_drm_plane.
> 
> The reason exynos needs that exynos_plane->enable is because it has its
> own per-plane dpms state. There's two problems with that:
> - It's highyl non-standard, the drm kms way is to just disable the plane
>   and not have some additional knob on top.
> - The atomic helpers will not be able to handle this. They assume that
>   there's only one dpms knob for the entire display pipeline, and
>   per-plane enable/disable is handled by setting plane->state->crtc, which
>   must be set iff plane->state->fb is set right now.
> 
> I recommend we rip this all out if we can adjust existing userspace to
> stop using the "mode" property on planes and crtcs.
> 
> And with that non-standard exynos plane mode thing gone we can indeed rip
> out exynos_plane_dpms and exynos_plane->enabled and just directly call
> manager->ops->win_enable/disble. And then rip out the win_enable since
> it's unused.

But this cleanup on current codes doesn't care now current operation
normally. First let's cleanup non-standard exynos plane dpms state as
you said.

Thanks.

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

* Re: [PATCH 04/14] drm/exynos: remove struct *_win_data abstraction on planes
  2015-02-04 14:28     ` Daniel Vetter
@ 2015-02-05  2:37       ` Joonyoung Shim
  2015-02-05  9:15         ` Daniel Vetter
  0 siblings, 1 reply; 37+ messages in thread
From: Joonyoung Shim @ 2015-02-05  2:37 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: linux-samsung-soc, Gustavo Padovan, dri-devel

Hi Daniel,

On 02/04/2015 11:28 PM, Daniel Vetter wrote:
> On Wed, Feb 04, 2015 at 04:44:12PM +0900, Joonyoung Shim wrote:
>> Hi,
>>
>> On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
>>> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>>>
>>> struct {fimd,mixer,vidi}_win_data was just keeping the same data
>>> as struct exynos_drm_plane thus get ride of it and use exynos_drm_plane
>>> directly.
>>>
>>> It changes how planes are created and remove .win_mode_set() callback
>>> that was only filling all *_win_data structs.
>>>
>>
>> I commented already on prior patch.
> 
> I think you don't quite understand how this primary/overlay plane stuff
> works in drm core. The entire point of the drm core primary plane is to
> work _exactly_ like an overlay plane and allow userspace to mangle the
> primary plane configuration through the overlay plane. The only reason we
> have primary planes is so that old userspace keeps working.
> 

Right, i misunderstood a bit because exynos hw drivers have dependency
of zpos(hw overlay position).

Current exynos drm driver has each primary plane of hw drivers and five
overlay planes. The primary plane is fixed on default hw overlay and all
overlay plane can map to all hw overlays using specific zpos property of
exynos drm plane.

Gustavo approach will include specific hw overlay data in overlay plane
and hw driver keeps overlay planes to array by zpos order. But current
zpos of overlay plane is 0 always if user doesn't modify it, so hw
driver will use only hw overlay data of primary plane always even if
user want to use overlay plane.

If user is modified zpos of overlay plane, hw driver can get wrong hw
overlay data from different overlay plane because hw driver keeps
overlay planes by zpos order.

Thanks.

> When I've done the testconversion with exynos to validate my atomic
> helpers I've noticed that exynos makes a mess here, and on a quick look
> Padovan seems to fix this up here. Not a detailed review, but this has my
> Ack.
> -Daniel
> 
>>
>> Thanks.
>>
>>> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>>> ---
>>>  drivers/gpu/drm/exynos/exynos_drm_crtc.c  |   9 +-
>>>  drivers/gpu/drm/exynos/exynos_drm_crtc.h  |   1 +
>>>  drivers/gpu/drm/exynos/exynos_drm_drv.c   |  14 --
>>>  drivers/gpu/drm/exynos/exynos_drm_drv.h   |   5 +-
>>>  drivers/gpu/drm/exynos/exynos_drm_fimd.c  | 182 ++++++++++---------------
>>>  drivers/gpu/drm/exynos/exynos_drm_plane.c |  20 +--
>>>  drivers/gpu/drm/exynos/exynos_drm_plane.h |   6 +-
>>>  drivers/gpu/drm/exynos/exynos_drm_vidi.c  | 123 +++++------------
>>>  drivers/gpu/drm/exynos/exynos_mixer.c     | 212 +++++++++++-------------------
>>>  9 files changed, 183 insertions(+), 389 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
>>> index ad675fb..d504f0b 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
>>> @@ -296,13 +296,13 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
>>>  }
>>>  
>>>  struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
>>> +					       struct drm_plane *plane,
>>>  					       int pipe,
>>>  					       enum exynos_drm_output_type type,
>>>  					       struct exynos_drm_crtc_ops *ops,
>>>  					       void *ctx)
>>>  {
>>>  	struct exynos_drm_crtc *exynos_crtc;
>>> -	struct drm_plane *plane;
>>>  	struct exynos_drm_private *private = drm_dev->dev_private;
>>>  	struct drm_crtc *crtc;
>>>  	int ret;
>>> @@ -318,12 +318,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
>>>  	exynos_crtc->type = type;
>>>  	exynos_crtc->ops = ops;
>>>  	exynos_crtc->ctx = ctx;
>>> -	plane = exynos_plane_init(drm_dev, 1 << pipe,
>>> -				  DRM_PLANE_TYPE_PRIMARY);
>>> -	if (IS_ERR(plane)) {
>>> -		ret = PTR_ERR(plane);
>>> -		goto err_plane;
>>> -	}
>>>  
>>>  	crtc = &exynos_crtc->base;
>>>  
>>> @@ -342,7 +336,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
>>>  
>>>  err_crtc:
>>>  	plane->funcs->destroy(plane);
>>> -err_plane:
>>>  	kfree(exynos_crtc);
>>>  	return ERR_PTR(ret);
>>>  }
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
>>> index 628b787..0ecd8fc 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
>>> @@ -18,6 +18,7 @@
>>>  #include "exynos_drm_drv.h"
>>>  
>>>  struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
>>> +					       struct drm_plane *plane,
>>>  					       int pipe,
>>>  					       enum exynos_drm_output_type type,
>>>  					       struct exynos_drm_crtc_ops *ops,
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
>>> index 737164d..778c91e 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
>>> @@ -55,7 +55,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
>>>  {
>>>  	struct exynos_drm_private *private;
>>>  	int ret;
>>> -	int nr;
>>>  
>>>  	private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
>>>  	if (!private)
>>> @@ -80,19 +79,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
>>>  
>>>  	exynos_drm_mode_config_init(dev);
>>>  
>>> -	for (nr = 0; nr < MAX_PLANE; nr++) {
>>> -		struct drm_plane *plane;
>>> -		unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;
>>> -
>>> -		plane = exynos_plane_init(dev, possible_crtcs,
>>> -					  DRM_PLANE_TYPE_OVERLAY);
>>> -		if (!IS_ERR(plane))
>>> -			continue;
>>> -
>>> -		ret = PTR_ERR(plane);
>>> -		goto err_mode_config_cleanup;
>>> -	}
>>> -
>>>  	/* setup possible_clones. */
>>>  	exynos_drm_encoder_setup(dev);
>>>  
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
>>> index 7411af2..cad54e7 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
>>> @@ -78,6 +78,7 @@ enum exynos_drm_output_type {
>>>   * @transparency: transparency on or off.
>>>   * @activated: activated or not.
>>>   * @enabled: enabled or not.
>>> + * @resume: to resume or not.
>>>   *
>>>   * this structure is common to exynos SoC and its contents would be copied
>>>   * to hardware specific overlay info.
>>> @@ -112,6 +113,7 @@ struct exynos_drm_plane {
>>>  	bool transparency:1;
>>>  	bool activated:1;
>>>  	bool enabled:1;
>>> +	bool resume:1;
>>>  };
>>>  
>>>  /*
>>> @@ -172,7 +174,6 @@ struct exynos_drm_display {
>>>   * @disable_vblank: specific driver callback for disabling vblank interrupt.
>>>   * @wait_for_vblank: wait for vblank interrupt to make sure that
>>>   *	hardware overlay is updated.
>>> - * @win_mode_set: copy drm overlay info to hw specific overlay info.
>>>   * @win_commit: apply hardware specific overlay data to registers.
>>>   * @win_enable: enable hardware specific overlay.
>>>   * @win_disable: disable hardware specific overlay.
>>> @@ -189,8 +190,6 @@ struct exynos_drm_crtc_ops {
>>>  	int (*enable_vblank)(struct exynos_drm_crtc *crtc);
>>>  	void (*disable_vblank)(struct exynos_drm_crtc *crtc);
>>>  	void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
>>> -	void (*win_mode_set)(struct exynos_drm_crtc *crtc,
>>> -				struct exynos_drm_plane *plane);
>>>  	void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos);
>>>  	void (*win_enable)(struct exynos_drm_crtc *crtc, int zpos);
>>>  	void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>>> index 925fc69..ebb4cdc 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>>> @@ -31,6 +31,7 @@
>>>  #include "exynos_drm_drv.h"
>>>  #include "exynos_drm_fbdev.h"
>>>  #include "exynos_drm_crtc.h"
>>> +#include "exynos_drm_plane.h"
>>>  #include "exynos_drm_iommu.h"
>>>  
>>>  /*
>>> @@ -140,31 +141,15 @@ static struct fimd_driver_data exynos5_fimd_driver_data = {
>>>  	.has_vtsel = 1,
>>>  };
>>>  
>>> -struct fimd_win_data {
>>> -	unsigned int		offset_x;
>>> -	unsigned int		offset_y;
>>> -	unsigned int		ovl_width;
>>> -	unsigned int		ovl_height;
>>> -	unsigned int		fb_width;
>>> -	unsigned int		fb_height;
>>> -	unsigned int		bpp;
>>> -	unsigned int		pixel_format;
>>> -	dma_addr_t		dma_addr;
>>> -	unsigned int		buf_offsize;
>>> -	unsigned int		line_size;	/* bytes */
>>> -	bool			enabled;
>>> -	bool			resume;
>>> -};
>>> -
>>>  struct fimd_context {
>>>  	struct device			*dev;
>>>  	struct drm_device		*drm_dev;
>>>  	struct exynos_drm_crtc		*crtc;
>>> +	struct exynos_drm_plane		planes[WINDOWS_NR];
>>>  	struct clk			*bus_clk;
>>>  	struct clk			*lcd_clk;
>>>  	void __iomem			*regs;
>>>  	struct regmap			*sysreg;
>>> -	struct fimd_win_data		win_data[WINDOWS_NR];
>>>  	unsigned int			default_win;
>>>  	unsigned long			irq_flags;
>>>  	u32				vidcon0;
>>> @@ -506,58 +491,9 @@ static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
>>>  	}
>>>  }
>>>  
>>> -static void fimd_win_mode_set(struct exynos_drm_crtc *crtc,
>>> -			struct exynos_drm_plane *plane)
>>> -{
>>> -	struct fimd_context *ctx = crtc->ctx;
>>> -	struct fimd_win_data *win_data;
>>> -	int win;
>>> -	unsigned long offset;
>>> -
>>> -	if (!plane) {
>>> -		DRM_ERROR("plane is NULL\n");
>>> -		return;
>>> -	}
>>> -
>>> -	win = plane->zpos;
>>> -	if (win == DEFAULT_ZPOS)
>>> -		win = ctx->default_win;
>>> -
>>> -	if (win < 0 || win >= WINDOWS_NR)
>>> -		return;
>>> -
>>> -	offset = plane->fb_x * (plane->bpp >> 3);
>>> -	offset += plane->fb_y * plane->pitch;
>>> -
>>> -	DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
>>> -
>>> -	win_data = &ctx->win_data[win];
>>> -
>>> -	win_data->offset_x = plane->crtc_x;
>>> -	win_data->offset_y = plane->crtc_y;
>>> -	win_data->ovl_width = plane->crtc_width;
>>> -	win_data->ovl_height = plane->crtc_height;
>>> -	win_data->fb_width = plane->fb_width;
>>> -	win_data->fb_height = plane->fb_height;
>>> -	win_data->dma_addr = plane->dma_addr[0] + offset;
>>> -	win_data->bpp = plane->bpp;
>>> -	win_data->pixel_format = plane->pixel_format;
>>> -	win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
>>> -				(plane->bpp >> 3);
>>> -	win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
>>> -
>>> -	DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
>>> -			win_data->offset_x, win_data->offset_y);
>>> -	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
>>> -			win_data->ovl_width, win_data->ovl_height);
>>> -	DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
>>> -	DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
>>> -			plane->fb_width, plane->crtc_width);
>>> -}
>>> -
>>>  static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
>>>  {
>>> -	struct fimd_win_data *win_data = &ctx->win_data[win];
>>> +	struct exynos_drm_plane *plane = &ctx->planes[win];
>>>  	unsigned long val;
>>>  
>>>  	val = WINCONx_ENWIN;
>>> @@ -567,11 +503,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
>>>  	 * So the request format is ARGB8888 then change it to XRGB8888.
>>>  	 */
>>>  	if (ctx->driver_data->has_limited_fmt && !win) {
>>> -		if (win_data->pixel_format == DRM_FORMAT_ARGB8888)
>>> -			win_data->pixel_format = DRM_FORMAT_XRGB8888;
>>> +		if (plane->pixel_format == DRM_FORMAT_ARGB8888)
>>> +			plane->pixel_format = DRM_FORMAT_XRGB8888;
>>>  	}
>>>  
>>> -	switch (win_data->pixel_format) {
>>> +	switch (plane->pixel_format) {
>>>  	case DRM_FORMAT_C8:
>>>  		val |= WINCON0_BPPMODE_8BPP_PALETTE;
>>>  		val |= WINCONx_BURSTLEN_8WORD;
>>> @@ -607,7 +543,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
>>>  		break;
>>>  	}
>>>  
>>> -	DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
>>> +	DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);
>>>  
>>>  	/*
>>>  	 * In case of exynos, setting dma-burst to 16Word causes permanent
>>> @@ -617,7 +553,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
>>>  	 * movement causes unstable DMA which results into iommu crash/tear.
>>>  	 */
>>>  
>>> -	if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
>>> +	if (plane->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
>>>  		val &= ~WINCONx_BURSTLEN_MASK;
>>>  		val |= WINCONx_BURSTLEN_4WORD;
>>>  	}
>>> @@ -668,11 +604,11 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
>>>  static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  {
>>>  	struct fimd_context *ctx = crtc->ctx;
>>> -	struct fimd_win_data *win_data;
>>> +	struct exynos_drm_plane *plane;
>>>  	int win = zpos;
>>> -	unsigned long val, alpha, size;
>>> -	unsigned int last_x;
>>> -	unsigned int last_y;
>>> +	dma_addr_t dma_addr;
>>> +	unsigned long val, alpha, size, offset;
>>> +	unsigned int last_x, last_y, buf_offsize, line_size;
>>>  
>>>  	if (ctx->suspended)
>>>  		return;
>>> @@ -683,11 +619,11 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  	if (win < 0 || win >= WINDOWS_NR)
>>>  		return;
>>>  
>>> -	win_data = &ctx->win_data[win];
>>> +	plane = &ctx->planes[win];
>>>  
>>>  	/* If suspended, enable this on resume */
>>>  	if (ctx->suspended) {
>>> -		win_data->resume = true;
>>> +		plane->resume = true;
>>>  		return;
>>>  	}
>>>  
>>> @@ -704,38 +640,45 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  	/* protect windows */
>>>  	fimd_shadow_protect_win(ctx, win, true);
>>>  
>>> +
>>> +	offset = plane->fb_x * (plane->bpp >> 3);
>>> +	offset += plane->fb_y * plane->pitch;
>>> +
>>>  	/* buffer start address */
>>> -	val = (unsigned long)win_data->dma_addr;
>>> +	dma_addr = plane->dma_addr[0] + offset;
>>> +	val = (unsigned long)dma_addr;
>>>  	writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
>>>  
>>>  	/* buffer end address */
>>> -	size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
>>> -	val = (unsigned long)(win_data->dma_addr + size);
>>> +	size = plane->fb_width * plane->crtc_height * (plane->bpp >> 3);
>>> +	val = (unsigned long)(dma_addr + size);
>>>  	writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
>>>  
>>>  	DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
>>> -			(unsigned long)win_data->dma_addr, val, size);
>>> +			(unsigned long)dma_addr, val, size);
>>>  	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
>>> -			win_data->ovl_width, win_data->ovl_height);
>>> +			plane->crtc_width, plane->crtc_height);
>>>  
>>>  	/* buffer size */
>>> -	val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
>>> -		VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size) |
>>> -		VIDW_BUF_SIZE_OFFSET_E(win_data->buf_offsize) |
>>> -		VIDW_BUF_SIZE_PAGEWIDTH_E(win_data->line_size);
>>> +	buf_offsize = (plane->fb_width - plane->crtc_width) * (plane->bpp >> 3);
>>> +	line_size = plane->crtc_width * (plane->bpp >> 3);
>>> +	val = VIDW_BUF_SIZE_OFFSET(buf_offsize) |
>>> +		VIDW_BUF_SIZE_PAGEWIDTH(line_size) |
>>> +		VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
>>> +		VIDW_BUF_SIZE_PAGEWIDTH_E(line_size);
>>>  	writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
>>>  
>>>  	/* OSD position */
>>> -	val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
>>> -		VIDOSDxA_TOPLEFT_Y(win_data->offset_y) |
>>> -		VIDOSDxA_TOPLEFT_X_E(win_data->offset_x) |
>>> -		VIDOSDxA_TOPLEFT_Y_E(win_data->offset_y);
>>> +	val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
>>> +		VIDOSDxA_TOPLEFT_Y(plane->crtc_y) |
>>> +		VIDOSDxA_TOPLEFT_X_E(plane->crtc_x) |
>>> +		VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y);
>>>  	writel(val, ctx->regs + VIDOSD_A(win));
>>>  
>>> -	last_x = win_data->offset_x + win_data->ovl_width;
>>> +	last_x = plane->crtc_x + plane->crtc_width;
>>>  	if (last_x)
>>>  		last_x--;
>>> -	last_y = win_data->offset_y + win_data->ovl_height;
>>> +	last_y = plane->crtc_y + plane->crtc_height;
>>>  	if (last_y)
>>>  		last_y--;
>>>  
>>> @@ -745,7 +688,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  	writel(val, ctx->regs + VIDOSD_B(win));
>>>  
>>>  	DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
>>> -			win_data->offset_x, win_data->offset_y, last_x, last_y);
>>> +			plane->crtc_x, plane->crtc_y, last_x, last_y);
>>>  
>>>  	/* hardware window 0 doesn't support alpha channel. */
>>>  	if (win != 0) {
>>> @@ -762,7 +705,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  		u32 offset = VIDOSD_D(win);
>>>  		if (win == 0)
>>>  			offset = VIDOSD_C(win);
>>> -		val = win_data->ovl_width * win_data->ovl_height;
>>> +		val = plane->crtc_width * plane->crtc_height;
>>>  		writel(val, ctx->regs + offset);
>>>  
>>>  		DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
>>> @@ -782,7 +725,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  	/* Enable DMA channel and unprotect windows */
>>>  	fimd_shadow_protect_win(ctx, win, false);
>>>  
>>> -	win_data->enabled = true;
>>> +	plane->enabled = true;
>>>  
>>>  	if (ctx->i80_if)
>>>  		atomic_set(&ctx->win_updated, 1);
>>> @@ -791,7 +734,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>>>  {
>>>  	struct fimd_context *ctx = crtc->ctx;
>>> -	struct fimd_win_data *win_data;
>>> +	struct exynos_drm_plane *plane;
>>>  	int win = zpos;
>>>  
>>>  	if (win == DEFAULT_ZPOS)
>>> @@ -800,11 +743,11 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>>>  	if (win < 0 || win >= WINDOWS_NR)
>>>  		return;
>>>  
>>> -	win_data = &ctx->win_data[win];
>>> +	plane = &ctx->planes[win];
>>>  
>>>  	if (ctx->suspended) {
>>>  		/* do not resume this window*/
>>> -		win_data->resume = false;
>>> +		plane->resume = false;
>>>  		return;
>>>  	}
>>>  
>>> @@ -819,42 +762,42 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>>>  	/* unprotect windows */
>>>  	fimd_shadow_protect_win(ctx, win, false);
>>>  
>>> -	win_data->enabled = false;
>>> +	plane->enabled = false;
>>>  }
>>>  
>>>  static void fimd_window_suspend(struct fimd_context *ctx)
>>>  {
>>> -	struct fimd_win_data *win_data;
>>> +	struct exynos_drm_plane *plane;
>>>  	int i;
>>>  
>>>  	for (i = 0; i < WINDOWS_NR; i++) {
>>> -		win_data = &ctx->win_data[i];
>>> -		win_data->resume = win_data->enabled;
>>> -		if (win_data->enabled)
>>> +		plane = &ctx->planes[i];
>>> +		plane->resume = plane->enabled;
>>> +		if (plane->enabled)
>>>  			fimd_win_disable(ctx->crtc, i);
>>>  	}
>>>  }
>>>  
>>>  static void fimd_window_resume(struct fimd_context *ctx)
>>>  {
>>> -	struct fimd_win_data *win_data;
>>> +	struct exynos_drm_plane *plane;
>>>  	int i;
>>>  
>>>  	for (i = 0; i < WINDOWS_NR; i++) {
>>> -		win_data = &ctx->win_data[i];
>>> -		win_data->enabled = win_data->resume;
>>> -		win_data->resume = false;
>>> +		plane = &ctx->planes[i];
>>> +		plane->enabled = plane->resume;
>>> +		plane->resume = false;
>>>  	}
>>>  }
>>>  
>>>  static void fimd_apply(struct fimd_context *ctx)
>>>  {
>>> -	struct fimd_win_data *win_data;
>>> +	struct exynos_drm_plane *plane;
>>>  	int i;
>>>  
>>>  	for (i = 0; i < WINDOWS_NR; i++) {
>>> -		win_data = &ctx->win_data[i];
>>> -		if (win_data->enabled)
>>> +		plane = &ctx->planes[i];
>>> +		if (plane->enabled)
>>>  			fimd_win_commit(ctx->crtc, i);
>>>  		else
>>>  			fimd_win_disable(ctx->crtc, i);
>>> @@ -1011,7 +954,6 @@ static struct exynos_drm_crtc_ops fimd_crtc_ops = {
>>>  	.enable_vblank = fimd_enable_vblank,
>>>  	.disable_vblank = fimd_disable_vblank,
>>>  	.wait_for_vblank = fimd_wait_for_vblank,
>>> -	.win_mode_set = fimd_win_mode_set,
>>>  	.win_commit = fimd_win_commit,
>>>  	.win_disable = fimd_win_disable,
>>>  	.te_handler = fimd_te_handler,
>>> @@ -1056,7 +998,16 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
>>>  {
>>>  	struct fimd_context *ctx = dev_get_drvdata(dev);
>>>  	struct drm_device *drm_dev = data;
>>> -	int ret;
>>> +	struct exynos_drm_plane *exynos_plane;
>>> +	enum drm_plane_type type;
>>> +	int i, ret;
>>> +
>>> +	for (i = 0; i < WINDOWS_NR; i++) {
>>> +		type = (i == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
>>> +						DRM_PLANE_TYPE_OVERLAY;
>>> +		exynos_plane_init(drm_dev, &ctx->planes[i], 1 << ctx->pipe,
>>> +				  type);
>>> +	}
>>>  
>>>  	ret = fimd_ctx_initialize(ctx, drm_dev);
>>>  	if (ret) {
>>> @@ -1064,8 +1015,9 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
>>>  		return ret;
>>>  	}
>>>  
>>> -	ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
>>> -					   EXYNOS_DISPLAY_TYPE_LCD,
>>> +	exynos_plane = &ctx->planes[ctx->default_win];
>>> +	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
>>> +					   ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
>>>  					   &fimd_crtc_ops, ctx);
>>>  	if (IS_ERR(ctx->crtc)) {
>>>  		fimd_ctx_remove(ctx);
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
>>> index 358cff6..dc13621 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
>>> @@ -93,7 +93,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
>>>  			  uint32_t src_w, uint32_t src_h)
>>>  {
>>>  	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
>>> -	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
>>>  	unsigned int actual_w;
>>>  	unsigned int actual_h;
>>>  
>>> @@ -140,9 +139,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
>>>  			exynos_plane->crtc_width, exynos_plane->crtc_height);
>>>  
>>>  	plane->crtc = crtc;
>>> -
>>> -	if (exynos_crtc->ops->win_mode_set)
>>> -		exynos_crtc->ops->win_mode_set(exynos_crtc, exynos_plane);
>>>  }
>>>  
>>>  void exynos_plane_dpms(struct drm_plane *plane, int mode)
>>> @@ -255,24 +251,18 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
>>>  	drm_object_attach_property(&plane->base, prop, 0);
>>>  }
>>>  
>>> -struct drm_plane *exynos_plane_init(struct drm_device *dev,
>>> -				    unsigned long possible_crtcs,
>>> -				    enum drm_plane_type type)
>>> +int exynos_plane_init(struct drm_device *dev,
>>> +		      struct exynos_drm_plane *exynos_plane,
>>> +		      unsigned long possible_crtcs, enum drm_plane_type type)
>>>  {
>>> -	struct exynos_drm_plane *exynos_plane;
>>>  	int err;
>>>  
>>> -	exynos_plane = kzalloc(sizeof(struct exynos_drm_plane), GFP_KERNEL);
>>> -	if (!exynos_plane)
>>> -		return ERR_PTR(-ENOMEM);
>>> -
>>>  	err = drm_universal_plane_init(dev, &exynos_plane->base, possible_crtcs,
>>>  				       &exynos_plane_funcs, formats,
>>>  				       ARRAY_SIZE(formats), type);
>>>  	if (err) {
>>>  		DRM_ERROR("failed to initialize plane\n");
>>> -		kfree(exynos_plane);
>>> -		return ERR_PTR(err);
>>> +		return err;
>>>  	}
>>>  
>>>  	if (type == DRM_PLANE_TYPE_PRIMARY)
>>> @@ -280,5 +270,5 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
>>>  	else
>>>  		exynos_plane_attach_zpos_property(&exynos_plane->base);
>>>  
>>> -	return &exynos_plane->base;
>>> +	return 0;
>>>  }
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
>>> index 59d4075..100ca5e 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
>>> @@ -21,6 +21,6 @@ int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>>>  			uint32_t src_x, uint32_t src_y,
>>>  			uint32_t src_w, uint32_t src_h);
>>>  void exynos_plane_dpms(struct drm_plane *plane, int mode);
>>> -struct drm_plane *exynos_plane_init(struct drm_device *dev,
>>> -				    unsigned long possible_crtcs,
>>> -				    enum drm_plane_type type);
>>> +int exynos_plane_init(struct drm_device *dev,
>>> +		      struct exynos_drm_plane *exynos_plane,
>>> +		      unsigned long possible_crtcs, enum drm_plane_type type);
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>> index b886972..08c7a1e 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>>> @@ -23,6 +23,7 @@
>>>  
>>>  #include "exynos_drm_drv.h"
>>>  #include "exynos_drm_crtc.h"
>>> +#include "exynos_drm_plane.h"
>>>  #include "exynos_drm_encoder.h"
>>>  #include "exynos_drm_vidi.h"
>>>  
>>> @@ -32,20 +33,6 @@
>>>  #define ctx_from_connector(c)	container_of(c, struct vidi_context, \
>>>  					connector)
>>>  
>>> -struct vidi_win_data {
>>> -	unsigned int		offset_x;
>>> -	unsigned int		offset_y;
>>> -	unsigned int		ovl_width;
>>> -	unsigned int		ovl_height;
>>> -	unsigned int		fb_width;
>>> -	unsigned int		fb_height;
>>> -	unsigned int		bpp;
>>> -	dma_addr_t		dma_addr;
>>> -	unsigned int		buf_offsize;
>>> -	unsigned int		line_size;	/* bytes */
>>> -	bool			enabled;
>>> -};
>>> -
>>>  struct vidi_context {
>>>  	struct exynos_drm_display	display;
>>>  	struct platform_device		*pdev;
>>> @@ -53,7 +40,7 @@ struct vidi_context {
>>>  	struct exynos_drm_crtc		*crtc;
>>>  	struct drm_encoder		*encoder;
>>>  	struct drm_connector		connector;
>>> -	struct vidi_win_data		win_data[WINDOWS_NR];
>>> +	struct exynos_drm_plane		planes[WINDOWS_NR];
>>>  	struct edid			*raw_edid;
>>>  	unsigned int			clkdiv;
>>>  	unsigned int			default_win;
>>> @@ -97,19 +84,6 @@ static const char fake_edid_info[] = {
>>>  	0x00, 0x00, 0x00, 0x06
>>>  };
>>>  
>>> -static void vidi_apply(struct vidi_context *ctx)
>>> -{
>>> -	struct exynos_drm_crtc_ops *crtc_ops = ctx->crtc->ops;
>>> -	struct vidi_win_data *win_data;
>>> -	int i;
>>> -
>>> -	for (i = 0; i < WINDOWS_NR; i++) {
>>> -		win_data = &ctx->win_data[i];
>>> -		if (win_data->enabled && (crtc_ops && crtc_ops->win_commit))
>>> -			crtc_ops->win_commit(ctx->crtc, i);
>>> -	}
>>> -}
>>> -
>>>  static int vidi_enable_vblank(struct exynos_drm_crtc *crtc)
>>>  {
>>>  	struct vidi_context *ctx = crtc->ctx;
>>> @@ -143,63 +117,10 @@ static void vidi_disable_vblank(struct exynos_drm_crtc *crtc)
>>>  		ctx->vblank_on = false;
>>>  }
>>>  
>>> -static void vidi_win_mode_set(struct exynos_drm_crtc *crtc,
>>> -			struct exynos_drm_plane *plane)
>>> -{
>>> -	struct vidi_context *ctx = crtc->ctx;
>>> -	struct vidi_win_data *win_data;
>>> -	int win;
>>> -	unsigned long offset;
>>> -
>>> -	if (!plane) {
>>> -		DRM_ERROR("plane is NULL\n");
>>> -		return;
>>> -	}
>>> -
>>> -	win = plane->zpos;
>>> -	if (win == DEFAULT_ZPOS)
>>> -		win = ctx->default_win;
>>> -
>>> -	if (win < 0 || win >= WINDOWS_NR)
>>> -		return;
>>> -
>>> -	offset = plane->fb_x * (plane->bpp >> 3);
>>> -	offset += plane->fb_y * plane->pitch;
>>> -
>>> -	DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
>>> -
>>> -	win_data = &ctx->win_data[win];
>>> -
>>> -	win_data->offset_x = plane->crtc_x;
>>> -	win_data->offset_y = plane->crtc_y;
>>> -	win_data->ovl_width = plane->crtc_width;
>>> -	win_data->ovl_height = plane->crtc_height;
>>> -	win_data->fb_width = plane->fb_width;
>>> -	win_data->fb_height = plane->fb_height;
>>> -	win_data->dma_addr = plane->dma_addr[0] + offset;
>>> -	win_data->bpp = plane->bpp;
>>> -	win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
>>> -				(plane->bpp >> 3);
>>> -	win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
>>> -
>>> -	/*
>>> -	 * some parts of win_data should be transferred to user side
>>> -	 * through specific ioctl.
>>> -	 */
>>> -
>>> -	DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
>>> -			win_data->offset_x, win_data->offset_y);
>>> -	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
>>> -			win_data->ovl_width, win_data->ovl_height);
>>> -	DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
>>> -	DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
>>> -			plane->fb_width, plane->crtc_width);
>>> -}
>>> -
>>>  static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  {
>>>  	struct vidi_context *ctx = crtc->ctx;
>>> -	struct vidi_win_data *win_data;
>>> +	struct exynos_drm_plane *plane;
>>>  	int win = zpos;
>>>  
>>>  	if (ctx->suspended)
>>> @@ -211,11 +132,11 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  	if (win < 0 || win >= WINDOWS_NR)
>>>  		return;
>>>  
>>> -	win_data = &ctx->win_data[win];
>>> +	plane = &ctx->planes[win];
>>>  
>>> -	win_data->enabled = true;
>>> +	plane->enabled = true;
>>>  
>>> -	DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data->dma_addr);
>>> +	DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
>>>  
>>>  	if (ctx->vblank_on)
>>>  		schedule_work(&ctx->work);
>>> @@ -224,7 +145,7 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>>>  {
>>>  	struct vidi_context *ctx = crtc->ctx;
>>> -	struct vidi_win_data *win_data;
>>> +	struct exynos_drm_plane *plane;
>>>  	int win = zpos;
>>>  
>>>  	if (win == DEFAULT_ZPOS)
>>> @@ -233,14 +154,17 @@ static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>>>  	if (win < 0 || win >= WINDOWS_NR)
>>>  		return;
>>>  
>>> -	win_data = &ctx->win_data[win];
>>> -	win_data->enabled = false;
>>> +	plane = &ctx->planes[win];
>>> +	plane->enabled = false;
>>>  
>>>  	/* TODO. */
>>>  }
>>>  
>>>  static int vidi_power_on(struct vidi_context *ctx, bool enable)
>>>  {
>>> +	struct exynos_drm_plane *plane;
>>> +	int i;
>>> +
>>>  	DRM_DEBUG_KMS("%s\n", __FILE__);
>>>  
>>>  	if (enable != false && enable != true)
>>> @@ -253,7 +177,11 @@ static int vidi_power_on(struct vidi_context *ctx, bool enable)
>>>  		if (test_and_clear_bit(0, &ctx->irq_flags))
>>>  			vidi_enable_vblank(ctx->crtc);
>>>  
>>> -		vidi_apply(ctx);
>>> +		for (i = 0; i < WINDOWS_NR; i++) {
>>> +			plane = &ctx->planes[i];
>>> +			if (plane->enabled)
>>> +				vidi_win_commit(ctx->crtc, i);
>>> +		}
>>>  	} else {
>>>  		ctx->suspended = true;
>>>  	}
>>> @@ -301,7 +229,6 @@ static struct exynos_drm_crtc_ops vidi_crtc_ops = {
>>>  	.dpms = vidi_dpms,
>>>  	.enable_vblank = vidi_enable_vblank,
>>>  	.disable_vblank = vidi_disable_vblank,
>>> -	.win_mode_set = vidi_win_mode_set,
>>>  	.win_commit = vidi_win_commit,
>>>  	.win_disable = vidi_win_disable,
>>>  };
>>> @@ -543,12 +470,22 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
>>>  {
>>>  	struct vidi_context *ctx = dev_get_drvdata(dev);
>>>  	struct drm_device *drm_dev = data;
>>> -	int ret;
>>> +	struct exynos_drm_plane *exynos_plane;
>>> +	enum drm_plane_type type;
>>> +	int i, ret;
>>> +
>>> +	for (i = 0; i < WINDOWS_NR; i++) {
>>> +		type = (i == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
>>> +						DRM_PLANE_TYPE_OVERLAY;
>>> +		exynos_plane_init(drm_dev, &ctx->planes[i], 1 << ctx->pipe,
>>> +				  type);
>>> +	}
>>>  
>>>  	vidi_ctx_initialize(ctx, drm_dev);
>>>  
>>> -	ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
>>> -					   EXYNOS_DISPLAY_TYPE_VIDI,
>>> +	exynos_plane = &ctx->planes[ctx->default_win];
>>> +	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
>>> +					   ctx->pipe, EXYNOS_DISPLAY_TYPE_VIDI,
>>>  					   &vidi_crtc_ops, ctx);
>>>  	if (IS_ERR(ctx->crtc)) {
>>>  		DRM_ERROR("failed to create crtc.\n");
>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
>>> index 736269a..d6864e6 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
>>> @@ -37,34 +37,13 @@
>>>  
>>>  #include "exynos_drm_drv.h"
>>>  #include "exynos_drm_crtc.h"
>>> +#include "exynos_drm_plane.h"
>>>  #include "exynos_drm_iommu.h"
>>>  #include "exynos_mixer.h"
>>>  
>>>  #define MIXER_WIN_NR		3
>>>  #define MIXER_DEFAULT_WIN	0
>>>  
>>> -struct hdmi_win_data {
>>> -	dma_addr_t		dma_addr;
>>> -	dma_addr_t		chroma_dma_addr;
>>> -	uint32_t		pixel_format;
>>> -	unsigned int		bpp;
>>> -	unsigned int		crtc_x;
>>> -	unsigned int		crtc_y;
>>> -	unsigned int		crtc_width;
>>> -	unsigned int		crtc_height;
>>> -	unsigned int		fb_x;
>>> -	unsigned int		fb_y;
>>> -	unsigned int		fb_width;
>>> -	unsigned int		fb_height;
>>> -	unsigned int		src_width;
>>> -	unsigned int		src_height;
>>> -	unsigned int		mode_width;
>>> -	unsigned int		mode_height;
>>> -	unsigned int		scan_flags;
>>> -	bool			enabled;
>>> -	bool			resume;
>>> -};
>>> -
>>>  struct mixer_resources {
>>>  	int			irq;
>>>  	void __iomem		*mixer_regs;
>>> @@ -88,6 +67,7 @@ struct mixer_context {
>>>  	struct device		*dev;
>>>  	struct drm_device	*drm_dev;
>>>  	struct exynos_drm_crtc	*crtc;
>>> +	struct exynos_drm_plane	planes[MIXER_WIN_NR];
>>>  	int			pipe;
>>>  	bool			interlace;
>>>  	bool			powered;
>>> @@ -97,7 +77,6 @@ struct mixer_context {
>>>  
>>>  	struct mutex		mixer_mutex;
>>>  	struct mixer_resources	mixer_res;
>>> -	struct hdmi_win_data	win_data[MIXER_WIN_NR];
>>>  	enum mixer_version_id	mxr_ver;
>>>  	wait_queue_head_t	wait_vsync_queue;
>>>  	atomic_t		wait_vsync_event;
>>> @@ -401,7 +380,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
>>>  {
>>>  	struct mixer_resources *res = &ctx->mixer_res;
>>>  	unsigned long flags;
>>> -	struct hdmi_win_data *win_data;
>>> +	struct exynos_drm_plane *plane;
>>>  	unsigned int x_ratio, y_ratio;
>>>  	unsigned int buf_num = 1;
>>>  	dma_addr_t luma_addr[2], chroma_addr[2];
>>> @@ -409,9 +388,9 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
>>>  	bool crcb_mode = false;
>>>  	u32 val;
>>>  
>>> -	win_data = &ctx->win_data[win];
>>> +	plane = &ctx->planes[win];
>>>  
>>> -	switch (win_data->pixel_format) {
>>> +	switch (plane->pixel_format) {
>>>  	case DRM_FORMAT_NV12MT:
>>>  		tiled_mode = true;
>>>  	case DRM_FORMAT_NV12:
>>> @@ -421,35 +400,35 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
>>>  	/* TODO: single buffer format NV12, NV21 */
>>>  	default:
>>>  		/* ignore pixel format at disable time */
>>> -		if (!win_data->dma_addr)
>>> +		if (!plane->dma_addr[0])
>>>  			break;
>>>  
>>>  		DRM_ERROR("pixel format for vp is wrong [%d].\n",
>>> -				win_data->pixel_format);
>>> +				plane->pixel_format);
>>>  		return;
>>>  	}
>>>  
>>>  	/* scaling feature: (src << 16) / dst */
>>> -	x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
>>> -	y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
>>> +	x_ratio = (plane->src_width << 16) / plane->crtc_width;
>>> +	y_ratio = (plane->src_height << 16) / plane->crtc_height;
>>>  
>>>  	if (buf_num == 2) {
>>> -		luma_addr[0] = win_data->dma_addr;
>>> -		chroma_addr[0] = win_data->chroma_dma_addr;
>>> +		luma_addr[0] = plane->dma_addr[0];
>>> +		chroma_addr[0] = plane->dma_addr[1];
>>>  	} else {
>>> -		luma_addr[0] = win_data->dma_addr;
>>> -		chroma_addr[0] = win_data->dma_addr
>>> -			+ (win_data->fb_width * win_data->fb_height);
>>> +		luma_addr[0] = plane->dma_addr[0];
>>> +		chroma_addr[0] = plane->dma_addr[0]
>>> +			+ (plane->fb_width * plane->fb_height);
>>>  	}
>>>  
>>> -	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
>>> +	if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) {
>>>  		ctx->interlace = true;
>>>  		if (tiled_mode) {
>>>  			luma_addr[1] = luma_addr[0] + 0x40;
>>>  			chroma_addr[1] = chroma_addr[0] + 0x40;
>>>  		} else {
>>> -			luma_addr[1] = luma_addr[0] + win_data->fb_width;
>>> -			chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
>>> +			luma_addr[1] = luma_addr[0] + plane->fb_width;
>>> +			chroma_addr[1] = chroma_addr[0] + plane->fb_width;
>>>  		}
>>>  	} else {
>>>  		ctx->interlace = false;
>>> @@ -470,26 +449,26 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
>>>  	vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
>>>  
>>>  	/* setting size of input image */
>>> -	vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
>>> -		VP_IMG_VSIZE(win_data->fb_height));
>>> +	vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->fb_width) |
>>> +		VP_IMG_VSIZE(plane->fb_height));
>>>  	/* chroma height has to reduced by 2 to avoid chroma distorions */
>>> -	vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
>>> -		VP_IMG_VSIZE(win_data->fb_height / 2));
>>> +	vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->fb_width) |
>>> +		VP_IMG_VSIZE(plane->fb_height / 2));
>>>  
>>> -	vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
>>> -	vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
>>> +	vp_reg_write(res, VP_SRC_WIDTH, plane->src_width);
>>> +	vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height);
>>>  	vp_reg_write(res, VP_SRC_H_POSITION,
>>> -			VP_SRC_H_POSITION_VAL(win_data->fb_x));
>>> -	vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
>>> +			VP_SRC_H_POSITION_VAL(plane->fb_x));
>>> +	vp_reg_write(res, VP_SRC_V_POSITION, plane->fb_y);
>>>  
>>> -	vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
>>> -	vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
>>> +	vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width);
>>> +	vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
>>>  	if (ctx->interlace) {
>>> -		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
>>> -		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
>>> +		vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2);
>>> +		vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
>>>  	} else {
>>> -		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
>>> -		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
>>> +		vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height);
>>> +		vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
>>>  	}
>>>  
>>>  	vp_reg_write(res, VP_H_RATIO, x_ratio);
>>> @@ -503,8 +482,8 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
>>>  	vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
>>>  	vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
>>>  
>>> -	mixer_cfg_scan(ctx, win_data->mode_height);
>>> -	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
>>> +	mixer_cfg_scan(ctx, plane->mode_height);
>>> +	mixer_cfg_rgb_fmt(ctx, plane->mode_height);
>>>  	mixer_cfg_layer(ctx, win, true);
>>>  	mixer_run(ctx);
>>>  
>>> @@ -525,21 +504,21 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
>>>  {
>>>  	struct mixer_resources *res = &ctx->mixer_res;
>>>  	unsigned long flags;
>>> -	struct hdmi_win_data *win_data;
>>> +	struct exynos_drm_plane *plane;
>>>  	unsigned int x_ratio, y_ratio;
>>>  	unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
>>>  	dma_addr_t dma_addr;
>>>  	unsigned int fmt;
>>>  	u32 val;
>>>  
>>> -	win_data = &ctx->win_data[win];
>>> +	plane = &ctx->planes[win];
>>>  
>>>  	#define RGB565 4
>>>  	#define ARGB1555 5
>>>  	#define ARGB4444 6
>>>  	#define ARGB8888 7
>>>  
>>> -	switch (win_data->bpp) {
>>> +	switch (plane->bpp) {
>>>  	case 16:
>>>  		fmt = ARGB4444;
>>>  		break;
>>> @@ -554,17 +533,17 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
>>>  	x_ratio = 0;
>>>  	y_ratio = 0;
>>>  
>>> -	dst_x_offset = win_data->crtc_x;
>>> -	dst_y_offset = win_data->crtc_y;
>>> +	dst_x_offset = plane->crtc_x;
>>> +	dst_y_offset = plane->crtc_y;
>>>  
>>>  	/* converting dma address base and source offset */
>>> -	dma_addr = win_data->dma_addr
>>> -		+ (win_data->fb_x * win_data->bpp >> 3)
>>> -		+ (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
>>> +	dma_addr = plane->dma_addr[0]
>>> +		+ (plane->fb_x * plane->bpp >> 3)
>>> +		+ (plane->fb_y * plane->fb_width * plane->bpp >> 3);
>>>  	src_x_offset = 0;
>>>  	src_y_offset = 0;
>>>  
>>> -	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
>>> +	if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE)
>>>  		ctx->interlace = true;
>>>  	else
>>>  		ctx->interlace = false;
>>> @@ -577,18 +556,18 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
>>>  		MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
>>>  
>>>  	/* setup geometry */
>>> -	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
>>> +	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), plane->fb_width);
>>>  
>>>  	/* setup display size */
>>>  	if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
>>>  		win == MIXER_DEFAULT_WIN) {
>>> -		val  = MXR_MXR_RES_HEIGHT(win_data->fb_height);
>>> -		val |= MXR_MXR_RES_WIDTH(win_data->fb_width);
>>> +		val  = MXR_MXR_RES_HEIGHT(plane->fb_height);
>>> +		val |= MXR_MXR_RES_WIDTH(plane->fb_width);
>>>  		mixer_reg_write(res, MXR_RESOLUTION, val);
>>>  	}
>>>  
>>> -	val  = MXR_GRP_WH_WIDTH(win_data->crtc_width);
>>> -	val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
>>> +	val  = MXR_GRP_WH_WIDTH(plane->crtc_width);
>>> +	val |= MXR_GRP_WH_HEIGHT(plane->crtc_height);
>>>  	val |= MXR_GRP_WH_H_SCALE(x_ratio);
>>>  	val |= MXR_GRP_WH_V_SCALE(y_ratio);
>>>  	mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
>>> @@ -606,8 +585,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
>>>  	/* set buffer address to mixer */
>>>  	mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
>>>  
>>> -	mixer_cfg_scan(ctx, win_data->mode_height);
>>> -	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
>>> +	mixer_cfg_scan(ctx, plane->mode_height);
>>> +	mixer_cfg_rgb_fmt(ctx, plane->mode_height);
>>>  	mixer_cfg_layer(ctx, win, true);
>>>  
>>>  	/* layer update mandatory for mixer 16.0.33.0 */
>>> @@ -913,58 +892,6 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
>>>  	mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
>>>  }
>>>  
>>> -static void mixer_win_mode_set(struct exynos_drm_crtc *crtc,
>>> -			struct exynos_drm_plane *plane)
>>> -{
>>> -	struct mixer_context *mixer_ctx = crtc->ctx;
>>> -	struct hdmi_win_data *win_data;
>>> -	int win;
>>> -
>>> -	if (!plane) {
>>> -		DRM_ERROR("plane is NULL\n");
>>> -		return;
>>> -	}
>>> -
>>> -	DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
>>> -				 plane->fb_width, plane->fb_height,
>>> -				 plane->fb_x, plane->fb_y,
>>> -				 plane->crtc_width, plane->crtc_height,
>>> -				 plane->crtc_x, plane->crtc_y);
>>> -
>>> -	win = plane->zpos;
>>> -	if (win == DEFAULT_ZPOS)
>>> -		win = MIXER_DEFAULT_WIN;
>>> -
>>> -	if (win < 0 || win >= MIXER_WIN_NR) {
>>> -		DRM_ERROR("mixer window[%d] is wrong\n", win);
>>> -		return;
>>> -	}
>>> -
>>> -	win_data = &mixer_ctx->win_data[win];
>>> -
>>> -	win_data->dma_addr = plane->dma_addr[0];
>>> -	win_data->chroma_dma_addr = plane->dma_addr[1];
>>> -	win_data->pixel_format = plane->pixel_format;
>>> -	win_data->bpp = plane->bpp;
>>> -
>>> -	win_data->crtc_x = plane->crtc_x;
>>> -	win_data->crtc_y = plane->crtc_y;
>>> -	win_data->crtc_width = plane->crtc_width;
>>> -	win_data->crtc_height = plane->crtc_height;
>>> -
>>> -	win_data->fb_x = plane->fb_x;
>>> -	win_data->fb_y = plane->fb_y;
>>> -	win_data->fb_width = plane->fb_width;
>>> -	win_data->fb_height = plane->fb_height;
>>> -	win_data->src_width = plane->src_width;
>>> -	win_data->src_height = plane->src_height;
>>> -
>>> -	win_data->mode_width = plane->mode_width;
>>> -	win_data->mode_height = plane->mode_height;
>>> -
>>> -	win_data->scan_flags = plane->scan_flag;
>>> -}
>>> -
>>>  static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  {
>>>  	struct mixer_context *mixer_ctx = crtc->ctx;
>>> @@ -984,7 +911,7 @@ static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  	else
>>>  		mixer_graph_buffer(mixer_ctx, win);
>>>  
>>> -	mixer_ctx->win_data[win].enabled = true;
>>> +	mixer_ctx->planes[win].enabled = true;
>>>  }
>>>  
>>>  static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>>> @@ -999,7 +926,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>>>  	mutex_lock(&mixer_ctx->mixer_mutex);
>>>  	if (!mixer_ctx->powered) {
>>>  		mutex_unlock(&mixer_ctx->mixer_mutex);
>>> -		mixer_ctx->win_data[win].resume = false;
>>> +		mixer_ctx->planes[win].resume = false;
>>>  		return;
>>>  	}
>>>  	mutex_unlock(&mixer_ctx->mixer_mutex);
>>> @@ -1012,7 +939,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
>>>  	mixer_vsync_set_update(mixer_ctx, true);
>>>  	spin_unlock_irqrestore(&res->reg_slock, flags);
>>>  
>>> -	mixer_ctx->win_data[win].enabled = false;
>>> +	mixer_ctx->planes[win].enabled = false;
>>>  }
>>>  
>>>  static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
>>> @@ -1049,12 +976,12 @@ static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
>>>  
>>>  static void mixer_window_suspend(struct mixer_context *ctx)
>>>  {
>>> -	struct hdmi_win_data *win_data;
>>> +	struct exynos_drm_plane *plane;
>>>  	int i;
>>>  
>>>  	for (i = 0; i < MIXER_WIN_NR; i++) {
>>> -		win_data = &ctx->win_data[i];
>>> -		win_data->resume = win_data->enabled;
>>> +		plane = &ctx->planes[i];
>>> +		plane->resume = plane->enabled;
>>>  		mixer_win_disable(ctx->crtc, i);
>>>  	}
>>>  	mixer_wait_for_vblank(ctx->crtc);
>>> @@ -1062,14 +989,14 @@ static void mixer_window_suspend(struct mixer_context *ctx)
>>>  
>>>  static void mixer_window_resume(struct mixer_context *ctx)
>>>  {
>>> -	struct hdmi_win_data *win_data;
>>> +	struct exynos_drm_plane *plane;
>>>  	int i;
>>>  
>>>  	for (i = 0; i < MIXER_WIN_NR; i++) {
>>> -		win_data = &ctx->win_data[i];
>>> -		win_data->enabled = win_data->resume;
>>> -		win_data->resume = false;
>>> -		if (win_data->enabled)
>>> +		plane = &ctx->planes[i];
>>> +		plane->enabled = plane->resume;
>>> +		plane->resume = false;
>>> +		if (plane->enabled)
>>>  			mixer_win_commit(ctx->crtc, i);
>>>  	}
>>>  }
>>> @@ -1179,7 +1106,6 @@ static struct exynos_drm_crtc_ops mixer_crtc_ops = {
>>>  	.enable_vblank		= mixer_enable_vblank,
>>>  	.disable_vblank		= mixer_disable_vblank,
>>>  	.wait_for_vblank	= mixer_wait_for_vblank,
>>> -	.win_mode_set		= mixer_win_mode_set,
>>>  	.win_commit		= mixer_win_commit,
>>>  	.win_disable		= mixer_win_disable,
>>>  };
>>> @@ -1243,15 +1169,25 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
>>>  {
>>>  	struct mixer_context *ctx = dev_get_drvdata(dev);
>>>  	struct drm_device *drm_dev = data;
>>> -	int ret;
>>> +	struct exynos_drm_plane *exynos_plane;
>>> +	enum drm_plane_type type;
>>> +	int i, ret;
>>> +
>>> +	for (i = 0; i < MIXER_WIN_NR; i++) {
>>> +		type = (i == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
>>> +						DRM_PLANE_TYPE_OVERLAY;
>>> +		exynos_plane_init(drm_dev, &ctx->planes[i], 1 << ctx->pipe,
>>> +				  type);
>>> +	}
>>>  
>>>  	ret = mixer_initialize(ctx, drm_dev);
>>>  	if (ret)
>>>  		return ret;
>>>  
>>> -	ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
>>> -				     EXYNOS_DISPLAY_TYPE_HDMI,
>>> -				     &mixer_crtc_ops, ctx);
>>> +	exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
>>> +	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
>>> +					   ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
>>> +					   &mixer_crtc_ops, ctx);
>>>  	if (IS_ERR(ctx->crtc)) {
>>>  		mixer_ctx_remove(ctx);
>>>  		ret = PTR_ERR(ctx->crtc);
>>>
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
> 

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 08/14] drm/exynos: atomic phase 1: add atomic_begin()/atomic_flush()
  2015-02-04 14:30     ` Daniel Vetter
@ 2015-02-05  2:48       ` Joonyoung Shim
  2015-02-05  9:18         ` Daniel Vetter
  0 siblings, 1 reply; 37+ messages in thread
From: Joonyoung Shim @ 2015-02-05  2:48 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Gustavo Padovan, linux-samsung-soc, Gustavo Padovan, dri-devel

Hi Daniel,

On 02/04/2015 11:30 PM, Daniel Vetter wrote:
> On Wed, Feb 04, 2015 at 04:49:25PM +0900, Joonyoung Shim wrote:
>> Hi,
>>
>> On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
>>> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>>>
>>> Add CRTC callbacks .atomic_begin() .atomic_flush(). On exynos they
>>> unprotect the windows before the commit and protects it after based on
>>> a plane mask tha store which plane will be updated.
>>>
>>
>> I don't think they need now.
> 
> This does exactly what I wanted to do in my atomic poc but couldn't
> because of the massive layer hell that was still around in atomic. Haven't
> looked into the patch in details, so no full r-b but good enough for an
> 

I agree about its operation but i think it is unnecessary now. Because
it's exactly same operation with current codes.

> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> Aside: If you think something doesn't need to be done please explain what
> you mean or at least ask about what you don't understand in a patch. As-is
> your review is pretty much unactionable.
> 

Yes, my fault, thanks for advice.

Thanks.

> 
>>
>> Thanks.
>>
>>> For that we create two new exynos_crtc callbacks: .win_protect() and
>>> .win_unprotect(). The only driver that implement those now is FIMD.
>>>
>>> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>>> ---
>>>  drivers/gpu/drm/exynos/exynos_drm_crtc.c  | 34 ++++++++++++++++++
>>>  drivers/gpu/drm/exynos/exynos_drm_drv.h   |  4 +++
>>>  drivers/gpu/drm/exynos/exynos_drm_fimd.c  | 57 ++++++++++++++++++++++---------
>>>  drivers/gpu/drm/exynos/exynos_drm_plane.c |  4 +++
>>>  4 files changed, 82 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
>>> index 09d4780..be36cca 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
>>> @@ -147,6 +147,38 @@ static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
>>>  	}
>>>  }
>>>  
>>> +static void exynos_crtc_atomic_begin(struct drm_crtc *crtc)
>>> +{
>>> +	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
>>> +	struct drm_plane *plane;
>>> +	int index = 0;
>>> +
>>> +	list_for_each_entry(plane, &crtc->dev->mode_config.plane_list, head) {
>>> +		if (exynos_crtc->ops->win_protect &&
>>> +		    exynos_crtc->plane_mask & (0x01 << index))
>>> +			exynos_crtc->ops->win_protect(exynos_crtc, index);
>>> +
>>> +		index++;
>>> +	}
>>> +}
>>> +
>>> +static void exynos_crtc_atomic_flush(struct drm_crtc *crtc)
>>> +{
>>> +	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
>>> +	struct drm_plane *plane;
>>> +	int index = 0;
>>> +
>>> +	list_for_each_entry(plane, &crtc->dev->mode_config.plane_list, head) {
>>> +		if (exynos_crtc->ops->win_unprotect &&
>>> +		    exynos_crtc->plane_mask & (0x01 << index))
>>> +			exynos_crtc->ops->win_unprotect(exynos_crtc, index);
>>> +
>>> +		index++;
>>> +	}
>>> +
>>> +	exynos_crtc->plane_mask = 0;
>>> +}
>>> +
>>>  static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
>>>  	.dpms		= exynos_drm_crtc_dpms,
>>>  	.prepare	= exynos_drm_crtc_prepare,
>>> @@ -155,6 +187,8 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
>>>  	.mode_set	= exynos_drm_crtc_mode_set,
>>>  	.mode_set_base	= exynos_drm_crtc_mode_set_base,
>>>  	.disable	= exynos_drm_crtc_disable,
>>> +	.atomic_begin	= exynos_crtc_atomic_begin,
>>> +	.atomic_flush	= exynos_crtc_atomic_flush,
>>>  };
>>>  
>>>  static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
>>> index cad54e7..43efd9f 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
>>> @@ -194,6 +194,8 @@ struct exynos_drm_crtc_ops {
>>>  	void (*win_enable)(struct exynos_drm_crtc *crtc, int zpos);
>>>  	void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
>>>  	void (*te_handler)(struct exynos_drm_crtc *crtc);
>>> +	void (*win_protect)(struct exynos_drm_crtc *crtc, int zpos);
>>> +	void (*win_unprotect)(struct exynos_drm_crtc *crtc, int zpos);
>>>  };
>>>  
>>>  enum exynos_crtc_mode {
>>> @@ -214,6 +216,7 @@ enum exynos_crtc_mode {
>>>   *	we can refer to the crtc to current hardware interrupt occurred through
>>>   *	this pipe value.
>>>   * @dpms: store the crtc dpms value
>>> + * @plane_mask: store planes to be updated on atomic modesetting
>>>   * @mode: store the crtc mode value
>>>   * @event: vblank event that is currently queued for flip
>>>   * @ops: pointer to callbacks for exynos drm specific functionality
>>> @@ -224,6 +227,7 @@ struct exynos_drm_crtc {
>>>  	enum exynos_drm_output_type	type;
>>>  	unsigned int			pipe;
>>>  	unsigned int			dpms;
>>> +	unsigned int			plane_mask;
>>>  	enum exynos_crtc_mode		mode;
>>>  	wait_queue_head_t		pending_flip_queue;
>>>  	struct drm_pending_vblank_event	*event;
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>>> index ebb4cdc..f498d86 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>>> @@ -585,6 +585,16 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
>>>  {
>>>  	u32 reg, bits, val;
>>>  
>>> +	/*
>>> +	 * SHADOWCON/PRTCON register is used for enabling timing.
>>> +	 *
>>> +	 * for example, once only width value of a register is set,
>>> +	 * if the dma is started then fimd hardware could malfunction so
>>> +	 * with protect window setting, the register fields with prefix '_F'
>>> +	 * wouldn't be updated at vsync also but updated once unprotect window
>>> +	 * is set.
>>> +	 */
>>> +
>>>  	if (ctx->driver_data->has_shadowcon) {
>>>  		reg = SHADOWCON;
>>>  		bits = SHADOWCON_WINx_PROTECT(win);
>>> @@ -627,20 +637,6 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  		return;
>>>  	}
>>>  
>>> -	/*
>>> -	 * SHADOWCON/PRTCON register is used for enabling timing.
>>> -	 *
>>> -	 * for example, once only width value of a register is set,
>>> -	 * if the dma is started then fimd hardware could malfunction so
>>> -	 * with protect window setting, the register fields with prefix '_F'
>>> -	 * wouldn't be updated at vsync also but updated once unprotect window
>>> -	 * is set.
>>> -	 */
>>> -
>>> -	/* protect windows */
>>> -	fimd_shadow_protect_win(ctx, win, true);
>>> -
>>> -
>>>  	offset = plane->fb_x * (plane->bpp >> 3);
>>>  	offset += plane->fb_y * plane->pitch;
>>>  
>>> @@ -722,9 +718,6 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
>>>  	if (ctx->driver_data->has_shadowcon)
>>>  		fimd_enable_shadow_channel_path(ctx, win, true);
>>>  
>>> -	/* Enable DMA channel and unprotect windows */
>>> -	fimd_shadow_protect_win(ctx, win, false);
>>> -
>>>  	plane->enabled = true;
>>>  
>>>  	if (ctx->i80_if)
>>> @@ -947,6 +940,34 @@ static void fimd_te_handler(struct exynos_drm_crtc *crtc)
>>>  		drm_handle_vblank(ctx->drm_dev, ctx->pipe);
>>>  }
>>>  
>>> +static void fimd_win_protect(struct exynos_drm_crtc *crtc, int zpos)
>>> +{
>>> +	struct fimd_context *ctx = crtc->ctx;
>>> +	int win = zpos;
>>> +
>>> +	if (win == DEFAULT_ZPOS)
>>> +		win = ctx->default_win;
>>> +
>>> +	if (win < 0 || win >= WINDOWS_NR)
>>> +		return;
>>> +
>>> +	fimd_shadow_protect_win(ctx, win, true);
>>> +}
>>> +
>>> +static void fimd_win_unprotect(struct exynos_drm_crtc *crtc, int zpos)
>>> +{
>>> +	struct fimd_context *ctx = crtc->ctx;
>>> +	int win = zpos;
>>> +
>>> +	if (win == DEFAULT_ZPOS)
>>> +		win = ctx->default_win;
>>> +
>>> +	if (win < 0 || win >= WINDOWS_NR)
>>> +		return;
>>> +
>>> +	fimd_shadow_protect_win(ctx, win, false);
>>> +}
>>> +
>>>  static struct exynos_drm_crtc_ops fimd_crtc_ops = {
>>>  	.dpms = fimd_dpms,
>>>  	.mode_fixup = fimd_mode_fixup,
>>> @@ -957,6 +978,8 @@ static struct exynos_drm_crtc_ops fimd_crtc_ops = {
>>>  	.win_commit = fimd_win_commit,
>>>  	.win_disable = fimd_win_disable,
>>>  	.te_handler = fimd_te_handler,
>>> +	.win_protect = fimd_win_protect,
>>> +	.win_unprotect = fimd_win_unprotect,
>>>  };
>>>  
>>>  static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
>>> index a3b0687..363d59d 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
>>> @@ -65,6 +65,7 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last)
>>>  int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb)
>>>  {
>>>  	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
>>> +	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(plane->crtc);
>>>  	int nr;
>>>  	int i;
>>>  
>>> @@ -83,6 +84,9 @@ int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb)
>>>  				i, (unsigned long)exynos_plane->dma_addr[i]);
>>>  	}
>>>  
>>> +	if (exynos_crtc)
>>> +		exynos_crtc->plane_mask += 1 << exynos_plane->zpos;
>>> +
>>>  	return 0;
>>>  }
>>>  
>>>
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
> 

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

* Re: [PATCH 02/14] drm/exynos: Remove exynos_plane_dpms() call with no effect
  2015-02-05  1:05       ` Joonyoung Shim
@ 2015-02-05  9:03         ` Daniel Vetter
  0 siblings, 0 replies; 37+ messages in thread
From: Daniel Vetter @ 2015-02-05  9:03 UTC (permalink / raw)
  To: Joonyoung Shim; +Cc: linux-samsung-soc, Gustavo Padovan, dri-devel

On Thu, Feb 05, 2015 at 10:05:43AM +0900, Joonyoung Shim wrote:
> Hi Daniel,
> 
> On 02/04/2015 11:16 PM, Daniel Vetter wrote:
> > On Wed, Feb 04, 2015 at 04:42:57PM +0900, Joonyoung Shim wrote:
> >> Hi,
> >>
> >> On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> >>> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> >>>
> >>> exynos_plane_dpms(DRM_MODE_DPMS_ON) calls the win_enable()'s callback
> >>> from the underlying layer. However neither one of these layers implement
> >>> win_enable() - FIMD, Mixer and VIDI. Thus the call to exynos_plane_dpms()
> >>> is pointless.
> >>>
> >>> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> >>> ---
> >>>  drivers/gpu/drm/exynos/exynos_drm_crtc.c | 2 --
> >>>  1 file changed, 2 deletions(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> >>> index b2a4b84..ad675fb 100644
> >>> --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> >>> +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
> >>> @@ -65,8 +65,6 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
> >>>  
> >>>  	if (exynos_crtc->ops->commit)
> >>>  		exynos_crtc->ops->commit(exynos_crtc);
> >>> -
> >>> -	exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON);
> >>
> >> As i said, this needs to keep pair enabled flag of struct
> >> exynos_drm_plane.
> > 
> > The reason exynos needs that exynos_plane->enable is because it has its
> > own per-plane dpms state. There's two problems with that:
> > - It's highyl non-standard, the drm kms way is to just disable the plane
> >   and not have some additional knob on top.
> > - The atomic helpers will not be able to handle this. They assume that
> >   there's only one dpms knob for the entire display pipeline, and
> >   per-plane enable/disable is handled by setting plane->state->crtc, which
> >   must be set iff plane->state->fb is set right now.
> > 
> > I recommend we rip this all out if we can adjust existing userspace to
> > stop using the "mode" property on planes and crtcs.
> > 
> > And with that non-standard exynos plane mode thing gone we can indeed rip
> > out exynos_plane_dpms and exynos_plane->enabled and just directly call
> > manager->ops->win_enable/disble. And then rip out the win_enable since
> > it's unused.
> 
> But this cleanup on current codes doesn't care now current operation
> normally. First let's cleanup non-standard exynos plane dpms state as
> you said.

Yeah my reply wasn't too clear, so let me clarify: I agree with you,
Padovan's patch as-is can't be merged. First we need to get rid of the
non-standard plane dpms stuff, then we can remove the ->win_enable hook
and then can we remove this call here.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 04/14] drm/exynos: remove struct *_win_data abstraction on planes
  2015-02-05  2:37       ` Joonyoung Shim
@ 2015-02-05  9:15         ` Daniel Vetter
  2015-02-05 12:26           ` Rob Clark
  0 siblings, 1 reply; 37+ messages in thread
From: Daniel Vetter @ 2015-02-05  9:15 UTC (permalink / raw)
  To: Joonyoung Shim; +Cc: linux-samsung-soc, Gustavo Padovan, dri-devel

On Thu, Feb 05, 2015 at 11:37:13AM +0900, Joonyoung Shim wrote:
> Hi Daniel,
> 
> On 02/04/2015 11:28 PM, Daniel Vetter wrote:
> > On Wed, Feb 04, 2015 at 04:44:12PM +0900, Joonyoung Shim wrote:
> >> Hi,
> >>
> >> On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> >>> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> >>>
> >>> struct {fimd,mixer,vidi}_win_data was just keeping the same data
> >>> as struct exynos_drm_plane thus get ride of it and use exynos_drm_plane
> >>> directly.
> >>>
> >>> It changes how planes are created and remove .win_mode_set() callback
> >>> that was only filling all *_win_data structs.
> >>>
> >>
> >> I commented already on prior patch.
> > 
> > I think you don't quite understand how this primary/overlay plane stuff
> > works in drm core. The entire point of the drm core primary plane is to
> > work _exactly_ like an overlay plane and allow userspace to mangle the
> > primary plane configuration through the overlay plane. The only reason we
> > have primary planes is so that old userspace keeps working.
> > 
> 
> Right, i misunderstood a bit because exynos hw drivers have dependency
> of zpos(hw overlay position).
> 
> Current exynos drm driver has each primary plane of hw drivers and five
> overlay planes. The primary plane is fixed on default hw overlay and all
> overlay plane can map to all hw overlays using specific zpos property of
> exynos drm plane.
> 
> Gustavo approach will include specific hw overlay data in overlay plane
> and hw driver keeps overlay planes to array by zpos order. But current
> zpos of overlay plane is 0 always if user doesn't modify it, so hw
> driver will use only hw overlay data of primary plane always even if
> user want to use overlay plane.
> 
> If user is modified zpos of overlay plane, hw driver can get wrong hw
> overlay data from different overlay plane because hw driver keeps
> overlay planes by zpos order.

Yeah I noticed the zpos fun when hacking around too. Exynos should
probably switch defaults so that overlays are visible by default. And we
need to standardize the zpos property so that other drivers can use it
too.

But that doesn't change anything with the primary plane just being a
special plane from the sw side (backwards compat), for exynos hw they all
look the same.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 08/14] drm/exynos: atomic phase 1: add atomic_begin()/atomic_flush()
  2015-02-05  2:48       ` Joonyoung Shim
@ 2015-02-05  9:18         ` Daniel Vetter
  0 siblings, 0 replies; 37+ messages in thread
From: Daniel Vetter @ 2015-02-05  9:18 UTC (permalink / raw)
  To: Joonyoung Shim
  Cc: Daniel Vetter, Gustavo Padovan, linux-samsung-soc,
	Gustavo Padovan, dri-devel

On Thu, Feb 05, 2015 at 11:48:18AM +0900, Joonyoung Shim wrote:
> Hi Daniel,
> 
> On 02/04/2015 11:30 PM, Daniel Vetter wrote:
> > On Wed, Feb 04, 2015 at 04:49:25PM +0900, Joonyoung Shim wrote:
> >> Hi,
> >>
> >> On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
> >>> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> >>>
> >>> Add CRTC callbacks .atomic_begin() .atomic_flush(). On exynos they
> >>> unprotect the windows before the commit and protects it after based on
> >>> a plane mask tha store which plane will be updated.
> >>>
> >>
> >> I don't think they need now.
> > 
> > This does exactly what I wanted to do in my atomic poc but couldn't
> > because of the massive layer hell that was still around in atomic. Haven't
> > looked into the patch in details, so no full r-b but good enough for an
> > 
> 
> I agree about its operation but i think it is unnecessary now. Because
> it's exactly same operation with current codes.

Well that's to be expected since if you don't want to have some duplicated
code while transitioning to atomic you must do it all in one giant patch.
With a bit of duplication you can move things over slowly, in differnt
phases and piece by piece like Padovan's patch series here. The
duplication should go away in the end again.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 04/14] drm/exynos: remove struct *_win_data abstraction on planes
  2015-02-05  9:15         ` Daniel Vetter
@ 2015-02-05 12:26           ` Rob Clark
  2015-02-05 12:48             ` Daniel Stone
  0 siblings, 1 reply; 37+ messages in thread
From: Rob Clark @ 2015-02-05 12:26 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Joonyoung Shim, moderated list:ARM/S5P EXYNOS AR...,
	Gustavo Padovan, dri-devel

On Thu, Feb 5, 2015 at 4:15 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Thu, Feb 05, 2015 at 11:37:13AM +0900, Joonyoung Shim wrote:
>> Hi Daniel,
>>
>> On 02/04/2015 11:28 PM, Daniel Vetter wrote:
>> > On Wed, Feb 04, 2015 at 04:44:12PM +0900, Joonyoung Shim wrote:
>> >> Hi,
>> >>
>> >> On 02/04/2015 04:14 AM, Gustavo Padovan wrote:
>> >>> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>> >>>
>> >>> struct {fimd,mixer,vidi}_win_data was just keeping the same data
>> >>> as struct exynos_drm_plane thus get ride of it and use exynos_drm_plane
>> >>> directly.
>> >>>
>> >>> It changes how planes are created and remove .win_mode_set() callback
>> >>> that was only filling all *_win_data structs.
>> >>>
>> >>
>> >> I commented already on prior patch.
>> >
>> > I think you don't quite understand how this primary/overlay plane stuff
>> > works in drm core. The entire point of the drm core primary plane is to
>> > work _exactly_ like an overlay plane and allow userspace to mangle the
>> > primary plane configuration through the overlay plane. The only reason we
>> > have primary planes is so that old userspace keeps working.
>> >
>>
>> Right, i misunderstood a bit because exynos hw drivers have dependency
>> of zpos(hw overlay position).
>>
>> Current exynos drm driver has each primary plane of hw drivers and five
>> overlay planes. The primary plane is fixed on default hw overlay and all
>> overlay plane can map to all hw overlays using specific zpos property of
>> exynos drm plane.
>>
>> Gustavo approach will include specific hw overlay data in overlay plane
>> and hw driver keeps overlay planes to array by zpos order. But current
>> zpos of overlay plane is 0 always if user doesn't modify it, so hw
>> driver will use only hw overlay data of primary plane always even if
>> user want to use overlay plane.
>>
>> If user is modified zpos of overlay plane, hw driver can get wrong hw
>> overlay data from different overlay plane because hw driver keeps
>> overlay planes by zpos order.
>
> Yeah I noticed the zpos fun when hacking around too. Exynos should
> probably switch defaults so that overlays are visible by default. And we
> need to standardize the zpos property so that other drivers can use it
> too.

jfyi, I have a bit of logic in mdp5_crtc_atomic_check() (and really
mdp4 probably needs the same) to sort attached planes and derive the
actual hw zpos (with each layer having a unique zpos)..

I suspect most hw will end up needing the same (ie. dislike having two
overlays at same zpos), so might not be a horrible idea to make the
atomic helpers do this sorting for us..

BR,
-R

> But that doesn't change anything with the primary plane just being a
> special plane from the sw side (backwards compat), for exynos hw they all
> look the same.
> -Daniel
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 04/14] drm/exynos: remove struct *_win_data abstraction on planes
  2015-02-05 12:26           ` Rob Clark
@ 2015-02-05 12:48             ` Daniel Stone
  2015-02-05 13:06               ` Daniel Vetter
  0 siblings, 1 reply; 37+ messages in thread
From: Daniel Stone @ 2015-02-05 12:48 UTC (permalink / raw)
  To: Rob Clark
  Cc: Daniel Vetter, moderated list:ARM/S5P EXYNOS AR...,
	Gustavo Padovan, dri-devel

Hi,

On 5 February 2015 at 12:26, Rob Clark <robdclark@gmail.com> wrote:
> On Thu, Feb 5, 2015 at 4:15 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
>> Yeah I noticed the zpos fun when hacking around too. Exynos should
>> probably switch defaults so that overlays are visible by default. And we
>> need to standardize the zpos property so that other drivers can use it
>> too.
>
> jfyi, I have a bit of logic in mdp5_crtc_atomic_check() (and really
> mdp4 probably needs the same) to sort attached planes and derive the
> actual hw zpos (with each layer having a unique zpos)..
>
> I suspect most hw will end up needing the same (ie. dislike having two
> overlays at same zpos), so might not be a horrible idea to make the
> atomic helpers do this sorting for us..

Same with Exynos, except it's a bit funnier still. In terms of its
hardware, each CRTC has a number of planes which have a fixed zpos.
The reason exynos_drm exposes zpos is because it sets up a fixed
number of planes for the entire device and declares they can run
across every single CRTC, and then works out from the combination of
CRTC assignment and zpos property, which hardware plane to assign it
to. This includes the primary, so if you accidentally get zpos==0 in
there, then you smash the primary plane. Or set a duplicate zpos and
then the last one in wins.

It also means if you're using multiple CRTCs (e.g. FIMD for internal
panel plus mixer for external HDMI), then you can only use 5 planes in
total, rather than 5 planes per head. (And let's not forget that each
backend has disjoint format support, so again the driver just lies to
you and claims to support them all, with a silent fallback via a
default case statement when the format isn't actually supported.
Whoops.)

I think a more ideal setup would be a much more direct 1:1 mapping
with the hardware, where each actual plane on each actual CRTC gets
exposed directly to userspace, perhaps with a fixed/read-only zpos
property to tell the userspace which plane it's actually configuring.
I suspect this would be a pretty good map to other hardware as well.

Cheers,
Daniel

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

* Re: [PATCH 04/14] drm/exynos: remove struct *_win_data abstraction on planes
  2015-02-05 12:48             ` Daniel Stone
@ 2015-02-05 13:06               ` Daniel Vetter
  2015-02-06  3:39                 ` Joonyoung Shim
  0 siblings, 1 reply; 37+ messages in thread
From: Daniel Vetter @ 2015-02-05 13:06 UTC (permalink / raw)
  To: Daniel Stone
  Cc: Rob Clark, Daniel Vetter, moderated list:ARM/S5P EXYNOS AR...,
	Gustavo Padovan, dri-devel

On Thu, Feb 05, 2015 at 12:48:07PM +0000, Daniel Stone wrote:
> Hi,
> 
> On 5 February 2015 at 12:26, Rob Clark <robdclark@gmail.com> wrote:
> > On Thu, Feb 5, 2015 at 4:15 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
> >> Yeah I noticed the zpos fun when hacking around too. Exynos should
> >> probably switch defaults so that overlays are visible by default. And we
> >> need to standardize the zpos property so that other drivers can use it
> >> too.
> >
> > jfyi, I have a bit of logic in mdp5_crtc_atomic_check() (and really
> > mdp4 probably needs the same) to sort attached planes and derive the
> > actual hw zpos (with each layer having a unique zpos)..
> >
> > I suspect most hw will end up needing the same (ie. dislike having two
> > overlays at same zpos), so might not be a horrible idea to make the
> > atomic helpers do this sorting for us..

Oh yeah such a helper would be nice. Especially since on intel hw flipping
planes around means fishing the right value out of some enum table ;-)
So some sort of helper to compute the absolute ordering in a stable way
would be nice.

> Same with Exynos, except it's a bit funnier still. In terms of its
> hardware, each CRTC has a number of planes which have a fixed zpos.
> The reason exynos_drm exposes zpos is because it sets up a fixed
> number of planes for the entire device and declares they can run
> across every single CRTC, and then works out from the combination of
> CRTC assignment and zpos property, which hardware plane to assign it
> to. This includes the primary, so if you accidentally get zpos==0 in
> there, then you smash the primary plane. Or set a duplicate zpos and
> then the last one in wins.
> 
> It also means if you're using multiple CRTCs (e.g. FIMD for internal
> panel plus mixer for external HDMI), then you can only use 5 planes in
> total, rather than 5 planes per head. (And let's not forget that each
> backend has disjoint format support, so again the driver just lies to
> you and claims to support them all, with a silent fallback via a
> default case statement when the format isn't actually supported.
> Whoops.)
> 
> I think a more ideal setup would be a much more direct 1:1 mapping
> with the hardware, where each actual plane on each actual CRTC gets
> exposed directly to userspace, perhaps with a fixed/read-only zpos
> property to tell the userspace which plane it's actually configuring.
> I suspect this would be a pretty good map to other hardware as well.

Hm that sounds indeed a bit funny. I agree that exynos should split planes
into per-crtc and separate the code and capability tables out so that
there's less lying. And zpos should probably be converted to a read-only
property to tell userspace about the facts, instead of doing something
funny behind the scenes.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 04/14] drm/exynos: remove struct *_win_data abstraction on planes
  2015-02-05 13:06               ` Daniel Vetter
@ 2015-02-06  3:39                 ` Joonyoung Shim
  0 siblings, 0 replies; 37+ messages in thread
From: Joonyoung Shim @ 2015-02-06  3:39 UTC (permalink / raw)
  To: Daniel Vetter, Daniel Stone
  Cc: Rob Clark, moderated list:ARM/S5P EXYNOS AR...,
	Gustavo Padovan, dri-devel

Hi,

On 02/05/2015 10:06 PM, Daniel Vetter wrote:
> On Thu, Feb 05, 2015 at 12:48:07PM +0000, Daniel Stone wrote:
>> Hi,
>>
>> On 5 February 2015 at 12:26, Rob Clark <robdclark@gmail.com> wrote:
>>> On Thu, Feb 5, 2015 at 4:15 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
>>>> Yeah I noticed the zpos fun when hacking around too. Exynos should
>>>> probably switch defaults so that overlays are visible by default. And we
>>>> need to standardize the zpos property so that other drivers can use it
>>>> too.
>>>
>>> jfyi, I have a bit of logic in mdp5_crtc_atomic_check() (and really
>>> mdp4 probably needs the same) to sort attached planes and derive the
>>> actual hw zpos (with each layer having a unique zpos)..
>>>
>>> I suspect most hw will end up needing the same (ie. dislike having two
>>> overlays at same zpos), so might not be a horrible idea to make the
>>> atomic helpers do this sorting for us..
> 
> Oh yeah such a helper would be nice. Especially since on intel hw flipping
> planes around means fishing the right value out of some enum table ;-)
> So some sort of helper to compute the absolute ordering in a stable way
> would be nice.
> 
>> Same with Exynos, except it's a bit funnier still. In terms of its
>> hardware, each CRTC has a number of planes which have a fixed zpos.
>> The reason exynos_drm exposes zpos is because it sets up a fixed
>> number of planes for the entire device and declares they can run
>> across every single CRTC, and then works out from the combination of
>> CRTC assignment and zpos property, which hardware plane to assign it
>> to. This includes the primary, so if you accidentally get zpos==0 in
>> there, then you smash the primary plane. Or set a duplicate zpos and
>> then the last one in wins.
>>
>> It also means if you're using multiple CRTCs (e.g. FIMD for internal
>> panel plus mixer for external HDMI), then you can only use 5 planes in
>> total, rather than 5 planes per head. (And let's not forget that each
>> backend has disjoint format support, so again the driver just lies to
>> you and claims to support them all, with a silent fallback via a
>> default case statement when the format isn't actually supported.
>> Whoops.)
>>
>> I think a more ideal setup would be a much more direct 1:1 mapping
>> with the hardware, where each actual plane on each actual CRTC gets
>> exposed directly to userspace, perhaps with a fixed/read-only zpos
>> property to tell the userspace which plane it's actually configuring.
>> I suspect this would be a pretty good map to other hardware as well.
> 
> Hm that sounds indeed a bit funny. I agree that exynos should split planes
> into per-crtc and separate the code and capability tables out so that
> there's less lying. And zpos should probably be converted to a read-only
> property to tell userspace about the facts, instead of doing something
> funny behind the scenes.

I agree, it seems be time to convert each planes have unique zpos.

Thanks.

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

end of thread, other threads:[~2015-02-06  3:39 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-03 19:14 [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Gustavo Padovan
2015-02-03 19:14 ` [PATCH 01/14] drm/exynos: track vblank events on a per crtc basis Gustavo Padovan
2015-02-03 19:14 ` [PATCH 02/14] drm/exynos: Remove exynos_plane_dpms() call with no effect Gustavo Padovan
2015-02-04  7:42   ` Joonyoung Shim
2015-02-04 14:16     ` Daniel Vetter
2015-02-05  1:05       ` Joonyoung Shim
2015-02-05  9:03         ` Daniel Vetter
2015-02-03 19:14 ` [PATCH 03/14] drm/exynos: remove leftover functions declarations Gustavo Padovan
2015-02-03 19:14 ` [PATCH 04/14] drm/exynos: remove struct *_win_data abstraction on planes Gustavo Padovan
2015-02-04  7:44   ` Joonyoung Shim
2015-02-04 14:28     ` Daniel Vetter
2015-02-05  2:37       ` Joonyoung Shim
2015-02-05  9:15         ` Daniel Vetter
2015-02-05 12:26           ` Rob Clark
2015-02-05 12:48             ` Daniel Stone
2015-02-05 13:06               ` Daniel Vetter
2015-02-06  3:39                 ` Joonyoung Shim
2015-02-03 19:14 ` [PATCH 05/14] drm/exynos: do not copy adjusted mode into mode during crtc mode_set Gustavo Padovan
2015-02-03 19:14 ` [PATCH 06/14] drm/exynos: atomic phase 1: use drm_plane_helper_update() Gustavo Padovan
2015-02-03 19:14 ` [PATCH 07/14] drm/exynos: atomic phase 1: use drm_plane_helper_disable() Gustavo Padovan
2015-02-04  7:47   ` Joonyoung Shim
2015-02-03 19:14 ` [PATCH 08/14] drm/exynos: atomic phase 1: add atomic_begin()/atomic_flush() Gustavo Padovan
2015-02-04  7:49   ` Joonyoung Shim
2015-02-04 14:30     ` Daniel Vetter
2015-02-05  2:48       ` Joonyoung Shim
2015-02-05  9:18         ` Daniel Vetter
2015-02-03 19:14 ` [PATCH 09/14] drm/exynos: atomic phase 1: add .mode_set_nofb() callback Gustavo Padovan
2015-02-04  7:51   ` Joonyoung Shim
2015-02-03 19:14 ` [PATCH 10/14] drm/exynos: atomic phase 2: wire up state reset(), duplicate() and destroy() Gustavo Padovan
2015-02-03 19:14 ` [PATCH 11/14] drm/exynos: atomic phase 2: keep track of framebuffer pointer Gustavo Padovan
2015-02-04  7:53   ` Joonyoung Shim
2015-02-04 14:33     ` Daniel Vetter
2015-02-03 19:14 ` [PATCH 12/14] drm/exynos: make exynos_plane_mode_set() static Gustavo Padovan
2015-02-03 19:14 ` [PATCH 13/14] drm/exynos: use correct pipe number on vblank event Gustavo Padovan
2015-02-03 19:14 ` [PATCH 14/14] drm/exynos: remove exynos_disable_plane() Gustavo Padovan
2015-02-04  7:37 ` [PATCH 00/14] drm/exynos: cleanups + atomic phases 1 and 2 Joonyoung Shim
2015-02-04 14:35   ` Daniel Vetter

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.