All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] drm/sti: update STI driver to be atomic
@ 2015-07-31 10:13 Vincent Abriou
  2015-07-31 10:13 ` [PATCH 1/4] drm/sti: fix dynamic z-ordering Vincent Abriou
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Vincent Abriou @ 2015-07-31 10:13 UTC (permalink / raw)
  To: dri-devel; +Cc: Fabien Dessenne, Benjamin Gaignard, kernel

This patch series aims to update the sti drm driver to be atomic.
To do so, the sti driver needs to be code cleaned to have good
fundations to enable the atomic plane update functionnality.
The driver is thereby simplier, more readable and better fit the
STI hardware structure.

Vincent Abriou (4):
  drm/sti: fix dynamic z-ordering
  drm/sti: code clean up
  drm/sti: rename files and functions
  drm/sti: atomic crtc/plane update

 drivers/gpu/drm/sti/Makefile         |   7 +-
 drivers/gpu/drm/sti/sti_compositor.c | 141 +++++----
 drivers/gpu/drm/sti/sti_compositor.h |  12 +-
 drivers/gpu/drm/sti/sti_crtc.c       | 396 ++++++++++++++++++++++++++
 drivers/gpu/drm/sti/sti_crtc.h       |  22 ++
 drivers/gpu/drm/sti/sti_cursor.c     | 243 +++++++++-------
 drivers/gpu/drm/sti/sti_cursor.h     |   5 +-
 drivers/gpu/drm/sti/sti_drm_crtc.c   | 322 ---------------------
 drivers/gpu/drm/sti/sti_drm_crtc.h   |  22 --
 drivers/gpu/drm/sti/sti_drm_drv.c    | 294 -------------------
 drivers/gpu/drm/sti/sti_drm_drv.h    |  35 ---
 drivers/gpu/drm/sti/sti_drm_plane.c  | 251 ----------------
 drivers/gpu/drm/sti/sti_drm_plane.h  |  18 --
 drivers/gpu/drm/sti/sti_drv.c        | 294 +++++++++++++++++++
 drivers/gpu/drm/sti/sti_drv.h        |  35 +++
 drivers/gpu/drm/sti/sti_gdp.c        | 536 ++++++++++++++++++++---------------
 drivers/gpu/drm/sti/sti_gdp.h        |   7 +-
 drivers/gpu/drm/sti/sti_hdmi.c       |   2 +-
 drivers/gpu/drm/sti/sti_hqvdp.c      | 482 ++++++++++++++++---------------
 drivers/gpu/drm/sti/sti_hqvdp.h      |  12 -
 drivers/gpu/drm/sti/sti_layer.c      | 213 --------------
 drivers/gpu/drm/sti/sti_layer.h      | 131 ---------
 drivers/gpu/drm/sti/sti_mixer.c      |  66 ++---
 drivers/gpu/drm/sti/sti_mixer.h      |  28 +-
 drivers/gpu/drm/sti/sti_plane.c      | 120 ++++++++
 drivers/gpu/drm/sti/sti_plane.h      |  71 +++++
 drivers/gpu/drm/sti/sti_tvout.c      |   8 +-
 drivers/gpu/drm/sti/sti_vid.c        |  72 ++---
 drivers/gpu/drm/sti/sti_vid.h        |  19 +-
 29 files changed, 1825 insertions(+), 2039 deletions(-)
 create mode 100644 drivers/gpu/drm/sti/sti_crtc.c
 create mode 100644 drivers/gpu/drm/sti/sti_crtc.h
 delete mode 100644 drivers/gpu/drm/sti/sti_drm_crtc.c
 delete mode 100644 drivers/gpu/drm/sti/sti_drm_crtc.h
 delete mode 100644 drivers/gpu/drm/sti/sti_drm_drv.c
 delete mode 100644 drivers/gpu/drm/sti/sti_drm_drv.h
 delete mode 100644 drivers/gpu/drm/sti/sti_drm_plane.c
 delete mode 100644 drivers/gpu/drm/sti/sti_drm_plane.h
 create mode 100644 drivers/gpu/drm/sti/sti_drv.c
 create mode 100644 drivers/gpu/drm/sti/sti_drv.h
 delete mode 100644 drivers/gpu/drm/sti/sti_hqvdp.h
 delete mode 100644 drivers/gpu/drm/sti/sti_layer.c
 delete mode 100644 drivers/gpu/drm/sti/sti_layer.h
 create mode 100644 drivers/gpu/drm/sti/sti_plane.c
 create mode 100644 drivers/gpu/drm/sti/sti_plane.h

-- 
1.9.1

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

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

* [PATCH 1/4] drm/sti: fix dynamic z-ordering
  2015-07-31 10:13 [PATCH 0/4] drm/sti: update STI driver to be atomic Vincent Abriou
@ 2015-07-31 10:13 ` Vincent Abriou
  2015-07-31 10:13 ` [PATCH 2/4] drm/sti: code clean up Vincent Abriou
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Vincent Abriou @ 2015-07-31 10:13 UTC (permalink / raw)
  To: dri-devel; +Cc: Fabien Dessenne, Benjamin Gaignard, kernel

Apply the plane depth when the plane is updated.
If the depth is different from the previous plane update,
the register controlling the plane depth is cleaned and updated
with the new depth.

Signed-off-by: Vincent Abriou <vincent.abriou@st.com>
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
---
 drivers/gpu/drm/sti/sti_drm_plane.c | 23 +++++++++--------------
 drivers/gpu/drm/sti/sti_mixer.c     | 19 ++++++++++++++-----
 drivers/gpu/drm/sti/sti_mixer.h     |  2 +-
 3 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/sti/sti_drm_plane.c b/drivers/gpu/drm/sti/sti_drm_plane.c
index 64d4ed4..5427bc2 100644
--- a/drivers/gpu/drm/sti/sti_drm_plane.c
+++ b/drivers/gpu/drm/sti/sti_drm_plane.c
@@ -15,17 +15,16 @@
 #include "sti_drm_plane.h"
 #include "sti_vtg.h"
 
+/* (Background) < GDP0 < GDP1 < VID0 < VID1 < GDP2 < GDP3 < (ForeGround) */
 enum sti_layer_desc sti_layer_default_zorder[] = {
 	STI_GDP_0,
-	STI_VID_0,
 	STI_GDP_1,
+	STI_VID_0,
 	STI_VID_1,
 	STI_GDP_2,
 	STI_GDP_3,
 };
 
-/* (Background) < GDP0 < VID0 < GDP1 < VID1 < GDP2 < GDP3 < (ForeGround) */
-
 static int
 sti_drm_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		     struct drm_framebuffer *fb, int crtc_x, int crtc_y,
@@ -191,8 +190,7 @@ static const struct drm_plane_helper_funcs sti_drm_plane_helpers_funcs = {
 	.atomic_disable = sti_drm_plane_atomic_disable,
 };
 
-static void sti_drm_plane_attach_zorder_property(struct drm_plane *plane,
-						 uint64_t default_val)
+static void sti_drm_plane_attach_zorder_property(struct drm_plane *plane)
 {
 	struct drm_device *dev = plane->dev;
 	struct sti_drm_private *private = dev->dev_private;
@@ -201,16 +199,15 @@ static void sti_drm_plane_attach_zorder_property(struct drm_plane *plane,
 
 	prop = private->plane_zorder_property;
 	if (!prop) {
-		prop = drm_property_create_range(dev, 0, "zpos", 0,
-						 GAM_MIXER_NB_DEPTH_LEVEL - 1);
+		prop = drm_property_create_range(dev, 0, "zpos", 1,
+						 GAM_MIXER_NB_DEPTH_LEVEL);
 		if (!prop)
 			return;
 
 		private->plane_zorder_property = prop;
 	}
 
-	drm_object_attach_property(&plane->base, prop, default_val);
-	layer->zorder = default_val;
+	drm_object_attach_property(&plane->base, prop, layer->zorder);
 }
 
 struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
@@ -219,7 +216,6 @@ struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
 				     enum drm_plane_type type)
 {
 	int err, i;
-	uint64_t default_zorder = 0;
 
 	err = drm_universal_plane_init(dev, &layer->plane, possible_crtcs,
 			     &sti_drm_plane_funcs,
@@ -236,15 +232,14 @@ struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
 		if (sti_layer_default_zorder[i] == layer->desc)
 			break;
 
-	default_zorder = i + 1;
+	layer->zorder = i + 1;
 
 	if (type == DRM_PLANE_TYPE_OVERLAY)
-		sti_drm_plane_attach_zorder_property(&layer->plane,
-				default_zorder);
+		sti_drm_plane_attach_zorder_property(&layer->plane);
 
 	DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%llu\n",
 			 layer->plane.base.id,
-			 sti_layer_to_str(layer), default_zorder);
+			 sti_layer_to_str(layer), layer->zorder);
 
 	return &layer->plane;
 }
diff --git a/drivers/gpu/drm/sti/sti_mixer.c b/drivers/gpu/drm/sti/sti_mixer.c
index 13a4b84..61a2048 100644
--- a/drivers/gpu/drm/sti/sti_mixer.c
+++ b/drivers/gpu/drm/sti/sti_mixer.c
@@ -103,10 +103,11 @@ static void sti_mixer_set_background_area(struct sti_mixer *mixer,
 
 int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer)
 {
-	int layer_id = 0, depth = layer->zorder;
+	int layer_id, depth = layer->zorder;
+	unsigned int i;
 	u32 mask, val;
 
-	if (depth >= GAM_MIXER_NB_DEPTH_LEVEL)
+	if ((depth < 1) || (depth > GAM_MIXER_NB_DEPTH_LEVEL))
 		return 1;
 
 	switch (layer->desc) {
@@ -136,15 +137,23 @@ int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer)
 		DRM_ERROR("Unknown layer %d\n", layer->desc);
 		return 1;
 	}
-	mask = GAM_DEPTH_MASK_ID << (3 * depth);
-	layer_id = layer_id << (3 * depth);
+
+	/* Search if a previous depth was already assigned to the layer */
+	val = sti_mixer_reg_read(mixer, GAM_MIXER_CRB);
+	for (i = 0; i < GAM_MIXER_NB_DEPTH_LEVEL; i++) {
+		mask = GAM_DEPTH_MASK_ID << (3 * i);
+		if ((val & mask) == layer_id << (3 * i))
+			break;
+	}
+
+	mask |= GAM_DEPTH_MASK_ID << (3 * (depth - 1));
+	layer_id = layer_id << (3 * (depth - 1));
 
 	DRM_DEBUG_DRIVER("%s %s depth=%d\n", sti_mixer_to_str(mixer),
 			 sti_layer_to_str(layer), depth);
 	dev_dbg(mixer->dev, "GAM_MIXER_CRB val 0x%x mask 0x%x\n",
 		layer_id, mask);
 
-	val = sti_mixer_reg_read(mixer, GAM_MIXER_CRB);
 	val &= ~mask;
 	val |= layer_id;
 	sti_mixer_reg_write(mixer, GAM_MIXER_CRB, val);
diff --git a/drivers/gpu/drm/sti/sti_mixer.h b/drivers/gpu/drm/sti/sti_mixer.h
index b972821..eb663f6 100644
--- a/drivers/gpu/drm/sti/sti_mixer.h
+++ b/drivers/gpu/drm/sti/sti_mixer.h
@@ -49,7 +49,7 @@ int sti_mixer_active_video_area(struct sti_mixer *mixer,
 void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable);
 
 /* depth in Cross-bar control = z order */
-#define GAM_MIXER_NB_DEPTH_LEVEL 7
+#define GAM_MIXER_NB_DEPTH_LEVEL 6
 
 #define STI_MIXER_MAIN 0
 #define STI_MIXER_AUX  1
-- 
1.9.1

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

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

* [PATCH 2/4] drm/sti: code clean up
  2015-07-31 10:13 [PATCH 0/4] drm/sti: update STI driver to be atomic Vincent Abriou
  2015-07-31 10:13 ` [PATCH 1/4] drm/sti: fix dynamic z-ordering Vincent Abriou
