diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
index 3371635..d30b61e 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
@@ -139,20 +139,51 @@ static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
 
 int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
 {
-	struct drm_plane *primary;
+	struct drm_device *drm = fsl_dev->drm;
+	struct drm_plane *primary, *cursor;
 	struct drm_crtc *crtc = &fsl_dev->crtc;
-	int ret;
+	int total_layer = fsl_dev->soc->total_layer;
+	int ret, i;
 
-	fsl_dcu_drm_init_planes(fsl_dev->drm);
+	fsl_dcu_drm_init_planes(drm);
 
-	primary = fsl_dcu_drm_primary_create_plane(fsl_dev->drm);
-	if (!primary)
-		return -ENOMEM;
+	primary = fsl_dcu_drm_create_plane(drm, DRM_PLANE_TYPE_PRIMARY);
+	if (IS_ERR(primary)) {
+		dev_err(fsl_dev->dev, "failed to construct primary plane\n");
+		ret = PTR_ERR(primary);
+		return ret;
+	}
+
+	/*
+	 * Initialize overlay layers. The hardware does not have specific
+	 * layer types, we just happen to use one layer as primary layer
+	 * and one layer as cursor layer, hence total_layer - 2 = overlays.
+	 */
+	for (i = 0; i < total_layer - 2; i++) {
+		struct drm_plane *plane =
+			fsl_dcu_drm_create_plane(drm, DRM_PLANE_TYPE_OVERLAY);
+
+		if (IS_ERR(plane))
+			continue;
+	}
 
-	ret = drm_crtc_init_with_planes(fsl_dev->drm, crtc, primary, NULL,
+	cursor = fsl_dcu_drm_create_plane(drm, DRM_PLANE_TYPE_CURSOR);
+	if (IS_ERR(cursor)) {
+		dev_warn(fsl_dev->dev, "failed to construct cursor plane\n");
+		cursor = NULL;
+	}
+
+	/*
+	 * Initialize cursor plane after overlay planes since the initialization
+	 * order is crucial to the layer id (and hence layer stacking order).
+	 */
+	ret = drm_crtc_init_with_planes(drm, crtc, primary, cursor,
 					&fsl_dcu_drm_crtc_funcs, NULL);
 	if (ret) {
-		primary->funcs->destroy(primary);
+		struct drm_plane *plane;
+
+		list_for_each_entry(plane, &drm->mode_config.plane_list, head)
+			drm_plane_cleanup(plane);
 		return ret;
 	}
 
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
index a7e5486..a6af3d9 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
@@ -178,7 +178,6 @@ static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
 static void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
 {
 	drm_plane_cleanup(plane);
-	kfree(plane);
 }
 
 static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
@@ -218,28 +217,30 @@ void fsl_dcu_drm_init_planes(struct drm_device *dev)
 		     DCU_UPDATE_MODE_READREG);
 }
 
-struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
+struct drm_plane *fsl_dcu_drm_create_plane(struct drm_device *dev,
+					   enum drm_plane_type type)
 {
-	struct drm_plane *primary;
+	struct drm_plane *plane;
 	int ret;
 
-	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
-	if (!primary) {
-		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
-		return NULL;
-	}
+	plane = devm_kzalloc(dev->dev, sizeof(struct drm_plane),
+			      GFP_KERNEL);
+	if (!plane)
+		return ERR_PTR(-ENOMEM);
 
-	/* possible_crtc's will be filled in later by crtc_init */
-	ret = drm_universal_plane_init(dev, primary, 0,
-				       &fsl_dcu_drm_plane_funcs,
+	ret = drm_universal_plane_init(dev, plane, 1, &fsl_dcu_drm_plane_funcs,
 				       fsl_dcu_drm_plane_formats,
 				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
-				       DRM_PLANE_TYPE_PRIMARY, NULL);
-	if (ret) {
-		kfree(primary);
-		primary = NULL;
-	}
-	drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
+				       type, NULL);
+	if (ret)
+		goto err_cleanup_plane;
+
+	drm_plane_helper_add(plane, &fsl_dcu_drm_plane_helper_funcs);
+
+	return plane;
+
+err_cleanup_plane:
+	drm_plane_cleanup(plane);
 
-	return primary;
+	return ERR_PTR(ret);
 }
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h
index 8ee45f8..bd36166 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h
@@ -13,6 +13,7 @@
 #define __FSL_DCU_DRM_PLANE_H__
 
 void fsl_dcu_drm_init_planes(struct drm_device *dev);
-struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev);
+struct drm_plane *fsl_dcu_drm_create_plane(struct drm_device *dev,
+					   enum drm_plane_type type);
 
 #endif /* __FSL_DCU_DRM_PLANE_H__ */