@ 2015-07-31 10:13 ` Vincent Abriou
  2015-07-31 10:13 ` [PATCH 3/4] drm/sti: rename files and functions Vincent Abriou
  2015-07-31 10:13 ` [PATCH 4/4] drm/sti: atomic crtc/plane update Vincent Abriou
  3 siblings, 0 replies; 9+ messages in thread
From: Vincent Abriou @ 2015-07-31 10:13 UTC (permalink / raw)
  To: dri-devel; +Cc: Fabien Dessenne, Benjamin Gaignard, kernel

Purpose is to simplify the STI driver:
- remove layer structure
- consider video subdev as part of the compositor (like mixer subdev)
- remove useless STI_VID0 and STI_VID1 enum

Signed-off-by: Vincent Abriou <vincent.abriou@st.com>
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
---
 drivers/gpu/drm/sti/Makefile         |   1 -
 drivers/gpu/drm/sti/sti_compositor.c | 135 ++++++++-------
 drivers/gpu/drm/sti/sti_compositor.h |  12 +-
 drivers/gpu/drm/sti/sti_cursor.c     | 108 ++++++------
 drivers/gpu/drm/sti/sti_cursor.h     |   3 +-
 drivers/gpu/drm/sti/sti_drm_crtc.c   |  34 ++--
 drivers/gpu/drm/sti/sti_drm_plane.c  | 322 +++++++++++++++++++++++------------
 drivers/gpu/drm/sti/sti_drm_plane.h  |  91 +++++++++-
 drivers/gpu/drm/sti/sti_gdp.c        | 185 ++++++++++----------
 drivers/gpu/drm/sti/sti_gdp.h        |   3 +-
 drivers/gpu/drm/sti/sti_hdmi.c       |   2 +-
 drivers/gpu/drm/sti/sti_hqvdp.c      | 201 +++++++++++-----------
 drivers/gpu/drm/sti/sti_hqvdp.h      |  12 --
 drivers/gpu/drm/sti/sti_layer.c      | 213 -----------------------
 drivers/gpu/drm/sti/sti_layer.h      | 131 --------------
 drivers/gpu/drm/sti/sti_mixer.c      |  55 +++---
 drivers/gpu/drm/sti/sti_mixer.h      |  16 +-
 drivers/gpu/drm/sti/sti_vid.c        |  57 ++-----
 drivers/gpu/drm/sti/sti_vid.h        |  18 +-
 19 files changed, 713 insertions(+), 886 deletions(-)
 delete mode 100644 drivers/gpu/drm/sti/sti_hqvdp.h
 delete mode 100644 drivers/gpu/drm/sti/sti_layer.c
 delete mode 100644 drivers/gpu/drm/sti/sti_layer.h

diff --git a/drivers/gpu/drm/sti/Makefile b/drivers/gpu/drm/sti/Makefile
index f0f1e4e..505b3ba 100644
--- a/drivers/gpu/drm/sti/Makefile
+++ b/drivers/gpu/drm/sti/Makefile
@@ -1,5 +1,4 @@
 sticompositor-y := \
-	sti_layer.o \
 	sti_mixer.o \
 	sti_gdp.o \
 	sti_vid.o \
diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c
index 43215d3..68c5c95 100644
--- a/drivers/gpu/drm/sti/sti_compositor.c
+++ b/drivers/gpu/drm/sti/sti_compositor.c
@@ -14,10 +14,12 @@
 #include <drm/drmP.h>
 
 #include "sti_compositor.h"
+#include "sti_cursor.h"
 #include "sti_drm_crtc.h"
 #include "sti_drm_drv.h"
 #include "sti_drm_plane.h"
 #include "sti_gdp.h"
+#include "sti_vid.h"
 #include "sti_vtg.h"
 
 /*
@@ -31,7 +33,7 @@ struct sti_compositor_data stih407_compositor_data = {
 			{STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200},
 			{STI_GPD_SUBDEV, (int)STI_GDP_2, 0x300},
 			{STI_GPD_SUBDEV, (int)STI_GDP_3, 0x400},
-			{STI_VID_SUBDEV, (int)STI_VID_0, 0x700},
+			{STI_VID_SUBDEV, (int)STI_HQVDP_0, 0x700},
 			{STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00},
 			{STI_MIXER_AUX_SUBDEV, STI_MIXER_AUX, 0xD00},
 	},
@@ -53,14 +55,31 @@ struct sti_compositor_data stih416_compositor_data = {
 	},
 };
 
-static int sti_compositor_init_subdev(struct sti_compositor *compo,
-		struct sti_compositor_subdev_descriptor *desc,
-		unsigned int array_size)
+static int sti_compositor_bind(struct device *dev,
+			       struct device *master,
+			       void *data)
 {
-	unsigned int i, mixer_id = 0, layer_id = 0;
+	struct sti_compositor *compo = dev_get_drvdata(dev);
+	struct drm_device *drm_dev = data;
+	unsigned int i, mixer_id = 0, vid_id = 0, crtc_id = 0, plane_id = 0;
+	struct sti_drm_private *dev_priv = drm_dev->dev_private;
+	struct drm_plane *cursor = NULL;
+	struct drm_plane *primary = NULL;
+	struct sti_compositor_subdev_descriptor *desc = compo->data.subdev_desc;
+	unsigned int array_size = compo->data.nb_subdev;
+
+	struct sti_plane *plane;
 
+	dev_priv->compo = compo;
+
+	/* Register mixer subdev and video subdev first */
 	for (i = 0; i < array_size; i++) {
 		switch (desc[i].type) {
+		case STI_VID_SUBDEV:
+			compo->vid[vid_id++] =
+			    sti_vid_create(compo->dev, desc[i].id,
+					   compo->regs + desc[i].offset);
+			break;
 		case STI_MIXER_MAIN_SUBDEV:
 		case STI_MIXER_AUX_SUBDEV:
 			compo->mixer[mixer_id++] =
@@ -68,81 +87,72 @@ static int sti_compositor_init_subdev(struct sti_compositor *compo,
 					     compo->regs + desc[i].offset);
 			break;
 		case STI_GPD_SUBDEV:
-		case STI_VID_SUBDEV:
 		case STI_CURSOR_SUBDEV:
-			compo->layer[layer_id++] =
-			    sti_layer_create(compo->dev, desc[i].id,
-					     compo->regs + desc[i].offset);
+			/* Nothing to do, wait for the second round */
 			break;
 		default:
 			DRM_ERROR("Unknow subdev compoment type\n");
 			return 1;
 		}
-
 	}
-	compo->nb_mixers = mixer_id;
-	compo->nb_layers = layer_id;
-
-	return 0;
-}
 
-static int sti_compositor_bind(struct device *dev, struct device *master,
-	void *data)
-{
-	struct sti_compositor *compo = dev_get_drvdata(dev);
-	struct drm_device *drm_dev = data;
-	unsigned int i, crtc = 0, plane = 0;
-	struct sti_drm_private *dev_priv = drm_dev->dev_private;
-	struct drm_plane *cursor = NULL;
-	struct drm_plane *primary = NULL;
-
-	dev_priv->compo = compo;
-
-	for (i = 0; i < compo->nb_layers; i++) {
-		if (compo->layer[i]) {
-			enum sti_layer_desc desc = compo->layer[i]->desc;
-			enum sti_layer_type type = desc & STI_LAYER_TYPE_MASK;
-			enum drm_plane_type plane_type = DRM_PLANE_TYPE_OVERLAY;
+	/* Register the other subdevs, create crtc and planes */
+	for (i = 0; i < array_size; i++) {
+		enum drm_plane_type plane_type = DRM_PLANE_TYPE_OVERLAY;
 
-			if (crtc < compo->nb_mixers)
-				plane_type = DRM_PLANE_TYPE_PRIMARY;
+		if (crtc_id < mixer_id)
+			plane_type = DRM_PLANE_TYPE_PRIMARY;
 
-			switch (type) {
-			case STI_CUR:
-				cursor = sti_drm_plane_init(drm_dev,
-						compo->layer[i],
-						1, DRM_PLANE_TYPE_CURSOR);
-				break;
-			case STI_GDP:
-			case STI_VID:
-				primary = sti_drm_plane_init(drm_dev,
-						compo->layer[i],
-						(1 << compo->nb_mixers) - 1,
-						plane_type);
-				plane++;
+		switch (desc[i].type) {
+		case STI_MIXER_MAIN_SUBDEV:
+		case STI_MIXER_AUX_SUBDEV:
+		case STI_VID_SUBDEV:
+			/* Nothing to do, already done at the first round */
+			break;
+		case STI_CURSOR_SUBDEV:
+			plane = sti_cursor_create(compo->dev, desc[i].id,
+						  compo->regs + desc[i].offset);
+			if (!plane) {
+				DRM_ERROR("Can't create CURSOR plane\n");
 				break;
-			case STI_BCK:
-			case STI_VDP:
+			}
+			cursor = sti_drm_plane_init(drm_dev, plane, 1,
+						    DRM_PLANE_TYPE_CURSOR);
+			plane_id++;
+			break;
+		case STI_GPD_SUBDEV:
+			plane = sti_gdp_create(compo->dev, desc[i].id,
+					       compo->regs + desc[i].offset);
+			if (!plane) {
+				DRM_ERROR("Can't create GDP plane\n");
 				break;
 			}
+			primary = sti_drm_plane_init(drm_dev, plane,
+						     (1 << mixer_id) - 1,
+						     plane_type);
+			plane_id++;
+			break;
+		default:
+			DRM_ERROR("Unknown subdev compoment type\n");
+			return 1;
+		}
 
-			/* The first planes are reserved for primary planes*/
-			if (crtc < compo->nb_mixers && primary) {
-				sti_drm_crtc_init(drm_dev, compo->mixer[crtc],
-						primary, cursor);
-				crtc++;
-				cursor = NULL;
-				primary = NULL;
-			}
+		/* The first planes are reserved for primary planes*/
+		if (crtc_id < mixer_id && primary) {
+			sti_drm_crtc_init(drm_dev, compo->mixer[crtc_id],
+					  primary, cursor);
+			crtc_id++;
+			cursor = NULL;
+			primary = NULL;
 		}
 	}
 
-	drm_vblank_init(drm_dev, crtc);
+	drm_vblank_init(drm_dev, crtc_id);
 	/* Allow usage of vblank without having to call drm_irq_install */
 	drm_dev->irq_enabled = 1;
 
 	DRM_DEBUG_DRIVER("Initialized %d DRM CRTC(s) and %d DRM plane(s)\n",
-			 crtc, plane);
+			 crtc_id, plane_id);
 	DRM_DEBUG_DRIVER("DRM plane(s) for VID/VDP not created yet\n");
 
 	return 0;
@@ -179,7 +189,6 @@ static int sti_compositor_probe(struct platform_device *pdev)
 	struct device_node *vtg_np;
 	struct sti_compositor *compo;
 	struct resource *res;
-	int err;
 
 	compo = devm_kzalloc(dev, sizeof(*compo), GFP_KERNEL);
 	if (!compo) {
@@ -251,12 +260,6 @@ static int sti_compositor_probe(struct platform_device *pdev)
 	if (vtg_np)
 		compo->vtg_aux = of_vtg_find(vtg_np);
 
-	/* Initialize compositor subdevices */
-	err = sti_compositor_init_subdev(compo, compo->data.subdev_desc,
-					 compo->data.nb_subdev);
-	if (err)
-		return err;
-
 	platform_set_drvdata(pdev, compo);
 
 	return component_add(&pdev->dev, &sti_compositor_ops);
diff --git a/drivers/gpu/drm/sti/sti_compositor.h b/drivers/gpu/drm/sti/sti_compositor.h
index 019eb44..77f9978 100644
--- a/drivers/gpu/drm/sti/sti_compositor.h
+++ b/drivers/gpu/drm/sti/sti_compositor.h
@@ -12,13 +12,13 @@
 #include <linux/clk.h>
 #include <linux/kernel.h>
 
-#include "sti_layer.h"
+#include "sti_drm_plane.h"
 #include "sti_mixer.h"
 
 #define WAIT_NEXT_VSYNC_MS      50 /*ms*/
 
-#define STI_MAX_LAYER 8
 #define STI_MAX_MIXER 2
+#define STI_MAX_VID   1
 
 enum sti_compositor_subdev_type {
 	STI_MIXER_MAIN_SUBDEV,
@@ -59,11 +59,9 @@ struct sti_compositor_data {
  * @rst_main: reset control of the main path
  * @rst_aux: reset control of the aux path
  * @mixer: array of mixers
+ * @vid: array of vids
  * @vtg_main: vtg for main data path
  * @vtg_aux: vtg for auxillary data path
- * @layer: array of layers
- * @nb_mixers: number of mixers for this compositor
- * @nb_layers: number of layers (GDP,VID,...) for this compositor
  * @vtg_vblank_nb: callback for VTG VSYNC notification
  */
 struct sti_compositor {
@@ -77,11 +75,9 @@ struct sti_compositor {
 	struct reset_control *rst_main;
 	struct reset_control *rst_aux;
 	struct sti_mixer *mixer[STI_MAX_MIXER];
+	struct sti_vid *vid[STI_MAX_VID];
 	struct sti_vtg *vtg_main;
 	struct sti_vtg *vtg_aux;
-	struct sti_layer *layer[STI_MAX_LAYER];
-	int nb_mixers;
-	int nb_layers;
 	struct notifier_block vtg_vblank_nb;
 };
 
diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c
index 010eaee..cd12403 100644
--- a/drivers/gpu/drm/sti/sti_cursor.c
+++ b/drivers/gpu/drm/sti/sti_cursor.c
@@ -8,7 +8,7 @@
 #include <drm/drmP.h>
 
 #include "sti_cursor.h"
-#include "sti_layer.h"
+#include "sti_drm_plane.h"
 #include "sti_vtg.h"
 
 /* Registers */
@@ -42,7 +42,9 @@ struct dma_pixmap {
 /**
  * STI Cursor structure
  *
- * @layer:      layer structure
+ * @sti_plane:  sti_plane structure
+ * @dev:        driver device
+ * @regs:       cursor registers
  * @width:      cursor width
  * @height:     cursor height
  * @clut:       color look up table
@@ -50,7 +52,9 @@ struct dma_pixmap {
  * @pixmap:     pixmap dma buffer (clut8-format cursor)
  */
 struct sti_cursor {
-	struct sti_layer layer;
+	struct sti_plane plane;
+	struct device *dev;
+	void __iomem *regs;
 	unsigned int width;
 	unsigned int height;
 	unsigned short *clut;
@@ -62,22 +66,22 @@ static const uint32_t cursor_supported_formats[] = {
 	DRM_FORMAT_ARGB8888,
 };
 
-#define to_sti_cursor(x) container_of(x, struct sti_cursor, layer)
+#define to_sti_cursor(x) container_of(x, struct sti_cursor, plane)
 
-static const uint32_t *sti_cursor_get_formats(struct sti_layer *layer)
+static const uint32_t *sti_cursor_get_formats(struct sti_plane *plane)
 {
 	return cursor_supported_formats;
 }
 
-static unsigned int sti_cursor_get_nb_formats(struct sti_layer *layer)
+static unsigned int sti_cursor_get_nb_formats(struct sti_plane *plane)
 {
 	return ARRAY_SIZE(cursor_supported_formats);
 }
 
-static void sti_cursor_argb8888_to_clut8(struct sti_layer *layer)
+static void sti_cursor_argb8888_to_clut8(struct sti_plane *plane)
 {
-	struct sti_cursor *cursor = to_sti_cursor(layer);
-	u32 *src = layer->vaddr;
+	struct sti_cursor *cursor = to_sti_cursor(plane);
+	u32 *src = plane->vaddr;
 	u8  *dst = cursor->pixmap.base;
 	unsigned int i, j;
 	u32 a, r, g, b;
@@ -96,42 +100,42 @@ static void sti_cursor_argb8888_to_clut8(struct sti_layer *layer)
 	}
 }
 
-static int sti_cursor_prepare_layer(struct sti_layer *layer, bool first_prepare)
+static int sti_cursor_prepare_plane(struct sti_plane *plane, bool first_prepare)
 {
-	struct sti_cursor *cursor = to_sti_cursor(layer);
-	struct drm_display_mode *mode = layer->mode;
+	struct sti_cursor *cursor = to_sti_cursor(plane);
+	struct drm_display_mode *mode = plane->mode;
 	u32 y, x;
 	u32 val;
 
 	DRM_DEBUG_DRIVER("\n");
 
-	dev_dbg(layer->dev, "%s %s\n", __func__, sti_layer_to_str(layer));
+	dev_dbg(cursor->dev, "%s %s\n", __func__, sti_plane_to_str(plane));
 
-	if (layer->src_w < STI_CURS_MIN_SIZE ||
-	    layer->src_h < STI_CURS_MIN_SIZE ||
-	    layer->src_w > STI_CURS_MAX_SIZE ||
-	    layer->src_h > STI_CURS_MAX_SIZE) {
+	if (plane->src_w < STI_CURS_MIN_SIZE ||
+	    plane->src_h < STI_CURS_MIN_SIZE ||
+	    plane->src_w > STI_CURS_MAX_SIZE ||
+	    plane->src_h > STI_CURS_MAX_SIZE) {
 		DRM_ERROR("Invalid cursor size (%dx%d)\n",
-				layer->src_w, layer->src_h);
+				plane->src_w, plane->src_h);
 		return -EINVAL;
 	}
 
 	/* If the cursor size has changed, re-allocated the pixmap */
 	if (!cursor->pixmap.base ||
-	    (cursor->width != layer->src_w) ||
-	    (cursor->height != layer->src_h)) {
-		cursor->width = layer->src_w;
-		cursor->height = layer->src_h;
+	    (cursor->width != plane->src_w) ||
+	    (cursor->height != plane->src_h)) {
+		cursor->width = plane->src_w;
+		cursor->height = plane->src_h;
 
 		if (cursor->pixmap.base)
-			dma_free_writecombine(layer->dev,
+			dma_free_writecombine(cursor->dev,
 					      cursor->pixmap.size,
 					      cursor->pixmap.base,
 					      cursor->pixmap.paddr);
 
 		cursor->pixmap.size = cursor->width * cursor->height;
 
-		cursor->pixmap.base = dma_alloc_writecombine(layer->dev,
+		cursor->pixmap.base = dma_alloc_writecombine(cursor->dev,
 							cursor->pixmap.size,
 							&cursor->pixmap.paddr,
 							GFP_KERNEL | GFP_DMA);
@@ -142,55 +146,54 @@ static int sti_cursor_prepare_layer(struct sti_layer *layer, bool first_prepare)
 	}
 
 	/* Convert ARGB8888 to CLUT8 */
-	sti_cursor_argb8888_to_clut8(layer);
+	sti_cursor_argb8888_to_clut8(plane);
 
 	/* AWS and AWE depend on the mode */
 	y = sti_vtg_get_line_number(*mode, 0);
 	x = sti_vtg_get_pixel_number(*mode, 0);
 	val = y << 16 | x;
-	writel(val, layer->regs + CUR_AWS);
+	writel(val, cursor->regs + CUR_AWS);
 	y = sti_vtg_get_line_number(*mode, mode->vdisplay - 1);
 	x = sti_vtg_get_pixel_number(*mode, mode->hdisplay - 1);
 	val = y << 16 | x;
-	writel(val, layer->regs + CUR_AWE);
+	writel(val, cursor->regs + CUR_AWE);
 
 	if (first_prepare) {
 		/* Set and fetch CLUT */
-		writel(cursor->clut_paddr, layer->regs + CUR_CML);
-		writel(CUR_CTL_CLUT_UPDATE, layer->regs + CUR_CTL);
+		writel(cursor->clut_paddr, cursor->regs + CUR_CML);
+		writel(CUR_CTL_CLUT_UPDATE, cursor->regs + CUR_CTL);
 	}
 
 	return 0;
 }
 
-static int sti_cursor_commit_layer(struct sti_layer *layer)
+static int sti_cursor_commit_plane(struct sti_plane *plane)
 {
-	struct sti_cursor *cursor = to_sti_cursor(layer);
-	struct drm_display_mode *mode = layer->mode;
+	struct sti_cursor *cursor = to_sti_cursor(plane);
+	struct drm_display_mode *mode = plane->mode;
 	u32 ydo, xdo;
 
-	dev_dbg(layer->dev, "%s %s\n", __func__, sti_layer_to_str(layer));
+	dev_dbg(cursor->dev, "%s %s\n", __func__, sti_plane_to_str(plane));
 
 	/* Set memory location, size, and position */
-	writel(cursor->pixmap.paddr, layer->regs + CUR_PML);
-	writel(cursor->width, layer->regs + CUR_PMP);
-	writel(cursor->height << 16 | cursor->width, layer->regs + CUR_SIZE);
+	writel(cursor->pixmap.paddr, cursor->regs + CUR_PML);
+	writel(cursor->width, cursor->regs + CUR_PMP);
+	writel(cursor->height << 16 | cursor->width, cursor->regs + CUR_SIZE);
 
-	ydo = sti_vtg_get_line_number(*mode, layer->dst_y);
-	xdo = sti_vtg_get_pixel_number(*mode, layer->dst_y);
-	writel((ydo << 16) | xdo, layer->regs + CUR_VPO);
+	ydo = sti_vtg_get_line_number(*mode, plane->dst_y);
+	xdo = sti_vtg_get_pixel_number(*mode, plane->dst_y);
+	writel((ydo << 16) | xdo, cursor->regs + CUR_VPO);
 
 	return 0;
 }
 
-static int sti_cursor_disable_layer(struct sti_layer *layer)
+static int sti_cursor_disable_plane(struct sti_plane *plane)
 {
 	return 0;
 }
 
-static void sti_cursor_init(struct sti_layer *layer)
+static void sti_cursor_init(struct sti_cursor *cursor)
 {
-	struct sti_cursor *cursor = to_sti_cursor(layer);
 	unsigned short *base = cursor->clut;
 	unsigned int a, r, g, b;
 
@@ -205,16 +208,16 @@ static void sti_cursor_init(struct sti_layer *layer)
 						  (b * 5);
 }
 
-static const struct sti_layer_funcs cursor_ops = {
+static const struct sti_plane_funcs cursor_plane_ops = {
 	.get_formats = sti_cursor_get_formats,
 	.get_nb_formats = sti_cursor_get_nb_formats,
-	.init = sti_cursor_init,
-	.prepare = sti_cursor_prepare_layer,
-	.commit = sti_cursor_commit_layer,
-	.disable = sti_cursor_disable_layer,
+	.prepare = sti_cursor_prepare_plane,
+	.commit = sti_cursor_commit_plane,
+	.disable = sti_cursor_disable_plane,
 };
 
-struct sti_layer *sti_cursor_create(struct device *dev)
+struct sti_plane *sti_cursor_create(struct device *dev, int desc,
+				    void __iomem *baseaddr)
 {
 	struct sti_cursor *cursor;
 
@@ -236,7 +239,12 @@ struct sti_layer *sti_cursor_create(struct device *dev)
 		return NULL;
 	}
 
-	cursor->layer.ops = &cursor_ops;
+	cursor->dev = dev;
+	cursor->regs = baseaddr;
+	cursor->plane.desc = desc;
+	cursor->plane.ops = &cursor_plane_ops;
 
-	return (struct sti_layer *)cursor;
+	sti_cursor_init(cursor);
+
+	return &cursor->plane;
 }
diff --git a/drivers/gpu/drm/sti/sti_cursor.h b/drivers/gpu/drm/sti/sti_cursor.h
index 3c98274..db973b7 100644
--- a/drivers/gpu/drm/sti/sti_cursor.h
+++ b/drivers/gpu/drm/sti/sti_cursor.h
@@ -7,6 +7,7 @@
 #ifndef _STI_CURSOR_H_
 #define _STI_CURSOR_H_
 
-struct sti_layer *sti_cursor_create(struct device *dev);
+struct sti_plane *sti_cursor_create(struct device *dev, int desc,
+				    void __iomem *baseaddr);
 
 #endif
diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c
index 6b641c5..a489b04 100644
--- a/drivers/gpu/drm/sti/sti_drm_crtc.c
+++ b/drivers/gpu/drm/sti/sti_drm_crtc.c
@@ -41,7 +41,7 @@ static void sti_drm_crtc_prepare(struct drm_crtc *crtc)
 			DRM_INFO("Failed to prepare/enable compo_aux clk\n");
 	}
 
-	sti_mixer_clear_all_layers(mixer);
+	sti_mixer_clear_all_planes(mixer);
 }
 
 static void sti_drm_crtc_commit(struct drm_crtc *crtc)
@@ -49,23 +49,21 @@ static void sti_drm_crtc_commit(struct drm_crtc *crtc)
 	struct sti_mixer *mixer = to_sti_mixer(crtc);
 	struct device *dev = mixer->dev;
 	struct sti_compositor *compo = dev_get_drvdata(dev);
-	struct sti_layer *layer;
+	struct sti_plane *plane;
 
 	if ((!mixer || !compo)) {
-		DRM_ERROR("Can not find mixer or compositor)\n");
+		DRM_ERROR("Can't find mixer or compositor)\n");
 		return;
 	}
 
 	/* get GDP which is reserved to the CRTC FB */
-	layer = to_sti_layer(crtc->primary);
-	if (layer)
-		sti_layer_commit(layer);
-	else
-		DRM_ERROR("Can not find CRTC dedicated plane (GDP0)\n");
+	plane = to_sti_plane(crtc->primary);
+	if (!plane)
+		DRM_ERROR("Can't find CRTC dedicated plane (GDP0)\n");
 
-	/* Enable layer on mixer */
-	if (sti_mixer_set_layer_status(mixer, layer, true))
-		DRM_ERROR("Can not enable layer at mixer\n");
+	/* Enable plane on mixer */
+	if (sti_mixer_set_plane_status(mixer, plane, true))
+		DRM_ERROR("Cannot enable plane at mixer\n");
 
 	drm_crtc_vblank_on(crtc);
 }
@@ -122,7 +120,7 @@ sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
 
 	res = sti_mixer_active_video_area(mixer, &crtc->mode);
 	if (res) {
-		DRM_ERROR("Can not set active video area\n");
+		DRM_ERROR("Can't set active video area\n");
 		return -EINVAL;
 	}
 
@@ -164,7 +162,7 @@ sti_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
 	sti_drm_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
 }
 
-static void sti_drm_atomic_begin(struct drm_crtc *crtc)
+static void sti_drm_crtc_atomic_begin(struct drm_crtc *crtc)
 {
 	struct sti_mixer *mixer = to_sti_mixer(crtc);
 
@@ -178,7 +176,7 @@ static void sti_drm_atomic_begin(struct drm_crtc *crtc)
 	}
 }
 
-static void sti_drm_atomic_flush(struct drm_crtc *crtc)
+static void sti_drm_crtc_atomic_flush(struct drm_crtc *crtc)
 {
 }
 
@@ -191,8 +189,8 @@ static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
 	.mode_set_nofb = sti_drm_crtc_mode_set_nofb,
 	.mode_set_base = drm_helper_crtc_mode_set_base,
 	.disable = sti_drm_crtc_disable,
-	.atomic_begin = sti_drm_atomic_begin,
-	.atomic_flush = sti_drm_atomic_flush,
+	.atomic_begin = sti_drm_crtc_atomic_begin,
+	.atomic_flush = sti_drm_crtc_atomic_flush,
 };
 
 static void sti_drm_crtc_destroy(struct drm_crtc *crtc)
@@ -248,6 +246,8 @@ int sti_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
 	struct sti_compositor *compo = dev_priv->compo;
 	struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
 
+	DRM_DEBUG_DRIVER("\n");
+
 	if (sti_vtg_register_client(crtc == STI_MIXER_MAIN ?
 			compo->vtg_main : compo->vtg_aux,
 			vtg_vblank_nb, crtc)) {
@@ -309,7 +309,7 @@ int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
 	res = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
 			&sti_crtc_funcs);
 	if (res) {
-		DRM_ERROR("Can not initialze CRTC\n");
+		DRM_ERROR("Can't initialze CRTC\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/gpu/drm/sti/sti_drm_plane.c b/drivers/gpu/drm/sti/sti_drm_plane.c
index 5427bc2..0d16722 100644
--- a/drivers/gpu/drm/sti/sti_drm_plane.c
+++ b/drivers/gpu/drm/sti/sti_drm_plane.c
@@ -8,6 +8,8 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_plane_helper.h>
 
 #include "sti_compositor.h"
@@ -15,120 +17,165 @@
 #include "sti_drm_plane.h"
 #include "sti_vtg.h"
 
-/* (Background) < GDP0 < GDP1 < VID0 < VID1 < GDP2 < GDP3 < (ForeGround) */
-enum sti_layer_desc sti_layer_default_zorder[] = {
+/* (Background) < GDP0 < GDP1 < HQVDP0 < GDP2 < GDP3 < (ForeGround) */
+enum sti_plane_desc sti_plane_default_zorder[] = {
 	STI_GDP_0,
 	STI_GDP_1,
-	STI_VID_0,
-	STI_VID_1,
+	STI_HQVDP_0,
 	STI_GDP_2,
 	STI_GDP_3,
 };
 
-static int
-sti_drm_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)
+const char *sti_plane_to_str(struct sti_plane *plane)
 {
-	struct sti_layer *layer = to_sti_layer(plane);
-	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	switch (plane->desc) {
+	case STI_GDP_0:
+		return "GDP0";
+	case STI_GDP_1:
+		return "GDP1";
+	case STI_GDP_2:
+		return "GDP2";
+	case STI_GDP_3:
+		return "GDP3";
+	case STI_HQVDP_0:
+		return "HQVDP0";
+	case STI_CURSOR:
+		return "CURSOR";
+	default:
+		return "<UNKNOWN PLANE>";
+	}
+}
+EXPORT_SYMBOL(sti_plane_to_str);
+
+static int sti_plane_prepare(struct sti_plane *plane,
+			     struct drm_crtc *crtc,
+			     struct drm_framebuffer *fb,
+			     struct drm_display_mode *mode, int mixer_id,
+			     int dest_x, int dest_y, int dest_w, int dest_h,
+			     int src_x, int src_y, int src_w, int src_h)
+{
+	struct drm_gem_cma_object *cma_obj;
+	unsigned int i;
 	int res;
 
-	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
-		      crtc->base.id, sti_mixer_to_str(mixer),
-		      plane->base.id, sti_layer_to_str(layer));
-	DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n", crtc_w, crtc_h, crtc_x, crtc_y);
+	if (!plane || !fb || !mode) {
+		DRM_ERROR("Null fb, plane or mode\n");
+		return 1;
+	}
 
-	res = sti_mixer_set_layer_depth(mixer, layer);
-	if (res) {
-		DRM_ERROR("Can not set layer depth\n");
-		return res;
+	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+	if (!cma_obj) {
+		DRM_ERROR("Can't get CMA GEM object for fb\n");
+		return 1;
 	}
 
-	/* src_x are in 16.16 format. */
-	res = sti_layer_prepare(layer, crtc, fb,
-			&crtc->mode, mixer->id,
-			crtc_x, crtc_y, crtc_w, crtc_h,
-			src_x >> 16, src_y >> 16,
-			src_w >> 16, src_h >> 16);
-	if (res) {
-		DRM_ERROR("Layer prepare failed\n");
-		return res;
+	plane->fb = fb;
+	plane->mode = mode;
+	plane->mixer_id = mixer_id;
+	plane->dst_x = dest_x;
+	plane->dst_y = dest_y;
+	plane->dst_w = clamp_val(dest_w, 0, mode->crtc_hdisplay - dest_x);
+	plane->dst_h = clamp_val(dest_h, 0, mode->crtc_vdisplay - dest_y);
+	plane->src_x = src_x;
+	plane->src_y = src_y;
+	plane->src_w = src_w;
+	plane->src_h = src_h;
+	plane->format = fb->pixel_format;
+	plane->vaddr = cma_obj->vaddr;
+	plane->paddr = cma_obj->paddr;
+	for (i = 0; i < 4; i++) {
+		plane->pitches[i] = fb->pitches[i];
+		plane->offsets[i] = fb->offsets[i];
 	}
 
-	res = sti_layer_commit(layer);
-	if (res) {
-		DRM_ERROR("Layer commit failed\n");
-		return res;
+	DRM_DEBUG_DRIVER("%s is associated with mixer_id %d\n",
+			 sti_plane_to_str(plane),
+			 plane->mixer_id);
+	DRM_DEBUG_DRIVER("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
+			 sti_plane_to_str(plane),
+			 plane->dst_w, plane->dst_h, plane->dst_x, plane->dst_y,
+			 plane->src_w, plane->src_h, plane->src_x,
+			 plane->src_y);
+
+	DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
+			 (char *)&plane->format, (unsigned long)plane->paddr);
+
+	if (!plane->ops->prepare) {
+		DRM_ERROR("Cannot prepare\n");
+		return 1;
 	}
 
-	res = sti_mixer_set_layer_status(mixer, layer, true);
+	res = plane->ops->prepare(plane, !plane->enabled);
 	if (res) {
-		DRM_ERROR("Can not enable layer at mixer\n");
+		DRM_ERROR("Plane prepare failed\n");
 		return res;
 	}
 
+	plane->enabled = true;
+
 	return 0;
 }
 
-static int sti_drm_disable_plane(struct drm_plane *plane)
+static int sti_plane_commit(struct sti_plane *plane)
 {
-	struct sti_layer *layer;
-	struct sti_mixer *mixer;
-	int lay_res, mix_res;
+	if (!plane)
+		return 1;
 
-	if (!plane->crtc) {
-		DRM_DEBUG_DRIVER("drm plane:%d not enabled\n", plane->base.id);
-		return 0;
+	if (!plane->ops->commit) {
+		DRM_ERROR("Cannot commit\n");
+		return 1;
 	}
-	layer = to_sti_layer(plane);
-	mixer = to_sti_mixer(plane->crtc);
 
-	DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
-			plane->crtc->base.id, sti_mixer_to_str(mixer),
-			plane->base.id, sti_layer_to_str(layer));
+	return plane->ops->commit(plane);
+}
 
-	/* Disable layer at mixer level */
-	mix_res = sti_mixer_set_layer_status(mixer, layer, false);
-	if (mix_res)
-		DRM_ERROR("Can not disable layer at mixer\n");
+static int sti_plane_disable(struct sti_plane *plane)
+{
+	int res;
 
-	/* Wait a while to be sure that a Vsync event is received */
-	msleep(WAIT_NEXT_VSYNC_MS);
+	DRM_DEBUG_DRIVER("%s\n", sti_plane_to_str(plane));
+	if (!plane)
+		return 1;
 
-	/* Then disable layer itself */
-	lay_res = sti_layer_disable(layer);
-	if (lay_res)
-		DRM_ERROR("Layer disable failed\n");
+	if (!plane->enabled)
+		return 0;
 
-	if (lay_res || mix_res)
-		return -EINVAL;
+	if (!plane->ops->disable) {
+		DRM_ERROR("Cannot disable\n");
+		return 1;
+	}
+
+	res = plane->ops->disable(plane);
+	if (res) {
+		DRM_ERROR("Plane disable failed\n");
+		return res;
+	}
+
+	plane->enabled = false;
 
 	return 0;
 }
 
-static void sti_drm_plane_destroy(struct drm_plane *plane)
+static void sti_drm_plane_destroy(struct drm_plane *drm_plane)
 {
 	DRM_DEBUG_DRIVER("\n");
 
-	drm_plane_helper_disable(plane);
-	drm_plane_cleanup(plane);
+	drm_plane_helper_disable(drm_plane);
+	drm_plane_cleanup(drm_plane);
 }
 
-static int sti_drm_plane_set_property(struct drm_plane *plane,
+static int sti_drm_plane_set_property(struct drm_plane *drm_plane,
 				      struct drm_property *property,
 				      uint64_t val)
 {
-	struct drm_device *dev = plane->dev;
+	struct drm_device *dev = drm_plane->dev;
 	struct sti_drm_private *private = dev->dev_private;
-	struct sti_layer *layer = to_sti_layer(plane);
+	struct sti_plane *plane = to_sti_plane(drm_plane);
 
 	DRM_DEBUG_DRIVER("\n");
 
 	if (property == private->plane_zorder_property) {
-		layer->zorder = val;
+		plane->zorder = val;
 		return 0;
 	}
 
@@ -145,57 +192,105 @@ static struct drm_plane_funcs sti_drm_plane_funcs = {
 	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
 };
 
-static int sti_drm_plane_prepare_fb(struct drm_plane *plane,
-				  struct drm_framebuffer *fb,
-				  const struct drm_plane_state *new_state)
-{
-	return 0;
-}
-
-static void sti_drm_plane_cleanup_fb(struct drm_plane *plane,
-				   struct drm_framebuffer *fb,
-				   const struct drm_plane_state *old_fb)
-{
-}
-
-static int sti_drm_plane_atomic_check(struct drm_plane *plane,
+static int sti_drm_plane_atomic_check(struct drm_plane *drm_plane,
 				      struct drm_plane_state *state)
 {
 	return 0;
 }
 
-static void sti_drm_plane_atomic_update(struct drm_plane *plane,
+static void sti_drm_plane_atomic_update(struct drm_plane *drm_plane,
 					struct drm_plane_state *oldstate)
 {
-	struct drm_plane_state *state = plane->state;
+	struct drm_plane_state *state = drm_plane->state;
+	struct sti_plane *plane = to_sti_plane(drm_plane);
+	struct sti_mixer *mixer = to_sti_mixer(state->crtc);
+	int res;
+
+	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
+		      state->crtc->base.id, sti_mixer_to_str(mixer),
+		      drm_plane->base.id, sti_plane_to_str(plane));
+	DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n",
+		      state->crtc_w, state->crtc_h,
+		      state->crtc_x, state->crtc_y);
+
+	res = sti_mixer_set_plane_depth(mixer, plane);
+	if (res) {
+		DRM_ERROR("Cannot set plane depth\n");
+		return;
+	}
 
-	sti_drm_update_plane(plane, state->crtc, state->fb,
-			    state->crtc_x, state->crtc_y,
-			    state->crtc_w, state->crtc_h,
-			    state->src_x, state->src_y,
-			    state->src_w, state->src_h);
+	/* src_x are in 16.16 format */
+	res = sti_plane_prepare(plane, state->crtc, state->fb,
+				&state->crtc->mode, mixer->id,
+				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);
+	if (res) {
+		DRM_ERROR("Plane prepare failed\n");
+		return;
+	}
+
+	res = sti_plane_commit(plane);
+	if (res) {
+		DRM_ERROR("Plane commit failed\n");
+		return;
+	}
+
+	res = sti_mixer_set_plane_status(mixer, plane, true);
+	if (res) {
+		DRM_ERROR("Cannot enable plane at mixer\n");
+		return;
+	}
 }
 
-static void sti_drm_plane_atomic_disable(struct drm_plane *plane,
+static void sti_drm_plane_atomic_disable(struct drm_plane *drm_plane,
 					 struct drm_plane_state *oldstate)
 {
-	sti_drm_disable_plane(plane);
+	struct sti_plane *plane = to_sti_plane(drm_plane);
+	struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);
+	int res;
+
+	if (!drm_plane->crtc) {
+		DRM_DEBUG_DRIVER("drm plane:%d not enabled\n",
+				 drm_plane->base.id);
+		return;
+	}
+
+	DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
+			 drm_plane->crtc->base.id, sti_mixer_to_str(mixer),
+			 drm_plane->base.id, sti_plane_to_str(plane));
+
+	/* Disable plane at mixer level */
+	res = sti_mixer_set_plane_status(mixer, plane, false);
+	if (res) {
+		DRM_ERROR("Cannot disable plane at mixer\n");
+		return;
+	}
+
+	/* Wait a while to be sure that a Vsync event is received */
+	msleep(WAIT_NEXT_VSYNC_MS);
+
+	/* Then disable plane itself */
+	res = sti_plane_disable(plane);
+	if (res) {
+		DRM_ERROR("Plane disable failed\n");
+		return;
+	}
 }
 
 static const struct drm_plane_helper_funcs sti_drm_plane_helpers_funcs = {
-	.prepare_fb = sti_drm_plane_prepare_fb,
-	.cleanup_fb = sti_drm_plane_cleanup_fb,
 	.atomic_check = sti_drm_plane_atomic_check,
 	.atomic_update = sti_drm_plane_atomic_update,
 	.atomic_disable = sti_drm_plane_atomic_disable,
 };
 
-static void sti_drm_plane_attach_zorder_property(struct drm_plane *plane)
+static void sti_drm_plane_attach_zorder_property(struct drm_plane *drm_plane)
 {
-	struct drm_device *dev = plane->dev;
+	struct drm_device *dev = drm_plane->dev;
 	struct sti_drm_private *private = dev->dev_private;
+	struct sti_plane *plane = to_sti_plane(drm_plane);
 	struct drm_property *prop;
-	struct sti_layer *layer = to_sti_layer(plane);
 
 	prop = private->plane_zorder_property;
 	if (!prop) {
@@ -207,40 +302,43 @@ static void sti_drm_plane_attach_zorder_property(struct drm_plane *plane)
 		private->plane_zorder_property = prop;
 	}
 
-	drm_object_attach_property(&plane->base, prop, layer->zorder);
+	drm_object_attach_property(&drm_plane->base, prop, plane->zorder);
 }
 
 struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
-				     struct sti_layer *layer,
-				     unsigned int possible_crtcs,
-				     enum drm_plane_type type)
+				 struct sti_plane *plane,
+				 unsigned int possible_crtcs,
+				 enum drm_plane_type type)
 {
 	int err, i;
 
-	err = drm_universal_plane_init(dev, &layer->plane, possible_crtcs,
-			     &sti_drm_plane_funcs,
-			     sti_layer_get_formats(layer),
-			     sti_layer_get_nb_formats(layer), type);
+	err = drm_universal_plane_init(dev, &plane->drm_plane,
+				       possible_crtcs,
+				       &sti_drm_plane_funcs,
+				       plane->ops->get_formats(plane),
+				       plane->ops->get_nb_formats(plane),
+				       type);
 	if (err) {
-		DRM_ERROR("Failed to initialize plane\n");
+		DRM_ERROR("Failed to initialize universal plane\n");
 		return NULL;
 	}
 
-	drm_plane_helper_add(&layer->plane, &sti_drm_plane_helpers_funcs);
+	drm_plane_helper_add(&plane->drm_plane,
+			     &sti_drm_plane_helpers_funcs);
 
-	for (i = 0; i < ARRAY_SIZE(sti_layer_default_zorder); i++)
-		if (sti_layer_default_zorder[i] == layer->desc)
+	for (i = 0; i < ARRAY_SIZE(sti_plane_default_zorder); i++)
+		if (sti_plane_default_zorder[i] == plane->desc)
 			break;
 
-	layer->zorder = i + 1;
+	plane->zorder = i + 1;
 
 	if (type == DRM_PLANE_TYPE_OVERLAY)
-		sti_drm_plane_attach_zorder_property(&layer->plane);
+		sti_drm_plane_attach_zorder_property(&plane->drm_plane);
 
-	DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%llu\n",
-			 layer->plane.base.id,
-			 sti_layer_to_str(layer), layer->zorder);
+	DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%d\n",
+			 plane->drm_plane.base.id,
+			 sti_plane_to_str(plane), plane->zorder);
 
-	return &layer->plane;
+	return &plane->drm_plane;
 }
 EXPORT_SYMBOL(sti_drm_plane_init);
diff --git a/drivers/gpu/drm/sti/sti_drm_plane.h b/drivers/gpu/drm/sti/sti_drm_plane.h
index 4f19183..e547366 100644
--- a/drivers/gpu/drm/sti/sti_drm_plane.h
+++ b/drivers/gpu/drm/sti/sti_drm_plane.h
@@ -9,10 +9,97 @@
 
 #include <drm/drmP.h>
 
-struct sti_layer;
+#define to_sti_plane(x) container_of(x, struct sti_plane, drm_plane)
+
+#define STI_PLANE_TYPE_SHIFT 8
+#define STI_PLANE_TYPE_MASK (~((1 << STI_PLANE_TYPE_SHIFT) - 1))
+
+enum sti_plane_type {
+	STI_GDP = 1 << STI_PLANE_TYPE_SHIFT,
+	STI_VDP = 2 << STI_PLANE_TYPE_SHIFT,
+	STI_CUR = 3 << STI_PLANE_TYPE_SHIFT,
+	STI_BCK = 4 << STI_PLANE_TYPE_SHIFT
+};
+
+enum sti_plane_id_of_type {
+	STI_ID_0 = 0,
+	STI_ID_1 = 1,
+	STI_ID_2 = 2,
+	STI_ID_3 = 3
+};
+
+enum sti_plane_desc {
+	STI_GDP_0       = STI_GDP | STI_ID_0,
+	STI_GDP_1       = STI_GDP | STI_ID_1,
+	STI_GDP_2       = STI_GDP | STI_ID_2,
+	STI_GDP_3       = STI_GDP | STI_ID_3,
+	STI_HQVDP_0     = STI_VDP | STI_ID_0,
+	STI_CURSOR      = STI_CUR,
+	STI_BACK        = STI_BCK
+};
+
+/**
+ * STI plane structure
+ *
+ * @plane:              drm plane it is bound to (if any)
+ * @fb:                 drm fb it is bound to
+ * @mode:               display mode
+ * @desc:               plane type & id
+ * @ops:                plane functions
+ * @zorder:             plane z-order
+ * @mixer_id:           id of the mixer used to display the plane
+ * @enabled:            to know if the plane is active or not
+ * @src_x src_y:        coordinates of the input (fb) area
+ * @src_w src_h:        size of the input (fb) area
+ * @dst_x dst_y:        coordinates of the output (crtc) area
+ * @dst_w dst_h:        size of the output (crtc) area
+ * @format:             format
+ * @pitches:            pitch of 'planes' (eg: Y, U, V)
+ * @offsets:            offset of 'planes'
+ * @vaddr:              virtual address of the input buffer
+ * @paddr:              physical address of the input buffer
+ */
+struct sti_plane {
+	struct drm_plane drm_plane;
+	struct drm_framebuffer *fb;
+	struct drm_display_mode *mode;
+	enum sti_plane_desc desc;
+	const struct sti_plane_funcs *ops;
+	int zorder;
+	int mixer_id;
+	bool enabled;
+	int src_x, src_y;
+	int src_w, src_h;
+	int dst_x, dst_y;
+	int dst_w, dst_h;
+	uint32_t format;
+	unsigned int pitches[4];
+	unsigned int offsets[4];
+	void *vaddr;
+	dma_addr_t paddr;
+};
+
+/**
+ * STI plane functions structure
+ *
+ * @get_formats:     get plane supported formats
+ * @get_nb_formats:  get number of format supported
+ * @prepare:         prepare plane before rendering
+ * @commit:          set plane for rendering
+ * @disable:         disable plane
+ */
+struct sti_plane_funcs {
+	const uint32_t* (*get_formats)(struct sti_plane *plane);
+	unsigned int (*get_nb_formats)(struct sti_plane *plane);
+	int (*prepare)(struct sti_plane *plane, bool first_prepare);
+	int (*commit)(struct sti_plane *plane);
+	int (*disable)(struct sti_plane *plane);
+};
 
 struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
-		struct sti_layer *layer,
+		struct sti_plane *sti_plane,
 		unsigned int possible_crtcs,
 		enum drm_plane_type type);
+const char *sti_plane_to_str(struct sti_plane *plane);
+
 #endif
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
index 087906f..e94d0be 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -10,8 +10,8 @@
 #include <linux/dma-mapping.h>
 
 #include "sti_compositor.h"
+#include "sti_drm_plane.h"
 #include "sti_gdp.h"
-#include "sti_layer.h"
 #include "sti_vtg.h"
 
 #define ALPHASWITCH     BIT(6)
@@ -85,16 +85,20 @@ struct sti_gdp_node_list {
 /**
  * STI GDP structure
  *
- * @layer:		layer structure
+ * @sti_plane:          sti_plane structure
+ * @dev:                driver device
+ * @regs:               gdp registers
  * @clk_pix:            pixel clock for the current gdp
  * @clk_main_parent:    gdp parent clock if main path used
  * @clk_aux_parent:     gdp parent clock if aux path used
  * @vtg_field_nb:       callback for VTG FIELD (top or bottom) notification
  * @is_curr_top:        true if the current node processed is the top field
- * @node_list:		array of node list
+ * @node_list:          array of node list
  */
 struct sti_gdp {
-	struct sti_layer layer;
+	struct sti_plane plane;
+	struct device *dev;
+	void __iomem *regs;
 	struct clk *clk_pix;
 	struct clk *clk_main_parent;
 	struct clk *clk_aux_parent;
@@ -103,7 +107,7 @@ struct sti_gdp {
 	struct sti_gdp_node_list node_list[GDP_NODE_NB_BANK];
 };
 
-#define to_sti_gdp(x) container_of(x, struct sti_gdp, layer)
+#define to_sti_gdp(x) container_of(x, struct sti_gdp, plane)
 
 static const uint32_t gdp_supported_formats[] = {
 	DRM_FORMAT_XRGB8888,
@@ -120,12 +124,12 @@ static const uint32_t gdp_supported_formats[] = {
 	DRM_FORMAT_C8,
 };
 
-static const uint32_t *sti_gdp_get_formats(struct sti_layer *layer)
+static const uint32_t *sti_gdp_get_formats(struct sti_plane *plane)
 {
 	return gdp_supported_formats;
 }
 
-static unsigned int sti_gdp_get_nb_formats(struct sti_layer *layer)
+static unsigned int sti_gdp_get_nb_formats(struct sti_plane *plane)
 {
 	return ARRAY_SIZE(gdp_supported_formats);
 }
@@ -175,20 +179,20 @@ static int sti_gdp_get_alpharange(int format)
 
 /**
  * sti_gdp_get_free_nodes
- * @layer: gdp layer
+ * @plane: gdp plane
  *
  * Look for a GDP node list that is not currently read by the HW.
  *
  * RETURNS:
  * Pointer to the free GDP node list
  */
-static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_layer *layer)
+static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_plane *plane)
 {
 	int hw_nvn;
-	struct sti_gdp *gdp = to_sti_gdp(layer);
+	struct sti_gdp *gdp = to_sti_gdp(plane);
 	unsigned int i;
 
-	hw_nvn = readl(layer->regs + GAM_GDP_NVN_OFFSET);
+	hw_nvn = readl(gdp->regs + GAM_GDP_NVN_OFFSET);
 	if (!hw_nvn)
 		goto end;
 
@@ -199,7 +203,7 @@ static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_layer *layer)
 
 	/* in hazardious cases restart with the first node */
 	DRM_ERROR("inconsistent NVN for %s: 0x%08X\n",
-			sti_layer_to_str(layer), hw_nvn);
+			sti_plane_to_str(plane), hw_nvn);
 
 end:
 	return &gdp->node_list[0];
@@ -207,7 +211,7 @@ end:
 
 /**
  * sti_gdp_get_current_nodes
- * @layer: GDP layer
+ * @plane: GDP plane
  *
  * Look for GDP nodes that are currently read by the HW.
  *
@@ -215,13 +219,13 @@ end:
  * Pointer to the current GDP node list
  */
 static
-struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_layer *layer)
+struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_plane *plane)
 {
 	int hw_nvn;
-	struct sti_gdp *gdp = to_sti_gdp(layer);
+	struct sti_gdp *gdp = to_sti_gdp(plane);
 	unsigned int i;
 
-	hw_nvn = readl(layer->regs + GAM_GDP_NVN_OFFSET);
+	hw_nvn = readl(gdp->regs + GAM_GDP_NVN_OFFSET);
 	if (!hw_nvn)
 		goto end;
 
@@ -232,28 +236,28 @@ struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_layer *layer)
 
 end:
 	DRM_DEBUG_DRIVER("Warning, NVN 0x%08X for %s does not match any node\n",
-				hw_nvn, sti_layer_to_str(layer));
+				hw_nvn, sti_plane_to_str(plane));
 
 	return NULL;
 }
 
 /**
- * sti_gdp_prepare_layer
- * @lay: gdp layer
+ * sti_gdp_prepare
+ * @plane: gdp plane
  * @first_prepare: true if it is the first time this function is called
  *
- * Update the free GDP node list according to the layer properties.
+ * Update the free GDP node list according to the plane properties.
  *
  * RETURNS:
  * 0 on success.
  */
-static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
+static int sti_gdp_prepare(struct sti_plane *plane, bool first_prepare)
 {
 	struct sti_gdp_node_list *list;
 	struct sti_gdp_node *top_field, *btm_field;
-	struct drm_display_mode *mode = layer->mode;
-	struct device *dev = layer->dev;
-	struct sti_gdp *gdp = to_sti_gdp(layer);
+	struct drm_display_mode *mode = plane->mode;
+	struct sti_gdp *gdp = to_sti_gdp(plane);
+	struct device *dev = gdp->dev;
 	struct sti_compositor *compo = dev_get_drvdata(dev);
 	int format;
 	unsigned int depth, bpp;
@@ -261,20 +265,20 @@ static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
 	int res;
 	u32 ydo, xdo, yds, xds;
 
-	list = sti_gdp_get_free_nodes(layer);
+	list = sti_gdp_get_free_nodes(plane);
 	top_field = list->top_field;
 	btm_field = list->btm_field;
 
 	dev_dbg(dev, "%s %s top_node:0x%p btm_node:0x%p\n", __func__,
-			sti_layer_to_str(layer), top_field, btm_field);
+			sti_plane_to_str(plane), top_field, btm_field);
 
-	/* Build the top field from layer params */
+	/* Build the top field from plane params */
 	top_field->gam_gdp_agc = GAM_GDP_AGC_FULL_RANGE;
 	top_field->gam_gdp_ctl = WAIT_NEXT_VSYNC;
-	format = sti_gdp_fourcc2format(layer->format);
+	format = sti_gdp_fourcc2format(plane->format);
 	if (format == -1) {
 		DRM_ERROR("Format not supported by GDP %.4s\n",
-			  (char *)&layer->format);
+			  (char *)&plane->format);
 		return 1;
 	}
 	top_field->gam_gdp_ctl |= format;
@@ -282,22 +286,22 @@ static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
 	top_field->gam_gdp_ppt &= ~GAM_GDP_PPT_IGNORE;
 
 	/* pixel memory location */
-	drm_fb_get_bpp_depth(layer->format, &depth, &bpp);
-	top_field->gam_gdp_pml = (u32) layer->paddr + layer->offsets[0];
-	top_field->gam_gdp_pml += layer->src_x * (bpp >> 3);
-	top_field->gam_gdp_pml += layer->src_y * layer->pitches[0];
+	drm_fb_get_bpp_depth(plane->format, &depth, &bpp);
+	top_field->gam_gdp_pml = (u32)plane->paddr + plane->offsets[0];
+	top_field->gam_gdp_pml += plane->src_x * (bpp >> 3);
+	top_field->gam_gdp_pml += plane->src_y * plane->pitches[0];
 
 	/* input parameters */
-	top_field->gam_gdp_pmp = layer->pitches[0];
+	top_field->gam_gdp_pmp = plane->pitches[0];
 	top_field->gam_gdp_size =
-	    clamp_val(layer->src_h, 0, GAM_GDP_SIZE_MAX) << 16 |
-	    clamp_val(layer->src_w, 0, GAM_GDP_SIZE_MAX);
+	    clamp_val(plane->src_h, 0, GAM_GDP_SIZE_MAX) << 16 |
+	    clamp_val(plane->src_w, 0, GAM_GDP_SIZE_MAX);
 
 	/* output parameters */
-	ydo = sti_vtg_get_line_number(*mode, layer->dst_y);
-	yds = sti_vtg_get_line_number(*mode, layer->dst_y + layer->dst_h - 1);
-	xdo = sti_vtg_get_pixel_number(*mode, layer->dst_x);
-	xds = sti_vtg_get_pixel_number(*mode, layer->dst_x + layer->dst_w - 1);
+	ydo = sti_vtg_get_line_number(*mode, plane->dst_y);
+	yds = sti_vtg_get_line_number(*mode, plane->dst_y + plane->dst_h - 1);
+	xdo = sti_vtg_get_pixel_number(*mode, plane->dst_x);
+	xds = sti_vtg_get_pixel_number(*mode, plane->dst_x + plane->dst_w - 1);
 	top_field->gam_gdp_vpo = (ydo << 16) | xdo;
 	top_field->gam_gdp_vps = (yds << 16) | xds;
 
@@ -307,15 +311,15 @@ static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
 	btm_field->gam_gdp_nvn = list->top_field_paddr;
 
 	/* Interlaced mode */
-	if (layer->mode->flags & DRM_MODE_FLAG_INTERLACE)
+	if (plane->mode->flags & DRM_MODE_FLAG_INTERLACE)
 		btm_field->gam_gdp_pml = top_field->gam_gdp_pml +
-		    layer->pitches[0];
+		    plane->pitches[0];
 
 	if (first_prepare) {
 		/* Register gdp callback */
-		if (sti_vtg_register_client(layer->mixer_id == STI_MIXER_MAIN ?
+		if (sti_vtg_register_client(plane->mixer_id == STI_MIXER_MAIN ?
 				compo->vtg_main : compo->vtg_aux,
-				&gdp->vtg_field_nb, layer->mixer_id)) {
+				&gdp->vtg_field_nb, plane->mixer_id)) {
 			DRM_ERROR("Cannot register VTG notifier\n");
 			return 1;
 		}
@@ -325,7 +329,7 @@ static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
 			struct clk *clkp;
 			/* According to the mixer used, the gdp pixel clock
 			 * should have a different parent clock. */
-			if (layer->mixer_id == STI_MIXER_MAIN)
+			if (plane->mixer_id == STI_MIXER_MAIN)
 				clkp = gdp->clk_main_parent;
 			else
 				clkp = gdp->clk_aux_parent;
@@ -351,8 +355,8 @@ static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
 }
 
 /**
- * sti_gdp_commit_layer
- * @lay: gdp layer
+ * sti_gdp_commit
+ * @plane: gdp plane
  *
  * Update the NVN field of the 'right' field of the current GDP node (being
  * used by the HW) with the address of the updated ('free') top field GDP node.
@@ -365,38 +369,38 @@ static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
  * RETURNS:
  * 0 on success.
  */
-static int sti_gdp_commit_layer(struct sti_layer *layer)
+static int sti_gdp_commit(struct sti_plane *plane)
 {
-	struct sti_gdp_node_list *updated_list = sti_gdp_get_free_nodes(layer);
+	struct sti_gdp_node_list *updated_list = sti_gdp_get_free_nodes(plane);
 	struct sti_gdp_node *updated_top_node = updated_list->top_field;
 	struct sti_gdp_node *updated_btm_node = updated_list->btm_field;
-	struct sti_gdp *gdp = to_sti_gdp(layer);
+	struct sti_gdp *gdp = to_sti_gdp(plane);
 	u32 dma_updated_top = updated_list->top_field_paddr;
 	u32 dma_updated_btm = updated_list->btm_field_paddr;
-	struct sti_gdp_node_list *curr_list = sti_gdp_get_current_nodes(layer);
+	struct sti_gdp_node_list *curr_list = sti_gdp_get_current_nodes(plane);
 
-	dev_dbg(layer->dev, "%s %s top/btm_node:0x%p/0x%p\n", __func__,
-			sti_layer_to_str(layer),
-			updated_top_node, updated_btm_node);
-	dev_dbg(layer->dev, "Current NVN:0x%X\n",
-		readl(layer->regs + GAM_GDP_NVN_OFFSET));
-	dev_dbg(layer->dev, "Posted buff: %lx current buff: %x\n",
-		(unsigned long)layer->paddr,
-		readl(layer->regs + GAM_GDP_PML_OFFSET));
+	dev_dbg(gdp->dev, "%s %s top/btm_node:0x%p/0x%p\n", __func__,
+		sti_plane_to_str(plane),
+		updated_top_node, updated_btm_node);
+	dev_dbg(gdp->dev, "Current NVN:0x%X\n",
+		readl(gdp->regs + GAM_GDP_NVN_OFFSET));
+	dev_dbg(gdp->dev, "Posted buff: %lx current buff: %x\n",
+		(unsigned long)plane->paddr,
+		readl(gdp->regs + GAM_GDP_PML_OFFSET));
 
 	if (curr_list == NULL) {
 		/* First update or invalid node should directly write in the
 		 * hw register */
 		DRM_DEBUG_DRIVER("%s first update (or invalid node)",
-				sti_layer_to_str(layer));
+				sti_plane_to_str(plane));
 
 		writel(gdp->is_curr_top == true ?
 				dma_updated_btm : dma_updated_top,
-				layer->regs + GAM_GDP_NVN_OFFSET);
+				gdp->regs + GAM_GDP_NVN_OFFSET);
 		return 0;
 	}
 
-	if (layer->mode->flags & DRM_MODE_FLAG_INTERLACE) {
+	if (plane->mode->flags & DRM_MODE_FLAG_INTERLACE) {
 		if (gdp->is_curr_top == true) {
 			/* Do not update in the middle of the frame, but
 			 * postpone the update after the bottom field has
@@ -405,32 +409,32 @@ static int sti_gdp_commit_layer(struct sti_layer *layer)
 		} else {
 			/* Direct update to avoid one frame delay */
 			writel(dma_updated_top,
-				layer->regs + GAM_GDP_NVN_OFFSET);
+				gdp->regs + GAM_GDP_NVN_OFFSET);
 		}
 	} else {
 		/* Direct update for progressive to avoid one frame delay */
-		writel(dma_updated_top, layer->regs + GAM_GDP_NVN_OFFSET);
+		writel(dma_updated_top, gdp->regs + GAM_GDP_NVN_OFFSET);
 	}
 
 	return 0;
 }
 
 /**
- * sti_gdp_disable_layer
- * @lay: gdp layer
+ * sti_gdp_disable
+ * @plane: gdp plane
  *
  * Disable a GDP.
  *
  * RETURNS:
  * 0 on success.
  */
-static int sti_gdp_disable_layer(struct sti_layer *layer)
+static int sti_gdp_disable(struct sti_plane *plane)
 {
 	unsigned int i;
-	struct sti_gdp *gdp = to_sti_gdp(layer);
-	struct sti_compositor *compo = dev_get_drvdata(layer->dev);
+	struct sti_gdp *gdp = to_sti_gdp(plane);
+	struct sti_compositor *compo = dev_get_drvdata(gdp->dev);
 
-	DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer));
+	DRM_DEBUG_DRIVER("%s\n", sti_plane_to_str(plane));
 
 	/* Set the nodes as 'to be ignored on mixer' */
 	for (i = 0; i < GDP_NODE_NB_BANK; i++) {
@@ -438,7 +442,7 @@ static int sti_gdp_disable_layer(struct sti_layer *layer)
 		gdp->node_list[i].btm_field->gam_gdp_ppt |= GAM_GDP_PPT_IGNORE;
 	}
 
-	if (sti_vtg_unregister_client(layer->mixer_id == STI_MIXER_MAIN ?
+	if (sti_vtg_unregister_client(plane->mixer_id == STI_MIXER_MAIN ?
 			compo->vtg_main : compo->vtg_aux, &gdp->vtg_field_nb))
 		DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
 
@@ -479,10 +483,9 @@ int sti_gdp_field_cb(struct notifier_block *nb,
 	return 0;
 }
 
-static void sti_gdp_init(struct sti_layer *layer)
+static void sti_gdp_init(struct sti_gdp *gdp)
 {
-	struct sti_gdp *gdp = to_sti_gdp(layer);
-	struct device_node *np = layer->dev->of_node;
+	struct device_node *np = gdp->dev->of_node;
 	dma_addr_t dma_addr;
 	void *base;
 	unsigned int i, size;
@@ -490,8 +493,8 @@ static void sti_gdp_init(struct sti_layer *layer)
 	/* Allocate all the nodes within a single memory page */
 	size = sizeof(struct sti_gdp_node) *
 	    GDP_NODE_PER_FIELD * GDP_NODE_NB_BANK;
-	base = dma_alloc_writecombine(layer->dev,
-			size, &dma_addr, GFP_KERNEL | GFP_DMA);
+	base = dma_alloc_writecombine(gdp->dev,
+				      size, &dma_addr, GFP_KERNEL | GFP_DMA);
 
 	if (!base) {
 		DRM_ERROR("Failed to allocate memory for GDP node\n");
@@ -526,7 +529,7 @@ static void sti_gdp_init(struct sti_layer *layer)
 		/* GDP of STiH407 chip have its own pixel clock */
 		char *clk_name;
 
-		switch (layer->desc) {
+		switch (gdp->plane.desc) {
 		case STI_GDP_0:
 			clk_name = "pix_gdp1";
 			break;
@@ -544,30 +547,30 @@ static void sti_gdp_init(struct sti_layer *layer)
 			return;
 		}
 
-		gdp->clk_pix = devm_clk_get(layer->dev, clk_name);
+		gdp->clk_pix = devm_clk_get(gdp->dev, clk_name);
 		if (IS_ERR(gdp->clk_pix))
 			DRM_ERROR("Cannot get %s clock\n", clk_name);
 
-		gdp->clk_main_parent = devm_clk_get(layer->dev, "main_parent");
+		gdp->clk_main_parent = devm_clk_get(gdp->dev, "main_parent");
 		if (IS_ERR(gdp->clk_main_parent))
 			DRM_ERROR("Cannot get main_parent clock\n");
 
-		gdp->clk_aux_parent = devm_clk_get(layer->dev, "aux_parent");
+		gdp->clk_aux_parent = devm_clk_get(gdp->dev, "aux_parent");
 		if (IS_ERR(gdp->clk_aux_parent))
 			DRM_ERROR("Cannot get aux_parent clock\n");
 	}
 }
 
-static const struct sti_layer_funcs gdp_ops = {
+static const struct sti_plane_funcs gdp_plane_ops = {
 	.get_formats = sti_gdp_get_formats,
 	.get_nb_formats = sti_gdp_get_nb_formats,
-	.init = sti_gdp_init,
-	.prepare = sti_gdp_prepare_layer,
-	.commit = sti_gdp_commit_layer,
-	.disable = sti_gdp_disable_layer,
+	.prepare = sti_gdp_prepare,
+	.commit = sti_gdp_commit,
+	.disable = sti_gdp_disable,
 };
 
-struct sti_layer *sti_gdp_create(struct device *dev, int id)
+struct sti_plane *sti_gdp_create(struct device *dev, int desc,
+				 void __iomem *baseaddr)
 {
 	struct sti_gdp *gdp;
 
@@ -577,8 +580,14 @@ struct sti_layer *sti_gdp_create(struct device *dev, int id)
 		return NULL;
 	}
 
-	gdp->layer.ops = &gdp_ops;
+	gdp->dev = dev;
+	gdp->regs = baseaddr;
+	gdp->plane.desc = desc;
+	gdp->plane.ops = &gdp_plane_ops;
+
 	gdp->vtg_field_nb.notifier_call = sti_gdp_field_cb;
 
-	return (struct sti_layer *)gdp;
+	sti_gdp_init(gdp);
+
+	return &gdp->plane;
 }
diff --git a/drivers/gpu/drm/sti/sti_gdp.h b/drivers/gpu/drm/sti/sti_gdp.h
index 1dab682..01818ea 100644
--- a/drivers/gpu/drm/sti/sti_gdp.h
+++ b/drivers/gpu/drm/sti/sti_gdp.h
@@ -11,6 +11,7 @@
 
 #include <linux/types.h>
 
-struct sti_layer *sti_gdp_create(struct device *dev, int id);
+struct sti_plane *sti_gdp_create(struct device *dev, int desc,
+				 void __iomem *baseaddr);
 
 #endif
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 06595e9..09e29e4 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -588,7 +588,7 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
 	return count;
 
 fail:
-	DRM_ERROR("Can not read HDMI EDID\n");
+	DRM_ERROR("Can't read HDMI EDID\n");
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index b0eb62d..54e8c2f 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -14,9 +14,7 @@
 #include <drm/drmP.h>
 
 #include "sti_drm_plane.h"
-#include "sti_hqvdp.h"
 #include "sti_hqvdp_lut.h"
-#include "sti_layer.h"
 #include "sti_vtg.h"
 
 /* Firmware name */
@@ -322,8 +320,7 @@ struct sti_hqvdp_cmd {
  * @dev:               driver device
  * @drm_dev:           the drm device
  * @regs:              registers
- * @layer:             layer structure for hqvdp it self
- * @vid_plane:         VID plug used as link with compositor IP
+ * @plane:             plane structure for hqvdp it self
  * @clk:               IP clock
  * @clk_pix_main:      pix main clock
  * @reset:             reset control
@@ -334,13 +331,13 @@ struct sti_hqvdp_cmd {
  * @hqvdp_cmd:         buffer of commands
  * @hqvdp_cmd_paddr:   physical address of hqvdp_cmd
  * @vtg:               vtg for main data path
+ * @xp70_initialized:  true if xp70 is already initialized
  */
 struct sti_hqvdp {
 	struct device *dev;
 	struct drm_device *drm_dev;
 	void __iomem *regs;
-	struct sti_layer layer;
-	struct drm_plane *vid_plane;
+	struct sti_plane plane;
 	struct clk *clk;
 	struct clk *clk_pix_main;
 	struct reset_control *reset;
@@ -351,20 +348,21 @@ struct sti_hqvdp {
 	void *hqvdp_cmd;
 	dma_addr_t hqvdp_cmd_paddr;
 	struct sti_vtg *vtg;
+	bool xp70_initialized;
 };
 
-#define to_sti_hqvdp(x) container_of(x, struct sti_hqvdp, layer)
+#define to_sti_hqvdp(x) container_of(x, struct sti_hqvdp, plane)
 
 static const uint32_t hqvdp_supported_formats[] = {
 	DRM_FORMAT_NV12,
 };
 
-static const uint32_t *sti_hqvdp_get_formats(struct sti_layer *layer)
+static const uint32_t *sti_hqvdp_get_formats(struct sti_plane *plane)
 {
 	return hqvdp_supported_formats;
 }
 
-static unsigned int sti_hqvdp_get_nb_formats(struct sti_layer *layer)
+static unsigned int sti_hqvdp_get_nb_formats(struct sti_plane *plane)
 {
 	return ARRAY_SIZE(hqvdp_supported_formats);
 }
@@ -484,7 +482,7 @@ static void sti_hqvdp_update_hvsrc(enum sti_hvsrc_orient orient, int scale,
 
 /**
  * sti_hqvdp_check_hw_scaling
- * @layer: hqvdp layer
+ * @plane: hqvdp plane
  *
  * Check if the HW is able to perform the scaling request
  * The firmware scaling limitation is "CEIL(1/Zy) <= FLOOR(LFW)" where:
@@ -498,23 +496,23 @@ static void sti_hqvdp_update_hvsrc(enum sti_hvsrc_orient orient, int scale,
  * RETURNS:
  * True if the HW can scale.
  */
-static bool sti_hqvdp_check_hw_scaling(struct sti_layer *layer)
+static bool sti_hqvdp_check_hw_scaling(struct sti_plane *plane)
 {
-	struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer);
+	struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
 	unsigned long lfw;
 	unsigned int inv_zy;
 
-	lfw = layer->mode->htotal * (clk_get_rate(hqvdp->clk) / 1000000);
-	lfw /= max(layer->src_w, layer->dst_w) * layer->mode->clock / 1000;
+	lfw = plane->mode->htotal * (clk_get_rate(hqvdp->clk) / 1000000);
+	lfw /= max(plane->src_w, plane->dst_w) * plane->mode->clock / 1000;
 
-	inv_zy = DIV_ROUND_UP(layer->src_h, layer->dst_h);
+	inv_zy = DIV_ROUND_UP(plane->src_h, plane->dst_h);
 
 	return (inv_zy <= lfw) ? true : false;
 }
 
 /**
- * sti_hqvdp_prepare_layer
- * @layer: hqvdp layer
+ * sti_hqvdp_prepare
+ * @plane: hqvdp plane
  * @first_prepare: true if it is the first time this function is called
  *
  * Prepares a command for the firmware
@@ -522,22 +520,14 @@ static bool sti_hqvdp_check_hw_scaling(struct sti_layer *layer)
  * RETURNS:
  * 0 on success.
  */
-static int sti_hqvdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
+static int sti_hqvdp_prepare(struct sti_plane *plane, bool first_prepare)
 {
-	struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer);
+	struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
 	struct sti_hqvdp_cmd *cmd;
 	int scale_h, scale_v;
 	int cmd_offset;
 
-	dev_dbg(hqvdp->dev, "%s %s\n", __func__, sti_layer_to_str(layer));
-
-	/* prepare and commit VID plane */
-	hqvdp->vid_plane->funcs->update_plane(hqvdp->vid_plane,
-					layer->crtc, layer->fb,
-					layer->dst_x, layer->dst_y,
-					layer->dst_w, layer->dst_h,
-					layer->src_x, layer->src_y,
-					layer->src_w, layer->src_h);
+	dev_dbg(hqvdp->dev, "%s %s\n", __func__, sti_plane_to_str(plane));
 
 	cmd_offset = sti_hqvdp_get_free_cmd(hqvdp);
 	if (cmd_offset == -1) {
@@ -546,7 +536,7 @@ static int sti_hqvdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
 	}
 	cmd = hqvdp->hqvdp_cmd + cmd_offset;
 
-	if (!sti_hqvdp_check_hw_scaling(layer)) {
+	if (!sti_hqvdp_check_hw_scaling(plane)) {
 		DRM_ERROR("Scaling beyond HW capabilities\n");
 		return -EINVAL;
 	}
@@ -565,42 +555,42 @@ static int sti_hqvdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
 	cmd->iqi.pxf_conf = IQI_PXF_CONF_DFLT;
 
 	/* Buffer planes address */
-	cmd->top.current_luma = (u32) layer->paddr + layer->offsets[0];
-	cmd->top.current_chroma = (u32) layer->paddr + layer->offsets[1];
+	cmd->top.current_luma = (u32)plane->paddr + plane->offsets[0];
+	cmd->top.current_chroma = (u32)plane->paddr + plane->offsets[1];
 
 	/* Pitches */
 	cmd->top.luma_processed_pitch = cmd->top.luma_src_pitch =
-			layer->pitches[0];
+			plane->pitches[0];
 	cmd->top.chroma_processed_pitch = cmd->top.chroma_src_pitch =
-			layer->pitches[1];
+			plane->pitches[1];
 
 	/* Input / output size
 	 * Align to upper even value */
-	layer->dst_w = ALIGN(layer->dst_w, 2);
-	layer->dst_h = ALIGN(layer->dst_h, 2);
+	plane->dst_w = ALIGN(plane->dst_w, 2);
+	plane->dst_h = ALIGN(plane->dst_h, 2);
 
-	if ((layer->src_w > MAX_WIDTH) || (layer->src_w < MIN_WIDTH) ||
-	    (layer->src_h > MAX_HEIGHT) || (layer->src_h < MIN_HEIGHT) ||
-	    (layer->dst_w > MAX_WIDTH) || (layer->dst_w < MIN_WIDTH) ||
-	    (layer->dst_h > MAX_HEIGHT) || (layer->dst_h < MIN_HEIGHT)) {
+	if ((plane->src_w > MAX_WIDTH) || (plane->src_w < MIN_WIDTH) ||
+	    (plane->src_h > MAX_HEIGHT) || (plane->src_h < MIN_HEIGHT) ||
+	    (plane->dst_w > MAX_WIDTH) || (plane->dst_w < MIN_WIDTH) ||
+	    (plane->dst_h > MAX_HEIGHT) || (plane->dst_h < MIN_HEIGHT)) {
 		DRM_ERROR("Invalid in/out size %dx%d -> %dx%d\n",
-				layer->src_w, layer->src_h,
-				layer->dst_w, layer->dst_h);
+				plane->src_w, plane->src_h,
+				plane->dst_w, plane->dst_h);
 		return -EINVAL;
 	}
 	cmd->top.input_viewport_size = cmd->top.input_frame_size =
-			layer->src_h << 16 | layer->src_w;
-	cmd->hvsrc.output_picture_size = layer->dst_h << 16 | layer->dst_w;
-	cmd->top.input_viewport_ori = layer->src_y << 16 | layer->src_x;
+			plane->src_h << 16 | plane->src_w;
+	cmd->hvsrc.output_picture_size = plane->dst_h << 16 | plane->dst_w;
+	cmd->top.input_viewport_ori = plane->src_y << 16 | plane->src_x;
 
 	/* Handle interlaced */
-	if (layer->fb->flags & DRM_MODE_FB_INTERLACED) {
+	if (plane->fb->flags & DRM_MODE_FB_INTERLACED) {
 		/* Top field to display */
 		cmd->top.config = TOP_CONFIG_INTER_TOP;
 
 		/* Update pitches and vert size */
-		cmd->top.input_frame_size = (layer->src_h / 2) << 16 |
-					     layer->src_w;
+		cmd->top.input_frame_size = (plane->src_h / 2) << 16 |
+					     plane->src_w;
 		cmd->top.luma_processed_pitch *= 2;
 		cmd->top.luma_src_pitch *= 2;
 		cmd->top.chroma_processed_pitch *= 2;
@@ -613,10 +603,10 @@ static int sti_hqvdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
 	}
 
 	/* Update hvsrc lut coef */
-	scale_h = SCALE_FACTOR * layer->dst_w / layer->src_w;
+	scale_h = SCALE_FACTOR * plane->dst_w / plane->src_w;
 	sti_hqvdp_update_hvsrc(HVSRC_HORI, scale_h, &cmd->hvsrc);
 
-	scale_v = SCALE_FACTOR * layer->dst_h / layer->src_h;
+	scale_v = SCALE_FACTOR * plane->dst_h / plane->src_h;
 	sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc);
 
 	if (first_prepare) {
@@ -627,9 +617,9 @@ static int sti_hqvdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
 		}
 
 		/* Register VTG Vsync callback to handle bottom fields */
-		if ((layer->fb->flags & DRM_MODE_FB_INTERLACED) &&
-				sti_vtg_register_client(hqvdp->vtg,
-					&hqvdp->vtg_nb, layer->mixer_id)) {
+		if ((plane->fb->flags & DRM_MODE_FB_INTERLACED) &&
+		    sti_vtg_register_client(hqvdp->vtg, &hqvdp->vtg_nb,
+					    plane->mixer_id)) {
 			DRM_ERROR("Cannot register VTG notifier\n");
 			return -ENXIO;
 		}
@@ -638,12 +628,21 @@ static int sti_hqvdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
 	return 0;
 }
 
-static int sti_hqvdp_commit_layer(struct sti_layer *layer)
+/**
+ * sti_hqvdp_commit
+ * @plane: hqvdp plane
+ *
+ * Enables the HQVDP plane
+ *
+ * RETURNS:
+ * 0 on success.
+ */
+static int sti_hqvdp_commit(struct sti_plane *plane)
 {
-	struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer);
+	struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
 	int cmd_offset;
 
-	dev_dbg(hqvdp->dev, "%s %s\n", __func__, sti_layer_to_str(layer));
+	dev_dbg(hqvdp->dev, "%s %s\n", __func__, sti_plane_to_str(plane));
 
 	cmd_offset = sti_hqvdp_get_free_cmd(hqvdp);
 	if (cmd_offset == -1) {
@@ -657,7 +656,7 @@ static int sti_hqvdp_commit_layer(struct sti_layer *layer)
 	hqvdp->curr_field_count++;
 
 	/* Interlaced : get ready to display the bottom field at next Vsync */
-	if (layer->fb->flags & DRM_MODE_FB_INTERLACED)
+	if (plane->fb->flags & DRM_MODE_FB_INTERLACED)
 		hqvdp->btm_field_pending = true;
 
 	dev_dbg(hqvdp->dev, "%s Posted command:0x%x\n",
@@ -666,16 +665,25 @@ static int sti_hqvdp_commit_layer(struct sti_layer *layer)
 	return 0;
 }
 
-static int sti_hqvdp_disable_layer(struct sti_layer *layer)
+/**
+ * sti_hqvdp_disable
+ * @plane: hqvdp plane
+ *
+ * Disables the HQVDP plane
+ *
+ * RETURNS:
+ * 0 on success.
+ */
+static int sti_hqvdp_disable(struct sti_plane *plane)
 {
-	struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer);
+	struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
 	int i;
 
-	DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer));
+	DRM_DEBUG_DRIVER("%s\n", sti_plane_to_str(plane));
 
 	/* Unregister VTG Vsync callback */
-	if ((layer->fb->flags & DRM_MODE_FB_INTERLACED) &&
-		sti_vtg_unregister_client(hqvdp->vtg, &hqvdp->vtg_nb))
+	if ((plane->fb->flags & DRM_MODE_FB_INTERLACED) &&
+	    sti_vtg_unregister_client(hqvdp->vtg, &hqvdp->vtg_nb))
 		DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
 
 	/* Set next cmd to NULL */
@@ -696,9 +704,6 @@ static int sti_hqvdp_disable_layer(struct sti_layer *layer)
 		return -ENXIO;
 	}
 
-	/* disable VID plane */
-	hqvdp->vid_plane->funcs->disable_plane(hqvdp->vid_plane);
-
 	return 0;
 }
 
@@ -758,32 +763,10 @@ int sti_hqvdp_vtg_cb(struct notifier_block *nb, unsigned long evt, void *data)
 	return 0;
 }
 
-static struct drm_plane *sti_hqvdp_find_vid(struct drm_device *dev, int id)
-{
-	struct drm_plane *plane;
-
-	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
-		struct sti_layer *layer = to_sti_layer(plane);
-
-		if (layer->desc == id)
-			return plane;
-	}
-
-	return NULL;
-}
-
-static void sti_hqvd_init(struct sti_layer *layer)
+static void sti_hqvdp_init(struct sti_hqvdp *hqvdp)
 {
-	struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer);
 	int size;
 
-	/* find the plane macthing with vid 0 */
-	hqvdp->vid_plane = sti_hqvdp_find_vid(hqvdp->drm_dev, STI_VID_0);
-	if (!hqvdp->vid_plane) {
-		DRM_ERROR("Cannot find Main video layer\n");
-		return;
-	}
-
 	hqvdp->vtg_nb.notifier_call = sti_hqvdp_vtg_cb;
 
 	/* Allocate memory for the VDP commands */
@@ -799,24 +782,25 @@ static void sti_hqvd_init(struct sti_layer *layer)
 	memset(hqvdp->hqvdp_cmd, 0, size);
 }
 
-static const struct sti_layer_funcs hqvdp_ops = {
+static const struct sti_plane_funcs hqvdp_plane_ops = {
 	.get_formats = sti_hqvdp_get_formats,
 	.get_nb_formats = sti_hqvdp_get_nb_formats,
-	.init = sti_hqvd_init,
-	.prepare = sti_hqvdp_prepare_layer,
-	.commit = sti_hqvdp_commit_layer,
-	.disable = sti_hqvdp_disable_layer,
+	.prepare = sti_hqvdp_prepare,
+	.commit = sti_hqvdp_commit,
+	.disable = sti_hqvdp_disable,
 };
 
-struct sti_layer *sti_hqvdp_create(struct device *dev)
+struct sti_plane *sti_hqvdp_create(struct device *dev, int desc)
 {
 	struct sti_hqvdp *hqvdp = dev_get_drvdata(dev);
 
-	hqvdp->layer.ops = &hqvdp_ops;
+	hqvdp->plane.desc = desc;
+	hqvdp->plane.ops = &hqvdp_plane_ops;
 
-	return &hqvdp->layer;
+	sti_hqvdp_init(hqvdp);
+
+	return &hqvdp->plane;
 }
-EXPORT_SYMBOL(sti_hqvdp_create);
 
 static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp)
 {
@@ -859,6 +843,12 @@ static void sti_hqvdp_start_xp70(const struct firmware *firmware, void *ctxt)
 	} *header;
 
 	DRM_DEBUG_DRIVER("\n");
+
+	if (hqvdp->xp70_initialized) {
+		DRM_INFO("HQVDP XP70 already initialized\n");
+		return;
+	}
+
 	/* Check firmware parts */
 	if (!firmware) {
 		DRM_ERROR("Firmware not available\n");
@@ -946,7 +936,10 @@ static void sti_hqvdp_start_xp70(const struct firmware *firmware, void *ctxt)
 	/* Launch Vsync */
 	writel(SOFT_VSYNC_HW, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
 
-	DRM_INFO("HQVDP XP70 started\n");
+	DRM_INFO("HQVDP XP70 initialized\n");
+
+	hqvdp->xp70_initialized = true;
+
 out:
 	release_firmware(firmware);
 }
@@ -955,7 +948,7 @@ int sti_hqvdp_bind(struct device *dev, struct device *master, void *data)
 {
 	struct sti_hqvdp *hqvdp = dev_get_drvdata(dev);
 	struct drm_device *drm_dev = data;
-	struct sti_layer *layer;
+	struct sti_plane *plane;
 	int err;
 
 	DRM_DEBUG_DRIVER("\n");
@@ -971,13 +964,13 @@ int sti_hqvdp_bind(struct device *dev, struct device *master, void *data)
 		return err;
 	}
 
-	layer = sti_layer_create(hqvdp->dev, STI_HQVDP_0, hqvdp->regs);
-	if (!layer) {
+	/* Create HQVDP plane once xp70 is initialized */
+	plane = sti_hqvdp_create(hqvdp->dev, STI_HQVDP_0);
+	if (plane)
+		sti_drm_plane_init(hqvdp->drm_dev, plane, 1,
+				   DRM_PLANE_TYPE_OVERLAY);
+	else
 		DRM_ERROR("Can't create HQVDP plane\n");
-		return -ENOMEM;
-	}
-
-	sti_drm_plane_init(drm_dev, layer, 1, DRM_PLANE_TYPE_OVERLAY);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.h b/drivers/gpu/drm/sti/sti_hqvdp.h
deleted file mode 100644
index cd5ecd0..0000000
--- a/drivers/gpu/drm/sti/sti_hqvdp.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#ifndef _STI_HQVDP_H_
-#define _STI_HQVDP_H_
-
-struct sti_layer *sti_hqvdp_create(struct device *dev);
-
-#endif
diff --git a/drivers/gpu/drm/sti/sti_layer.c b/drivers/gpu/drm/sti/sti_layer.c
deleted file mode 100644
index 899104f..0000000
--- a/drivers/gpu/drm/sti/sti_layer.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
- *          Fabien Dessenne <fabien.dessenne@st.com>
- *          for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-
-#include "sti_compositor.h"
-#include "sti_cursor.h"
-#include "sti_gdp.h"
-#include "sti_hqvdp.h"
-#include "sti_layer.h"
-#include "sti_vid.h"
-
-const char *sti_layer_to_str(struct sti_layer *layer)
-{
-	switch (layer->desc) {
-	case STI_GDP_0:
-		return "GDP0";
-	case STI_GDP_1:
-		return "GDP1";
-	case STI_GDP_2:
-		return "GDP2";
-	case STI_GDP_3:
-		return "GDP3";
-	case STI_VID_0:
-		return "VID0";
-	case STI_VID_1:
-		return "VID1";
-	case STI_CURSOR:
-		return "CURSOR";
-	case STI_HQVDP_0:
-		return "HQVDP0";
-	default:
-		return "<UNKNOWN LAYER>";
-	}
-}
-EXPORT_SYMBOL(sti_layer_to_str);
-
-struct sti_layer *sti_layer_create(struct device *dev, int desc,
-				   void __iomem *baseaddr)
-{
-
-	struct sti_layer *layer = NULL;
-
-	switch (desc & STI_LAYER_TYPE_MASK) {
-	case STI_GDP:
-		layer = sti_gdp_create(dev, desc);
-		break;
-	case STI_VID:
-		layer = sti_vid_create(dev);
-		break;
-	case STI_CUR:
-		layer = sti_cursor_create(dev);
-		break;
-	case STI_VDP:
-		layer = sti_hqvdp_create(dev);
-		break;
-	}
-
-	if (!layer) {
-		DRM_ERROR("Failed to create layer\n");
-		return NULL;
-	}
-
-	layer->desc = desc;
-	layer->dev = dev;
-	layer->regs = baseaddr;
-
-	layer->ops->init(layer);
-
-	DRM_DEBUG_DRIVER("%s created\n", sti_layer_to_str(layer));
-
-	return layer;
-}
-EXPORT_SYMBOL(sti_layer_create);
-
-int sti_layer_prepare(struct sti_layer *layer,
-		      struct drm_crtc *crtc,
-		      struct drm_framebuffer *fb,
-		      struct drm_display_mode *mode, int mixer_id,
-		      int dest_x, int dest_y, int dest_w, int dest_h,
-		      int src_x, int src_y, int src_w, int src_h)
-{
-	int ret;
-	unsigned int i;
-	struct drm_gem_cma_object *cma_obj;
-
-	if (!layer || !fb || !mode) {
-		DRM_ERROR("Null fb, layer or mode\n");
-		return 1;
-	}
-
-	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-	if (!cma_obj) {
-		DRM_ERROR("Can't get CMA GEM object for fb\n");
-		return 1;
-	}
-
-	layer->crtc = crtc;
-	layer->fb = fb;
-	layer->mode = mode;
-	layer->mixer_id = mixer_id;
-	layer->dst_x = dest_x;
-	layer->dst_y = dest_y;
-	layer->dst_w = clamp_val(dest_w, 0, mode->crtc_hdisplay - dest_x);
-	layer->dst_h = clamp_val(dest_h, 0, mode->crtc_vdisplay - dest_y);
-	layer->src_x = src_x;
-	layer->src_y = src_y;
-	layer->src_w = src_w;
-	layer->src_h = src_h;
-	layer->format = fb->pixel_format;
-	layer->vaddr = cma_obj->vaddr;
-	layer->paddr = cma_obj->paddr;
-	for (i = 0; i < 4; i++) {
-		layer->pitches[i] = fb->pitches[i];
-		layer->offsets[i] = fb->offsets[i];
-	}
-
-	DRM_DEBUG_DRIVER("%s is associated with mixer_id %d\n",
-			 sti_layer_to_str(layer),
-			 layer->mixer_id);
-	DRM_DEBUG_DRIVER("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
-			 sti_layer_to_str(layer),
-			 layer->dst_w, layer->dst_h, layer->dst_x, layer->dst_y,
-			 layer->src_w, layer->src_h, layer->src_x,
-			 layer->src_y);
-
-	DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
-			 (char *)&layer->format, (unsigned long)layer->paddr);
-
-	if (!layer->ops->prepare)
-		goto err_no_prepare;
-
-	ret = layer->ops->prepare(layer, !layer->enabled);
-	if (!ret)
-		layer->enabled = true;
-
-	return ret;
-
-err_no_prepare:
-	DRM_ERROR("Cannot prepare\n");
-	return 1;
-}
-
-int sti_layer_commit(struct sti_layer *layer)
-{
-	if (!layer)
-		return 1;
-
-	if (!layer->ops->commit)
-		goto err_no_commit;
-
-	return layer->ops->commit(layer);
-
-err_no_commit:
-	DRM_ERROR("Cannot commit\n");
-	return 1;
-}
-
-int sti_layer_disable(struct sti_layer *layer)
-{
-	int ret;
-
-	DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer));
-	if (!layer)
-		return 1;
-
-	if (!layer->enabled)
-		return 0;
-
-	if (!layer->ops->disable)
-		goto err_no_disable;
-
-	ret = layer->ops->disable(layer);
-	if (!ret)
-		layer->enabled = false;
-	else
-		DRM_ERROR("Disable failed\n");
-
-	return ret;
-
-err_no_disable:
-	DRM_ERROR("Cannot disable\n");
-	return 1;
-}
-
-const uint32_t *sti_layer_get_formats(struct sti_layer *layer)
-{
-	if (!layer)
-		return NULL;
-
-	if (!layer->ops->get_formats)
-		return NULL;
-
-	return layer->ops->get_formats(layer);
-}
-
-unsigned int sti_layer_get_nb_formats(struct sti_layer *layer)
-{
-	if (!layer)
-		return 0;
-
-	if (!layer->ops->get_nb_formats)
-		return 0;
-
-	return layer->ops->get_nb_formats(layer);
-}
diff --git a/drivers/gpu/drm/sti/sti_layer.h b/drivers/gpu/drm/sti/sti_layer.h
deleted file mode 100644
index ceff497..0000000
--- a/drivers/gpu/drm/sti/sti_layer.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
- *          Fabien Dessenne <fabien.dessenne@st.com>
- *          for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#ifndef _STI_LAYER_H_
-#define _STI_LAYER_H_
-
-#include <drm/drmP.h>
-
-#define to_sti_layer(x) container_of(x, struct sti_layer, plane)
-
-#define STI_LAYER_TYPE_SHIFT 8
-#define STI_LAYER_TYPE_MASK (~((1<<STI_LAYER_TYPE_SHIFT)-1))
-
-struct sti_layer;
-
-enum sti_layer_type {
-	STI_GDP = 1 << STI_LAYER_TYPE_SHIFT,
-	STI_VID = 2 << STI_LAYER_TYPE_SHIFT,
-	STI_CUR = 3 << STI_LAYER_TYPE_SHIFT,
-	STI_BCK = 4 << STI_LAYER_TYPE_SHIFT,
-	STI_VDP = 5 << STI_LAYER_TYPE_SHIFT
-};
-
-enum sti_layer_id_of_type {
-	STI_ID_0 = 0,
-	STI_ID_1 = 1,
-	STI_ID_2 = 2,
-	STI_ID_3 = 3
-};
-
-enum sti_layer_desc {
-	STI_GDP_0       = STI_GDP | STI_ID_0,
-	STI_GDP_1       = STI_GDP | STI_ID_1,
-	STI_GDP_2       = STI_GDP | STI_ID_2,
-	STI_GDP_3       = STI_GDP | STI_ID_3,
-	STI_VID_0       = STI_VID | STI_ID_0,
-	STI_VID_1       = STI_VID | STI_ID_1,
-	STI_HQVDP_0     = STI_VDP | STI_ID_0,
-	STI_CURSOR      = STI_CUR,
-	STI_BACK        = STI_BCK
-};
-
-/**
- * STI layer functions structure
- *
- * @get_formats:	get layer supported formats
- * @get_nb_formats:	get number of format supported
- * @init:               initialize the layer
- * @prepare:		prepare layer before rendering
- * @commit:		set layer for rendering
- * @disable:		disable layer
- */
-struct sti_layer_funcs {
-	const uint32_t* (*get_formats)(struct sti_layer *layer);
-	unsigned int (*get_nb_formats)(struct sti_layer *layer);
-	void (*init)(struct sti_layer *layer);
-	int (*prepare)(struct sti_layer *layer, bool first_prepare);
-	int (*commit)(struct sti_layer *layer);
-	int (*disable)(struct sti_layer *layer);
-};
-
-/**
- * STI layer structure
- *
- * @plane:              drm plane it is bound to (if any)
- * @fb:                 drm fb it is bound to
- * @crtc:               crtc it is bound to
- * @mode:               display mode
- * @desc:               layer type & id
- * @device:		driver device
- * @regs:		layer registers
- * @ops:                layer functions
- * @zorder:             layer z-order
- * @mixer_id:           id of the mixer used to display the layer
- * @enabled:            to know if the layer is active or not
- * @src_x src_y:        coordinates of the input (fb) area
- * @src_w src_h:        size of the input (fb) area
- * @dst_x dst_y:        coordinates of the output (crtc) area
- * @dst_w dst_h:        size of the output (crtc) area
- * @format:             format
- * @pitches:            pitch of 'planes' (eg: Y, U, V)
- * @offsets:            offset of 'planes'
- * @vaddr:              virtual address of the input buffer
- * @paddr:              physical address of the input buffer
- */
-struct sti_layer {
-	struct drm_plane plane;
-	struct drm_framebuffer *fb;
-	struct drm_crtc *crtc;
-	struct drm_display_mode *mode;
-	enum sti_layer_desc desc;
-	struct device *dev;
-	void __iomem *regs;
-	const struct sti_layer_funcs *ops;
-	int zorder;
-	int mixer_id;
-	bool enabled;
-	int src_x, src_y;
-	int src_w, src_h;
-	int dst_x, dst_y;
-	int dst_w, dst_h;
-	uint32_t format;
-	unsigned int pitches[4];
-	unsigned int offsets[4];
-	void *vaddr;
-	dma_addr_t paddr;
-};
-
-struct sti_layer *sti_layer_create(struct device *dev, int desc,
-			void __iomem *baseaddr);
-int sti_layer_prepare(struct sti_layer *layer,
-			struct drm_crtc *crtc,
-			struct drm_framebuffer *fb,
-			struct drm_display_mode *mode,
-			int mixer_id,
-			int dest_x, int dest_y,
-			int dest_w, int dest_h,
-			int src_x, int src_y,
-			int src_w, int src_h);
-int sti_layer_commit(struct sti_layer *layer);
-int sti_layer_disable(struct sti_layer *layer);
-const uint32_t *sti_layer_get_formats(struct sti_layer *layer);
-unsigned int sti_layer_get_nb_formats(struct sti_layer *layer);
-const char *sti_layer_to_str(struct sti_layer *layer);
-
-#endif
diff --git a/drivers/gpu/drm/sti/sti_mixer.c b/drivers/gpu/drm/sti/sti_mixer.c
index 61a2048..d5a9656 100644
--- a/drivers/gpu/drm/sti/sti_mixer.c
+++ b/drivers/gpu/drm/sti/sti_mixer.c
@@ -101,61 +101,57 @@ static void sti_mixer_set_background_area(struct sti_mixer *mixer,
 	sti_mixer_reg_write(mixer, GAM_MIXER_BCS, yds << 16 | xds);
 }
 
-int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer)
+int sti_mixer_set_plane_depth(struct sti_mixer *mixer, struct sti_plane *plane)
 {
-	int layer_id, depth = layer->zorder;
+	int plane_id, depth = plane->zorder;
 	unsigned int i;
 	u32 mask, val;
 
 	if ((depth < 1) || (depth > GAM_MIXER_NB_DEPTH_LEVEL))
 		return 1;
 
-	switch (layer->desc) {
+	switch (plane->desc) {
 	case STI_GDP_0:
-		layer_id = GAM_DEPTH_GDP0_ID;
+		plane_id = GAM_DEPTH_GDP0_ID;
 		break;
 	case STI_GDP_1:
-		layer_id = GAM_DEPTH_GDP1_ID;
+		plane_id = GAM_DEPTH_GDP1_ID;
 		break;
 	case STI_GDP_2:
-		layer_id = GAM_DEPTH_GDP2_ID;
+		plane_id = GAM_DEPTH_GDP2_ID;
 		break;
 	case STI_GDP_3:
-		layer_id = GAM_DEPTH_GDP3_ID;
+		plane_id = GAM_DEPTH_GDP3_ID;
 		break;
-	case STI_VID_0:
 	case STI_HQVDP_0:
-		layer_id = GAM_DEPTH_VID0_ID;
-		break;
-	case STI_VID_1:
-		layer_id = GAM_DEPTH_VID1_ID;
+		plane_id = GAM_DEPTH_VID0_ID;
 		break;
 	case STI_CURSOR:
 		/* no need to set depth for cursor */
 		return 0;
 	default:
-		DRM_ERROR("Unknown layer %d\n", layer->desc);
+		DRM_ERROR("Unknown plane %d\n", plane->desc);
 		return 1;
 	}
 
-	/* Search if a previous depth was already assigned to the layer */
+	/* Search if a previous depth was already assigned to the plane */
 	val = sti_mixer_reg_read(mixer, GAM_MIXER_CRB);
 	for (i = 0; i < GAM_MIXER_NB_DEPTH_LEVEL; i++) {
 		mask = GAM_DEPTH_MASK_ID << (3 * i);
-		if ((val & mask) == layer_id << (3 * i))
+		if ((val & mask) == plane_id << (3 * i))
 			break;
 	}
 
 	mask |= GAM_DEPTH_MASK_ID << (3 * (depth - 1));
-	layer_id = layer_id << (3 * (depth - 1));
+	plane_id = plane_id << (3 * (depth - 1));
 
 	DRM_DEBUG_DRIVER("%s %s depth=%d\n", sti_mixer_to_str(mixer),
-			 sti_layer_to_str(layer), depth);
+			 sti_plane_to_str(plane), depth);
 	dev_dbg(mixer->dev, "GAM_MIXER_CRB val 0x%x mask 0x%x\n",
-		layer_id, mask);
+		plane_id, mask);
 
 	val &= ~mask;
-	val |= layer_id;
+	val |= plane_id;
 	sti_mixer_reg_write(mixer, GAM_MIXER_CRB, val);
 
 	dev_dbg(mixer->dev, "Read GAM_MIXER_CRB 0x%x\n",
@@ -185,9 +181,9 @@ int sti_mixer_active_video_area(struct sti_mixer *mixer,
 	return 0;
 }
 
-static u32 sti_mixer_get_layer_mask(struct sti_layer *layer)
+static u32 sti_mixer_get_plane_mask(struct sti_plane *plane)
 {
-	switch (layer->desc) {
+	switch (plane->desc) {
 	case STI_BACK:
 		return GAM_CTL_BACK_MASK;
 	case STI_GDP_0:
@@ -198,11 +194,8 @@ static u32 sti_mixer_get_layer_mask(struct sti_layer *layer)
 		return GAM_CTL_GDP2_MASK;
 	case STI_GDP_3:
 		return GAM_CTL_GDP3_MASK;
-	case STI_VID_0:
 	case STI_HQVDP_0:
 		return GAM_CTL_VID0_MASK;
-	case STI_VID_1:
-		return GAM_CTL_VID1_MASK;
 	case STI_CURSOR:
 		return GAM_CTL_CURSOR_MASK;
 	default:
@@ -210,17 +203,17 @@ static u32 sti_mixer_get_layer_mask(struct sti_layer *layer)
 	}
 }
 
-int sti_mixer_set_layer_status(struct sti_mixer *mixer,
-			       struct sti_layer *layer, bool status)
+int sti_mixer_set_plane_status(struct sti_mixer *mixer,
+			       struct sti_plane *plane, bool status)
 {
 	u32 mask, val;
 
 	DRM_DEBUG_DRIVER("%s %s %s\n", status ? "enable" : "disable",
-			 sti_mixer_to_str(mixer), sti_layer_to_str(layer));
+			 sti_mixer_to_str(mixer), sti_plane_to_str(plane));
 
-	mask = sti_mixer_get_layer_mask(layer);
+	mask = sti_mixer_get_plane_mask(plane);
 	if (!mask) {
-		DRM_ERROR("Can not find layer mask\n");
+		DRM_ERROR("Can't find layer mask\n");
 		return -EINVAL;
 	}
 
@@ -232,11 +225,11 @@ int sti_mixer_set_layer_status(struct sti_mixer *mixer,
 	return 0;
 }
 
-void sti_mixer_clear_all_layers(struct sti_mixer *mixer)
+void sti_mixer_clear_all_planes(struct sti_mixer *mixer)
 {
 	u32 val;
 
-	DRM_DEBUG_DRIVER("%s clear all layer\n", sti_mixer_to_str(mixer));
+	DRM_DEBUG_DRIVER("%s clear all planes\n", sti_mixer_to_str(mixer));
 	val = sti_mixer_reg_read(mixer, GAM_MIXER_CTL) & 0xFFFF0000;
 	sti_mixer_reg_write(mixer, GAM_MIXER_CTL, val);
 }
diff --git a/drivers/gpu/drm/sti/sti_mixer.h b/drivers/gpu/drm/sti/sti_mixer.h
index eb663f6..9d51eac 100644
--- a/drivers/gpu/drm/sti/sti_mixer.h
+++ b/drivers/gpu/drm/sti/sti_mixer.h
@@ -11,7 +11,7 @@
 
 #include <drm/drmP.h>
 
-#include "sti_layer.h"
+#include "sti_drm_plane.h"
 
 #define to_sti_mixer(x) container_of(x, struct sti_mixer, drm_crtc)
 
@@ -29,7 +29,7 @@ struct sti_mixer {
 	struct device *dev;
 	void __iomem *regs;
 	int id;
-	struct drm_crtc	drm_crtc;
+	struct drm_crtc drm_crtc;
 	struct drm_pending_vblank_event *pending_event;
 	bool enabled;
 };
@@ -37,14 +37,14 @@ struct sti_mixer {
 const char *sti_mixer_to_str(struct sti_mixer *mixer);
 
 struct sti_mixer *sti_mixer_create(struct device *dev, int id,
-		void __iomem *baseaddr);
+				   void __iomem *baseaddr);
 
-int sti_mixer_set_layer_status(struct sti_mixer *mixer,
-		struct sti_layer *layer, bool status);
-void sti_mixer_clear_all_layers(struct sti_mixer *mixer);
-int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer);
+int sti_mixer_set_plane_status(struct sti_mixer *mixer,
+			       struct sti_plane *plane, bool status);
+void sti_mixer_clear_all_planes(struct sti_mixer *mixer);
+int sti_mixer_set_plane_depth(struct sti_mixer *mixer, struct sti_plane *plane);
 int sti_mixer_active_video_area(struct sti_mixer *mixer,
-		struct drm_display_mode *mode);
+				struct drm_display_mode *mode);
 
 void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable);
 
diff --git a/drivers/gpu/drm/sti/sti_vid.c b/drivers/gpu/drm/sti/sti_vid.c
index 10ced6a..b82a34f 100644
--- a/drivers/gpu/drm/sti/sti_vid.c
+++ b/drivers/gpu/drm/sti/sti_vid.c
@@ -6,7 +6,7 @@
 
 #include <drm/drmP.h>
 
-#include "sti_layer.h"
+#include "sti_drm_plane.h"
 #include "sti_vid.h"
 #include "sti_vtg.h"
 
@@ -43,27 +43,20 @@
 #define VID_MPR2_BT709          0x07150545
 #define VID_MPR3_BT709          0x00000AE8
 
-static int sti_vid_prepare_layer(struct sti_layer *vid, bool first_prepare)
+int sti_vid_commit(struct sti_vid *vid, struct sti_plane *plane)
 {
-	u32 val;
+	struct drm_display_mode *mode = plane->mode;
+	u32 val, ydo, xdo, yds, xds;
 
 	/* Unmask */
 	val = readl(vid->regs + VID_CTL);
 	val &= ~VID_CTL_IGNORE;
 	writel(val, vid->regs + VID_CTL);
 
-	return 0;
-}
-
-static int sti_vid_commit_layer(struct sti_layer *vid)
-{
-	struct drm_display_mode *mode = vid->mode;
-	u32 ydo, xdo, yds, xds;
-
-	ydo = sti_vtg_get_line_number(*mode, vid->dst_y);
-	yds = sti_vtg_get_line_number(*mode, vid->dst_y + vid->dst_h - 1);
-	xdo = sti_vtg_get_pixel_number(*mode, vid->dst_x);
-	xds = sti_vtg_get_pixel_number(*mode, vid->dst_x + vid->dst_w - 1);
+	ydo = sti_vtg_get_line_number(*mode, plane->dst_y);
+	yds = sti_vtg_get_line_number(*mode, plane->dst_y + plane->dst_h - 1);
+	xdo = sti_vtg_get_pixel_number(*mode, plane->dst_x);
+	xds = sti_vtg_get_pixel_number(*mode, plane->dst_x + plane->dst_w - 1);
 
 	writel((ydo << 16) | xdo, vid->regs + VID_VPO);
 	writel((yds << 16) | xds, vid->regs + VID_VPS);
@@ -71,7 +64,7 @@ static int sti_vid_commit_layer(struct sti_layer *vid)
 	return 0;
 }
 
-static int sti_vid_disable_layer(struct sti_layer *vid)
+int sti_vid_disable(struct sti_vid *vid)
 {
 	u32 val;
 
@@ -83,17 +76,7 @@ static int sti_vid_disable_layer(struct sti_layer *vid)
 	return 0;
 }
 
-static const uint32_t *sti_vid_get_formats(struct sti_layer *layer)
-{
-	return NULL;
-}
-
-static unsigned int sti_vid_get_nb_formats(struct sti_layer *layer)
-{
-	return 0;
-}
-
-static void sti_vid_init(struct sti_layer *vid)
+static void sti_vid_init(struct sti_vid *vid)
 {
 	/* Enable PSI, Mask layer */
 	writel(VID_CTL_PSI_ENABLE | VID_CTL_IGNORE, vid->regs + VID_CTL);
@@ -113,18 +96,10 @@ static void sti_vid_init(struct sti_layer *vid)
 	writel(VID_CSAT_DFLT, vid->regs + VID_CSAT);
 }
 
-static const struct sti_layer_funcs vid_ops = {
-	.get_formats = sti_vid_get_formats,
-	.get_nb_formats = sti_vid_get_nb_formats,
-	.init = sti_vid_init,
-	.prepare = sti_vid_prepare_layer,
-	.commit = sti_vid_commit_layer,
-	.disable = sti_vid_disable_layer,
-};
-
-struct sti_layer *sti_vid_create(struct device *dev)
+struct sti_vid *sti_vid_create(struct device *dev, int id,
+			       void __iomem *baseaddr)
 {
-	struct sti_layer *vid;
+	struct sti_vid *vid;
 
 	vid = devm_kzalloc(dev, sizeof(*vid), GFP_KERNEL);
 	if (!vid) {
@@ -132,7 +107,11 @@ struct sti_layer *sti_vid_create(struct device *dev)
 		return NULL;
 	}
 
-	vid->ops = &vid_ops;
+	vid->dev = dev;
+	vid->regs = baseaddr;
+	vid->id = id;
+
+	sti_vid_init(vid);
 
 	return vid;
 }
diff --git a/drivers/gpu/drm/sti/sti_vid.h b/drivers/gpu/drm/sti/sti_vid.h
index 2c0aecd..cc680a2 100644
--- a/drivers/gpu/drm/sti/sti_vid.h
+++ b/drivers/gpu/drm/sti/sti_vid.h
@@ -7,6 +7,22 @@
 #ifndef _STI_VID_H_
 #define _STI_VID_H_
 
-struct sti_layer *sti_vid_create(struct device *dev);
+/**
+ * STI VID structure
+ *
+ * @dev:   driver device
+ * @regs:  vid registers
+ * @id:    id of the vid
+ */
+struct sti_vid {
+	struct device *dev;
+	void __iomem *regs;
+	int id;
+};
+
+int sti_vid_commit(struct sti_vid *vid, struct sti_plane *plane);
+int sti_vid_disable(struct sti_vid *vid);
+struct sti_vid *sti_vid_create(struct device *dev, int id,
+			       void __iomem *baseaddr);
 
 #endif
-- 
1.9.1

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

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

* [PATCH 3/4] drm/sti: rename files and functions
  2015-07-31 10:13 [PATCH 0/4] drm/sti: update STI driver to be atomic Vincent Abriou
  2015-07-31 10:13 ` [PATCH 1/4] drm/sti: fix dynamic z-ordering Vincent Abriou
  2015-07-31 10:13 ` [PATCH 2/4] drm/sti: code clean up Vincent Abriou
@ 2015-07-31 10:13 ` Vincent Abriou
  2015-07-31 10:13 ` [PATCH 4/4] drm/sti: atomic crtc/plane update Vincent Abriou
  3 siblings, 0 replies; 9+ messages in thread
From: Vincent Abriou @ 2015-07-31 10:13 UTC (permalink / raw)
  To: dri-devel; +Cc: Fabien Dessenne, Benjamin Gaignard, kernel

replace all "sti_drm_" occurences by "sti_"

Signed-off-by: Vincent Abriou <vincent.abriou@st.com>
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
---
 drivers/gpu/drm/sti/Makefile         |   6 +-
 drivers/gpu/drm/sti/sti_compositor.c |  24 +--
 drivers/gpu/drm/sti/sti_compositor.h |   2 +-
 drivers/gpu/drm/sti/sti_crtc.c       | 322 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sti/sti_crtc.h       |  22 +++
 drivers/gpu/drm/sti/sti_cursor.c     |   2 +-
 drivers/gpu/drm/sti/sti_drm_crtc.c   | 322 --------------------------------
 drivers/gpu/drm/sti/sti_drm_crtc.h   |  22 ---
 drivers/gpu/drm/sti/sti_drm_drv.c    | 294 ------------------------------
 drivers/gpu/drm/sti/sti_drm_drv.h    |  35 ----
 drivers/gpu/drm/sti/sti_drm_plane.c  | 344 -----------------------------------
 drivers/gpu/drm/sti/sti_drm_plane.h  | 105 -----------
 drivers/gpu/drm/sti/sti_drv.c        | 294 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/sti/sti_drv.h        |  35 ++++
 drivers/gpu/drm/sti/sti_gdp.c        |   2 +-
 drivers/gpu/drm/sti/sti_hqvdp.c      |   6 +-
 drivers/gpu/drm/sti/sti_mixer.h      |   2 +-
 drivers/gpu/drm/sti/sti_plane.c      | 343 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sti/sti_plane.h      | 105 +++++++++++
 drivers/gpu/drm/sti/sti_tvout.c      |   8 +-
 drivers/gpu/drm/sti/sti_vid.c        |   2 +-
 21 files changed, 1148 insertions(+), 1149 deletions(-)
 create mode 100644 drivers/gpu/drm/sti/sti_crtc.c
 create mode 100644 drivers/gpu/drm/sti/sti_crtc.h
 delete mode 100644 drivers/gpu/drm/sti/sti_drm_crtc.c
 delete mode 100644 drivers/gpu/drm/sti/sti_drm_crtc.h
 delete mode 100644 drivers/gpu/drm/sti/sti_drm_drv.c
 delete mode 100644 drivers/gpu/drm/sti/sti_drm_drv.h
 delete mode 100644 drivers/gpu/drm/sti/sti_drm_plane.c
 delete mode 100644 drivers/gpu/drm/sti/sti_drm_plane.h
 create mode 100644 drivers/gpu/drm/sti/sti_drv.c
 create mode 100644 drivers/gpu/drm/sti/sti_drv.h
 create mode 100644 drivers/gpu/drm/sti/sti_plane.c
 create mode 100644 drivers/gpu/drm/sti/sti_plane.h

diff --git a/drivers/gpu/drm/sti/Makefile b/drivers/gpu/drm/sti/Makefile
index 505b3ba..e27490b 100644
--- a/drivers/gpu/drm/sti/Makefile
+++ b/drivers/gpu/drm/sti/Makefile
@@ -4,8 +4,8 @@ sticompositor-y := \
 	sti_vid.o \
 	sti_cursor.o \
 	sti_compositor.o \
-	sti_drm_crtc.o \
-	sti_drm_plane.o
+	sti_crtc.o \
+	sti_plane.o
 
 stihdmi-y := sti_hdmi.o \
 	sti_hdmi_tx3g0c55phy.o \
@@ -23,4 +23,4 @@ obj-$(CONFIG_DRM_STI) = \
 	sticompositor.o \
 	sti_hqvdp.o \
 	stidvo.o \
-	sti_drm_drv.o
+	sti_drv.o
diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c
index 68c5c95..d62ed7f 100644
--- a/drivers/gpu/drm/sti/sti_compositor.c
+++ b/drivers/gpu/drm/sti/sti_compositor.c
@@ -14,11 +14,11 @@
 #include <drm/drmP.h>
 
 #include "sti_compositor.h"
+#include "sti_crtc.h"
 #include "sti_cursor.h"
-#include "sti_drm_crtc.h"
-#include "sti_drm_drv.h"
-#include "sti_drm_plane.h"
+#include "sti_drv.h"
 #include "sti_gdp.h"
+#include "sti_plane.h"
 #include "sti_vid.h"
 #include "sti_vtg.h"
 
@@ -62,7 +62,7 @@ static int sti_compositor_bind(struct device *dev,
 	struct sti_compositor *compo = dev_get_drvdata(dev);
 	struct drm_device *drm_dev = data;
 	unsigned int i, mixer_id = 0, vid_id = 0, crtc_id = 0, plane_id = 0;
-	struct sti_drm_private *dev_priv = drm_dev->dev_private;
+	struct sti_private *dev_priv = drm_dev->dev_private;
 	struct drm_plane *cursor = NULL;
 	struct drm_plane *primary = NULL;
 	struct sti_compositor_subdev_descriptor *desc = compo->data.subdev_desc;
@@ -116,8 +116,8 @@ static int sti_compositor_bind(struct device *dev,
 				DRM_ERROR("Can't create CURSOR plane\n");
 				break;
 			}
-			cursor = sti_drm_plane_init(drm_dev, plane, 1,
-						    DRM_PLANE_TYPE_CURSOR);
+			cursor = sti_plane_init(drm_dev, plane, 1,
+						DRM_PLANE_TYPE_CURSOR);
 			plane_id++;
 			break;
 		case STI_GPD_SUBDEV:
@@ -127,9 +127,9 @@ static int sti_compositor_bind(struct device *dev,
 				DRM_ERROR("Can't create GDP plane\n");
 				break;
 			}
-			primary = sti_drm_plane_init(drm_dev, plane,
-						     (1 << mixer_id) - 1,
-						     plane_type);
+			primary = sti_plane_init(drm_dev, plane,
+						 (1 << mixer_id) - 1,
+						 plane_type);
 			plane_id++;
 			break;
 		default:
@@ -139,8 +139,8 @@ static int sti_compositor_bind(struct device *dev,
 
 		/* The first planes are reserved for primary planes*/
 		if (crtc_id < mixer_id && primary) {
-			sti_drm_crtc_init(drm_dev, compo->mixer[crtc_id],
-					  primary, cursor);
+			sti_crtc_init(drm_dev, compo->mixer[crtc_id],
+				      primary, cursor);
 			crtc_id++;
 			cursor = NULL;
 			primary = NULL;
@@ -196,7 +196,7 @@ static int sti_compositor_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 	compo->dev = dev;
-	compo->vtg_vblank_nb.notifier_call = sti_drm_crtc_vblank_cb;
+	compo->vtg_vblank_nb.notifier_call = sti_crtc_vblank_cb;
 
 	/* populate data structure depending on compatibility */
 	BUG_ON(!of_match_node(compositor_of_match, np)->data);
diff --git a/drivers/gpu/drm/sti/sti_compositor.h b/drivers/gpu/drm/sti/sti_compositor.h
index 77f9978..1a4a73d 100644
--- a/drivers/gpu/drm/sti/sti_compositor.h
+++ b/drivers/gpu/drm/sti/sti_compositor.h
@@ -12,8 +12,8 @@
 #include <linux/clk.h>
 #include <linux/kernel.h>
 
-#include "sti_drm_plane.h"
 #include "sti_mixer.h"
+#include "sti_plane.h"
 
 #define WAIT_NEXT_VSYNC_MS      50 /*ms*/
 
diff --git a/drivers/gpu/drm/sti/sti_crtc.c b/drivers/gpu/drm/sti/sti_crtc.c
new file mode 100644
index 0000000..27b3ef2
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_crtc.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include "sti_compositor.h"
+#include "sti_crtc.h"
+#include "sti_drv.h"
+#include "sti_vtg.h"
+
+static void sti_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	DRM_DEBUG_KMS("\n");
+}
+
+static void sti_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	struct device *dev = mixer->dev;
+	struct sti_compositor *compo = dev_get_drvdata(dev);
+
+	mixer->enabled = true;
+
+	/* Prepare and enable the compo IP clock */
+	if (mixer->id == STI_MIXER_MAIN) {
+		if (clk_prepare_enable(compo->clk_compo_main))
+			DRM_INFO("Failed to prepare/enable compo_main clk\n");
+	} else {
+		if (clk_prepare_enable(compo->clk_compo_aux))
+			DRM_INFO("Failed to prepare/enable compo_aux clk\n");
+	}
+
+	sti_mixer_clear_all_planes(mixer);
+}
+
+static void sti_crtc_commit(struct drm_crtc *crtc)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	struct device *dev = mixer->dev;
+	struct sti_compositor *compo = dev_get_drvdata(dev);
+	struct sti_plane *plane;
+
+	if ((!mixer || !compo)) {
+		DRM_ERROR("Can't find mixer or compositor)\n");
+		return;
+	}
+
+	/* get GDP which is reserved to the CRTC FB */
+	plane = to_sti_plane(crtc->primary);
+	if (!plane)
+		DRM_ERROR("Can't find CRTC dedicated plane (GDP0)\n");
+
+	/* Enable plane on mixer */
+	if (sti_mixer_set_plane_status(mixer, plane, true))
+		DRM_ERROR("Cannot enable plane at mixer\n");
+
+	drm_crtc_vblank_on(crtc);
+}
+
+static bool sti_crtc_mode_fixup(struct drm_crtc *crtc,
+				const struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	/* accept the provided drm_display_mode, do not fix it up */
+	return true;
+}
+
+static int
+sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	struct device *dev = mixer->dev;
+	struct sti_compositor *compo = dev_get_drvdata(dev);
+	struct clk *clk;
+	int rate = mode->clock * 1000;
+	int res;
+
+	DRM_DEBUG_KMS("CRTC:%d (%s) mode:%d (%s)\n",
+		      crtc->base.id, sti_mixer_to_str(mixer),
+		      mode->base.id, mode->name);
+
+	DRM_DEBUG_KMS("%d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
+		      mode->vrefresh, mode->clock,
+		      mode->hdisplay,
+		      mode->hsync_start, mode->hsync_end,
+		      mode->htotal,
+		      mode->vdisplay,
+		      mode->vsync_start, mode->vsync_end,
+		      mode->vtotal, mode->type, mode->flags);
+
+	/* Set rate and prepare/enable pixel clock */
+	if (mixer->id == STI_MIXER_MAIN)
+		clk = compo->clk_pix_main;
+	else
+		clk = compo->clk_pix_aux;
+
+	res = clk_set_rate(clk, rate);
+	if (res < 0) {
+		DRM_ERROR("Cannot set rate (%dHz) for pix clk\n", rate);
+		return -EINVAL;
+	}
+	if (clk_prepare_enable(clk)) {
+		DRM_ERROR("Failed to prepare/enable pix clk\n");
+		return -EINVAL;
+	}
+
+	sti_vtg_set_config(mixer->id == STI_MIXER_MAIN ?
+			compo->vtg_main : compo->vtg_aux, &crtc->mode);
+
+	res = sti_mixer_active_video_area(mixer, &crtc->mode);
+	if (res) {
+		DRM_ERROR("Can't set active video area\n");
+		return -EINVAL;
+	}
+
+	return res;
+}
+
+static void sti_crtc_disable(struct drm_crtc *crtc)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	struct device *dev = mixer->dev;
+	struct sti_compositor *compo = dev_get_drvdata(dev);
+
+	if (!mixer->enabled)
+		return;
+
+	DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer));
+
+	/* Disable Background */
+	sti_mixer_set_background_status(mixer, false);
+
+	drm_crtc_vblank_off(crtc);
+
+	/* Disable pixel clock and compo IP clocks */
+	if (mixer->id == STI_MIXER_MAIN) {
+		clk_disable_unprepare(compo->clk_pix_main);
+		clk_disable_unprepare(compo->clk_compo_main);
+	} else {
+		clk_disable_unprepare(compo->clk_pix_aux);
+		clk_disable_unprepare(compo->clk_compo_aux);
+	}
+
+	mixer->enabled = false;
+}
+
+static void
+sti_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	sti_crtc_prepare(crtc);
+	sti_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
+}
+
+static void sti_crtc_atomic_begin(struct drm_crtc *crtc)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+
+	if (crtc->state->event) {
+		crtc->state->event->pipe = drm_crtc_index(crtc);
+
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+		mixer->pending_event = crtc->state->event;
+		crtc->state->event = NULL;
+	}
+}
+
+static void sti_crtc_atomic_flush(struct drm_crtc *crtc)
+{
+}
+
+static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
+	.dpms = sti_crtc_dpms,
+	.prepare = sti_crtc_prepare,
+	.commit = sti_crtc_commit,
+	.mode_fixup = sti_crtc_mode_fixup,
+	.mode_set = drm_helper_crtc_mode_set,
+	.mode_set_nofb = sti_crtc_mode_set_nofb,
+	.mode_set_base = drm_helper_crtc_mode_set_base,
+	.disable = sti_crtc_disable,
+	.atomic_begin = sti_crtc_atomic_begin,
+	.atomic_flush = sti_crtc_atomic_flush,
+};
+
+static void sti_crtc_destroy(struct drm_crtc *crtc)
+{
+	DRM_DEBUG_KMS("\n");
+	drm_crtc_cleanup(crtc);
+}
+
+static int sti_crtc_set_property(struct drm_crtc *crtc,
+				 struct drm_property *property,
+				 uint64_t val)
+{
+	DRM_DEBUG_KMS("\n");
+	return 0;
+}
+
+int sti_crtc_vblank_cb(struct notifier_block *nb,
+		       unsigned long event, void *data)
+{
+	struct drm_device *drm_dev;
+	struct sti_compositor *compo =
+		container_of(nb, struct sti_compositor, vtg_vblank_nb);
+	int *crtc = data;
+	unsigned long flags;
+	struct sti_private *priv;
+
+	drm_dev = compo->mixer[*crtc]->drm_crtc.dev;
+	priv = drm_dev->dev_private;
+
+	if ((event != VTG_TOP_FIELD_EVENT) &&
+	    (event != VTG_BOTTOM_FIELD_EVENT)) {
+		DRM_ERROR("unknown event: %lu\n", event);
+		return -EINVAL;
+	}
+
+	drm_handle_vblank(drm_dev, *crtc);
+
+	spin_lock_irqsave(&drm_dev->event_lock, flags);
+	if (compo->mixer[*crtc]->pending_event) {
+		drm_send_vblank_event(drm_dev, -1,
+				      compo->mixer[*crtc]->pending_event);
+		drm_vblank_put(drm_dev, *crtc);
+		compo->mixer[*crtc]->pending_event = NULL;
+	}
+	spin_unlock_irqrestore(&drm_dev->event_lock, flags);
+
+	return 0;
+}
+
+int sti_crtc_enable_vblank(struct drm_device *dev, int crtc)
+{
+	struct sti_private *dev_priv = dev->dev_private;
+	struct sti_compositor *compo = dev_priv->compo;
+	struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	if (sti_vtg_register_client(crtc == STI_MIXER_MAIN ?
+			compo->vtg_main : compo->vtg_aux,
+			vtg_vblank_nb, crtc)) {
+		DRM_ERROR("Cannot register VTG notifier\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(sti_crtc_enable_vblank);
+
+void sti_crtc_disable_vblank(struct drm_device *dev, int crtc)
+{
+	struct sti_private *priv = dev->dev_private;
+	struct sti_compositor *compo = priv->compo;
+	struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	if (sti_vtg_unregister_client(crtc == STI_MIXER_MAIN ?
+			compo->vtg_main : compo->vtg_aux, vtg_vblank_nb))
+		DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
+
+	/* free the resources of the pending requests */
+	if (compo->mixer[crtc]->pending_event) {
+		drm_vblank_put(dev, crtc);
+		compo->mixer[crtc]->pending_event = NULL;
+	}
+}
+EXPORT_SYMBOL(sti_crtc_disable_vblank);
+
+static struct drm_crtc_funcs sti_crtc_funcs = {
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.destroy = sti_crtc_destroy,
+	.set_property = sti_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,
+};
+
+bool sti_crtc_is_main(struct drm_crtc *crtc)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+
+	if (mixer->id == STI_MIXER_MAIN)
+		return true;
+
+	return false;
+}
+EXPORT_SYMBOL(sti_crtc_is_main);
+
+int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
+		  struct drm_plane *primary, struct drm_plane *cursor)
+{
+	struct drm_crtc *crtc = &mixer->drm_crtc;
+	int res;
+
+	res = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
+					&sti_crtc_funcs);
+	if (res) {
+		DRM_ERROR("Can't initialze CRTC\n");
+		return -EINVAL;
+	}
+
+	drm_crtc_helper_add(crtc, &sti_crtc_helper_funcs);
+
+	DRM_DEBUG_DRIVER("drm CRTC:%d mapped to %s\n",
+			 crtc->base.id, sti_mixer_to_str(mixer));
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/sti/sti_crtc.h b/drivers/gpu/drm/sti/sti_crtc.h
new file mode 100644
index 0000000..51963e6
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_crtc.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_CRTC_H_
+#define _STI_CRTC_H_
+
+#include <drm/drmP.h>
+
+struct sti_mixer;
+
+int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
+		  struct drm_plane *primary, struct drm_plane *cursor);
+int sti_crtc_enable_vblank(struct drm_device *dev, int crtc);
+void sti_crtc_disable_vblank(struct drm_device *dev, int crtc);
+int sti_crtc_vblank_cb(struct notifier_block *nb,
+		       unsigned long event, void *data);
+bool sti_crtc_is_main(struct drm_crtc *drm_crtc);
+
+#endif
diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c
index cd12403..2868909 100644
--- a/drivers/gpu/drm/sti/sti_cursor.c
+++ b/drivers/gpu/drm/sti/sti_cursor.c
@@ -8,7 +8,7 @@
 #include <drm/drmP.h>
 
 #include "sti_cursor.h"
-#include "sti_drm_plane.h"
+#include "sti_plane.h"
 #include "sti_vtg.h"
 
 /* Registers */
diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c
deleted file mode 100644
index a489b04..0000000
--- a/drivers/gpu/drm/sti/sti_drm_crtc.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
- *          Fabien Dessenne <fabien.dessenne@st.com>
- *          for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#include <linux/clk.h>
-
-#include <drm/drmP.h>
-#include <drm/drm_atomic.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_plane_helper.h>
-
-#include "sti_compositor.h"
-#include "sti_drm_drv.h"
-#include "sti_drm_crtc.h"
-#include "sti_vtg.h"
-
-static void sti_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-	DRM_DEBUG_KMS("\n");
-}
-
-static void sti_drm_crtc_prepare(struct drm_crtc *crtc)
-{
-	struct sti_mixer *mixer = to_sti_mixer(crtc);
-	struct device *dev = mixer->dev;
-	struct sti_compositor *compo = dev_get_drvdata(dev);
-
-	mixer->enabled = true;
-
-	/* Prepare and enable the compo IP clock */
-	if (mixer->id == STI_MIXER_MAIN) {
-		if (clk_prepare_enable(compo->clk_compo_main))
-			DRM_INFO("Failed to prepare/enable compo_main clk\n");
-	} else {
-		if (clk_prepare_enable(compo->clk_compo_aux))
-			DRM_INFO("Failed to prepare/enable compo_aux clk\n");
-	}
-
-	sti_mixer_clear_all_planes(mixer);
-}
-
-static void sti_drm_crtc_commit(struct drm_crtc *crtc)
-{
-	struct sti_mixer *mixer = to_sti_mixer(crtc);
-	struct device *dev = mixer->dev;
-	struct sti_compositor *compo = dev_get_drvdata(dev);
-	struct sti_plane *plane;
-
-	if ((!mixer || !compo)) {
-		DRM_ERROR("Can't find mixer or compositor)\n");
-		return;
-	}
-
-	/* get GDP which is reserved to the CRTC FB */
-	plane = to_sti_plane(crtc->primary);
-	if (!plane)
-		DRM_ERROR("Can't find CRTC dedicated plane (GDP0)\n");
-
-	/* Enable plane on mixer */
-	if (sti_mixer_set_plane_status(mixer, plane, true))
-		DRM_ERROR("Cannot enable plane at mixer\n");
-
-	drm_crtc_vblank_on(crtc);
-}
-
-static bool sti_drm_crtc_mode_fixup(struct drm_crtc *crtc,
-				    const struct drm_display_mode *mode,
-				    struct drm_display_mode *adjusted_mode)
-{
-	/* accept the provided drm_display_mode, do not fix it up */
-	return true;
-}
-
-static int
-sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
-{
-	struct sti_mixer *mixer = to_sti_mixer(crtc);
-	struct device *dev = mixer->dev;
-	struct sti_compositor *compo = dev_get_drvdata(dev);
-	struct clk *clk;
-	int rate = mode->clock * 1000;
-	int res;
-
-	DRM_DEBUG_KMS("CRTC:%d (%s) mode:%d (%s)\n",
-		      crtc->base.id, sti_mixer_to_str(mixer),
-		      mode->base.id, mode->name);
-
-	DRM_DEBUG_KMS("%d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
-		      mode->vrefresh, mode->clock,
-		      mode->hdisplay,
-		      mode->hsync_start, mode->hsync_end,
-		      mode->htotal,
-		      mode->vdisplay,
-		      mode->vsync_start, mode->vsync_end,
-		      mode->vtotal, mode->type, mode->flags);
-
-	/* Set rate and prepare/enable pixel clock */
-	if (mixer->id == STI_MIXER_MAIN)
-		clk = compo->clk_pix_main;
-	else
-		clk = compo->clk_pix_aux;
-
-	res = clk_set_rate(clk, rate);
-	if (res < 0) {
-		DRM_ERROR("Cannot set rate (%dHz) for pix clk\n", rate);
-		return -EINVAL;
-	}
-	if (clk_prepare_enable(clk)) {
-		DRM_ERROR("Failed to prepare/enable pix clk\n");
-		return -EINVAL;
-	}
-
-	sti_vtg_set_config(mixer->id == STI_MIXER_MAIN ?
-			compo->vtg_main : compo->vtg_aux, &crtc->mode);
-
-	res = sti_mixer_active_video_area(mixer, &crtc->mode);
-	if (res) {
-		DRM_ERROR("Can't set active video area\n");
-		return -EINVAL;
-	}
-
-	return res;
-}
-
-static void sti_drm_crtc_disable(struct drm_crtc *crtc)
-{
-	struct sti_mixer *mixer = to_sti_mixer(crtc);
-	struct device *dev = mixer->dev;
-	struct sti_compositor *compo = dev_get_drvdata(dev);
-
-	if (!mixer->enabled)
-		return;
-
-	DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer));
-
-	/* Disable Background */
-	sti_mixer_set_background_status(mixer, false);
-
-	drm_crtc_vblank_off(crtc);
-
-	/* Disable pixel clock and compo IP clocks */
-	if (mixer->id == STI_MIXER_MAIN) {
-		clk_disable_unprepare(compo->clk_pix_main);
-		clk_disable_unprepare(compo->clk_compo_main);
-	} else {
-		clk_disable_unprepare(compo->clk_pix_aux);
-		clk_disable_unprepare(compo->clk_compo_aux);
-	}
-
-	mixer->enabled = false;
-}
-
-static void
-sti_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
-{
-	sti_drm_crtc_prepare(crtc);
-	sti_drm_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
-}
-
-static void sti_drm_crtc_atomic_begin(struct drm_crtc *crtc)
-{
-	struct sti_mixer *mixer = to_sti_mixer(crtc);
-
-	if (crtc->state->event) {
-		crtc->state->event->pipe = drm_crtc_index(crtc);
-
-		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
-
-		mixer->pending_event = crtc->state->event;
-		crtc->state->event = NULL;
-	}
-}
-
-static void sti_drm_crtc_atomic_flush(struct drm_crtc *crtc)
-{
-}
-
-static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
-	.dpms = sti_drm_crtc_dpms,
-	.prepare = sti_drm_crtc_prepare,
-	.commit = sti_drm_crtc_commit,
-	.mode_fixup = sti_drm_crtc_mode_fixup,
-	.mode_set = drm_helper_crtc_mode_set,
-	.mode_set_nofb = sti_drm_crtc_mode_set_nofb,
-	.mode_set_base = drm_helper_crtc_mode_set_base,
-	.disable = sti_drm_crtc_disable,
-	.atomic_begin = sti_drm_crtc_atomic_begin,
-	.atomic_flush = sti_drm_crtc_atomic_flush,
-};
-
-static void sti_drm_crtc_destroy(struct drm_crtc *crtc)
-{
-	DRM_DEBUG_KMS("\n");
-	drm_crtc_cleanup(crtc);
-}
-
-static int sti_drm_crtc_set_property(struct drm_crtc *crtc,
-				     struct drm_property *property,
-				     uint64_t val)
-{
-	DRM_DEBUG_KMS("\n");
-	return 0;
-}
-
-int sti_drm_crtc_vblank_cb(struct notifier_block *nb,
-			   unsigned long event, void *data)
-{
-	struct drm_device *drm_dev;
-	struct sti_compositor *compo =
-		container_of(nb, struct sti_compositor, vtg_vblank_nb);
-	int *crtc = data;
-	unsigned long flags;
-	struct sti_drm_private *priv;
-
-	drm_dev = compo->mixer[*crtc]->drm_crtc.dev;
-	priv = drm_dev->dev_private;
-
-	if ((event != VTG_TOP_FIELD_EVENT) &&
-	    (event != VTG_BOTTOM_FIELD_EVENT)) {
-		DRM_ERROR("unknown event: %lu\n", event);
-		return -EINVAL;
-	}
-
-	drm_handle_vblank(drm_dev, *crtc);
-
-	spin_lock_irqsave(&drm_dev->event_lock, flags);
-	if (compo->mixer[*crtc]->pending_event) {
-		drm_send_vblank_event(drm_dev, -1,
-				compo->mixer[*crtc]->pending_event);
-		drm_vblank_put(drm_dev, *crtc);
-		compo->mixer[*crtc]->pending_event = NULL;
-	}
-	spin_unlock_irqrestore(&drm_dev->event_lock, flags);
-
-	return 0;
-}
-
-int sti_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
-{
-	struct sti_drm_private *dev_priv = dev->dev_private;
-	struct sti_compositor *compo = dev_priv->compo;
-	struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
-
-	DRM_DEBUG_DRIVER("\n");
-
-	if (sti_vtg_register_client(crtc == STI_MIXER_MAIN ?
-			compo->vtg_main : compo->vtg_aux,
-			vtg_vblank_nb, crtc)) {
-		DRM_ERROR("Cannot register VTG notifier\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(sti_drm_crtc_enable_vblank);
-
-void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
-{
-	struct sti_drm_private *priv = dev->dev_private;
-	struct sti_compositor *compo = priv->compo;
-	struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
-
-	DRM_DEBUG_DRIVER("\n");
-
-	if (sti_vtg_unregister_client(crtc == STI_MIXER_MAIN ?
-			compo->vtg_main : compo->vtg_aux, vtg_vblank_nb))
-		DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
-
-	/* free the resources of the pending requests */
-	if (compo->mixer[crtc]->pending_event) {
-		drm_vblank_put(dev, crtc);
-		compo->mixer[crtc]->pending_event = NULL;
-	}
-}
-EXPORT_SYMBOL(sti_drm_crtc_disable_vblank);
-
-static struct drm_crtc_funcs sti_crtc_funcs = {
-	.set_config = drm_atomic_helper_set_config,
-	.page_flip = drm_atomic_helper_page_flip,
-	.destroy = sti_drm_crtc_destroy,
-	.set_property = sti_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,
-};
-
-bool sti_drm_crtc_is_main(struct drm_crtc *crtc)
-{
-	struct sti_mixer *mixer = to_sti_mixer(crtc);
-
-	if (mixer->id == STI_MIXER_MAIN)
-		return true;
-
-	return false;
-}
-EXPORT_SYMBOL(sti_drm_crtc_is_main);
-
-int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
-		struct drm_plane *primary, struct drm_plane *cursor)
-{
-	struct drm_crtc *crtc = &mixer->drm_crtc;
-	int res;
-
-	res = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
-			&sti_crtc_funcs);
-	if (res) {
-		DRM_ERROR("Can't initialze CRTC\n");
-		return -EINVAL;
-	}
-
-	drm_crtc_helper_add(crtc, &sti_crtc_helper_funcs);
-
-	DRM_DEBUG_DRIVER("drm CRTC:%d mapped to %s\n",
-			 crtc->base.id, sti_mixer_to_str(mixer));
-
-	return 0;
-}
diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.h b/drivers/gpu/drm/sti/sti_drm_crtc.h
deleted file mode 100644
index caca8b1..0000000
--- a/drivers/gpu/drm/sti/sti_drm_crtc.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#ifndef _STI_DRM_CRTC_H_
-#define _STI_DRM_CRTC_H_
-
-#include <drm/drmP.h>
-
-struct sti_mixer;
-
-int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
-		struct drm_plane *primary, struct drm_plane *cursor);
-int sti_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
-void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
-int sti_drm_crtc_vblank_cb(struct notifier_block *nb,
-		unsigned long event, void *data);
-bool sti_drm_crtc_is_main(struct drm_crtc *drm_crtc);
-
-#endif
diff --git a/drivers/gpu/drm/sti/sti_drm_drv.c b/drivers/gpu/drm/sti/sti_drm_drv.c
deleted file mode 100644
index 8ad9fe6..0000000
--- a/drivers/gpu/drm/sti/sti_drm_drv.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#include <drm/drmP.h>
-
-#include <linux/component.h>
-#include <linux/debugfs.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of_platform.h>
-
-#include <drm/drm_atomic.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-
-#include "sti_drm_drv.h"
-#include "sti_drm_crtc.h"
-
-#define DRIVER_NAME	"sti"
-#define DRIVER_DESC	"STMicroelectronics SoC DRM"
-#define DRIVER_DATE	"20140601"
-#define DRIVER_MAJOR	1
-#define DRIVER_MINOR	0
-
-#define STI_MAX_FB_HEIGHT	4096
-#define STI_MAX_FB_WIDTH	4096
-
-static void sti_drm_atomic_schedule(struct sti_drm_private *private,
-				  struct drm_atomic_state *state)
-{
-	private->commit.state = state;
-	schedule_work(&private->commit.work);
-}
-
-static void sti_drm_atomic_complete(struct sti_drm_private *private,
-				  struct drm_atomic_state *state)
-{
-	struct drm_device *drm = private->drm_dev;
-
-	/*
-	 * Everything below can be run asynchronously without the need to grab
-	 * any modeset locks at all under one condition: It must be guaranteed
-	 * that the asynchronous work has either been cancelled (if the driver
-	 * supports it, which at least requires that the framebuffers get
-	 * cleaned up with drm_atomic_helper_cleanup_planes()) or completed
-	 * before the new state gets committed on the software side with
-	 * drm_atomic_helper_swap_state().
-	 *
-	 * This scheme allows new atomic state updates to be prepared and
-	 * checked in parallel to the asynchronous completion of the previous
-	 * update. Which is important since compositors need to figure out the
-	 * composition of the next frame right after having submitted the
-	 * current layout.
-	 */
-
-	drm_atomic_helper_commit_modeset_disables(drm, state);
-	drm_atomic_helper_commit_planes(drm, state);
-	drm_atomic_helper_commit_modeset_enables(drm, state);
-
-	drm_atomic_helper_wait_for_vblanks(drm, state);
-
-	drm_atomic_helper_cleanup_planes(drm, state);
-	drm_atomic_state_free(state);
-}
-
-static void sti_drm_atomic_work(struct work_struct *work)
-{
-	struct sti_drm_private *private = container_of(work,
-			struct sti_drm_private, commit.work);
-
-	sti_drm_atomic_complete(private, private->commit.state);
-}
-
-static int sti_drm_atomic_commit(struct drm_device *drm,
-			       struct drm_atomic_state *state, bool async)
-{
-	struct sti_drm_private *private = drm->dev_private;
-	int err;
-
-	err = drm_atomic_helper_prepare_planes(drm, state);
-	if (err)
-		return err;
-
-	/* serialize outstanding asynchronous commits */
-	mutex_lock(&private->commit.lock);
-	flush_work(&private->commit.work);
-
-	/*
-	 * This is the point of no return - everything below never fails except
-	 * when the hw goes bonghits. Which means we can commit the new state on
-	 * the software side now.
-	 */
-
-	drm_atomic_helper_swap_state(drm, state);
-
-	if (async)
-		sti_drm_atomic_schedule(private, state);
-	else
-		sti_drm_atomic_complete(private, state);
-
-	mutex_unlock(&private->commit.lock);
-	return 0;
-}
-
-static struct drm_mode_config_funcs sti_drm_mode_config_funcs = {
-	.fb_create = drm_fb_cma_create,
-	.atomic_check = drm_atomic_helper_check,
-	.atomic_commit = sti_drm_atomic_commit,
-};
-
-static void sti_drm_mode_config_init(struct drm_device *dev)
-{
-	dev->mode_config.min_width = 0;
-	dev->mode_config.min_height = 0;
-
-	/*
-	 * set max width and height as default value.
-	 * this value would be used to check framebuffer size limitation
-	 * at drm_mode_addfb().
-	 */
-	dev->mode_config.max_width = STI_MAX_FB_HEIGHT;
-	dev->mode_config.max_height = STI_MAX_FB_WIDTH;
-
-	dev->mode_config.funcs = &sti_drm_mode_config_funcs;
-}
-
-static int sti_drm_load(struct drm_device *dev, unsigned long flags)
-{
-	struct sti_drm_private *private;
-	int ret;
-
-	private = kzalloc(sizeof(struct sti_drm_private), GFP_KERNEL);
-	if (!private) {
-		DRM_ERROR("Failed to allocate private\n");
-		return -ENOMEM;
-	}
-	dev->dev_private = (void *)private;
-	private->drm_dev = dev;
-
-	mutex_init(&private->commit.lock);
-	INIT_WORK(&private->commit.work, sti_drm_atomic_work);
-
-	drm_mode_config_init(dev);
-	drm_kms_helper_poll_init(dev);
-
-	sti_drm_mode_config_init(dev);
-
-	ret = component_bind_all(dev->dev, dev);
-	if (ret) {
-		drm_kms_helper_poll_fini(dev);
-		drm_mode_config_cleanup(dev);
-		kfree(private);
-		return ret;
-	}
-
-	drm_mode_config_reset(dev);
-
-#ifdef CONFIG_DRM_STI_FBDEV
-	drm_fbdev_cma_init(dev, 32,
-		   dev->mode_config.num_crtc,
-		   dev->mode_config.num_connector);
-#endif
-	return 0;
-}
-
-static const struct file_operations sti_drm_driver_fops = {
-	.owner = THIS_MODULE,
-	.open = drm_open,
-	.mmap = drm_gem_cma_mmap,
-	.poll = drm_poll,
-	.read = drm_read,
-	.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl = drm_compat_ioctl,
-#endif
-	.release = drm_release,
-};
-
-static struct dma_buf *sti_drm_gem_prime_export(struct drm_device *dev,
-						struct drm_gem_object *obj,
-						int flags)
-{
-	/* we want to be able to write in mmapped buffer */
-	flags |= O_RDWR;
-	return drm_gem_prime_export(dev, obj, flags);
-}
-
-static struct drm_driver sti_drm_driver = {
-	.driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET |
-	    DRIVER_GEM | DRIVER_PRIME,
-	.load = sti_drm_load,
-	.gem_free_object = drm_gem_cma_free_object,
-	.gem_vm_ops = &drm_gem_cma_vm_ops,
-	.dumb_create = drm_gem_cma_dumb_create,
-	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
-	.dumb_destroy = drm_gem_dumb_destroy,
-	.fops = &sti_drm_driver_fops,
-
-	.get_vblank_counter = drm_vblank_count,
-	.enable_vblank = sti_drm_crtc_enable_vblank,
-	.disable_vblank = sti_drm_crtc_disable_vblank,
-
-	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
-	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-	.gem_prime_export = sti_drm_gem_prime_export,
-	.gem_prime_import = drm_gem_prime_import,
-	.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
-	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
-	.gem_prime_vmap = drm_gem_cma_prime_vmap,
-	.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
-	.gem_prime_mmap = drm_gem_cma_prime_mmap,
-
-	.name = DRIVER_NAME,
-	.desc = DRIVER_DESC,
-	.date = DRIVER_DATE,
-	.major = DRIVER_MAJOR,
-	.minor = DRIVER_MINOR,
-};
-
-static int compare_of(struct device *dev, void *data)
-{
-	return dev->of_node == data;
-}
-
-static int sti_drm_bind(struct device *dev)
-{
-	return drm_platform_init(&sti_drm_driver, to_platform_device(dev));
-}
-
-static void sti_drm_unbind(struct device *dev)
-{
-	drm_put_dev(dev_get_drvdata(dev));
-}
-
-static const struct component_master_ops sti_drm_ops = {
-	.bind = sti_drm_bind,
-	.unbind = sti_drm_unbind,
-};
-
-static int sti_drm_platform_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct device_node *node = dev->of_node;
-	struct device_node *child_np;
-	struct component_match *match = NULL;
-
-	dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
-
-	of_platform_populate(node, NULL, NULL, dev);
-
-	child_np = of_get_next_available_child(node, NULL);
-
-	while (child_np) {
-		component_match_add(dev, &match, compare_of, child_np);
-		of_node_put(child_np);
-		child_np = of_get_next_available_child(node, child_np);
-	}
-
-	return component_master_add_with_match(dev, &sti_drm_ops, match);
-}
-
-static int sti_drm_platform_remove(struct platform_device *pdev)
-{
-	component_master_del(&pdev->dev, &sti_drm_ops);
-	of_platform_depopulate(&pdev->dev);
-
-	return 0;
-}
-
-static const struct of_device_id sti_drm_dt_ids[] = {
-	{ .compatible = "st,sti-display-subsystem", },
-	{ /* end node */ },
-};
-MODULE_DEVICE_TABLE(of, sti_drm_dt_ids);
-
-static struct platform_driver sti_drm_platform_driver = {
-	.probe = sti_drm_platform_probe,
-	.remove = sti_drm_platform_remove,
-	.driver = {
-		.name = DRIVER_NAME,
-		.of_match_table = sti_drm_dt_ids,
-	},
-};
-
-module_platform_driver(sti_drm_platform_driver);
-
-MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
-MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_drm_drv.h b/drivers/gpu/drm/sti/sti_drm_drv.h
deleted file mode 100644
index c413aa3..0000000
--- a/drivers/gpu/drm/sti/sti_drm_drv.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#ifndef _STI_DRM_DRV_H_
-#define _STI_DRM_DRV_H_
-
-#include <drm/drmP.h>
-
-struct sti_compositor;
-struct sti_tvout;
-
-/**
- * STI drm private structure
- * This structure is stored as private in the drm_device
- *
- * @compo:                 compositor
- * @plane_zorder_property: z-order property for CRTC planes
- * @drm_dev:               drm device
- */
-struct sti_drm_private {
-	struct sti_compositor *compo;
-	struct drm_property *plane_zorder_property;
-	struct drm_device *drm_dev;
-
-	struct {
-		struct drm_atomic_state *state;
-		struct work_struct work;
-		struct mutex lock;
-	} commit;
-};
-
-#endif
diff --git a/drivers/gpu/drm/sti/sti_drm_plane.c b/drivers/gpu/drm/sti/sti_drm_plane.c
deleted file mode 100644
index 0d16722..0000000
--- a/drivers/gpu/drm/sti/sti_drm_plane.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
- *          Fabien Dessenne <fabien.dessenne@st.com>
- *          for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_plane_helper.h>
-
-#include "sti_compositor.h"
-#include "sti_drm_drv.h"
-#include "sti_drm_plane.h"
-#include "sti_vtg.h"
-
-/* (Background) < GDP0 < GDP1 < HQVDP0 < GDP2 < GDP3 < (ForeGround) */
-enum sti_plane_desc sti_plane_default_zorder[] = {
-	STI_GDP_0,
-	STI_GDP_1,
-	STI_HQVDP_0,
-	STI_GDP_2,
-	STI_GDP_3,
-};
-
-const char *sti_plane_to_str(struct sti_plane *plane)
-{
-	switch (plane->desc) {
-	case STI_GDP_0:
-		return "GDP0";
-	case STI_GDP_1:
-		return "GDP1";
-	case STI_GDP_2:
-		return "GDP2";
-	case STI_GDP_3:
-		return "GDP3";
-	case STI_HQVDP_0:
-		return "HQVDP0";
-	case STI_CURSOR:
-		return "CURSOR";
-	default:
-		return "<UNKNOWN PLANE>";
-	}
-}
-EXPORT_SYMBOL(sti_plane_to_str);
-
-static int sti_plane_prepare(struct sti_plane *plane,
-			     struct drm_crtc *crtc,
-			     struct drm_framebuffer *fb,
-			     struct drm_display_mode *mode, int mixer_id,
-			     int dest_x, int dest_y, int dest_w, int dest_h,
-			     int src_x, int src_y, int src_w, int src_h)
-{
-	struct drm_gem_cma_object *cma_obj;
-	unsigned int i;
-	int res;
-
-	if (!plane || !fb || !mode) {
-		DRM_ERROR("Null fb, plane or mode\n");
-		return 1;
-	}
-
-	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-	if (!cma_obj) {
-		DRM_ERROR("Can't get CMA GEM object for fb\n");
-		return 1;
-	}
-
-	plane->fb = fb;
-	plane->mode = mode;
-	plane->mixer_id = mixer_id;
-	plane->dst_x = dest_x;
-	plane->dst_y = dest_y;
-	plane->dst_w = clamp_val(dest_w, 0, mode->crtc_hdisplay - dest_x);
-	plane->dst_h = clamp_val(dest_h, 0, mode->crtc_vdisplay - dest_y);
-	plane->src_x = src_x;
-	plane->src_y = src_y;
-	plane->src_w = src_w;
-	plane->src_h = src_h;
-	plane->format = fb->pixel_format;
-	plane->vaddr = cma_obj->vaddr;
-	plane->paddr = cma_obj->paddr;
-	for (i = 0; i < 4; i++) {
-		plane->pitches[i] = fb->pitches[i];
-		plane->offsets[i] = fb->offsets[i];
-	}
-
-	DRM_DEBUG_DRIVER("%s is associated with mixer_id %d\n",
-			 sti_plane_to_str(plane),
-			 plane->mixer_id);
-	DRM_DEBUG_DRIVER("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
-			 sti_plane_to_str(plane),
-			 plane->dst_w, plane->dst_h, plane->dst_x, plane->dst_y,
-			 plane->src_w, plane->src_h, plane->src_x,
-			 plane->src_y);
-
-	DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
-			 (char *)&plane->format, (unsigned long)plane->paddr);
-
-	if (!plane->ops->prepare) {
-		DRM_ERROR("Cannot prepare\n");
-		return 1;
-	}
-
-	res = plane->ops->prepare(plane, !plane->enabled);
-	if (res) {
-		DRM_ERROR("Plane prepare failed\n");
-		return res;
-	}
-
-	plane->enabled = true;
-
-	return 0;
-}
-
-static int sti_plane_commit(struct sti_plane *plane)
-{
-	if (!plane)
-		return 1;
-
-	if (!plane->ops->commit) {
-		DRM_ERROR("Cannot commit\n");
-		return 1;
-	}
-
-	return plane->ops->commit(plane);
-}
-
-static int sti_plane_disable(struct sti_plane *plane)
-{
-	int res;
-
-	DRM_DEBUG_DRIVER("%s\n", sti_plane_to_str(plane));
-	if (!plane)
-		return 1;
-
-	if (!plane->enabled)
-		return 0;
-
-	if (!plane->ops->disable) {
-		DRM_ERROR("Cannot disable\n");
-		return 1;
-	}
-
-	res = plane->ops->disable(plane);
-	if (res) {
-		DRM_ERROR("Plane disable failed\n");
-		return res;
-	}
-
-	plane->enabled = false;
-
-	return 0;
-}
-
-static void sti_drm_plane_destroy(struct drm_plane *drm_plane)
-{
-	DRM_DEBUG_DRIVER("\n");
-
-	drm_plane_helper_disable(drm_plane);
-	drm_plane_cleanup(drm_plane);
-}
-
-static int sti_drm_plane_set_property(struct drm_plane *drm_plane,
-				      struct drm_property *property,
-				      uint64_t val)
-{
-	struct drm_device *dev = drm_plane->dev;
-	struct sti_drm_private *private = dev->dev_private;
-	struct sti_plane *plane = to_sti_plane(drm_plane);
-
-	DRM_DEBUG_DRIVER("\n");
-
-	if (property == private->plane_zorder_property) {
-		plane->zorder = val;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static struct drm_plane_funcs sti_drm_plane_funcs = {
-	.update_plane = drm_atomic_helper_update_plane,
-	.disable_plane = drm_atomic_helper_disable_plane,
-	.destroy = sti_drm_plane_destroy,
-	.set_property = sti_drm_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 sti_drm_plane_atomic_check(struct drm_plane *drm_plane,
-				      struct drm_plane_state *state)
-{
-	return 0;
-}
-
-static void sti_drm_plane_atomic_update(struct drm_plane *drm_plane,
-					struct drm_plane_state *oldstate)
-{
-	struct drm_plane_state *state = drm_plane->state;
-	struct sti_plane *plane = to_sti_plane(drm_plane);
-	struct sti_mixer *mixer = to_sti_mixer(state->crtc);
-	int res;
-
-	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
-		      state->crtc->base.id, sti_mixer_to_str(mixer),
-		      drm_plane->base.id, sti_plane_to_str(plane));
-	DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n",
-		      state->crtc_w, state->crtc_h,
-		      state->crtc_x, state->crtc_y);
-
-	res = sti_mixer_set_plane_depth(mixer, plane);
-	if (res) {
-		DRM_ERROR("Cannot set plane depth\n");
-		return;
-	}
-
-	/* src_x are in 16.16 format */
-	res = sti_plane_prepare(plane, state->crtc, state->fb,
-				&state->crtc->mode, mixer->id,
-				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);
-	if (res) {
-		DRM_ERROR("Plane prepare failed\n");
-		return;
-	}
-
-	res = sti_plane_commit(plane);
-	if (res) {
-		DRM_ERROR("Plane commit failed\n");
-		return;
-	}
-
-	res = sti_mixer_set_plane_status(mixer, plane, true);
-	if (res) {
-		DRM_ERROR("Cannot enable plane at mixer\n");
-		return;
-	}
-}
-
-static void sti_drm_plane_atomic_disable(struct drm_plane *drm_plane,
-					 struct drm_plane_state *oldstate)
-{
-	struct sti_plane *plane = to_sti_plane(drm_plane);
-	struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);
-	int res;
-
-	if (!drm_plane->crtc) {
-		DRM_DEBUG_DRIVER("drm plane:%d not enabled\n",
-				 drm_plane->base.id);
-		return;
-	}
-
-	DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
-			 drm_plane->crtc->base.id, sti_mixer_to_str(mixer),
-			 drm_plane->base.id, sti_plane_to_str(plane));
-
-	/* Disable plane at mixer level */
-	res = sti_mixer_set_plane_status(mixer, plane, false);
-	if (res) {
-		DRM_ERROR("Cannot disable plane at mixer\n");
-		return;
-	}
-
-	/* Wait a while to be sure that a Vsync event is received */
-	msleep(WAIT_NEXT_VSYNC_MS);
-
-	/* Then disable plane itself */
-	res = sti_plane_disable(plane);
-	if (res) {
-		DRM_ERROR("Plane disable failed\n");
-		return;
-	}
-}
-
-static const struct drm_plane_helper_funcs sti_drm_plane_helpers_funcs = {
-	.atomic_check = sti_drm_plane_atomic_check,
-	.atomic_update = sti_drm_plane_atomic_update,
-	.atomic_disable = sti_drm_plane_atomic_disable,
-};
-
-static void sti_drm_plane_attach_zorder_property(struct drm_plane *drm_plane)
-{
-	struct drm_device *dev = drm_plane->dev;
-	struct sti_drm_private *private = dev->dev_private;
-	struct sti_plane *plane = to_sti_plane(drm_plane);
-	struct drm_property *prop;
-
-	prop = private->plane_zorder_property;
-	if (!prop) {
-		prop = drm_property_create_range(dev, 0, "zpos", 1,
-						 GAM_MIXER_NB_DEPTH_LEVEL);
-		if (!prop)
-			return;
-
-		private->plane_zorder_property = prop;
-	}
-
-	drm_object_attach_property(&drm_plane->base, prop, plane->zorder);
-}
-
-struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
-				 struct sti_plane *plane,
-				 unsigned int possible_crtcs,
-				 enum drm_plane_type type)
-{
-	int err, i;
-
-	err = drm_universal_plane_init(dev, &plane->drm_plane,
-				       possible_crtcs,
-				       &sti_drm_plane_funcs,
-				       plane->ops->get_formats(plane),
-				       plane->ops->get_nb_formats(plane),
-				       type);
-	if (err) {
-		DRM_ERROR("Failed to initialize universal plane\n");
-		return NULL;
-	}
-
-	drm_plane_helper_add(&plane->drm_plane,
-			     &sti_drm_plane_helpers_funcs);
-
-	for (i = 0; i < ARRAY_SIZE(sti_plane_default_zorder); i++)
-		if (sti_plane_default_zorder[i] == plane->desc)
-			break;
-
-	plane->zorder = i + 1;
-
-	if (type == DRM_PLANE_TYPE_OVERLAY)
-		sti_drm_plane_attach_zorder_property(&plane->drm_plane);
-
-	DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%d\n",
-			 plane->drm_plane.base.id,
-			 sti_plane_to_str(plane), plane->zorder);
-
-	return &plane->drm_plane;
-}
-EXPORT_SYMBOL(sti_drm_plane_init);
diff --git a/drivers/gpu/drm/sti/sti_drm_plane.h b/drivers/gpu/drm/sti/sti_drm_plane.h
deleted file mode 100644
index e547366..0000000
--- a/drivers/gpu/drm/sti/sti_drm_plane.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#ifndef _STI_DRM_PLANE_H_
-#define _STI_DRM_PLANE_H_
-
-#include <drm/drmP.h>
-
-#define to_sti_plane(x) container_of(x, struct sti_plane, drm_plane)
-
-#define STI_PLANE_TYPE_SHIFT 8
-#define STI_PLANE_TYPE_MASK (~((1 << STI_PLANE_TYPE_SHIFT) - 1))
-
-enum sti_plane_type {
-	STI_GDP = 1 << STI_PLANE_TYPE_SHIFT,
-	STI_VDP = 2 << STI_PLANE_TYPE_SHIFT,
-	STI_CUR = 3 << STI_PLANE_TYPE_SHIFT,
-	STI_BCK = 4 << STI_PLANE_TYPE_SHIFT
-};
-
-enum sti_plane_id_of_type {
-	STI_ID_0 = 0,
-	STI_ID_1 = 1,
-	STI_ID_2 = 2,
-	STI_ID_3 = 3
-};
-
-enum sti_plane_desc {
-	STI_GDP_0       = STI_GDP | STI_ID_0,
-	STI_GDP_1       = STI_GDP | STI_ID_1,
-	STI_GDP_2       = STI_GDP | STI_ID_2,
-	STI_GDP_3       = STI_GDP | STI_ID_3,
-	STI_HQVDP_0     = STI_VDP | STI_ID_0,
-	STI_CURSOR      = STI_CUR,
-	STI_BACK        = STI_BCK
-};
-
-/**
- * STI plane structure
- *
- * @plane:              drm plane it is bound to (if any)
- * @fb:                 drm fb it is bound to
- * @mode:               display mode
- * @desc:               plane type & id
- * @ops:                plane functions
- * @zorder:             plane z-order
- * @mixer_id:           id of the mixer used to display the plane
- * @enabled:            to know if the plane is active or not
- * @src_x src_y:        coordinates of the input (fb) area
- * @src_w src_h:        size of the input (fb) area
- * @dst_x dst_y:        coordinates of the output (crtc) area
- * @dst_w dst_h:        size of the output (crtc) area
- * @format:             format
- * @pitches:            pitch of 'planes' (eg: Y, U, V)
- * @offsets:            offset of 'planes'
- * @vaddr:              virtual address of the input buffer
- * @paddr:              physical address of the input buffer
- */
-struct sti_plane {
-	struct drm_plane drm_plane;
-	struct drm_framebuffer *fb;
-	struct drm_display_mode *mode;
-	enum sti_plane_desc desc;
-	const struct sti_plane_funcs *ops;
-	int zorder;
-	int mixer_id;
-	bool enabled;
-	int src_x, src_y;
-	int src_w, src_h;
-	int dst_x, dst_y;
-	int dst_w, dst_h;
-	uint32_t format;
-	unsigned int pitches[4];
-	unsigned int offsets[4];
-	void *vaddr;
-	dma_addr_t paddr;
-};
-
-/**
- * STI plane functions structure
- *
- * @get_formats:     get plane supported formats
- * @get_nb_formats:  get number of format supported
- * @prepare:         prepare plane before rendering
- * @commit:          set plane for rendering
- * @disable:         disable plane
- */
-struct sti_plane_funcs {
-	const uint32_t* (*get_formats)(struct sti_plane *plane);
-	unsigned int (*get_nb_formats)(struct sti_plane *plane);
-	int (*prepare)(struct sti_plane *plane, bool first_prepare);
-	int (*commit)(struct sti_plane *plane);
-	int (*disable)(struct sti_plane *plane);
-};
-
-struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
-		struct sti_plane *sti_plane,
-		unsigned int possible_crtcs,
-		enum drm_plane_type type);
-const char *sti_plane_to_str(struct sti_plane *plane);
-
-#endif
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c
new file mode 100644
index 0000000..6f4af6a
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_drv.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <drm/drmP.h>
+
+#include <linux/component.h>
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "sti_crtc.h"
+#include "sti_drv.h"
+
+#define DRIVER_NAME	"sti"
+#define DRIVER_DESC	"STMicroelectronics SoC DRM"
+#define DRIVER_DATE	"20140601"
+#define DRIVER_MAJOR	1
+#define DRIVER_MINOR	0
+
+#define STI_MAX_FB_HEIGHT	4096
+#define STI_MAX_FB_WIDTH	4096
+
+static void sti_atomic_schedule(struct sti_private *private,
+				struct drm_atomic_state *state)
+{
+	private->commit.state = state;
+	schedule_work(&private->commit.work);
+}
+
+static void sti_atomic_complete(struct sti_private *private,
+				struct drm_atomic_state *state)
+{
+	struct drm_device *drm = private->drm_dev;
+
+	/*
+	 * Everything below can be run asynchronously without the need to grab
+	 * any modeset locks at all under one condition: It must be guaranteed
+	 * that the asynchronous work has either been cancelled (if the driver
+	 * supports it, which at least requires that the framebuffers get
+	 * cleaned up with drm_atomic_helper_cleanup_planes()) or completed
+	 * before the new state gets committed on the software side with
+	 * drm_atomic_helper_swap_state().
+	 *
+	 * This scheme allows new atomic state updates to be prepared and
+	 * checked in parallel to the asynchronous completion of the previous
+	 * update. Which is important since compositors need to figure out the
+	 * composition of the next frame right after having submitted the
+	 * current layout.
+	 */
+
+	drm_atomic_helper_commit_modeset_disables(drm, state);
+	drm_atomic_helper_commit_planes(drm, state);
+	drm_atomic_helper_commit_modeset_enables(drm, state);
+
+	drm_atomic_helper_wait_for_vblanks(drm, state);
+
+	drm_atomic_helper_cleanup_planes(drm, state);
+	drm_atomic_state_free(state);
+}
+
+static void sti_atomic_work(struct work_struct *work)
+{
+	struct sti_private *private = container_of(work,
+			struct sti_private, commit.work);
+
+	sti_atomic_complete(private, private->commit.state);
+}
+
+static int sti_atomic_commit(struct drm_device *drm,
+			     struct drm_atomic_state *state, bool async)
+{
+	struct sti_private *private = drm->dev_private;
+	int err;
+
+	err = drm_atomic_helper_prepare_planes(drm, state);
+	if (err)
+		return err;
+
+	/* serialize outstanding asynchronous commits */
+	mutex_lock(&private->commit.lock);
+	flush_work(&private->commit.work);
+
+	/*
+	 * This is the point of no return - everything below never fails except
+	 * when the hw goes bonghits. Which means we can commit the new state on
+	 * the software side now.
+	 */
+
+	drm_atomic_helper_swap_state(drm, state);
+
+	if (async)
+		sti_atomic_schedule(private, state);
+	else
+		sti_atomic_complete(private, state);
+
+	mutex_unlock(&private->commit.lock);
+	return 0;
+}
+
+static struct drm_mode_config_funcs sti_mode_config_funcs = {
+	.fb_create = drm_fb_cma_create,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = sti_atomic_commit,
+};
+
+static void sti_mode_config_init(struct drm_device *dev)
+{
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+
+	/*
+	 * set max width and height as default value.
+	 * this value would be used to check framebuffer size limitation
+	 * at drm_mode_addfb().
+	 */
+	dev->mode_config.max_width = STI_MAX_FB_HEIGHT;
+	dev->mode_config.max_height = STI_MAX_FB_WIDTH;
+
+	dev->mode_config.funcs = &sti_mode_config_funcs;
+}
+
+static int sti_load(struct drm_device *dev, unsigned long flags)
+{
+	struct sti_private *private;
+	int ret;
+
+	private = kzalloc(sizeof(*private), GFP_KERNEL);
+	if (!private) {
+		DRM_ERROR("Failed to allocate private\n");
+		return -ENOMEM;
+	}
+	dev->dev_private = (void *)private;
+	private->drm_dev = dev;
+
+	mutex_init(&private->commit.lock);
+	INIT_WORK(&private->commit.work, sti_atomic_work);
+
+	drm_mode_config_init(dev);
+	drm_kms_helper_poll_init(dev);
+
+	sti_mode_config_init(dev);
+
+	ret = component_bind_all(dev->dev, dev);
+	if (ret) {
+		drm_kms_helper_poll_fini(dev);
+		drm_mode_config_cleanup(dev);
+		kfree(private);
+		return ret;
+	}
+
+	drm_mode_config_reset(dev);
+
+#ifdef CONFIG_DRM_STI_FBDEV
+	drm_fbdev_cma_init(dev, 32,
+			   dev->mode_config.num_crtc,
+			   dev->mode_config.num_connector);
+#endif
+	return 0;
+}
+
+static const struct file_operations sti_driver_fops = {
+	.owner = THIS_MODULE,
+	.open = drm_open,
+	.mmap = drm_gem_cma_mmap,
+	.poll = drm_poll,
+	.read = drm_read,
+	.unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = drm_compat_ioctl,
+#endif
+	.release = drm_release,
+};
+
+static struct dma_buf *sti_gem_prime_export(struct drm_device *dev,
+					    struct drm_gem_object *obj,
+					    int flags)
+{
+	/* we want to be able to write in mmapped buffer */
+	flags |= O_RDWR;
+	return drm_gem_prime_export(dev, obj, flags);
+}
+
+static struct drm_driver sti_driver = {
+	.driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET |
+	    DRIVER_GEM | DRIVER_PRIME,
+	.load = sti_load,
+	.gem_free_object = drm_gem_cma_free_object,
+	.gem_vm_ops = &drm_gem_cma_vm_ops,
+	.dumb_create = drm_gem_cma_dumb_create,
+	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
+	.dumb_destroy = drm_gem_dumb_destroy,
+	.fops = &sti_driver_fops,
+
+	.get_vblank_counter = drm_vblank_count,
+	.enable_vblank = sti_crtc_enable_vblank,
+	.disable_vblank = sti_crtc_disable_vblank,
+
+	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+	.gem_prime_export = sti_gem_prime_export,
+	.gem_prime_import = drm_gem_prime_import,
+	.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap = drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap = drm_gem_cma_prime_mmap,
+
+	.name = DRIVER_NAME,
+	.desc = DRIVER_DESC,
+	.date = DRIVER_DATE,
+	.major = DRIVER_MAJOR,
+	.minor = DRIVER_MINOR,
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static int sti_bind(struct device *dev)
+{
+	return drm_platform_init(&sti_driver, to_platform_device(dev));
+}
+
+static void sti_unbind(struct device *dev)
+{
+	drm_put_dev(dev_get_drvdata(dev));
+}
+
+static const struct component_master_ops sti_ops = {
+	.bind = sti_bind,
+	.unbind = sti_unbind,
+};
+
+static int sti_platform_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct device_node *child_np;
+	struct component_match *match = NULL;
+
+	dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+
+	of_platform_populate(node, NULL, NULL, dev);
+
+	child_np = of_get_next_available_child(node, NULL);
+
+	while (child_np) {
+		component_match_add(dev, &match, compare_of, child_np);
+		of_node_put(child_np);
+		child_np = of_get_next_available_child(node, child_np);
+	}
+
+	return component_master_add_with_match(dev, &sti_ops, match);
+}
+
+static int sti_platform_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &sti_ops);
+	of_platform_depopulate(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id sti_dt_ids[] = {
+	{ .compatible = "st,sti-display-subsystem", },
+	{ /* end node */ },
+};
+MODULE_DEVICE_TABLE(of, sti_dt_ids);
+
+static struct platform_driver sti_platform_driver = {
+	.probe = sti_platform_probe,
+	.remove = sti_platform_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = sti_dt_ids,
+	},
+};
+
+module_platform_driver(sti_platform_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_drv.h b/drivers/gpu/drm/sti/sti_drv.h
new file mode 100644
index 0000000..9372f69
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_drv.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_DRV_H_
+#define _STI_DRV_H_
+
+#include <drm/drmP.h>
+
+struct sti_compositor;
+struct sti_tvout;
+
+/**
+ * STI drm private structure
+ * This structure is stored as private in the drm_device
+ *
+ * @compo:                 compositor
+ * @plane_zorder_property: z-order property for CRTC planes
+ * @drm_dev:               drm device
+ */
+struct sti_private {
+	struct sti_compositor *compo;
+	struct drm_property *plane_zorder_property;
+	struct drm_device *drm_dev;
+
+	struct {
+		struct drm_atomic_state *state;
+		struct work_struct work;
+		struct mutex lock;
+	} commit;
+};
+
+#endif
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
index e94d0be..e323310 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -10,8 +10,8 @@
 #include <linux/dma-mapping.h>
 
 #include "sti_compositor.h"
-#include "sti_drm_plane.h"
 #include "sti_gdp.h"
+#include "sti_plane.h"
 #include "sti_vtg.h"
 
 #define ALPHASWITCH     BIT(6)
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index 54e8c2f..b91a009 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -13,8 +13,8 @@
 
 #include <drm/drmP.h>
 
-#include "sti_drm_plane.h"
 #include "sti_hqvdp_lut.h"
+#include "sti_plane.h"
 #include "sti_vtg.h"
 
 /* Firmware name */
@@ -967,8 +967,8 @@ int sti_hqvdp_bind(struct device *dev, struct device *master, void *data)
 	/* Create HQVDP plane once xp70 is initialized */
 	plane = sti_hqvdp_create(hqvdp->dev, STI_HQVDP_0);
 	if (plane)
-		sti_drm_plane_init(hqvdp->drm_dev, plane, 1,
-				   DRM_PLANE_TYPE_OVERLAY);
+		sti_plane_init(hqvdp->drm_dev, plane, 1,
+			       DRM_PLANE_TYPE_OVERLAY);
 	else
 		DRM_ERROR("Can't create HQVDP plane\n");
 
diff --git a/drivers/gpu/drm/sti/sti_mixer.h b/drivers/gpu/drm/sti/sti_mixer.h
index 9d51eac..2f69b00 100644
--- a/drivers/gpu/drm/sti/sti_mixer.h
+++ b/drivers/gpu/drm/sti/sti_mixer.h
@@ -11,7 +11,7 @@
 
 #include <drm/drmP.h>
 
-#include "sti_drm_plane.h"
+#include "sti_plane.h"
 
 #define to_sti_mixer(x) container_of(x, struct sti_mixer, drm_crtc)
 
diff --git a/drivers/gpu/drm/sti/sti_plane.c b/drivers/gpu/drm/sti/sti_plane.c
new file mode 100644
index 0000000..6a38521
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_plane.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include "sti_compositor.h"
+#include "sti_drv.h"
+#include "sti_plane.h"
+#include "sti_vtg.h"
+
+/* (Background) < GDP0 < GDP1 < HQVDP0 < GDP2 < GDP3 < (ForeGround) */
+enum sti_plane_desc sti_plane_default_zorder[] = {
+	STI_GDP_0,
+	STI_GDP_1,
+	STI_HQVDP_0,
+	STI_GDP_2,
+	STI_GDP_3,
+};
+
+const char *sti_plane_to_str(struct sti_plane *plane)
+{
+	switch (plane->desc) {
+	case STI_GDP_0:
+		return "GDP0";
+	case STI_GDP_1:
+		return "GDP1";
+	case STI_GDP_2:
+		return "GDP2";
+	case STI_GDP_3:
+		return "GDP3";
+	case STI_HQVDP_0:
+		return "HQVDP0";
+	case STI_CURSOR:
+		return "CURSOR";
+	default:
+		return "<UNKNOWN PLANE>";
+	}
+}
+EXPORT_SYMBOL(sti_plane_to_str);
+
+static int sti_plane_prepare(struct sti_plane *plane,
+			     struct drm_crtc *crtc,
+			     struct drm_framebuffer *fb,
+			     struct drm_display_mode *mode, int mixer_id,
+			     int dest_x, int dest_y, int dest_w, int dest_h,
+			     int src_x, int src_y, int src_w, int src_h)
+{
+	struct drm_gem_cma_object *cma_obj;
+	unsigned int i;
+	int res;
+
+	if (!plane || !fb || !mode) {
+		DRM_ERROR("Null fb, plane or mode\n");
+		return 1;
+	}
+
+	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+	if (!cma_obj) {
+		DRM_ERROR("Can't get CMA GEM object for fb\n");
+		return 1;
+	}
+
+	plane->fb = fb;
+	plane->mode = mode;
+	plane->mixer_id = mixer_id;
+	plane->dst_x = dest_x;
+	plane->dst_y = dest_y;
+	plane->dst_w = clamp_val(dest_w, 0, mode->crtc_hdisplay - dest_x);
+	plane->dst_h = clamp_val(dest_h, 0, mode->crtc_vdisplay - dest_y);
+	plane->src_x = src_x;
+	plane->src_y = src_y;
+	plane->src_w = src_w;
+	plane->src_h = src_h;
+	plane->format = fb->pixel_format;
+	plane->vaddr = cma_obj->vaddr;
+	plane->paddr = cma_obj->paddr;
+	for (i = 0; i < 4; i++) {
+		plane->pitches[i] = fb->pitches[i];
+		plane->offsets[i] = fb->offsets[i];
+	}
+
+	DRM_DEBUG_DRIVER("%s is associated with mixer_id %d\n",
+			 sti_plane_to_str(plane),
+			 plane->mixer_id);
+	DRM_DEBUG_DRIVER("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
+			 sti_plane_to_str(plane),
+			 plane->dst_w, plane->dst_h, plane->dst_x, plane->dst_y,
+			 plane->src_w, plane->src_h, plane->src_x,
+			 plane->src_y);
+
+	DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
+			 (char *)&plane->format, (unsigned long)plane->paddr);
+
+	if (!plane->ops->prepare) {
+		DRM_ERROR("Cannot prepare\n");
+		return 1;
+	}
+
+	res = plane->ops->prepare(plane, !plane->enabled);
+	if (res) {
+		DRM_ERROR("Plane prepare failed\n");
+		return res;
+	}
+
+	plane->enabled = true;
+
+	return 0;
+}
+
+static int sti_plane_commit(struct sti_plane *plane)
+{
+	if (!plane)
+		return 1;
+
+	if (!plane->ops->commit) {
+		DRM_ERROR("Cannot commit\n");
+		return 1;
+	}
+
+	return plane->ops->commit(plane);
+}
+
+static int sti_plane_disable(struct sti_plane *plane)
+{
+	int res;
+
+	DRM_DEBUG_DRIVER("%s\n", sti_plane_to_str(plane));
+	if (!plane)
+		return 1;
+
+	if (!plane->enabled)
+		return 0;
+
+	if (!plane->ops->disable) {
+		DRM_ERROR("Cannot disable\n");
+		return 1;
+	}
+
+	res = plane->ops->disable(plane);
+	if (res) {
+		DRM_ERROR("Plane disable failed\n");
+		return res;
+	}
+
+	plane->enabled = false;
+
+	return 0;
+}
+
+static void sti_plane_destroy(struct drm_plane *drm_plane)
+{
+	DRM_DEBUG_DRIVER("\n");
+
+	drm_plane_helper_disable(drm_plane);
+	drm_plane_cleanup(drm_plane);
+}
+
+static int sti_plane_set_property(struct drm_plane *drm_plane,
+				  struct drm_property *property,
+				  uint64_t val)
+{
+	struct drm_device *dev = drm_plane->dev;
+	struct sti_private *private = dev->dev_private;
+	struct sti_plane *plane = to_sti_plane(drm_plane);
+
+	DRM_DEBUG_DRIVER("\n");
+
+	if (property == private->plane_zorder_property) {
+		plane->zorder = val;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static struct drm_plane_funcs sti_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = sti_plane_destroy,
+	.set_property = sti_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 sti_plane_atomic_check(struct drm_plane *drm_plane,
+				  struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void sti_plane_atomic_update(struct drm_plane *drm_plane,
+				    struct drm_plane_state *oldstate)
+{
+	struct drm_plane_state *state = drm_plane->state;
+	struct sti_plane *plane = to_sti_plane(drm_plane);
+	struct sti_mixer *mixer = to_sti_mixer(state->crtc);
+	int res;
+
+	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
+		      state->crtc->base.id, sti_mixer_to_str(mixer),
+		      drm_plane->base.id, sti_plane_to_str(plane));
+	DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n",
+		      state->crtc_w, state->crtc_h,
+		      state->crtc_x, state->crtc_y);
+
+	res = sti_mixer_set_plane_depth(mixer, plane);
+	if (res) {
+		DRM_ERROR("Cannot set plane depth\n");
+		return;
+	}
+
+	/* src_x are in 16.16 format */
+	res = sti_plane_prepare(plane, state->crtc, state->fb,
+				&state->crtc->mode, mixer->id,
+				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);
+	if (res) {
+		DRM_ERROR("Plane prepare failed\n");
+		return;
+	}
+
+	res = sti_plane_commit(plane);
+	if (res) {
+		DRM_ERROR("Plane commit failed\n");
+		return;
+	}
+
+	res = sti_mixer_set_plane_status(mixer, plane, true);
+	if (res) {
+		DRM_ERROR("Cannot enable plane at mixer\n");
+		return;
+	}
+}
+
+static void sti_plane_atomic_disable(struct drm_plane *drm_plane,
+				     struct drm_plane_state *oldstate)
+{
+	struct sti_plane *plane = to_sti_plane(drm_plane);
+	struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);
+	int res;
+
+	if (!drm_plane->crtc) {
+		DRM_DEBUG_DRIVER("drm plane:%d not enabled\n",
+				 drm_plane->base.id);
+		return;
+	}
+
+	DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
+			 drm_plane->crtc->base.id, sti_mixer_to_str(mixer),
+			 drm_plane->base.id, sti_plane_to_str(plane));
+
+	/* Disable plane at mixer level */
+	res = sti_mixer_set_plane_status(mixer, plane, false);
+	if (res) {
+		DRM_ERROR("Cannot disable plane at mixer\n");
+		return;
+	}
+
+	/* Wait a while to be sure that a Vsync event is received */
+	msleep(WAIT_NEXT_VSYNC_MS);
+
+	/* Then disable plane itself */
+	res = sti_plane_disable(plane);
+	if (res) {
+		DRM_ERROR("Plane disable failed\n");
+		return;
+	}
+}
+
+static const struct drm_plane_helper_funcs sti_plane_helpers_funcs = {
+	.atomic_check = sti_plane_atomic_check,
+	.atomic_update = sti_plane_atomic_update,
+	.atomic_disable = sti_plane_atomic_disable,
+};
+
+static void sti_plane_attach_zorder_property(struct drm_plane *drm_plane)
+{
+	struct drm_device *dev = drm_plane->dev;
+	struct sti_private *private = dev->dev_private;
+	struct sti_plane *plane = to_sti_plane(drm_plane);
+	struct drm_property *prop;
+
+	prop = private->plane_zorder_property;
+	if (!prop) {
+		prop = drm_property_create_range(dev, 0, "zpos", 1,
+						 GAM_MIXER_NB_DEPTH_LEVEL);
+		if (!prop)
+			return;
+
+		private->plane_zorder_property = prop;
+	}
+
+	drm_object_attach_property(&drm_plane->base, prop, plane->zorder);
+}
+
+struct drm_plane *sti_plane_init(struct drm_device *dev,
+				 struct sti_plane *plane,
+				 unsigned int possible_crtcs,
+				 enum drm_plane_type type)
+{
+	int err, i;
+
+	err = drm_universal_plane_init(dev, &plane->drm_plane,
+				       possible_crtcs,
+				       &sti_plane_funcs,
+				       plane->ops->get_formats(plane),
+				       plane->ops->get_nb_formats(plane),
+				       type);
+	if (err) {
+		DRM_ERROR("Failed to initialize universal plane\n");
+		return NULL;
+	}
+
+	drm_plane_helper_add(&plane->drm_plane, &sti_plane_helpers_funcs);
+
+	for (i = 0; i < ARRAY_SIZE(sti_plane_default_zorder); i++)
+		if (sti_plane_default_zorder[i] == plane->desc)
+			break;
+
+	plane->zorder = i + 1;
+
+	if (type == DRM_PLANE_TYPE_OVERLAY)
+		sti_plane_attach_zorder_property(&plane->drm_plane);
+
+	DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%d\n",
+			 plane->drm_plane.base.id,
+			 sti_plane_to_str(plane), plane->zorder);
+
+	return &plane->drm_plane;
+}
+EXPORT_SYMBOL(sti_plane_init);
diff --git a/drivers/gpu/drm/sti/sti_plane.h b/drivers/gpu/drm/sti/sti_plane.h
new file mode 100644
index 0000000..bd52754
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_plane.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_PLANE_H_
+#define _STI_PLANE_H_
+
+#include <drm/drmP.h>
+
+#define to_sti_plane(x) container_of(x, struct sti_plane, drm_plane)
+
+#define STI_PLANE_TYPE_SHIFT 8
+#define STI_PLANE_TYPE_MASK (~((1 << STI_PLANE_TYPE_SHIFT) - 1))
+
+enum sti_plane_type {
+	STI_GDP = 1 << STI_PLANE_TYPE_SHIFT,
+	STI_VDP = 2 << STI_PLANE_TYPE_SHIFT,
+	STI_CUR = 3 << STI_PLANE_TYPE_SHIFT,
+	STI_BCK = 4 << STI_PLANE_TYPE_SHIFT
+};
+
+enum sti_plane_id_of_type {
+	STI_ID_0 = 0,
+	STI_ID_1 = 1,
+	STI_ID_2 = 2,
+	STI_ID_3 = 3
+};
+
+enum sti_plane_desc {
+	STI_GDP_0       = STI_GDP | STI_ID_0,
+	STI_GDP_1       = STI_GDP | STI_ID_1,
+	STI_GDP_2       = STI_GDP | STI_ID_2,
+	STI_GDP_3       = STI_GDP | STI_ID_3,
+	STI_HQVDP_0     = STI_VDP | STI_ID_0,
+	STI_CURSOR      = STI_CUR,
+	STI_BACK        = STI_BCK
+};
+
+/**
+ * STI plane structure
+ *
+ * @plane:              drm plane it is bound to (if any)
+ * @fb:                 drm fb it is bound to
+ * @mode:               display mode
+ * @desc:               plane type & id
+ * @ops:                plane functions
+ * @zorder:             plane z-order
+ * @mixer_id:           id of the mixer used to display the plane
+ * @enabled:            to know if the plane is active or not
+ * @src_x src_y:        coordinates of the input (fb) area
+ * @src_w src_h:        size of the input (fb) area
+ * @dst_x dst_y:        coordinates of the output (crtc) area
+ * @dst_w dst_h:        size of the output (crtc) area
+ * @format:             format
+ * @pitches:            pitch of 'planes' (eg: Y, U, V)
+ * @offsets:            offset of 'planes'
+ * @vaddr:              virtual address of the input buffer
+ * @paddr:              physical address of the input buffer
+ */
+struct sti_plane {
+	struct drm_plane drm_plane;
+	struct drm_framebuffer *fb;
+	struct drm_display_mode *mode;
+	enum sti_plane_desc desc;
+	const struct sti_plane_funcs *ops;
+	int zorder;
+	int mixer_id;
+	bool enabled;
+	int src_x, src_y;
+	int src_w, src_h;
+	int dst_x, dst_y;
+	int dst_w, dst_h;
+	uint32_t format;
+	unsigned int pitches[4];
+	unsigned int offsets[4];
+	void *vaddr;
+	dma_addr_t paddr;
+};
+
+/**
+ * STI plane functions structure
+ *
+ * @get_formats:     get plane supported formats
+ * @get_nb_formats:  get number of format supported
+ * @prepare:         prepare plane before rendering
+ * @commit:          set plane for rendering
+ * @disable:         disable plane
+ */
+struct sti_plane_funcs {
+	const uint32_t* (*get_formats)(struct sti_plane *plane);
+	unsigned int (*get_nb_formats)(struct sti_plane *plane);
+	int (*prepare)(struct sti_plane *plane, bool first_prepare);
+	int (*commit)(struct sti_plane *plane);
+	int (*disable)(struct sti_plane *plane);
+};
+
+struct drm_plane *sti_plane_init(struct drm_device *dev,
+				 struct sti_plane *sti_plane,
+				 unsigned int possible_crtcs,
+				 enum drm_plane_type type);
+const char *sti_plane_to_str(struct sti_plane *plane);
+
+#endif
diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c
index 576b5be..c1aac8e 100644
--- a/drivers/gpu/drm/sti/sti_tvout.c
+++ b/drivers/gpu/drm/sti/sti_tvout.c
@@ -16,7 +16,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 
-#include "sti_drm_crtc.h"
+#include "sti_crtc.h"
 
 /* glue registers */
 #define TVO_CSC_MAIN_M0                  0x000
@@ -473,7 +473,7 @@ static void sti_dvo_encoder_commit(struct drm_encoder *encoder)
 {
 	struct sti_tvout *tvout = to_sti_tvout(encoder);
 
-	tvout_dvo_start(tvout, sti_drm_crtc_is_main(encoder->crtc));
+	tvout_dvo_start(tvout, sti_crtc_is_main(encoder->crtc));
 }
 
 static void sti_dvo_encoder_disable(struct drm_encoder *encoder)
@@ -523,7 +523,7 @@ static void sti_hda_encoder_commit(struct drm_encoder *encoder)
 {
 	struct sti_tvout *tvout = to_sti_tvout(encoder);
 
-	tvout_hda_start(tvout, sti_drm_crtc_is_main(encoder->crtc));
+	tvout_hda_start(tvout, sti_crtc_is_main(encoder->crtc));
 }
 
 static void sti_hda_encoder_disable(struct drm_encoder *encoder)
@@ -575,7 +575,7 @@ static void sti_hdmi_encoder_commit(struct drm_encoder *encoder)
 {
 	struct sti_tvout *tvout = to_sti_tvout(encoder);
 
-	tvout_hdmi_start(tvout, sti_drm_crtc_is_main(encoder->crtc));
+	tvout_hdmi_start(tvout, sti_crtc_is_main(encoder->crtc));
 }
 
 static void sti_hdmi_encoder_disable(struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/sti/sti_vid.c b/drivers/gpu/drm/sti/sti_vid.c
index b82a34f..1e7e1d7 100644
--- a/drivers/gpu/drm/sti/sti_vid.c
+++ b/drivers/gpu/drm/sti/sti_vid.c
@@ -6,7 +6,7 @@
 
 #include <drm/drmP.h>
 
-#include "sti_drm_plane.h"
+#include "sti_plane.h"
 #include "sti_vid.h"
 #include "sti_vtg.h"
 
-- 
1.9.1

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

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

* [PATCH 4/4] drm/sti: atomic crtc/plane update
  2015-07-31 10:13 [PATCH 0/4] drm/sti: update STI driver to be atomic Vincent Abriou
                   ` (2 preceding siblings ...)
  2015-07-31 10:13 ` [PATCH 3/4] drm/sti: rename files and functions Vincent Abriou
@ 2015-07-31 10:13 ` Vincent Abriou
  2015-07-31 12:22   ` Emil Velikov
  2015-07-31 13:45   ` Daniel Vetter
  3 siblings, 2 replies; 9+ messages in thread
From: Vincent Abriou @ 2015-07-31 10:13 UTC (permalink / raw)
  To: dri-devel; +Cc: Fabien Dessenne, Benjamin Gaignard, kernel

Better fit STI hardware structure.
Planes are no more responsible of updating mixer information such
as z-order and status. It is now up to the CRTC atomic flush to
do it. Plane actions (enable or disable) are performed atomically.
Disabling of a plane is synchronize with the vsync event.

Signed-off-by: Vincent Abriou <vincent.abriou@st.com>
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
---
 drivers/gpu/drm/sti/sti_compositor.c |  32 +--
 drivers/gpu/drm/sti/sti_crtc.c       | 120 +++++++--
 drivers/gpu/drm/sti/sti_cursor.c     | 211 +++++++++------
 drivers/gpu/drm/sti/sti_cursor.h     |   6 +-
 drivers/gpu/drm/sti/sti_gdp.c        | 493 +++++++++++++++++++----------------
 drivers/gpu/drm/sti/sti_gdp.h        |   8 +-
 drivers/gpu/drm/sti/sti_hqvdp.c      | 429 ++++++++++++++++--------------
 drivers/gpu/drm/sti/sti_mixer.h      |  10 +-
 drivers/gpu/drm/sti/sti_plane.c      | 251 +-----------------
 drivers/gpu/drm/sti/sti_plane.h      |  66 ++---
 drivers/gpu/drm/sti/sti_vid.c        |  29 ++-
 drivers/gpu/drm/sti/sti_vid.h        |   5 +-
 12 files changed, 808 insertions(+), 852 deletions(-)

diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c
index d62ed7f..c652627 100644
--- a/drivers/gpu/drm/sti/sti_compositor.c
+++ b/drivers/gpu/drm/sti/sti_compositor.c
@@ -61,15 +61,13 @@ static int sti_compositor_bind(struct device *dev,
 {
 	struct sti_compositor *compo = dev_get_drvdata(dev);
 	struct drm_device *drm_dev = data;
-	unsigned int i, mixer_id = 0, vid_id = 0, crtc_id = 0, plane_id = 0;
+	unsigned int i, mixer_id = 0, vid_id = 0, crtc_id = 0;
 	struct sti_private *dev_priv = drm_dev->dev_private;
 	struct drm_plane *cursor = NULL;
 	struct drm_plane *primary = NULL;
 	struct sti_compositor_subdev_descriptor *desc = compo->data.subdev_desc;
 	unsigned int array_size = compo->data.nb_subdev;
 
-	struct sti_plane *plane;
-
 	dev_priv->compo = compo;
 
 	/* Register mixer subdev and video subdev first */
@@ -110,27 +108,25 @@ static int sti_compositor_bind(struct device *dev,
 			/* Nothing to do, already done at the first round */
 			break;
 		case STI_CURSOR_SUBDEV:
-			plane = sti_cursor_create(compo->dev, desc[i].id,
-						  compo->regs + desc[i].offset);
-			if (!plane) {
+			cursor = sti_cursor_create(drm_dev, compo->dev,
+						   desc[i].id,
+						   compo->regs + desc[i].offset,
+						   1);
+			if (!cursor) {
 				DRM_ERROR("Can't create CURSOR plane\n");
 				break;
 			}
-			cursor = sti_plane_init(drm_dev, plane, 1,
-						DRM_PLANE_TYPE_CURSOR);
-			plane_id++;
 			break;
 		case STI_GPD_SUBDEV:
-			plane = sti_gdp_create(compo->dev, desc[i].id,
-					       compo->regs + desc[i].offset);
-			if (!plane) {
+			primary = sti_gdp_create(drm_dev, compo->dev,
+						 desc[i].id,
+						 compo->regs + desc[i].offset,
+						 (1 << mixer_id) - 1,
+						 plane_type);
+			if (!primary) {
 				DRM_ERROR("Can't create GDP plane\n");
 				break;
 			}
-			primary = sti_plane_init(drm_dev, plane,
-						 (1 << mixer_id) - 1,
-						 plane_type);
-			plane_id++;
 			break;
 		default:
 			DRM_ERROR("Unknown subdev compoment type\n");
@@ -151,10 +147,6 @@ static int sti_compositor_bind(struct device *dev,
 	/* Allow usage of vblank without having to call drm_irq_install */
 	drm_dev->irq_enabled = 1;
 
-	DRM_DEBUG_DRIVER("Initialized %d DRM CRTC(s) and %d DRM plane(s)\n",
-			 crtc_id, plane_id);
-	DRM_DEBUG_DRIVER("DRM plane(s) for VID/VDP not created yet\n");
-
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/sti/sti_crtc.c b/drivers/gpu/drm/sti/sti_crtc.c
index 27b3ef2..2a12738 100644
--- a/drivers/gpu/drm/sti/sti_crtc.c
+++ b/drivers/gpu/drm/sti/sti_crtc.c
@@ -17,6 +17,7 @@
 #include "sti_compositor.h"
 #include "sti_crtc.h"
 #include "sti_drv.h"
+#include "sti_vid.h"
 #include "sti_vtg.h"
 
 static void sti_crtc_dpms(struct drm_crtc *crtc, int mode)
@@ -24,13 +25,13 @@ static void sti_crtc_dpms(struct drm_crtc *crtc, int mode)
 	DRM_DEBUG_KMS("\n");
 }
 
-static void sti_crtc_prepare(struct drm_crtc *crtc)
+static void sti_crtc_helper_prepare(struct drm_crtc *crtc)
 {
 	struct sti_mixer *mixer = to_sti_mixer(crtc);
 	struct device *dev = mixer->dev;
 	struct sti_compositor *compo = dev_get_drvdata(dev);
 
-	mixer->enabled = true;
+	mixer->status = STI_MIXER_READY;
 
 	/* Prepare and enable the compo IP clock */
 	if (mixer->id == STI_MIXER_MAIN) {
@@ -44,28 +45,25 @@ static void sti_crtc_prepare(struct drm_crtc *crtc)
 	sti_mixer_clear_all_planes(mixer);
 }
 
-static void sti_crtc_commit(struct drm_crtc *crtc)
+static void sti_crtc_helper_commit(struct drm_crtc *crtc)
 {
 	struct sti_mixer *mixer = to_sti_mixer(crtc);
 	struct device *dev = mixer->dev;
 	struct sti_compositor *compo = dev_get_drvdata(dev);
-	struct sti_plane *plane;
 
 	if ((!mixer || !compo)) {
 		DRM_ERROR("Can't find mixer or compositor)\n");
 		return;
 	}
 
-	/* get GDP which is reserved to the CRTC FB */
-	plane = to_sti_plane(crtc->primary);
-	if (!plane)
-		DRM_ERROR("Can't find CRTC dedicated plane (GDP0)\n");
+	drm_crtc_vblank_on(crtc);
+}
 
-	/* Enable plane on mixer */
-	if (sti_mixer_set_plane_status(mixer, plane, true))
-		DRM_ERROR("Cannot enable plane at mixer\n");
+static void sti_crtc_helper_disable(struct drm_crtc *crtc)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
 
-	drm_crtc_vblank_on(crtc);
+	mixer->status = STI_MIXER_DISABLING;
 }
 
 static bool sti_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -133,9 +131,6 @@ static void sti_crtc_disable(struct drm_crtc *crtc)
 	struct device *dev = mixer->dev;
 	struct sti_compositor *compo = dev_get_drvdata(dev);
 
-	if (!mixer->enabled)
-		return;
-
 	DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer));
 
 	/* Disable Background */
@@ -152,13 +147,13 @@ static void sti_crtc_disable(struct drm_crtc *crtc)
 		clk_disable_unprepare(compo->clk_compo_aux);
 	}
 
-	mixer->enabled = false;
+	mixer->status = STI_MIXER_DISABLED;
 }
 
 static void
 sti_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
-	sti_crtc_prepare(crtc);
+	sti_crtc_helper_prepare(crtc);
 	sti_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
 }
 
@@ -178,17 +173,81 @@ static void sti_crtc_atomic_begin(struct drm_crtc *crtc)
 
 static void sti_crtc_atomic_flush(struct drm_crtc *crtc)
 {
+	struct drm_device *drm_dev = crtc->dev;
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	struct sti_compositor *compo = dev_get_drvdata(mixer->dev);
+	struct drm_plane *p;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	/* perform plane actions */
+	list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
+		struct sti_plane *plane = to_sti_plane(p);
+
+		switch (plane->status) {
+		case STI_PLANE_UPDATED:
+			/* update planes tag as updated */
+			DRM_DEBUG_DRIVER("update plane %s\n",
+					 sti_plane_to_str(plane));
+
+			if (sti_mixer_set_plane_depth(mixer, plane)) {
+				DRM_ERROR("Cannot set plane %s depth\n",
+					  sti_plane_to_str(plane));
+				break;
+			}
+
+			if (sti_mixer_set_plane_status(mixer, plane, true)) {
+				DRM_ERROR("Cannot enable plane %s at mixer\n",
+					  sti_plane_to_str(plane));
+				break;
+			}
+
+			/* if plane is HQVDP_0 then commit the vid[0] */
+			if (plane->desc == STI_HQVDP_0)
+				sti_vid_commit(compo->vid[0], p->state);
+
+			plane->status = STI_PLANE_READY;
+
+			break;
+		case STI_PLANE_DISABLING:
+			/* disabling sequence for planes tag as disabling */
+			DRM_DEBUG_DRIVER("disable plane %s from mixer\n",
+					 sti_plane_to_str(plane));
+
+			if (sti_mixer_set_plane_status(mixer, plane, false)) {
+				DRM_ERROR("Cannot disable plane %s at mixer\n",
+					  sti_plane_to_str(plane));
+				continue;
+			}
+
+			if (plane->desc == STI_CURSOR)
+				/* tag plane status for disabled */
+				plane->status = STI_PLANE_DISABLED;
+			else
+				/* tag plane status for flushing */
+				plane->status = STI_PLANE_FLUSHING;
+
+			/* if plane is HQVDP_0 then disable the vid[0] */
+			if (plane->desc == STI_HQVDP_0)
+				sti_vid_disable(compo->vid[0]);
+
+			break;
+		default:
+			/* Other status case are not handled */
+			break;
+		}
+	}
 }
 
 static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
 	.dpms = sti_crtc_dpms,
-	.prepare = sti_crtc_prepare,
-	.commit = sti_crtc_commit,
+	.prepare = sti_crtc_helper_prepare,
+	.commit = sti_crtc_helper_commit,
+	.disable = sti_crtc_helper_disable,
 	.mode_fixup = sti_crtc_mode_fixup,
 	.mode_set = drm_helper_crtc_mode_set,
 	.mode_set_nofb = sti_crtc_mode_set_nofb,
 	.mode_set_base = drm_helper_crtc_mode_set_base,
-	.disable = sti_crtc_disable,
 	.atomic_begin = sti_crtc_atomic_begin,
 	.atomic_flush = sti_crtc_atomic_flush,
 };
@@ -237,6 +296,21 @@ int sti_crtc_vblank_cb(struct notifier_block *nb,
 	}
 	spin_unlock_irqrestore(&drm_dev->event_lock, flags);
 
+	if (compo->mixer[*crtc]->status == STI_MIXER_DISABLING) {
+		struct drm_plane *p;
+
+		/* Disable mixer only if all overlay planes (GDP and VDP)
+		 * are disabled */
+		list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
+			struct sti_plane *plane = to_sti_plane(p);
+
+			if ((plane->desc & STI_PLANE_TYPE_MASK) <= STI_VDP)
+				if (plane->status != STI_PLANE_DISABLED)
+					return 0;
+		}
+		sti_crtc_disable(&compo->mixer[*crtc]->drm_crtc);
+	}
+
 	return 0;
 }
 
@@ -259,9 +333,9 @@ int sti_crtc_enable_vblank(struct drm_device *dev, int crtc)
 }
 EXPORT_SYMBOL(sti_crtc_enable_vblank);
 
-void sti_crtc_disable_vblank(struct drm_device *dev, int crtc)
+void sti_crtc_disable_vblank(struct drm_device *drm_dev, int crtc)
 {
-	struct sti_private *priv = dev->dev_private;
+	struct sti_private *priv = drm_dev->dev_private;
 	struct sti_compositor *compo = priv->compo;
 	struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
 
@@ -273,7 +347,7 @@ void sti_crtc_disable_vblank(struct drm_device *dev, int crtc)
 
 	/* free the resources of the pending requests */
 	if (compo->mixer[crtc]->pending_event) {
-		drm_vblank_put(dev, crtc);
+		drm_vblank_put(drm_dev, crtc);
 		compo->mixer[crtc]->pending_event = NULL;
 	}
 }
diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c
index 2868909..dd10321 100644
--- a/drivers/gpu/drm/sti/sti_cursor.c
+++ b/drivers/gpu/drm/sti/sti_cursor.c
@@ -7,6 +7,12 @@
  */
 #include <drm/drmP.h>
 
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include "sti_compositor.h"
 #include "sti_cursor.h"
 #include "sti_plane.h"
 #include "sti_vtg.h"
@@ -42,14 +48,14 @@ struct dma_pixmap {
 /**
  * STI Cursor structure
  *
- * @sti_plane:  sti_plane structure
- * @dev:        driver device
- * @regs:       cursor registers
- * @width:      cursor width
- * @height:     cursor height
- * @clut:       color look up table
- * @clut_paddr: color look up table physical address
- * @pixmap:     pixmap dma buffer (clut8-format cursor)
+ * @sti_plane:    sti_plane structure
+ * @dev:          driver device
+ * @regs:         cursor registers
+ * @width:        cursor width
+ * @height:       cursor height
+ * @clut:         color look up table
+ * @clut_paddr:   color look up table physical address
+ * @pixmap:       pixmap dma buffer (clut8-format cursor)
  */
 struct sti_cursor {
 	struct sti_plane plane;
@@ -68,20 +74,8 @@ static const uint32_t cursor_supported_formats[] = {
 
 #define to_sti_cursor(x) container_of(x, struct sti_cursor, plane)
 
-static const uint32_t *sti_cursor_get_formats(struct sti_plane *plane)
-{
-	return cursor_supported_formats;
-}
-
-static unsigned int sti_cursor_get_nb_formats(struct sti_plane *plane)
-{
-	return ARRAY_SIZE(cursor_supported_formats);
-}
-
-static void sti_cursor_argb8888_to_clut8(struct sti_plane *plane)
+static void sti_cursor_argb8888_to_clut8(struct sti_cursor *cursor, u32 *src)
 {
-	struct sti_cursor *cursor = to_sti_cursor(plane);
-	u32 *src = plane->vaddr;
 	u8  *dst = cursor->pixmap.base;
 	unsigned int i, j;
 	u32 a, r, g, b;
@@ -100,32 +94,67 @@ static void sti_cursor_argb8888_to_clut8(struct sti_plane *plane)
 	}
 }
 
-static int sti_cursor_prepare_plane(struct sti_plane *plane, bool first_prepare)
+static void sti_cursor_init(struct sti_cursor *cursor)
+{
+	unsigned short *base = cursor->clut;
+	unsigned int a, r, g, b;
+
+	/* Assign CLUT values, ARGB444 format */
+	for (a = 0; a < 4; a++)
+		for (r = 0; r < 4; r++)
+			for (g = 0; g < 4; g++)
+				for (b = 0; b < 4; b++)
+					*base++ = (a * 5) << 12 |
+						  (r * 5) << 8 |
+						  (g * 5) << 4 |
+						  (b * 5);
+}
+
+static void sti_cursor_atomic_update(struct drm_plane *drm_plane,
+				     struct drm_plane_state *oldstate)
 {
+	struct drm_plane_state *state = drm_plane->state;
+	struct sti_plane *plane = to_sti_plane(drm_plane);
 	struct sti_cursor *cursor = to_sti_cursor(plane);
-	struct drm_display_mode *mode = plane->mode;
+	struct drm_crtc *crtc = state->crtc;
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_display_mode *mode = &crtc->mode;
+	int dst_x = state->crtc_x;
+	int dst_y = state->crtc_y;
+	int dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
+	int dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
+	/* src_x are in 16.16 format */
+	int src_w = state->src_w >> 16;
+	int src_h = state->src_h >> 16;
+	bool first_prepare = plane->status == STI_PLANE_DISABLED ? true : false;
+	struct drm_gem_cma_object *cma_obj;
 	u32 y, x;
 	u32 val;
 
-	DRM_DEBUG_DRIVER("\n");
+	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
+		      crtc->base.id, sti_mixer_to_str(mixer),
+		      drm_plane->base.id, sti_plane_to_str(plane));
+	DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n", dst_w, dst_h, dst_x, dst_y);
 
-	dev_dbg(cursor->dev, "%s %s\n", __func__, sti_plane_to_str(plane));
+	dev_dbg(cursor->dev, "%s %s\n", __func__,
+		sti_plane_to_str(plane));
 
-	if (plane->src_w < STI_CURS_MIN_SIZE ||
-	    plane->src_h < STI_CURS_MIN_SIZE ||
-	    plane->src_w > STI_CURS_MAX_SIZE ||
-	    plane->src_h > STI_CURS_MAX_SIZE) {
+	if (src_w < STI_CURS_MIN_SIZE ||
+	    src_h < STI_CURS_MIN_SIZE ||
+	    src_w > STI_CURS_MAX_SIZE ||
+	    src_h > STI_CURS_MAX_SIZE) {
 		DRM_ERROR("Invalid cursor size (%dx%d)\n",
-				plane->src_w, plane->src_h);
-		return -EINVAL;
+				src_w, src_h);
+		return;
 	}
 
 	/* If the cursor size has changed, re-allocated the pixmap */
 	if (!cursor->pixmap.base ||
-	    (cursor->width != plane->src_w) ||
-	    (cursor->height != plane->src_h)) {
-		cursor->width = plane->src_w;
-		cursor->height = plane->src_h;
+	    (cursor->width != src_w) ||
+	    (cursor->height != src_h)) {
+		cursor->width = src_w;
+		cursor->height = src_h;
 
 		if (cursor->pixmap.base)
 			dma_free_writecombine(cursor->dev,
@@ -141,12 +170,18 @@ static int sti_cursor_prepare_plane(struct sti_plane *plane, bool first_prepare)
 							GFP_KERNEL | GFP_DMA);
 		if (!cursor->pixmap.base) {
 			DRM_ERROR("Failed to allocate memory for pixmap\n");
-			return -ENOMEM;
+			return;
 		}
 	}
 
+	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+	if (!cma_obj) {
+		DRM_ERROR("Can't get CMA GEM object for fb\n");
+		return;
+	}
+
 	/* Convert ARGB8888 to CLUT8 */
-	sti_cursor_argb8888_to_clut8(plane);
+	sti_cursor_argb8888_to_clut8(cursor, (u32 *)cma_obj->vaddr);
 
 	/* AWS and AWE depend on the mode */
 	y = sti_vtg_get_line_number(*mode, 0);
@@ -164,62 +199,50 @@ static int sti_cursor_prepare_plane(struct sti_plane *plane, bool first_prepare)
 		writel(CUR_CTL_CLUT_UPDATE, cursor->regs + CUR_CTL);
 	}
 
-	return 0;
-}
-
-static int sti_cursor_commit_plane(struct sti_plane *plane)
-{
-	struct sti_cursor *cursor = to_sti_cursor(plane);
-	struct drm_display_mode *mode = plane->mode;
-	u32 ydo, xdo;
-
-	dev_dbg(cursor->dev, "%s %s\n", __func__, sti_plane_to_str(plane));
-
 	/* Set memory location, size, and position */
 	writel(cursor->pixmap.paddr, cursor->regs + CUR_PML);
 	writel(cursor->width, cursor->regs + CUR_PMP);
 	writel(cursor->height << 16 | cursor->width, cursor->regs + CUR_SIZE);
 
-	ydo = sti_vtg_get_line_number(*mode, plane->dst_y);
-	xdo = sti_vtg_get_pixel_number(*mode, plane->dst_y);
-	writel((ydo << 16) | xdo, cursor->regs + CUR_VPO);
+	y = sti_vtg_get_line_number(*mode, dst_y);
+	x = sti_vtg_get_pixel_number(*mode, dst_y);
+	writel((y << 16) | x, cursor->regs + CUR_VPO);
 
-	return 0;
+	plane->status = STI_PLANE_UPDATED;
 }
 
-static int sti_cursor_disable_plane(struct sti_plane *plane)
+static void sti_cursor_atomic_disable(struct drm_plane *drm_plane,
+				      struct drm_plane_state *oldstate)
 {
-	return 0;
-}
+	struct sti_plane *plane = to_sti_plane(drm_plane);
+	struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);
 
-static void sti_cursor_init(struct sti_cursor *cursor)
-{
-	unsigned short *base = cursor->clut;
-	unsigned int a, r, g, b;
+	if (!drm_plane->crtc) {
+		DRM_DEBUG_DRIVER("drm plane:%d not enabled\n",
+				 drm_plane->base.id);
+		return;
+	}
 
-	/* Assign CLUT values, ARGB444 format */
-	for (a = 0; a < 4; a++)
-		for (r = 0; r < 4; r++)
-			for (g = 0; g < 4; g++)
-				for (b = 0; b < 4; b++)
-					*base++ = (a * 5) << 12 |
-						  (r * 5) << 8 |
-						  (g * 5) << 4 |
-						  (b * 5);
+	DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
+			 drm_plane->crtc->base.id, sti_mixer_to_str(mixer),
+			 drm_plane->base.id, sti_plane_to_str(plane));
+
+	plane->status = STI_PLANE_DISABLING;
 }
 
-static const struct sti_plane_funcs cursor_plane_ops = {
-	.get_formats = sti_cursor_get_formats,
-	.get_nb_formats = sti_cursor_get_nb_formats,
-	.prepare = sti_cursor_prepare_plane,
-	.commit = sti_cursor_commit_plane,
-	.disable = sti_cursor_disable_plane,
+static const struct drm_plane_helper_funcs sti_cursor_helpers_funcs = {
+	.atomic_update = sti_cursor_atomic_update,
+	.atomic_disable = sti_cursor_atomic_disable,
 };
 
-struct sti_plane *sti_cursor_create(struct device *dev, int desc,
-				    void __iomem *baseaddr)
+struct drm_plane *sti_cursor_create(struct drm_device *drm_dev,
+				    struct device *dev, int desc,
+				    void __iomem *baseaddr,
+				    unsigned int possible_crtcs)
 {
 	struct sti_cursor *cursor;
+	size_t size;
+	int res;
 
 	cursor = devm_kzalloc(dev, sizeof(*cursor), GFP_KERNEL);
 	if (!cursor) {
@@ -228,23 +251,43 @@ struct sti_plane *sti_cursor_create(struct device *dev, int desc,
 	}
 
 	/* Allocate clut buffer */
-	cursor->clut = dma_alloc_writecombine(dev,
-			0x100 * sizeof(unsigned short),
-			&cursor->clut_paddr,
-			GFP_KERNEL | GFP_DMA);
+	size = 0x100 * sizeof(unsigned short);
+	cursor->clut = dma_alloc_writecombine(dev, size, &cursor->clut_paddr,
+					      GFP_KERNEL | GFP_DMA);
 
 	if (!cursor->clut) {
 		DRM_ERROR("Failed to allocate memory for cursor clut\n");
-		devm_kfree(dev, cursor);
-		return NULL;
+		goto err_clut;
 	}
 
 	cursor->dev = dev;
 	cursor->regs = baseaddr;
 	cursor->plane.desc = desc;
-	cursor->plane.ops = &cursor_plane_ops;
+	cursor->plane.status = STI_PLANE_DISABLED;
 
 	sti_cursor_init(cursor);
 
-	return &cursor->plane;
+	res = drm_universal_plane_init(drm_dev, &cursor->plane.drm_plane,
+				       possible_crtcs,
+				       &sti_plane_helpers_funcs,
+				       cursor_supported_formats,
+				       ARRAY_SIZE(cursor_supported_formats),
+				       DRM_PLANE_TYPE_CURSOR);
+	if (res) {
+		DRM_ERROR("Failed to initialize universal plane\n");
+		goto err_plane;
+	}
+
+	drm_plane_helper_add(&cursor->plane.drm_plane,
+			     &sti_cursor_helpers_funcs);
+
+	sti_plane_init_property(&cursor->plane, DRM_PLANE_TYPE_CURSOR);
+
+	return &cursor->plane.drm_plane;
+
+err_plane:
+	dma_free_writecombine(dev, size, cursor->clut, cursor->clut_paddr);
+err_clut:
+	devm_kfree(dev, cursor);
+	return NULL;
 }
diff --git a/drivers/gpu/drm/sti/sti_cursor.h b/drivers/gpu/drm/sti/sti_cursor.h
index db973b7..2ee5c10 100644
--- a/drivers/gpu/drm/sti/sti_cursor.h
+++ b/drivers/gpu/drm/sti/sti_cursor.h
@@ -7,7 +7,9 @@
 #ifndef _STI_CURSOR_H_
 #define _STI_CURSOR_H_
 
-struct sti_plane *sti_cursor_create(struct device *dev, int desc,
-				    void __iomem *baseaddr);
+struct drm_plane *sti_cursor_create(struct drm_device *drm_dev,
+				    struct device *dev, int desc,
+				    void __iomem *baseaddr,
+				    unsigned int possible_crtcs);
 
 #endif
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
index e323310..9365670 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -9,6 +9,9 @@
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
 #include "sti_compositor.h"
 #include "sti_gdp.h"
 #include "sti_plane.h"
@@ -26,7 +29,7 @@
 #define GDP_XBGR8888    (GDP_RGB888_32 | BIGNOTLITTLE | ALPHASWITCH)
 #define GDP_ARGB8565    0x04
 #define GDP_ARGB8888    0x05
-#define GDP_ABGR8888	(GDP_ARGB8888 | BIGNOTLITTLE | ALPHASWITCH)
+#define GDP_ABGR8888    (GDP_ARGB8888 | BIGNOTLITTLE | ALPHASWITCH)
 #define GDP_ARGB1555    0x06
 #define GDP_ARGB4444    0x07
 #define GDP_CLUT8       0x0B
@@ -53,8 +56,8 @@
 #define GAM_GDP_PPT_IGNORE      (BIT(1) | BIT(0))
 #define GAM_GDP_SIZE_MAX        0x7FF
 
-#define GDP_NODE_NB_BANK	2
-#define GDP_NODE_PER_FIELD	2
+#define GDP_NODE_NB_BANK        2
+#define GDP_NODE_PER_FIELD      2
 
 struct sti_gdp_node {
 	u32 gam_gdp_ctl;
@@ -124,16 +127,6 @@ static const uint32_t gdp_supported_formats[] = {
 	DRM_FORMAT_C8,
 };
 
-static const uint32_t *sti_gdp_get_formats(struct sti_plane *plane)
-{
-	return gdp_supported_formats;
-}
-
-static unsigned int sti_gdp_get_nb_formats(struct sti_plane *plane)
-{
-	return ARRAY_SIZE(gdp_supported_formats);
-}
-
 static int sti_gdp_fourcc2format(int fourcc)
 {
 	switch (fourcc) {
@@ -179,17 +172,16 @@ static int sti_gdp_get_alpharange(int format)
 
 /**
  * sti_gdp_get_free_nodes
- * @plane: gdp plane
+ * @gdp: gdp pointer
  *
  * Look for a GDP node list that is not currently read by the HW.
  *
  * RETURNS:
  * Pointer to the free GDP node list
  */
-static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_plane *plane)
+static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_gdp *gdp)
 {
 	int hw_nvn;
-	struct sti_gdp *gdp = to_sti_gdp(plane);
 	unsigned int i;
 
 	hw_nvn = readl(gdp->regs + GAM_GDP_NVN_OFFSET);
@@ -203,7 +195,7 @@ static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_plane *plane)
 
 	/* in hazardious cases restart with the first node */
 	DRM_ERROR("inconsistent NVN for %s: 0x%08X\n",
-			sti_plane_to_str(plane), hw_nvn);
+			sti_plane_to_str(&gdp->plane), hw_nvn);
 
 end:
 	return &gdp->node_list[0];
@@ -211,7 +203,7 @@ end:
 
 /**
  * sti_gdp_get_current_nodes
- * @plane: GDP plane
+ * @gdp: gdp pointer
  *
  * Look for GDP nodes that are currently read by the HW.
  *
@@ -219,10 +211,9 @@ end:
  * Pointer to the current GDP node list
  */
 static
-struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_plane *plane)
+struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_gdp *gdp)
 {
 	int hw_nvn;
-	struct sti_gdp *gdp = to_sti_gdp(plane);
 	unsigned int i;
 
 	hw_nvn = readl(gdp->regs + GAM_GDP_NVN_OFFSET);
@@ -236,205 +227,25 @@ struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_plane *plane)
 
 end:
 	DRM_DEBUG_DRIVER("Warning, NVN 0x%08X for %s does not match any node\n",
-				hw_nvn, sti_plane_to_str(plane));
+				hw_nvn, sti_plane_to_str(&gdp->plane));
 
 	return NULL;
 }
 
 /**
- * sti_gdp_prepare
- * @plane: gdp plane
- * @first_prepare: true if it is the first time this function is called
- *
- * Update the free GDP node list according to the plane properties.
- *
- * RETURNS:
- * 0 on success.
- */
-static int sti_gdp_prepare(struct sti_plane *plane, bool first_prepare)
-{
-	struct sti_gdp_node_list *list;
-	struct sti_gdp_node *top_field, *btm_field;
-	struct drm_display_mode *mode = plane->mode;
-	struct sti_gdp *gdp = to_sti_gdp(plane);
-	struct device *dev = gdp->dev;
-	struct sti_compositor *compo = dev_get_drvdata(dev);
-	int format;
-	unsigned int depth, bpp;
-	int rate = mode->clock * 1000;
-	int res;
-	u32 ydo, xdo, yds, xds;
-
-	list = sti_gdp_get_free_nodes(plane);
-	top_field = list->top_field;
-	btm_field = list->btm_field;
-
-	dev_dbg(dev, "%s %s top_node:0x%p btm_node:0x%p\n", __func__,
-			sti_plane_to_str(plane), top_field, btm_field);
-
-	/* Build the top field from plane params */
-	top_field->gam_gdp_agc = GAM_GDP_AGC_FULL_RANGE;
-	top_field->gam_gdp_ctl = WAIT_NEXT_VSYNC;
-	format = sti_gdp_fourcc2format(plane->format);
-	if (format == -1) {
-		DRM_ERROR("Format not supported by GDP %.4s\n",
-			  (char *)&plane->format);
-		return 1;
-	}
-	top_field->gam_gdp_ctl |= format;
-	top_field->gam_gdp_ctl |= sti_gdp_get_alpharange(format);
-	top_field->gam_gdp_ppt &= ~GAM_GDP_PPT_IGNORE;
-
-	/* pixel memory location */
-	drm_fb_get_bpp_depth(plane->format, &depth, &bpp);
-	top_field->gam_gdp_pml = (u32)plane->paddr + plane->offsets[0];
-	top_field->gam_gdp_pml += plane->src_x * (bpp >> 3);
-	top_field->gam_gdp_pml += plane->src_y * plane->pitches[0];
-
-	/* input parameters */
-	top_field->gam_gdp_pmp = plane->pitches[0];
-	top_field->gam_gdp_size =
-	    clamp_val(plane->src_h, 0, GAM_GDP_SIZE_MAX) << 16 |
-	    clamp_val(plane->src_w, 0, GAM_GDP_SIZE_MAX);
-
-	/* output parameters */
-	ydo = sti_vtg_get_line_number(*mode, plane->dst_y);
-	yds = sti_vtg_get_line_number(*mode, plane->dst_y + plane->dst_h - 1);
-	xdo = sti_vtg_get_pixel_number(*mode, plane->dst_x);
-	xds = sti_vtg_get_pixel_number(*mode, plane->dst_x + plane->dst_w - 1);
-	top_field->gam_gdp_vpo = (ydo << 16) | xdo;
-	top_field->gam_gdp_vps = (yds << 16) | xds;
-
-	/* Same content and chained together */
-	memcpy(btm_field, top_field, sizeof(*btm_field));
-	top_field->gam_gdp_nvn = list->btm_field_paddr;
-	btm_field->gam_gdp_nvn = list->top_field_paddr;
-
-	/* Interlaced mode */
-	if (plane->mode->flags & DRM_MODE_FLAG_INTERLACE)
-		btm_field->gam_gdp_pml = top_field->gam_gdp_pml +
-		    plane->pitches[0];
-
-	if (first_prepare) {
-		/* Register gdp callback */
-		if (sti_vtg_register_client(plane->mixer_id == STI_MIXER_MAIN ?
-				compo->vtg_main : compo->vtg_aux,
-				&gdp->vtg_field_nb, plane->mixer_id)) {
-			DRM_ERROR("Cannot register VTG notifier\n");
-			return 1;
-		}
-
-		/* Set and enable gdp clock */
-		if (gdp->clk_pix) {
-			struct clk *clkp;
-			/* According to the mixer used, the gdp pixel clock
-			 * should have a different parent clock. */
-			if (plane->mixer_id == STI_MIXER_MAIN)
-				clkp = gdp->clk_main_parent;
-			else
-				clkp = gdp->clk_aux_parent;
-
-			if (clkp)
-				clk_set_parent(gdp->clk_pix, clkp);
-
-			res = clk_set_rate(gdp->clk_pix, rate);
-			if (res < 0) {
-				DRM_ERROR("Cannot set rate (%dHz) for gdp\n",
-						rate);
-				return 1;
-			}
-
-			if (clk_prepare_enable(gdp->clk_pix)) {
-				DRM_ERROR("Failed to prepare/enable gdp\n");
-				return 1;
-			}
-		}
-	}
-
-	return 0;
-}
-
-/**
- * sti_gdp_commit
- * @plane: gdp plane
- *
- * Update the NVN field of the 'right' field of the current GDP node (being
- * used by the HW) with the address of the updated ('free') top field GDP node.
- * - In interlaced mode the 'right' field is the bottom field as we update
- *   frames starting from their top field
- * - In progressive mode, we update both bottom and top fields which are
- *   equal nodes.
- * At the next VSYNC, the updated node list will be used by the HW.
- *
- * RETURNS:
- * 0 on success.
- */
-static int sti_gdp_commit(struct sti_plane *plane)
-{
-	struct sti_gdp_node_list *updated_list = sti_gdp_get_free_nodes(plane);
-	struct sti_gdp_node *updated_top_node = updated_list->top_field;
-	struct sti_gdp_node *updated_btm_node = updated_list->btm_field;
-	struct sti_gdp *gdp = to_sti_gdp(plane);
-	u32 dma_updated_top = updated_list->top_field_paddr;
-	u32 dma_updated_btm = updated_list->btm_field_paddr;
-	struct sti_gdp_node_list *curr_list = sti_gdp_get_current_nodes(plane);
-
-	dev_dbg(gdp->dev, "%s %s top/btm_node:0x%p/0x%p\n", __func__,
-		sti_plane_to_str(plane),
-		updated_top_node, updated_btm_node);
-	dev_dbg(gdp->dev, "Current NVN:0x%X\n",
-		readl(gdp->regs + GAM_GDP_NVN_OFFSET));
-	dev_dbg(gdp->dev, "Posted buff: %lx current buff: %x\n",
-		(unsigned long)plane->paddr,
-		readl(gdp->regs + GAM_GDP_PML_OFFSET));
-
-	if (curr_list == NULL) {
-		/* First update or invalid node should directly write in the
-		 * hw register */
-		DRM_DEBUG_DRIVER("%s first update (or invalid node)",
-				sti_plane_to_str(plane));
-
-		writel(gdp->is_curr_top == true ?
-				dma_updated_btm : dma_updated_top,
-				gdp->regs + GAM_GDP_NVN_OFFSET);
-		return 0;
-	}
-
-	if (plane->mode->flags & DRM_MODE_FLAG_INTERLACE) {
-		if (gdp->is_curr_top == true) {
-			/* Do not update in the middle of the frame, but
-			 * postpone the update after the bottom field has
-			 * been displayed */
-			curr_list->btm_field->gam_gdp_nvn = dma_updated_top;
-		} else {
-			/* Direct update to avoid one frame delay */
-			writel(dma_updated_top,
-				gdp->regs + GAM_GDP_NVN_OFFSET);
-		}
-	} else {
-		/* Direct update for progressive to avoid one frame delay */
-		writel(dma_updated_top, gdp->regs + GAM_GDP_NVN_OFFSET);
-	}
-
-	return 0;
-}
-
-/**
  * sti_gdp_disable
- * @plane: gdp plane
+ * @gdp: gdp pointer
  *
  * Disable a GDP.
- *
- * RETURNS:
- * 0 on success.
  */
-static int sti_gdp_disable(struct sti_plane *plane)
+static void sti_gdp_disable(struct sti_gdp *gdp)
 {
-	unsigned int i;
-	struct sti_gdp *gdp = to_sti_gdp(plane);
+	struct drm_plane *drm_plane = &gdp->plane.drm_plane;
+	struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);
 	struct sti_compositor *compo = dev_get_drvdata(gdp->dev);
+	unsigned int i;
 
-	DRM_DEBUG_DRIVER("%s\n", sti_plane_to_str(plane));
+	DRM_DEBUG_DRIVER("%s\n", sti_plane_to_str(&gdp->plane));
 
 	/* Set the nodes as 'to be ignored on mixer' */
 	for (i = 0; i < GDP_NODE_NB_BANK; i++) {
@@ -442,14 +253,14 @@ static int sti_gdp_disable(struct sti_plane *plane)
 		gdp->node_list[i].btm_field->gam_gdp_ppt |= GAM_GDP_PPT_IGNORE;
 	}
 
-	if (sti_vtg_unregister_client(plane->mixer_id == STI_MIXER_MAIN ?
+	if (sti_vtg_unregister_client(mixer->id == STI_MIXER_MAIN ?
 			compo->vtg_main : compo->vtg_aux, &gdp->vtg_field_nb))
 		DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
 
 	if (gdp->clk_pix)
 		clk_disable_unprepare(gdp->clk_pix);
 
-	return 0;
+	gdp->plane.status = STI_PLANE_DISABLED;
 }
 
 /**
@@ -468,6 +279,14 @@ int sti_gdp_field_cb(struct notifier_block *nb,
 {
 	struct sti_gdp *gdp = container_of(nb, struct sti_gdp, vtg_field_nb);
 
+	if (gdp->plane.status == STI_PLANE_FLUSHING) {
+		/* disable need to be synchronize on vsync event */
+		DRM_DEBUG_DRIVER("Vsync event received => disable %s\n",
+				 sti_plane_to_str(&gdp->plane));
+
+		sti_gdp_disable(gdp);
+	}
+
 	switch (event) {
 	case VTG_TOP_FIELD_EVENT:
 		gdp->is_curr_top = true;
@@ -561,18 +380,235 @@ static void sti_gdp_init(struct sti_gdp *gdp)
 	}
 }
 
-static const struct sti_plane_funcs gdp_plane_ops = {
-	.get_formats = sti_gdp_get_formats,
-	.get_nb_formats = sti_gdp_get_nb_formats,
-	.prepare = sti_gdp_prepare,
-	.commit = sti_gdp_commit,
-	.disable = sti_gdp_disable,
+static void sti_gdp_atomic_update(struct drm_plane *drm_plane,
+				  struct drm_plane_state *oldstate)
+{
+	struct drm_plane_state *state = drm_plane->state;
+	struct sti_plane *plane = to_sti_plane(drm_plane);
+	struct sti_gdp *gdp = to_sti_gdp(plane);
+	struct drm_crtc *crtc = state->crtc;
+	struct sti_compositor *compo = dev_get_drvdata(gdp->dev);
+	struct drm_framebuffer *fb =  state->fb;
+	bool first_prepare = plane->status == STI_PLANE_DISABLED ? true : false;
+	struct sti_mixer *mixer;
+	struct drm_display_mode *mode;
+	int dst_x, dst_y, dst_w, dst_h;
+	int src_x, src_y, src_w, src_h;
+	struct drm_gem_cma_object *cma_obj;
+	struct sti_gdp_node_list *list;
+	struct sti_gdp_node_list *curr_list;
+	struct sti_gdp_node *top_field, *btm_field;
+	u32 dma_updated_top;
+	u32 dma_updated_btm;
+	int format;
+	unsigned int depth, bpp;
+	u32 ydo, xdo, yds, xds;
+	int res;
+
+	/* Manage the case where crtc is null (disabled) */
+	if (!crtc)
+		return;
+
+	mixer = to_sti_mixer(crtc);
+	mode = &crtc->mode;
+	dst_x = state->crtc_x;
+	dst_y = state->crtc_y;
+	dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
+	dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
+	/* src_x are in 16.16 format */
+	src_x = state->src_x >> 16;
+	src_y = state->src_y >> 16;
+	src_w = state->src_w >> 16;
+	src_h = state->src_h >> 16;
+
+	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
+		      crtc->base.id, sti_mixer_to_str(mixer),
+		      drm_plane->base.id, sti_plane_to_str(plane));
+	DRM_DEBUG_KMS("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
+		      sti_plane_to_str(plane),
+		      dst_w, dst_h, dst_x, dst_y,
+		      src_w, src_h, src_x, src_y);
+
+	list = sti_gdp_get_free_nodes(gdp);
+	top_field = list->top_field;
+	btm_field = list->btm_field;
+
+	dev_dbg(gdp->dev, "%s %s top_node:0x%p btm_node:0x%p\n", __func__,
+		sti_plane_to_str(plane), top_field, btm_field);
+
+	/* build the top field */
+	top_field->gam_gdp_agc = GAM_GDP_AGC_FULL_RANGE;
+	top_field->gam_gdp_ctl = WAIT_NEXT_VSYNC;
+	format = sti_gdp_fourcc2format(fb->pixel_format);
+	if (format == -1) {
+		DRM_ERROR("Format not supported by GDP %.4s\n",
+			  (char *)&fb->pixel_format);
+		return;
+	}
+	top_field->gam_gdp_ctl |= format;
+	top_field->gam_gdp_ctl |= sti_gdp_get_alpharange(format);
+	top_field->gam_gdp_ppt &= ~GAM_GDP_PPT_IGNORE;
+
+	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+	if (!cma_obj) {
+		DRM_ERROR("Can't get CMA GEM object for fb\n");
+		return;
+	}
+
+	DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
+			 (char *)&fb->pixel_format,
+			 (unsigned long)cma_obj->paddr);
+
+	/* pixel memory location */
+	drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
+	top_field->gam_gdp_pml = (u32)cma_obj->paddr + fb->offsets[0];
+	top_field->gam_gdp_pml += src_x * (bpp >> 3);
+	top_field->gam_gdp_pml += src_y * fb->pitches[0];
+
+	/* input parameters */
+	top_field->gam_gdp_pmp = fb->pitches[0];
+	top_field->gam_gdp_size = clamp_val(src_h, 0, GAM_GDP_SIZE_MAX) << 16 |
+				  clamp_val(src_w, 0, GAM_GDP_SIZE_MAX);
+
+	/* output parameters */
+	ydo = sti_vtg_get_line_number(*mode, dst_y);
+	yds = sti_vtg_get_line_number(*mode, dst_y + dst_h - 1);
+	xdo = sti_vtg_get_pixel_number(*mode, dst_x);
+	xds = sti_vtg_get_pixel_number(*mode, dst_x + dst_w - 1);
+	top_field->gam_gdp_vpo = (ydo << 16) | xdo;
+	top_field->gam_gdp_vps = (yds << 16) | xds;
+
+	/* Same content and chained together */
+	memcpy(btm_field, top_field, sizeof(*btm_field));
+	top_field->gam_gdp_nvn = list->btm_field_paddr;
+	btm_field->gam_gdp_nvn = list->top_field_paddr;
+
+	/* Interlaced mode */
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		btm_field->gam_gdp_pml = top_field->gam_gdp_pml +
+					 fb->pitches[0];
+
+	if (first_prepare) {
+		/* Register gdp callback */
+		if (sti_vtg_register_client(mixer->id == STI_MIXER_MAIN ?
+				compo->vtg_main : compo->vtg_aux,
+				&gdp->vtg_field_nb, mixer->id)) {
+			DRM_ERROR("Cannot register VTG notifier\n");
+			return;
+		}
+
+		/* Set and enable gdp clock */
+		if (gdp->clk_pix) {
+			struct clk *clkp;
+			int rate = mode->clock * 1000;
+
+			/* According to the mixer used, the gdp pixel clock
+			 * should have a different parent clock. */
+			if (mixer->id == STI_MIXER_MAIN)
+				clkp = gdp->clk_main_parent;
+			else
+				clkp = gdp->clk_aux_parent;
+
+			if (clkp)
+				clk_set_parent(gdp->clk_pix, clkp);
+
+			res = clk_set_rate(gdp->clk_pix, rate);
+			if (res < 0) {
+				DRM_ERROR("Cannot set rate (%dHz) for gdp\n",
+					  rate);
+				return;
+			}
+
+			if (clk_prepare_enable(gdp->clk_pix)) {
+				DRM_ERROR("Failed to prepare/enable gdp\n");
+				return;
+			}
+		}
+	}
+
+	/* Update the NVN field of the 'right' field of the current GDP node
+	 * (being used by the HW) with the address of the updated ('free') top
+	 * field GDP node.
+	 * - In interlaced mode the 'right' field is the bottom field as we
+	 *   update frames starting from their top field
+	 * - In progressive mode, we update both bottom and top fields which
+	 *   are equal nodes.
+	 * At the next VSYNC, the updated node list will be used by the HW.
+	 */
+	curr_list = sti_gdp_get_current_nodes(gdp);
+	dma_updated_top = list->top_field_paddr;
+	dma_updated_btm = list->btm_field_paddr;
+
+	dev_dbg(gdp->dev, "Current NVN:0x%X\n",
+		readl(gdp->regs + GAM_GDP_NVN_OFFSET));
+	dev_dbg(gdp->dev, "Posted buff: %lx current buff: %x\n",
+		(unsigned long)cma_obj->paddr,
+		readl(gdp->regs + GAM_GDP_PML_OFFSET));
+
+	if (!curr_list) {
+		/* First update or invalid node should directly write in the
+		 * hw register */
+		DRM_DEBUG_DRIVER("%s first update (or invalid node)",
+				 sti_plane_to_str(plane));
+
+		writel(gdp->is_curr_top ?
+				dma_updated_btm : dma_updated_top,
+				gdp->regs + GAM_GDP_NVN_OFFSET);
+		goto end;
+	}
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		if (gdp->is_curr_top) {
+			/* Do not update in the middle of the frame, but
+			 * postpone the update after the bottom field has
+			 * been displayed */
+			curr_list->btm_field->gam_gdp_nvn = dma_updated_top;
+		} else {
+			/* Direct update to avoid one frame delay */
+			writel(dma_updated_top,
+			       gdp->regs + GAM_GDP_NVN_OFFSET);
+		}
+	} else {
+		/* Direct update for progressive to avoid one frame delay */
+		writel(dma_updated_top, gdp->regs + GAM_GDP_NVN_OFFSET);
+	}
+
+end:
+	plane->status = STI_PLANE_UPDATED;
+}
+
+static void sti_gdp_atomic_disable(struct drm_plane *drm_plane,
+				   struct drm_plane_state *oldstate)
+{
+	struct sti_plane *plane = to_sti_plane(drm_plane);
+	struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);
+
+	if (!drm_plane->crtc) {
+		DRM_DEBUG_DRIVER("drm plane:%d not enabled\n",
+				 drm_plane->base.id);
+		return;
+	}
+
+	DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
+			 drm_plane->crtc->base.id, sti_mixer_to_str(mixer),
+			 drm_plane->base.id, sti_plane_to_str(plane));
+
+	plane->status = STI_PLANE_DISABLING;
+}
+
+static const struct drm_plane_helper_funcs sti_gdp_helpers_funcs = {
+	.atomic_update = sti_gdp_atomic_update,
+	.atomic_disable = sti_gdp_atomic_disable,
 };
 
-struct sti_plane *sti_gdp_create(struct device *dev, int desc,
-				 void __iomem *baseaddr)
+struct drm_plane *sti_gdp_create(struct drm_device *drm_dev,
+				 struct device *dev, int desc,
+				 void __iomem *baseaddr,
+				 unsigned int possible_crtcs,
+				 enum drm_plane_type type)
 {
 	struct sti_gdp *gdp;
+	int res;
 
 	gdp = devm_kzalloc(dev, sizeof(*gdp), GFP_KERNEL);
 	if (!gdp) {
@@ -583,11 +619,30 @@ struct sti_plane *sti_gdp_create(struct device *dev, int desc,
 	gdp->dev = dev;
 	gdp->regs = baseaddr;
 	gdp->plane.desc = desc;
-	gdp->plane.ops = &gdp_plane_ops;
+	gdp->plane.status = STI_PLANE_DISABLED;
 
 	gdp->vtg_field_nb.notifier_call = sti_gdp_field_cb;
 
 	sti_gdp_init(gdp);
 
-	return &gdp->plane;
+	res = drm_universal_plane_init(drm_dev, &gdp->plane.drm_plane,
+				       possible_crtcs,
+				       &sti_plane_helpers_funcs,
+				       gdp_supported_formats,
+				       ARRAY_SIZE(gdp_supported_formats),
+				       type);
+	if (res) {
+		DRM_ERROR("Failed to initialize universal plane\n");
+		goto err;
+	}
+
+	drm_plane_helper_add(&gdp->plane.drm_plane, &sti_gdp_helpers_funcs);
+
+	sti_plane_init_property(&gdp->plane, type);
+
+	return &gdp->plane.drm_plane;
+
+err:
+	devm_kfree(dev, gdp);
+	return NULL;
 }
diff --git a/drivers/gpu/drm/sti/sti_gdp.h b/drivers/gpu/drm/sti/sti_gdp.h
index 01818ea..73947a4 100644
--- a/drivers/gpu/drm/sti/sti_gdp.h
+++ b/drivers/gpu/drm/sti/sti_gdp.h
@@ -11,7 +11,9 @@
 
 #include <linux/types.h>
 
-struct sti_plane *sti_gdp_create(struct device *dev, int desc,
-				 void __iomem *baseaddr);
-
+struct drm_plane *sti_gdp_create(struct drm_device *drm_dev,
+				 struct device *dev, int desc,
+				 void __iomem *baseaddr,
+				 unsigned int possible_crtcs,
+				 enum drm_plane_type type);
 #endif
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index b91a009..7c8f9b8 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -12,7 +12,10 @@
 #include <linux/reset.h>
 
 #include <drm/drmP.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
 
+#include "sti_compositor.h"
 #include "sti_hqvdp_lut.h"
 #include "sti_plane.h"
 #include "sti_vtg.h"
@@ -357,16 +360,6 @@ static const uint32_t hqvdp_supported_formats[] = {
 	DRM_FORMAT_NV12,
 };
 
-static const uint32_t *sti_hqvdp_get_formats(struct sti_plane *plane)
-{
-	return hqvdp_supported_formats;
-}
-
-static unsigned int sti_hqvdp_get_nb_formats(struct sti_plane *plane)
-{
-	return ARRAY_SIZE(hqvdp_supported_formats);
-}
-
 /**
  * sti_hqvdp_get_free_cmd
  * @hqvdp: hqvdp structure
@@ -482,7 +475,12 @@ static void sti_hqvdp_update_hvsrc(enum sti_hvsrc_orient orient, int scale,
 
 /**
  * sti_hqvdp_check_hw_scaling
- * @plane: hqvdp plane
+ * @hqvdp: hqvdp pointer
+ * @mode: display mode with timing constraints
+ * @src_w: source width
+ * @src_h: source height
+ * @dst_w: destination width
+ * @dst_h: destination height
  *
  * Check if the HW is able to perform the scaling request
  * The firmware scaling limitation is "CEIL(1/Zy) <= FLOOR(LFW)" where:
@@ -496,194 +494,36 @@ static void sti_hqvdp_update_hvsrc(enum sti_hvsrc_orient orient, int scale,
  * RETURNS:
  * True if the HW can scale.
  */
-static bool sti_hqvdp_check_hw_scaling(struct sti_plane *plane)
+static bool sti_hqvdp_check_hw_scaling(struct sti_hqvdp *hqvdp,
+				       struct drm_display_mode *mode,
+				       int src_w, int src_h,
+				       int dst_w, int dst_h)
 {
-	struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
 	unsigned long lfw;
 	unsigned int inv_zy;
 
-	lfw = plane->mode->htotal * (clk_get_rate(hqvdp->clk) / 1000000);
-	lfw /= max(plane->src_w, plane->dst_w) * plane->mode->clock / 1000;
+	lfw = mode->htotal * (clk_get_rate(hqvdp->clk) / 1000000);
+	lfw /= max(src_w, dst_w) * mode->clock / 1000;
 
-	inv_zy = DIV_ROUND_UP(plane->src_h, plane->dst_h);
+	inv_zy = DIV_ROUND_UP(src_h, dst_h);
 
 	return (inv_zy <= lfw) ? true : false;
 }
 
 /**
- * sti_hqvdp_prepare
- * @plane: hqvdp plane
- * @first_prepare: true if it is the first time this function is called
- *
- * Prepares a command for the firmware
- *
- * RETURNS:
- * 0 on success.
- */
-static int sti_hqvdp_prepare(struct sti_plane *plane, bool first_prepare)
-{
-	struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
-	struct sti_hqvdp_cmd *cmd;
-	int scale_h, scale_v;
-	int cmd_offset;
-
-	dev_dbg(hqvdp->dev, "%s %s\n", __func__, sti_plane_to_str(plane));
-
-	cmd_offset = sti_hqvdp_get_free_cmd(hqvdp);
-	if (cmd_offset == -1) {
-		DRM_ERROR("No available hqvdp_cmd now\n");
-		return -EBUSY;
-	}
-	cmd = hqvdp->hqvdp_cmd + cmd_offset;
-
-	if (!sti_hqvdp_check_hw_scaling(plane)) {
-		DRM_ERROR("Scaling beyond HW capabilities\n");
-		return -EINVAL;
-	}
-
-	/* Static parameters, defaulting to progressive mode */
-	cmd->top.config = TOP_CONFIG_PROGRESSIVE;
-	cmd->top.mem_format = TOP_MEM_FORMAT_DFLT;
-	cmd->hvsrc.param_ctrl = HVSRC_PARAM_CTRL_DFLT;
-	cmd->csdi.config = CSDI_CONFIG_PROG;
-
-	/* VC1RE, FMD bypassed : keep everything set to 0
-	 * IQI/P2I bypassed */
-	cmd->iqi.config = IQI_CONFIG_DFLT;
-	cmd->iqi.con_bri = IQI_CON_BRI_DFLT;
-	cmd->iqi.sat_gain = IQI_SAT_GAIN_DFLT;
-	cmd->iqi.pxf_conf = IQI_PXF_CONF_DFLT;
-
-	/* Buffer planes address */
-	cmd->top.current_luma = (u32)plane->paddr + plane->offsets[0];
-	cmd->top.current_chroma = (u32)plane->paddr + plane->offsets[1];
-
-	/* Pitches */
-	cmd->top.luma_processed_pitch = cmd->top.luma_src_pitch =
-			plane->pitches[0];
-	cmd->top.chroma_processed_pitch = cmd->top.chroma_src_pitch =
-			plane->pitches[1];
-
-	/* Input / output size
-	 * Align to upper even value */
-	plane->dst_w = ALIGN(plane->dst_w, 2);
-	plane->dst_h = ALIGN(plane->dst_h, 2);
-
-	if ((plane->src_w > MAX_WIDTH) || (plane->src_w < MIN_WIDTH) ||
-	    (plane->src_h > MAX_HEIGHT) || (plane->src_h < MIN_HEIGHT) ||
-	    (plane->dst_w > MAX_WIDTH) || (plane->dst_w < MIN_WIDTH) ||
-	    (plane->dst_h > MAX_HEIGHT) || (plane->dst_h < MIN_HEIGHT)) {
-		DRM_ERROR("Invalid in/out size %dx%d -> %dx%d\n",
-				plane->src_w, plane->src_h,
-				plane->dst_w, plane->dst_h);
-		return -EINVAL;
-	}
-	cmd->top.input_viewport_size = cmd->top.input_frame_size =
-			plane->src_h << 16 | plane->src_w;
-	cmd->hvsrc.output_picture_size = plane->dst_h << 16 | plane->dst_w;
-	cmd->top.input_viewport_ori = plane->src_y << 16 | plane->src_x;
-
-	/* Handle interlaced */
-	if (plane->fb->flags & DRM_MODE_FB_INTERLACED) {
-		/* Top field to display */
-		cmd->top.config = TOP_CONFIG_INTER_TOP;
-
-		/* Update pitches and vert size */
-		cmd->top.input_frame_size = (plane->src_h / 2) << 16 |
-					     plane->src_w;
-		cmd->top.luma_processed_pitch *= 2;
-		cmd->top.luma_src_pitch *= 2;
-		cmd->top.chroma_processed_pitch *= 2;
-		cmd->top.chroma_src_pitch *= 2;
-
-		/* Enable directional deinterlacing processing */
-		cmd->csdi.config = CSDI_CONFIG_INTER_DIR;
-		cmd->csdi.config2 = CSDI_CONFIG2_DFLT;
-		cmd->csdi.dcdi_config = CSDI_DCDI_CONFIG_DFLT;
-	}
-
-	/* Update hvsrc lut coef */
-	scale_h = SCALE_FACTOR * plane->dst_w / plane->src_w;
-	sti_hqvdp_update_hvsrc(HVSRC_HORI, scale_h, &cmd->hvsrc);
-
-	scale_v = SCALE_FACTOR * plane->dst_h / plane->src_h;
-	sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc);
-
-	if (first_prepare) {
-		/* Prevent VTG shutdown */
-		if (clk_prepare_enable(hqvdp->clk_pix_main)) {
-			DRM_ERROR("Failed to prepare/enable pix main clk\n");
-			return -ENXIO;
-		}
-
-		/* Register VTG Vsync callback to handle bottom fields */
-		if ((plane->fb->flags & DRM_MODE_FB_INTERLACED) &&
-		    sti_vtg_register_client(hqvdp->vtg, &hqvdp->vtg_nb,
-					    plane->mixer_id)) {
-			DRM_ERROR("Cannot register VTG notifier\n");
-			return -ENXIO;
-		}
-	}
-
-	return 0;
-}
-
-/**
- * sti_hqvdp_commit
- * @plane: hqvdp plane
- *
- * Enables the HQVDP plane
- *
- * RETURNS:
- * 0 on success.
- */
-static int sti_hqvdp_commit(struct sti_plane *plane)
-{
-	struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
-	int cmd_offset;
-
-	dev_dbg(hqvdp->dev, "%s %s\n", __func__, sti_plane_to_str(plane));
-
-	cmd_offset = sti_hqvdp_get_free_cmd(hqvdp);
-	if (cmd_offset == -1) {
-		DRM_ERROR("No available hqvdp_cmd now\n");
-		return -EBUSY;
-	}
-
-	writel(hqvdp->hqvdp_cmd_paddr + cmd_offset,
-			hqvdp->regs + HQVDP_MBX_NEXT_CMD);
-
-	hqvdp->curr_field_count++;
-
-	/* Interlaced : get ready to display the bottom field at next Vsync */
-	if (plane->fb->flags & DRM_MODE_FB_INTERLACED)
-		hqvdp->btm_field_pending = true;
-
-	dev_dbg(hqvdp->dev, "%s Posted command:0x%x\n",
-			__func__, hqvdp->hqvdp_cmd_paddr + cmd_offset);
-
-	return 0;
-}
-
-/**
  * sti_hqvdp_disable
- * @plane: hqvdp plane
+ * @hqvdp: hqvdp pointer
  *
  * Disables the HQVDP plane
- *
- * RETURNS:
- * 0 on success.
  */
-static int sti_hqvdp_disable(struct sti_plane *plane)
+static void sti_hqvdp_disable(struct sti_hqvdp *hqvdp)
 {
-	struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
 	int i;
 
-	DRM_DEBUG_DRIVER("%s\n", sti_plane_to_str(plane));
+	DRM_DEBUG_DRIVER("%s\n", sti_plane_to_str(&hqvdp->plane));
 
 	/* Unregister VTG Vsync callback */
-	if ((plane->fb->flags & DRM_MODE_FB_INTERLACED) &&
-	    sti_vtg_unregister_client(hqvdp->vtg, &hqvdp->vtg_nb))
+	if (sti_vtg_unregister_client(hqvdp->vtg, &hqvdp->vtg_nb))
 		DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
 
 	/* Set next cmd to NULL */
@@ -699,12 +539,10 @@ static int sti_hqvdp_disable(struct sti_plane *plane)
 	/* VTG can stop now */
 	clk_disable_unprepare(hqvdp->clk_pix_main);
 
-	if (i == POLL_MAX_ATTEMPT) {
+	if (i == POLL_MAX_ATTEMPT)
 		DRM_ERROR("XP70 could not revert to idle\n");
-		return -ENXIO;
-	}
 
-	return 0;
+	hqvdp->plane.status = STI_PLANE_DISABLED;
 }
 
 /**
@@ -729,6 +567,14 @@ int sti_hqvdp_vtg_cb(struct notifier_block *nb, unsigned long evt, void *data)
 		return 0;
 	}
 
+	if (hqvdp->plane.status == STI_PLANE_FLUSHING) {
+		/* disable need to be synchronize on vsync event */
+		DRM_DEBUG_DRIVER("Vsync event received => disable %s\n",
+				 sti_plane_to_str(&hqvdp->plane));
+
+		sti_hqvdp_disable(hqvdp);
+	}
+
 	if (hqvdp->btm_field_pending) {
 		/* Create the btm field command from the current one */
 		btm_cmd_offset = sti_hqvdp_get_free_cmd(hqvdp);
@@ -782,24 +628,212 @@ static void sti_hqvdp_init(struct sti_hqvdp *hqvdp)
 	memset(hqvdp->hqvdp_cmd, 0, size);
 }
 
-static const struct sti_plane_funcs hqvdp_plane_ops = {
-	.get_formats = sti_hqvdp_get_formats,
-	.get_nb_formats = sti_hqvdp_get_nb_formats,
-	.prepare = sti_hqvdp_prepare,
-	.commit = sti_hqvdp_commit,
-	.disable = sti_hqvdp_disable,
+static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
+				    struct drm_plane_state *oldstate)
+{
+	struct drm_plane_state *state = drm_plane->state;
+	struct sti_plane *plane = to_sti_plane(drm_plane);
+	struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
+	struct drm_crtc *crtc = state->crtc;
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_display_mode *mode = &crtc->mode;
+	int dst_x = state->crtc_x;
+	int dst_y = state->crtc_y;
+	int dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
+	int dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
+	/* src_x are in 16.16 format */
+	int src_x = state->src_x >> 16;
+	int src_y = state->src_y >> 16;
+	int src_w = state->src_w >> 16;
+	int src_h = state->src_h >> 16;
+	bool first_prepare = plane->status == STI_PLANE_DISABLED ? true : false;
+	struct drm_gem_cma_object *cma_obj;
+	struct sti_hqvdp_cmd *cmd;
+	int scale_h, scale_v;
+	int cmd_offset;
+
+	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
+		      crtc->base.id, sti_mixer_to_str(mixer),
+		      drm_plane->base.id, sti_plane_to_str(plane));
+	DRM_DEBUG_KMS("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
+		      sti_plane_to_str(plane),
+		      dst_w, dst_h, dst_x, dst_y,
+		      src_w, src_h, src_x, src_y);
+
+	cmd_offset = sti_hqvdp_get_free_cmd(hqvdp);
+	if (cmd_offset == -1) {
+		DRM_ERROR("No available hqvdp_cmd now\n");
+		return;
+	}
+	cmd = hqvdp->hqvdp_cmd + cmd_offset;
+
+	if (!sti_hqvdp_check_hw_scaling(hqvdp, mode,
+					src_w, src_h,
+					dst_w, dst_h)) {
+		DRM_ERROR("Scaling beyond HW capabilities\n");
+		return;
+	}
+
+	/* Static parameters, defaulting to progressive mode */
+	cmd->top.config = TOP_CONFIG_PROGRESSIVE;
+	cmd->top.mem_format = TOP_MEM_FORMAT_DFLT;
+	cmd->hvsrc.param_ctrl = HVSRC_PARAM_CTRL_DFLT;
+	cmd->csdi.config = CSDI_CONFIG_PROG;
+
+	/* VC1RE, FMD bypassed : keep everything set to 0
+	 * IQI/P2I bypassed */
+	cmd->iqi.config = IQI_CONFIG_DFLT;
+	cmd->iqi.con_bri = IQI_CON_BRI_DFLT;
+	cmd->iqi.sat_gain = IQI_SAT_GAIN_DFLT;
+	cmd->iqi.pxf_conf = IQI_PXF_CONF_DFLT;
+
+	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+	if (!cma_obj) {
+		DRM_ERROR("Can't get CMA GEM object for fb\n");
+		return;
+	}
+
+	DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
+			 (char *)&fb->pixel_format,
+			 (unsigned long)cma_obj->paddr);
+
+	/* Buffer planes address */
+	cmd->top.current_luma = (u32)cma_obj->paddr + fb->offsets[0];
+	cmd->top.current_chroma = (u32)cma_obj->paddr + fb->offsets[1];
+
+	/* Pitches */
+	cmd->top.luma_processed_pitch = fb->pitches[0];
+	cmd->top.luma_src_pitch = fb->pitches[0];
+	cmd->top.chroma_processed_pitch = fb->pitches[1];
+	cmd->top.chroma_src_pitch = fb->pitches[1];
+
+	/* Input / output size
+	 * Align to upper even value */
+	dst_w = ALIGN(dst_w, 2);
+	dst_h = ALIGN(dst_h, 2);
+
+	if ((src_w > MAX_WIDTH) || (src_w < MIN_WIDTH) ||
+	    (src_h > MAX_HEIGHT) || (src_h < MIN_HEIGHT) ||
+	    (dst_w > MAX_WIDTH) || (dst_w < MIN_WIDTH) ||
+	    (dst_h > MAX_HEIGHT) || (dst_h < MIN_HEIGHT)) {
+		DRM_ERROR("Invalid in/out size %dx%d -> %dx%d\n",
+			  src_w, src_h,
+			  dst_w, dst_h);
+		return;
+	}
+
+	cmd->top.input_viewport_size = src_h << 16 | src_w;
+	cmd->top.input_frame_size = src_h << 16 | src_w;
+	cmd->hvsrc.output_picture_size = dst_h << 16 | dst_w;
+	cmd->top.input_viewport_ori = src_y << 16 | src_x;
+
+	/* Handle interlaced */
+	if (fb->flags & DRM_MODE_FB_INTERLACED) {
+		/* Top field to display */
+		cmd->top.config = TOP_CONFIG_INTER_TOP;
+
+		/* Update pitches and vert size */
+		cmd->top.input_frame_size = (src_h / 2) << 16 | src_w;
+		cmd->top.luma_processed_pitch *= 2;
+		cmd->top.luma_src_pitch *= 2;
+		cmd->top.chroma_processed_pitch *= 2;
+		cmd->top.chroma_src_pitch *= 2;
+
+		/* Enable directional deinterlacing processing */
+		cmd->csdi.config = CSDI_CONFIG_INTER_DIR;
+		cmd->csdi.config2 = CSDI_CONFIG2_DFLT;
+		cmd->csdi.dcdi_config = CSDI_DCDI_CONFIG_DFLT;
+	}
+
+	/* Update hvsrc lut coef */
+	scale_h = SCALE_FACTOR * dst_w / src_w;
+	sti_hqvdp_update_hvsrc(HVSRC_HORI, scale_h, &cmd->hvsrc);
+
+	scale_v = SCALE_FACTOR * dst_h / src_h;
+	sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc);
+
+	if (first_prepare) {
+		/* Prevent VTG shutdown */
+		if (clk_prepare_enable(hqvdp->clk_pix_main)) {
+			DRM_ERROR("Failed to prepare/enable pix main clk\n");
+			return;
+		}
+
+		/* Register VTG Vsync callback to handle bottom fields */
+		if (sti_vtg_register_client(hqvdp->vtg,
+					    &hqvdp->vtg_nb,
+					    mixer->id)) {
+			DRM_ERROR("Cannot register VTG notifier\n");
+			return;
+		}
+	}
+
+	writel(hqvdp->hqvdp_cmd_paddr + cmd_offset,
+	       hqvdp->regs + HQVDP_MBX_NEXT_CMD);
+
+	hqvdp->curr_field_count++;
+
+	/* Interlaced : get ready to display the bottom field at next Vsync */
+	if (fb->flags & DRM_MODE_FB_INTERLACED)
+		hqvdp->btm_field_pending = true;
+
+	dev_dbg(hqvdp->dev, "%s Posted command:0x%x\n",
+		__func__, hqvdp->hqvdp_cmd_paddr + cmd_offset);
+
+	plane->status = STI_PLANE_UPDATED;
+}
+
+static void sti_hqvdp_atomic_disable(struct drm_plane *drm_plane,
+				     struct drm_plane_state *oldstate)
+{
+	struct sti_plane *plane = to_sti_plane(drm_plane);
+	struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);
+
+	if (!drm_plane->crtc) {
+		DRM_DEBUG_DRIVER("drm plane:%d not enabled\n",
+				 drm_plane->base.id);
+		return;
+	}
+
+	DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
+			 drm_plane->crtc->base.id, sti_mixer_to_str(mixer),
+			 drm_plane->base.id, sti_plane_to_str(plane));
+
+	plane->status = STI_PLANE_DISABLING;
+}
+
+static const struct drm_plane_helper_funcs sti_hqvdp_helpers_funcs = {
+	.atomic_update = sti_hqvdp_atomic_update,
+	.atomic_disable = sti_hqvdp_atomic_disable,
 };
 
-struct sti_plane *sti_hqvdp_create(struct device *dev, int desc)
+static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev,
+					  struct device *dev, int desc)
 {
 	struct sti_hqvdp *hqvdp = dev_get_drvdata(dev);
+	int res;
 
 	hqvdp->plane.desc = desc;
-	hqvdp->plane.ops = &hqvdp_plane_ops;
+	hqvdp->plane.status = STI_PLANE_DISABLED;
 
 	sti_hqvdp_init(hqvdp);
 
-	return &hqvdp->plane;
+	res = drm_universal_plane_init(drm_dev, &hqvdp->plane.drm_plane, 1,
+				       &sti_plane_helpers_funcs,
+				       hqvdp_supported_formats,
+				       ARRAY_SIZE(hqvdp_supported_formats),
+				       DRM_PLANE_TYPE_OVERLAY);
+	if (res) {
+		DRM_ERROR("Failed to initialize universal plane\n");
+		return NULL;
+	}
+
+	drm_plane_helper_add(&hqvdp->plane.drm_plane, &sti_hqvdp_helpers_funcs);
+
+	sti_plane_init_property(&hqvdp->plane, DRM_PLANE_TYPE_OVERLAY);
+
+	return &hqvdp->plane.drm_plane;
 }
 
 static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp)
@@ -948,7 +982,7 @@ int sti_hqvdp_bind(struct device *dev, struct device *master, void *data)
 {
 	struct sti_hqvdp *hqvdp = dev_get_drvdata(dev);
 	struct drm_device *drm_dev = data;
-	struct sti_plane *plane;
+	struct drm_plane *plane;
 	int err;
 
 	DRM_DEBUG_DRIVER("\n");
@@ -965,11 +999,8 @@ int sti_hqvdp_bind(struct device *dev, struct device *master, void *data)
 	}
 
 	/* Create HQVDP plane once xp70 is initialized */
-	plane = sti_hqvdp_create(hqvdp->dev, STI_HQVDP_0);
-	if (plane)
-		sti_plane_init(hqvdp->drm_dev, plane, 1,
-			       DRM_PLANE_TYPE_OVERLAY);
-	else
+	plane = sti_hqvdp_create(drm_dev, hqvdp->dev, STI_HQVDP_0);
+	if (!plane)
 		DRM_ERROR("Can't create HQVDP plane\n");
 
 	return 0;
diff --git a/drivers/gpu/drm/sti/sti_mixer.h b/drivers/gpu/drm/sti/sti_mixer.h
index 2f69b00..4acf4f8 100644
--- a/drivers/gpu/drm/sti/sti_mixer.h
+++ b/drivers/gpu/drm/sti/sti_mixer.h
@@ -15,6 +15,12 @@
 
 #define to_sti_mixer(x) container_of(x, struct sti_mixer, drm_crtc)
 
+enum sti_mixer_status {
+	STI_MIXER_READY,
+	STI_MIXER_DISABLING,
+	STI_MIXER_DISABLED,
+};
+
 /**
  * STI Mixer subdevice structure
  *
@@ -23,7 +29,7 @@
  * @id: id of the mixer
  * @drm_crtc: crtc object link to the mixer
  * @pending_event: set if a flip event is pending on crtc
- * @enabled: to know if the mixer is active or not
+ * @status: to know the status of the mixer
  */
 struct sti_mixer {
 	struct device *dev;
@@ -31,7 +37,7 @@ struct sti_mixer {
 	int id;
 	struct drm_crtc drm_crtc;
 	struct drm_pending_vblank_event *pending_event;
-	bool enabled;
+	enum sti_mixer_status status;
 };
 
 const char *sti_mixer_to_str(struct sti_mixer *mixer);
diff --git a/drivers/gpu/drm/sti/sti_plane.c b/drivers/gpu/drm/sti/sti_plane.c
index 6a38521..14685cf 100644
--- a/drivers/gpu/drm/sti/sti_plane.c
+++ b/drivers/gpu/drm/sti/sti_plane.c
@@ -7,15 +7,12 @@
  */
 
 #include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_cma_helper.h>
 
 #include "sti_compositor.h"
 #include "sti_drv.h"
 #include "sti_plane.h"
-#include "sti_vtg.h"
 
 /* (Background) < GDP0 < GDP1 < HQVDP0 < GDP2 < GDP3 < (ForeGround) */
 enum sti_plane_desc sti_plane_default_zorder[] = {
@@ -47,115 +44,6 @@ const char *sti_plane_to_str(struct sti_plane *plane)
 }
 EXPORT_SYMBOL(sti_plane_to_str);
 
-static int sti_plane_prepare(struct sti_plane *plane,
-			     struct drm_crtc *crtc,
-			     struct drm_framebuffer *fb,
-			     struct drm_display_mode *mode, int mixer_id,
-			     int dest_x, int dest_y, int dest_w, int dest_h,
-			     int src_x, int src_y, int src_w, int src_h)
-{
-	struct drm_gem_cma_object *cma_obj;
-	unsigned int i;
-	int res;
-
-	if (!plane || !fb || !mode) {
-		DRM_ERROR("Null fb, plane or mode\n");
-		return 1;
-	}
-
-	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-	if (!cma_obj) {
-		DRM_ERROR("Can't get CMA GEM object for fb\n");
-		return 1;
-	}
-
-	plane->fb = fb;
-	plane->mode = mode;
-	plane->mixer_id = mixer_id;
-	plane->dst_x = dest_x;
-	plane->dst_y = dest_y;
-	plane->dst_w = clamp_val(dest_w, 0, mode->crtc_hdisplay - dest_x);
-	plane->dst_h = clamp_val(dest_h, 0, mode->crtc_vdisplay - dest_y);
-	plane->src_x = src_x;
-	plane->src_y = src_y;
-	plane->src_w = src_w;
-	plane->src_h = src_h;
-	plane->format = fb->pixel_format;
-	plane->vaddr = cma_obj->vaddr;
-	plane->paddr = cma_obj->paddr;
-	for (i = 0; i < 4; i++) {
-		plane->pitches[i] = fb->pitches[i];
-		plane->offsets[i] = fb->offsets[i];
-	}
-
-	DRM_DEBUG_DRIVER("%s is associated with mixer_id %d\n",
-			 sti_plane_to_str(plane),
-			 plane->mixer_id);
-	DRM_DEBUG_DRIVER("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
-			 sti_plane_to_str(plane),
-			 plane->dst_w, plane->dst_h, plane->dst_x, plane->dst_y,
-			 plane->src_w, plane->src_h, plane->src_x,
-			 plane->src_y);
-
-	DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
-			 (char *)&plane->format, (unsigned long)plane->paddr);
-
-	if (!plane->ops->prepare) {
-		DRM_ERROR("Cannot prepare\n");
-		return 1;
-	}
-
-	res = plane->ops->prepare(plane, !plane->enabled);
-	if (res) {
-		DRM_ERROR("Plane prepare failed\n");
-		return res;
-	}
-
-	plane->enabled = true;
-
-	return 0;
-}
-
-static int sti_plane_commit(struct sti_plane *plane)
-{
-	if (!plane)
-		return 1;
-
-	if (!plane->ops->commit) {
-		DRM_ERROR("Cannot commit\n");
-		return 1;
-	}
-
-	return plane->ops->commit(plane);
-}
-
-static int sti_plane_disable(struct sti_plane *plane)
-{
-	int res;
-
-	DRM_DEBUG_DRIVER("%s\n", sti_plane_to_str(plane));
-	if (!plane)
-		return 1;
-
-	if (!plane->enabled)
-		return 0;
-
-	if (!plane->ops->disable) {
-		DRM_ERROR("Cannot disable\n");
-		return 1;
-	}
-
-	res = plane->ops->disable(plane);
-	if (res) {
-		DRM_ERROR("Plane disable failed\n");
-		return res;
-	}
-
-	plane->enabled = false;
-
-	return 0;
-}
-
 static void sti_plane_destroy(struct drm_plane *drm_plane)
 {
 	DRM_DEBUG_DRIVER("\n");
@@ -182,109 +70,6 @@ static int sti_plane_set_property(struct drm_plane *drm_plane,
 	return -EINVAL;
 }
 
-static struct drm_plane_funcs sti_plane_funcs = {
-	.update_plane = drm_atomic_helper_update_plane,
-	.disable_plane = drm_atomic_helper_disable_plane,
-	.destroy = sti_plane_destroy,
-	.set_property = sti_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 sti_plane_atomic_check(struct drm_plane *drm_plane,
-				  struct drm_plane_state *state)
-{
-	return 0;
-}
-
-static void sti_plane_atomic_update(struct drm_plane *drm_plane,
-				    struct drm_plane_state *oldstate)
-{
-	struct drm_plane_state *state = drm_plane->state;
-	struct sti_plane *plane = to_sti_plane(drm_plane);
-	struct sti_mixer *mixer = to_sti_mixer(state->crtc);
-	int res;
-
-	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
-		      state->crtc->base.id, sti_mixer_to_str(mixer),
-		      drm_plane->base.id, sti_plane_to_str(plane));
-	DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n",
-		      state->crtc_w, state->crtc_h,
-		      state->crtc_x, state->crtc_y);
-
-	res = sti_mixer_set_plane_depth(mixer, plane);
-	if (res) {
-		DRM_ERROR("Cannot set plane depth\n");
-		return;
-	}
-
-	/* src_x are in 16.16 format */
-	res = sti_plane_prepare(plane, state->crtc, state->fb,
-				&state->crtc->mode, mixer->id,
-				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);
-	if (res) {
-		DRM_ERROR("Plane prepare failed\n");
-		return;
-	}
-
-	res = sti_plane_commit(plane);
-	if (res) {
-		DRM_ERROR("Plane commit failed\n");
-		return;
-	}
-
-	res = sti_mixer_set_plane_status(mixer, plane, true);
-	if (res) {
-		DRM_ERROR("Cannot enable plane at mixer\n");
-		return;
-	}
-}
-
-static void sti_plane_atomic_disable(struct drm_plane *drm_plane,
-				     struct drm_plane_state *oldstate)
-{
-	struct sti_plane *plane = to_sti_plane(drm_plane);
-	struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);
-	int res;
-
-	if (!drm_plane->crtc) {
-		DRM_DEBUG_DRIVER("drm plane:%d not enabled\n",
-				 drm_plane->base.id);
-		return;
-	}
-
-	DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
-			 drm_plane->crtc->base.id, sti_mixer_to_str(mixer),
-			 drm_plane->base.id, sti_plane_to_str(plane));
-
-	/* Disable plane at mixer level */
-	res = sti_mixer_set_plane_status(mixer, plane, false);
-	if (res) {
-		DRM_ERROR("Cannot disable plane at mixer\n");
-		return;
-	}
-
-	/* Wait a while to be sure that a Vsync event is received */
-	msleep(WAIT_NEXT_VSYNC_MS);
-
-	/* Then disable plane itself */
-	res = sti_plane_disable(plane);
-	if (res) {
-		DRM_ERROR("Plane disable failed\n");
-		return;
-	}
-}
-
-static const struct drm_plane_helper_funcs sti_plane_helpers_funcs = {
-	.atomic_check = sti_plane_atomic_check,
-	.atomic_update = sti_plane_atomic_update,
-	.atomic_disable = sti_plane_atomic_disable,
-};
-
 static void sti_plane_attach_zorder_property(struct drm_plane *drm_plane)
 {
 	struct drm_device *dev = drm_plane->dev;
@@ -305,25 +90,10 @@ static void sti_plane_attach_zorder_property(struct drm_plane *drm_plane)
 	drm_object_attach_property(&drm_plane->base, prop, plane->zorder);
 }
 
-struct drm_plane *sti_plane_init(struct drm_device *dev,
-				 struct sti_plane *plane,
-				 unsigned int possible_crtcs,
-				 enum drm_plane_type type)
+void sti_plane_init_property(struct sti_plane *plane,
+			     enum drm_plane_type type)
 {
-	int err, i;
-
-	err = drm_universal_plane_init(dev, &plane->drm_plane,
-				       possible_crtcs,
-				       &sti_plane_funcs,
-				       plane->ops->get_formats(plane),
-				       plane->ops->get_nb_formats(plane),
-				       type);
-	if (err) {
-		DRM_ERROR("Failed to initialize universal plane\n");
-		return NULL;
-	}
-
-	drm_plane_helper_add(&plane->drm_plane, &sti_plane_helpers_funcs);
+	unsigned int i;
 
 	for (i = 0; i < ARRAY_SIZE(sti_plane_default_zorder); i++)
 		if (sti_plane_default_zorder[i] == plane->desc)
@@ -337,7 +107,14 @@ struct drm_plane *sti_plane_init(struct drm_device *dev,
 	DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%d\n",
 			 plane->drm_plane.base.id,
 			 sti_plane_to_str(plane), plane->zorder);
-
-	return &plane->drm_plane;
 }
-EXPORT_SYMBOL(sti_plane_init);
+
+struct drm_plane_funcs sti_plane_helpers_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = sti_plane_destroy,
+	.set_property = sti_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,
+};
diff --git a/drivers/gpu/drm/sti/sti_plane.h b/drivers/gpu/drm/sti/sti_plane.h
index bd52754..86f1e6f 100644
--- a/drivers/gpu/drm/sti/sti_plane.h
+++ b/drivers/gpu/drm/sti/sti_plane.h
@@ -8,6 +8,10 @@
 #define _STI_PLANE_H_
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+
+extern struct drm_plane_funcs sti_plane_helpers_funcs;
 
 #define to_sti_plane(x) container_of(x, struct sti_plane, drm_plane)
 
@@ -38,68 +42,30 @@ enum sti_plane_desc {
 	STI_BACK        = STI_BCK
 };
 
+enum sti_plane_status {
+	STI_PLANE_READY,
+	STI_PLANE_UPDATED,
+	STI_PLANE_DISABLING,
+	STI_PLANE_FLUSHING,
+	STI_PLANE_DISABLED,
+};
+
 /**
  * STI plane structure
  *
  * @plane:              drm plane it is bound to (if any)
- * @fb:                 drm fb it is bound to
- * @mode:               display mode
  * @desc:               plane type & id
- * @ops:                plane functions
+ * @status:             to know the status of the plane
  * @zorder:             plane z-order
- * @mixer_id:           id of the mixer used to display the plane
- * @enabled:            to know if the plane is active or not
- * @src_x src_y:        coordinates of the input (fb) area
- * @src_w src_h:        size of the input (fb) area
- * @dst_x dst_y:        coordinates of the output (crtc) area
- * @dst_w dst_h:        size of the output (crtc) area
- * @format:             format
- * @pitches:            pitch of 'planes' (eg: Y, U, V)
- * @offsets:            offset of 'planes'
- * @vaddr:              virtual address of the input buffer
- * @paddr:              physical address of the input buffer
  */
 struct sti_plane {
 	struct drm_plane drm_plane;
-	struct drm_framebuffer *fb;
-	struct drm_display_mode *mode;
 	enum sti_plane_desc desc;
-	const struct sti_plane_funcs *ops;
+	enum sti_plane_status status;
 	int zorder;
-	int mixer_id;
-	bool enabled;
-	int src_x, src_y;
-	int src_w, src_h;
-	int dst_x, dst_y;
-	int dst_w, dst_h;
-	uint32_t format;
-	unsigned int pitches[4];
-	unsigned int offsets[4];
-	void *vaddr;
-	dma_addr_t paddr;
 };
 
-/**
- * STI plane functions structure
- *
- * @get_formats:     get plane supported formats
- * @get_nb_formats:  get number of format supported
- * @prepare:         prepare plane before rendering
- * @commit:          set plane for rendering
- * @disable:         disable plane
- */
-struct sti_plane_funcs {
-	const uint32_t* (*get_formats)(struct sti_plane *plane);
-	unsigned int (*get_nb_formats)(struct sti_plane *plane);
-	int (*prepare)(struct sti_plane *plane, bool first_prepare);
-	int (*commit)(struct sti_plane *plane);
-	int (*disable)(struct sti_plane *plane);
-};
-
-struct drm_plane *sti_plane_init(struct drm_device *dev,
-				 struct sti_plane *sti_plane,
-				 unsigned int possible_crtcs,
-				 enum drm_plane_type type);
 const char *sti_plane_to_str(struct sti_plane *plane);
-
+void sti_plane_init_property(struct sti_plane *plane,
+			     enum drm_plane_type type);
 #endif
diff --git a/drivers/gpu/drm/sti/sti_vid.c b/drivers/gpu/drm/sti/sti_vid.c
index 1e7e1d7..a8254cc 100644
--- a/drivers/gpu/drm/sti/sti_vid.c
+++ b/drivers/gpu/drm/sti/sti_vid.c
@@ -43,28 +43,37 @@
 #define VID_MPR2_BT709          0x07150545
 #define VID_MPR3_BT709          0x00000AE8
 
-int sti_vid_commit(struct sti_vid *vid, struct sti_plane *plane)
+void sti_vid_commit(struct sti_vid *vid,
+		    struct drm_plane_state *state)
 {
-	struct drm_display_mode *mode = plane->mode;
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_display_mode *mode = &crtc->mode;
+	int dst_x = state->crtc_x;
+	int dst_y = state->crtc_y;
+	int dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
+	int dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
 	u32 val, ydo, xdo, yds, xds;
 
+	/* Input / output size
+	 * Align to upper even value */
+	dst_w = ALIGN(dst_w, 2);
+	dst_h = ALIGN(dst_h, 2);
+
 	/* Unmask */
 	val = readl(vid->regs + VID_CTL);
 	val &= ~VID_CTL_IGNORE;
 	writel(val, vid->regs + VID_CTL);
 
-	ydo = sti_vtg_get_line_number(*mode, plane->dst_y);
-	yds = sti_vtg_get_line_number(*mode, plane->dst_y + plane->dst_h - 1);
-	xdo = sti_vtg_get_pixel_number(*mode, plane->dst_x);
-	xds = sti_vtg_get_pixel_number(*mode, plane->dst_x + plane->dst_w - 1);
+	ydo = sti_vtg_get_line_number(*mode, dst_y);
+	yds = sti_vtg_get_line_number(*mode, dst_y + dst_h - 1);
+	xdo = sti_vtg_get_pixel_number(*mode, dst_x);
+	xds = sti_vtg_get_pixel_number(*mode, dst_x + dst_w - 1);
 
 	writel((ydo << 16) | xdo, vid->regs + VID_VPO);
 	writel((yds << 16) | xds, vid->regs + VID_VPS);
-
-	return 0;
 }
 
-int sti_vid_disable(struct sti_vid *vid)
+void sti_vid_disable(struct sti_vid *vid)
 {
 	u32 val;
 
@@ -72,8 +81,6 @@ int sti_vid_disable(struct sti_vid *vid)
 	val = readl(vid->regs + VID_CTL);
 	val |= VID_CTL_IGNORE;
 	writel(val, vid->regs + VID_CTL);
-
-	return 0;
 }
 
 static void sti_vid_init(struct sti_vid *vid)
diff --git a/drivers/gpu/drm/sti/sti_vid.h b/drivers/gpu/drm/sti/sti_vid.h
index cc680a2..5dea479 100644
--- a/drivers/gpu/drm/sti/sti_vid.h
+++ b/drivers/gpu/drm/sti/sti_vid.h
@@ -20,8 +20,9 @@ struct sti_vid {
 	int id;
 };
 
-int sti_vid_commit(struct sti_vid *vid, struct sti_plane *plane);
-int sti_vid_disable(struct sti_vid *vid);
+void sti_vid_commit(struct sti_vid *vid,
+		    struct drm_plane_state *state);
+void sti_vid_disable(struct sti_vid *vid);
 struct sti_vid *sti_vid_create(struct device *dev, int id,
 			       void __iomem *baseaddr);
 
-- 
1.9.1

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

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

* Re: [PATCH 4/4] drm/sti: atomic crtc/plane update
  2015-07-31 10:13 ` [PATCH 4/4] drm/sti: atomic crtc/plane update Vincent Abriou
@ 2015-07-31 12:22   ` Emil Velikov
  2015-07-31 12:54     ` Benjamin Gaignard
  2015-07-31 13:45   ` Daniel Vetter
  1 sibling, 1 reply; 9+ messages in thread
From: Emil Velikov @ 2015-07-31 12:22 UTC (permalink / raw)
  To: Vincent Abriou; +Cc: Benjamin Gaignard, Fabien Dessenne, ML dri-devel, kernel

Hello Vincent,

On 31 July 2015 at 11:13, Vincent Abriou <vincent.abriou@st.com> wrote:
> Better fit STI hardware structure.
> Planes are no more responsible of updating mixer information such
> as z-order and status. It is now up to the CRTC atomic flush to
> do it. Plane actions (enable or disable) are performed atomically.
> Disabling of a plane is synchronize with the vsync event.
>
> Signed-off-by: Vincent Abriou <vincent.abriou@st.com>
> Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
> ---
>  drivers/gpu/drm/sti/sti_compositor.c |  32 +--
>  drivers/gpu/drm/sti/sti_crtc.c       | 120 +++++++--
>  drivers/gpu/drm/sti/sti_cursor.c     | 211 +++++++++------
>  drivers/gpu/drm/sti/sti_cursor.h     |   6 +-
>  drivers/gpu/drm/sti/sti_gdp.c        | 493 +++++++++++++++++++----------------
>  drivers/gpu/drm/sti/sti_gdp.h        |   8 +-
>  drivers/gpu/drm/sti/sti_hqvdp.c      | 429 ++++++++++++++++--------------
>  drivers/gpu/drm/sti/sti_mixer.h      |  10 +-
>  drivers/gpu/drm/sti/sti_plane.c      | 251 +-----------------
>  drivers/gpu/drm/sti/sti_plane.h      |  66 ++---
>  drivers/gpu/drm/sti/sti_vid.c        |  29 ++-
>  drivers/gpu/drm/sti/sti_vid.h        |   5 +-
>  12 files changed, 808 insertions(+), 852 deletions(-)
>
Just a friendly note - other drivers transitioning to atomics have
done so in a more gradual manner. I believe the idea/intent was to
ensure commits are simple and straightforward enough to minimise the
cases of regressions/bugs.

Either way the decision is between you and the driver maintainer.
Speaking of which there isn't one listed in MAINTAINERS. Is that
intentional ?

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

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

* Re: [PATCH 4/4] drm/sti: atomic crtc/plane update
  2015-07-31 12:22   ` Emil Velikov
@ 2015-07-31 12:54     ` Benjamin Gaignard
  2015-07-31 13:24       ` Emil Velikov
  0 siblings, 1 reply; 9+ messages in thread
From: Benjamin Gaignard @ 2015-07-31 12:54 UTC (permalink / raw)
  To: Emil Velikov; +Cc: Fabien Dessenne, ML dri-devel, kernel

Hello Emil,

This series of patches is the second step to convert sit driver to atomic,
I have the first step few weeks ago.
This time we really take benefit of the atomic helpers to make match
correctly code and hardware split. To give you an example, before
those patches, we were calling code driving hardware planes while
setting crtc hardware...

I agree that is a big change but we can to less then that to keep
everything working.
We have done quite many tests with modetest and weston to be sure we
do not have regressions.

Both Vincent and I should be put in MAINTAINERS file, I will do a
patch for that.

Regards,
Benjamin


2015-07-31 14:22 GMT+02:00 Emil Velikov <emil.l.velikov@gmail.com>:
> Hello Vincent,
>
> On 31 July 2015 at 11:13, Vincent Abriou <vincent.abriou@st.com> wrote:
>> Better fit STI hardware structure.
>> Planes are no more responsible of updating mixer information such
>> as z-order and status. It is now up to the CRTC atomic flush to
>> do it. Plane actions (enable or disable) are performed atomically.
>> Disabling of a plane is synchronize with the vsync event.
>>
>> Signed-off-by: Vincent Abriou <vincent.abriou@st.com>
>> Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
>> ---
>>  drivers/gpu/drm/sti/sti_compositor.c |  32 +--
>>  drivers/gpu/drm/sti/sti_crtc.c       | 120 +++++++--
>>  drivers/gpu/drm/sti/sti_cursor.c     | 211 +++++++++------
>>  drivers/gpu/drm/sti/sti_cursor.h     |   6 +-
>>  drivers/gpu/drm/sti/sti_gdp.c        | 493 +++++++++++++++++++----------------
>>  drivers/gpu/drm/sti/sti_gdp.h        |   8 +-
>>  drivers/gpu/drm/sti/sti_hqvdp.c      | 429 ++++++++++++++++--------------
>>  drivers/gpu/drm/sti/sti_mixer.h      |  10 +-
>>  drivers/gpu/drm/sti/sti_plane.c      | 251 +-----------------
>>  drivers/gpu/drm/sti/sti_plane.h      |  66 ++---
>>  drivers/gpu/drm/sti/sti_vid.c        |  29 ++-
>>  drivers/gpu/drm/sti/sti_vid.h        |   5 +-
>>  12 files changed, 808 insertions(+), 852 deletions(-)
>>
> Just a friendly note - other drivers transitioning to atomics have
> done so in a more gradual manner. I believe the idea/intent was to
> ensure commits are simple and straightforward enough to minimise the
> cases of regressions/bugs.
>
> Either way the decision is between you and the driver maintainer.
> Speaking of which there isn't one listed in MAINTAINERS. Is that
> intentional ?
>
> Cheers,
> Emil



-- 
Benjamin Gaignard

Graphic Working Group

Linaro.org │ Open source software for ARM SoCs

Follow Linaro: Facebook | Twitter | Blog
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 4/4] drm/sti: atomic crtc/plane update
  2015-07-31 12:54     ` Benjamin Gaignard
@ 2015-07-31 13:24       ` Emil Velikov
  0 siblings, 0 replies; 9+ messages in thread
From: Emil Velikov @ 2015-07-31 13:24 UTC (permalink / raw)
  To: Benjamin Gaignard; +Cc: Fabien Dessenne, ML dri-devel, kernel

On 31 July 2015 at 13:54, Benjamin Gaignard
<benjamin.gaignard@linaro.org> wrote:
> Hello Emil,
>
> This series of patches is the second step to convert sit driver to atomic,
> I have the first step few weeks ago.
> This time we really take benefit of the atomic helpers to make match
> correctly code and hardware split. To give you an example, before
> those patches, we were calling code driving hardware planes while
> setting crtc hardware...
>
> I agree that is a big change but we can to less then that to keep
> everything working.
> We have done quite many tests with modetest and weston to be sure we
> do not have regressions.
>
Fair enough. Just wanted to put it out on the table, as other teams
(with more developers and testers) do occasionally stumble upon corner
cases with atomics. I did not mean to tell you how you should do your
job, but mitigate the awkward cases like the one floating around a
couple of days ago.

> Both Vincent and I should be put in MAINTAINERS file, I will do a
> patch for that.
>
Great. Now if we can convince a few others to do the same ;-)

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

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

* Re: [PATCH 4/4] drm/sti: atomic crtc/plane update
  2015-07-31 10:13 ` [PATCH 4/4] drm/sti: atomic crtc/plane update Vincent Abriou
  2015-07-31 12:22   ` Emil Velikov
@ 2015-07-31 13:45   ` Daniel Vetter
  1 sibling, 0 replies; 9+ messages in thread
From: Daniel Vetter @ 2015-07-31 13:45 UTC (permalink / raw)
  To: Vincent Abriou; +Cc: Benjamin Gaignard, Fabien Dessenne, dri-devel, kernel

On Fri, Jul 31, 2015 at 12:13:27PM +0200, Vincent Abriou wrote:
>  static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
>  	.dpms = sti_crtc_dpms,

dpms isn't needed any more with atomic, you should use
drm_atomic_helper_connector_dpms instead of drm_helper_connector_dpms.

> -	.prepare = sti_crtc_prepare,
> -	.commit = sti_crtc_commit,
> +	.prepare = sti_crtc_helper_prepare,

prepare is now called .enable for clarity.

> +	.commit = sti_crtc_helper_commit,

commit and disable are redundant with atomic.

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
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] 9+ messages in thread

end of thread, other threads:[~2015-07-31 13:46 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-31 10:13 [PATCH 0/4] drm/sti: update STI driver to be atomic Vincent Abriou
2015-07-31 10:13 ` [PATCH 1/4] drm/sti: fix dynamic z-ordering Vincent Abriou
2015-07-31 10:13 ` [PATCH 2/4] drm/sti: code clean up Vincent Abriou
2015-07-31 10:13 ` [PATCH 3/4] drm/sti: rename files and functions Vincent Abriou
2015-07-31 10:13 ` [PATCH 4/4] drm/sti: atomic crtc/plane update Vincent Abriou
2015-07-31 12:22   ` Emil Velikov
2015-07-31 12:54     ` Benjamin Gaignard
2015-07-31 13:24       ` Emil Velikov
2015-07-31 13:45   ` 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.