diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 37ee20c773c7..4c43ef239136 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -16,6 +16,7 @@
  */
 
 #include <linux/sys_soc.h>
+#include <linux/sort.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
@@ -116,6 +117,112 @@ static void omap_atomic_commit_tail(struct drm_atomic_state *old_state)
 	priv->dispc_ops->runtime_put();
 }
 
+static int omap_atomic_state_zpos_cmp(const void *a, const void *b)
+{
+	const struct drm_plane_state *sa = *(struct drm_plane_state **)a;
+	const struct drm_plane_state *sb = *(struct drm_plane_state **)b;
+
+	if (sa->zpos != sb->zpos)
+		return sa->zpos - sb->zpos;
+	else
+		return sa->plane->base.id - sb->plane->base.id;
+}
+
+static int omap_atomic_crtc_normalize_zpos(struct drm_crtc *crtc,
+					   struct drm_crtc_state *crtc_state)
+{
+	struct drm_atomic_state *state = crtc_state->state;
+	struct drm_device *dev = crtc->dev;
+	int total_planes = dev->mode_config.num_total_plane;
+	struct drm_plane_state **states;
+	struct drm_plane *plane;
+	int i, inc, n = 0;
+	int ret = 0;
+
+	DRM_DEBUG_ATOMIC("[CRTC:%d:%s] calculating normalized zpos values\n",
+			 crtc->base.id, crtc->name);
+
+	states = kmalloc_array(total_planes, sizeof(*states), GFP_KERNEL);
+	if (!states)
+		return -ENOMEM;
+
+	/*
+	 * Normalization process might create new states for planes which
+	 * normalized_zpos has to be recalculated.
+	 */
+	drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) {
+		struct drm_plane_state *plane_state =
+			drm_atomic_get_plane_state(state, plane);
+		if (IS_ERR(plane_state)) {
+			ret = PTR_ERR(plane_state);
+			goto done;
+		}
+		states[n++] = plane_state;
+		DRM_DEBUG_ATOMIC("[PLANE:%d:%s] processing zpos value %d\n",
+				 plane->base.id, plane->name,
+				 plane_state->zpos);
+	}
+
+	sort(states, n, sizeof(*states), omap_atomic_state_zpos_cmp, NULL);
+
+	for (inc = 0, i = 0; i < n; i++) {
+		plane = states[i]->plane;
+
+		states[i]->normalized_zpos = i + inc;
+		DRM_DEBUG_ATOMIC("[PLANE:%d:%s] normalized zpos value %d\n",
+				 plane->base.id, plane->name, i + inc);
+		/*
+		 * If the current plane is virtual it uses 2 hw planes
+		 * therefore the very next zpos is used by the secondary/aux
+		 * plane so we need to skip one zpos from this point on.
+		 */
+		if (is_omap_plane_virtual(plane))
+			inc++;
+	}
+	crtc_state->zpos_changed = true;
+
+done:
+	kfree(states);
+	return ret;
+}
+
+static int omap_atomic_normalize_zpos(struct drm_device *dev,
+				      struct drm_atomic_state *state)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+	int i, ret = 0;
+
+	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+		if (old_crtc_state->plane_mask != new_crtc_state->plane_mask ||
+		    new_crtc_state->zpos_changed) {
+			ret = omap_atomic_crtc_normalize_zpos(crtc,
+							      new_crtc_state);
+			if (ret)
+				return ret;
+		}
+	}
+	return 0;
+}
+
+static int omap_atomic_check(struct drm_device *dev,
+			     struct drm_atomic_state *state)
+{
+	int ret;
+
+	ret = drm_atomic_helper_check(dev, state);
+	if (ret)
+		return ret;
+
+	if (dev->mode_config.normalize_zpos) {
+		ret = omap_atomic_normalize_zpos(dev, state);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static const struct drm_mode_config_helper_funcs omap_mode_config_helper_funcs = {
 	.atomic_commit_tail = omap_atomic_commit_tail,
 };
@@ -123,7 +230,7 @@ static const struct drm_mode_config_helper_funcs omap_mode_config_helper_funcs =
 static const struct drm_mode_config_funcs omap_mode_config_funcs = {
 	.fb_create = omap_framebuffer_create,
 	.output_poll_changed = drm_fb_helper_output_poll_changed,
-	.atomic_check = drm_atomic_helper_check,
+	.atomic_check = omap_atomic_check,
 	.atomic_commit = drm_atomic_helper_commit,
 };
 
@@ -188,10 +295,9 @@ static int omap_connect_dssdevs(void)
 	return r;
 }
 
-static int omap_modeset_init_properties(struct drm_device *dev)
+static int omap_modeset_init_properties(struct drm_device *dev, u32 num_planes)
 {
 	struct omap_drm_private *priv = dev->dev_private;
-	unsigned int num_planes = priv->dispc_ops->get_num_ovls();
 
 	priv->zorder_prop = drm_property_create_range(dev, 0, "zorder", 0,
 						      num_planes - 1);
@@ -210,10 +316,19 @@ static int omap_modeset_init(struct drm_device *dev)
 	int num_crtcs, crtc_idx, plane_idx;
 	int ret;
 	u32 plane_crtc_mask;
+	struct dispc_plane_mappings plane_mappings = {0};
 
 	drm_mode_config_init(dev);
 
-	ret = omap_modeset_init_properties(dev);
+	ret = priv->dispc_ops->get_plane_mapping(&plane_mappings);
+	if (ret < 0)
+		return ret;
+
+	/* use plane mappings info */
+	if (plane_mappings.num_planes)
+		num_ovls = plane_mappings.num_planes;
+
+	ret = omap_modeset_init_properties(dev, num_ovls);
 	if (ret < 0)
 		return ret;
 
@@ -266,7 +381,7 @@ static int omap_modeset_init(struct drm_device *dev)
 			return -ENOMEM;
 
 		plane = omap_plane_init(dev, plane_idx, DRM_PLANE_TYPE_PRIMARY,
-					plane_crtc_mask);
+					plane_crtc_mask, &plane_mappings);
 		if (IS_ERR(plane))
 			return PTR_ERR(plane);
 
@@ -296,7 +411,7 @@ static int omap_modeset_init(struct drm_device *dev)
 			return -EINVAL;
 
 		plane = omap_plane_init(dev, plane_idx, DRM_PLANE_TYPE_OVERLAY,
-			plane_crtc_mask);
+					plane_crtc_mask, &plane_mappings);
 		if (IS_ERR(plane))
 			return PTR_ERR(plane);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index b2539a90e1a4..80b29b7f5696 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -153,25 +153,27 @@ static uint32_t drm_rotation_to_tiler(unsigned int drm_rot)
 /* update ovl info for scanout, handles cases of multi-planar fb's, etc.
  */
 void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
-		struct drm_plane_state *state, struct omap_overlay_info *info)
+		struct drm_plane_state *state,
+		struct omap_overlay_info *main_info,
+		struct omap_overlay_info *aux_info)
 {
 	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
 	const struct drm_format_info *format = omap_fb->format;
 	struct plane *plane = &omap_fb->planes[0];
 	uint32_t x, y, orient = 0;
 
-	info->fourcc = fb->format->format;
+	main_info->fourcc = fb->format->format;
 
-	info->pos_x      = state->crtc_x;
-	info->pos_y      = state->crtc_y;
-	info->out_width  = state->crtc_w;
-	info->out_height = state->crtc_h;
-	info->width      = state->src_w >> 16;
-	info->height     = state->src_h >> 16;
+	main_info->pos_x      = state->crtc_x;
+	main_info->pos_y      = state->crtc_y;
+	main_info->out_width  = state->crtc_w;
+	main_info->out_height = state->crtc_h;
+	main_info->width      = state->src_w >> 16;
+	main_info->height     = state->src_h >> 16;
 
 	/* DSS driver wants the w & h in rotated orientation */
 	if (drm_rotation_90_or_270(state->rotation))
-		swap(info->width, info->height);
+		swap(main_info->width, main_info->height);
 
 	x = state->src_x >> 16;
 	y = state->src_y >> 16;
@@ -202,11 +204,12 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
 
 		/* Note: x and y are in TILER units, not pixels */
 		omap_gem_rotated_dma_addr(plane->bo, orient, x, y,
-					  &info->paddr);
-		info->rotation_type = OMAP_DSS_ROT_TILER;
-		info->rotation = state->rotation ?: DRM_MODE_ROTATE_0;
+					  &main_info->paddr);
+		main_info->rotation_type = OMAP_DSS_ROT_TILER;
+		main_info->rotation = state->rotation ?: DRM_MODE_ROTATE_0;
 		/* Note: stride in TILER units, not pixels */
-		info->screen_width  = omap_gem_tiled_stride(plane->bo, orient);
+		main_info->screen_width  =
+				omap_gem_tiled_stride(plane->bo, orient);
 	} else {
 		switch (state->rotation & DRM_MODE_ROTATE_MASK) {
 		case 0:
@@ -221,27 +224,46 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
 			break;
 		}
 
-		info->paddr         = get_linear_addr(plane, format, 0, x, y);
-		info->rotation_type = OMAP_DSS_ROT_NONE;
-		info->rotation      = DRM_MODE_ROTATE_0;
-		info->screen_width  = plane->pitch;
+		main_info->paddr = get_linear_addr(plane, format, 0, x, y);
+		main_info->rotation_type = OMAP_DSS_ROT_NONE;
+		main_info->rotation = DRM_MODE_ROTATE_0;
+		main_info->screen_width = plane->pitch;
 	}
 
 	/* convert to pixels: */
-	info->screen_width /= format->cpp[0];
+	main_info->screen_width /= format->cpp[0];
 
 	if (fb->format->format == DRM_FORMAT_NV12) {
 		plane = &omap_fb->planes[1];
 
-		if (info->rotation_type == OMAP_DSS_ROT_TILER) {
+		if (main_info->rotation_type == OMAP_DSS_ROT_TILER) {
 			WARN_ON(!(omap_gem_flags(plane->bo) & OMAP_BO_TILED));
 			omap_gem_rotated_dma_addr(plane->bo, orient, x/2, y/2,
-						  &info->p_uv_addr);
+						  &main_info->p_uv_addr);
 		} else {
-			info->p_uv_addr = get_linear_addr(plane, format, 1, x, y);
+			main_info->p_uv_addr =
+				get_linear_addr(plane, format, 1, x, y);
 		}
 	} else {
-		info->p_uv_addr = 0;
+		main_info->p_uv_addr = 0;
+	}
+
+	if (aux_info) {
+		main_info->width /= 2;
+		main_info->out_width /= 2;
+
+		*aux_info = *main_info;
+
+		aux_info->pos_x = main_info->pos_x + main_info->out_width;
+
+		aux_info->paddr =
+				get_linear_addr(&omap_fb->planes[0], format, 0,
+						x + main_info->width, y);
+		if (fb->format->format == DRM_FORMAT_NV12) {
+			aux_info->p_uv_addr =
+				get_linear_addr(&omap_fb->planes[1], format, 1,
+						x + main_info->width, y);
+		}
 	}
 }
 
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.h b/drivers/gpu/drm/omapdrm/omap_fb.h
index 94ad5f9e4404..f68e81353288 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.h
+++ b/drivers/gpu/drm/omapdrm/omap_fb.h
@@ -37,7 +37,9 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 int omap_framebuffer_pin(struct drm_framebuffer *fb);
 void omap_framebuffer_unpin(struct drm_framebuffer *fb);
 void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
-		struct drm_plane_state *state, struct omap_overlay_info *info);
+		struct drm_plane_state *state,
+		struct omap_overlay_info *main_info,
+		struct omap_overlay_info *aux_info);
 struct drm_connector *omap_framebuffer_get_next_connector(
 		struct drm_framebuffer *fb, struct drm_connector *from);
 bool omap_framebuffer_supports_rotation(struct drm_framebuffer *fb);
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 2c19d2239bc5..21c927bbf5a7 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -30,10 +30,14 @@
 
 struct omap_plane {
 	struct drm_plane base;
-	enum omap_plane_id id;
+	enum omap_plane_id main_id;
+	enum omap_plane_id aux_id;
 	const char *name;
+	bool virtual_plane;
 };
 
+static const char *plane_id_to_name[];
+
 static int omap_plane_prepare_fb(struct drm_plane *plane,
 				 struct drm_plane_state *new_state)
 {
@@ -56,38 +60,75 @@ static void omap_plane_atomic_update(struct drm_plane *plane,
 	struct omap_drm_private *priv = plane->dev->dev_private;
 	struct omap_plane *omap_plane = to_omap_plane(plane);
 	struct drm_plane_state *state = plane->state;
-	struct omap_overlay_info info;
+	struct omap_overlay_info main_info, aux_info;
 	int ret;
+	bool dual_plane = omap_plane->virtual_plane;
 
 	DBG("%s, crtc=%p fb=%p", omap_plane->name, state->crtc, state->fb);
 
-	memset(&info, 0, sizeof(info));
-	info.rotation_type = OMAP_DSS_ROT_NONE;
-	info.rotation = DRM_MODE_ROTATE_0;
-	info.global_alpha = 0xff;
-	info.zorder = state->normalized_zpos;
+	memset(&main_info, 0, sizeof(main_info));
+	main_info.rotation_type = OMAP_DSS_ROT_NONE;
+	main_info.rotation = DRM_MODE_ROTATE_0;
+	main_info.global_alpha = 0xff;
+	main_info.zorder = state->normalized_zpos;
 
-	/* update scanout: */
-	omap_framebuffer_update_scanout(state->fb, state, &info);
+	aux_info = main_info;
 
-	DBG("%dx%d -> %dx%d (%d)", info.width, info.height,
-			info.out_width, info.out_height,
-			info.screen_width);
-	DBG("%d,%d %pad %pad", info.pos_x, info.pos_y,
-			&info.paddr, &info.p_uv_addr);
+	/* update scanout: */
+	omap_framebuffer_update_scanout(state->fb, state, &main_info,
+					dual_plane ? &aux_info : NULL);
+
+	DBG("%s: %dx%d -> %dx%d (%d)",
+	    plane_id_to_name[omap_plane->main_id],
+	    main_info.width, main_info.height,
+	    main_info.out_width, main_info.out_height,
+	    main_info.screen_width);
+	DBG("%d,%d %pad %pad", main_info.pos_x, main_info.pos_y,
+	    &main_info.paddr, &main_info.p_uv_addr);
+
+	if (dual_plane) {
+		/*
+		 * If the current plane is virtual it uses 2 hw planes
+		 * therefore the very next zorder is used by the aux_id
+		 * plane so we just use the main_id zorder + 1
+		 */
+		aux_info.zorder = main_info.zorder + 1;
+
+		DBG("%s: %dx%d -> %dx%d (%d)",
+		    plane_id_to_name[omap_plane->aux_id],
+		    aux_info.width, aux_info.height,
+		    aux_info.out_width, aux_info.out_height,
+		    aux_info.screen_width);
+		DBG("%d,%d %pad %pad", aux_info.pos_x, aux_info.pos_y,
+		    &aux_info.paddr, &aux_info.p_uv_addr);
+	}
 
-	/* and finally, update omapdss: */
-	ret = priv->dispc_ops->ovl_setup(omap_plane->id, &info,
+	ret = priv->dispc_ops->ovl_setup(omap_plane->main_id, &main_info,
 			      omap_crtc_timings(state->crtc), false,
 			      omap_crtc_channel(state->crtc));
 	if (ret) {
-		dev_err(plane->dev->dev, "Failed to setup plane %s\n",
+		dev_err(plane->dev->dev, "Failed to setup plane1 %s\n",
 			omap_plane->name);
-		priv->dispc_ops->ovl_enable(omap_plane->id, false);
+		priv->dispc_ops->ovl_enable(omap_plane->main_id, false);
 		return;
 	}
 
-	priv->dispc_ops->ovl_enable(omap_plane->id, true);
+	priv->dispc_ops->ovl_enable(omap_plane->main_id, true);
+
+	if (dual_plane) {
+		ret = priv->dispc_ops->ovl_setup(omap_plane->aux_id, &aux_info,
+				      omap_crtc_timings(state->crtc), false,
+				      omap_crtc_channel(state->crtc));
+		if (ret) {
+			dev_err(plane->dev->dev, "Failed to setup plane2 %s\n",
+				omap_plane->name);
+			priv->dispc_ops->ovl_enable(omap_plane->aux_id, false);
+			priv->dispc_ops->ovl_enable(omap_plane->main_id, false);
+			return;
+		}
+
+		priv->dispc_ops->ovl_enable(omap_plane->aux_id, true);
+	}
 }
 
 static void omap_plane_atomic_disable(struct drm_plane *plane,
@@ -95,12 +136,15 @@ static void omap_plane_atomic_disable(struct drm_plane *plane,
 {
 	struct omap_drm_private *priv = plane->dev->dev_private;
 	struct omap_plane *omap_plane = to_omap_plane(plane);
+	bool dual_plane = omap_plane->virtual_plane;
 
 	plane->state->rotation = DRM_MODE_ROTATE_0;
 	plane->state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY
-			   ? 0 : omap_plane->id;
+			   ? 0 : omap_plane->main_id;
 
-	priv->dispc_ops->ovl_enable(omap_plane->id, false);
+	priv->dispc_ops->ovl_enable(omap_plane->main_id, false);
+	if (dual_plane)
+		priv->dispc_ops->ovl_enable(omap_plane->aux_id, false);
 }
 
 static int omap_plane_atomic_check(struct drm_plane *plane,
@@ -158,6 +202,13 @@ static void omap_plane_destroy(struct drm_plane *plane)
 	kfree(omap_plane);
 }
 
+bool is_omap_plane_virtual(struct drm_plane *plane)
+{
+	struct omap_plane *omap_plane = to_omap_plane(plane);
+
+	return omap_plane->virtual_plane;
+}
+
 /* helper to install properties which are common to planes and crtcs */
 void omap_plane_install_properties(struct drm_plane *plane,
 		struct drm_mode_object *obj)
@@ -195,7 +246,7 @@ static void omap_plane_reset(struct drm_plane *plane)
 	 * plane.
 	 */
 	plane->state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY
-			   ? 0 : omap_plane->id;
+			   ? 0 : omap_plane->main_id;
 }
 
 static int omap_plane_atomic_set_property(struct drm_plane *plane,
@@ -246,43 +297,65 @@ static const char *plane_id_to_name[] = {
 	[OMAP_DSS_VIDEO3] = "vid3",
 };
 
-static const enum omap_plane_id plane_idx_to_id[] = {
-	OMAP_DSS_GFX,
-	OMAP_DSS_VIDEO1,
-	OMAP_DSS_VIDEO2,
-	OMAP_DSS_VIDEO3,
+static const char * const virtual_plane_id_to_name[] = {
+	[OMAP_DSS_GFX] = "virt-gfx",
+	[OMAP_DSS_VIDEO1] = "virt-vid1",
+	[OMAP_DSS_VIDEO2] = "virt-vid2",
+	[OMAP_DSS_VIDEO3] = "virt-vid3",
 };
 
-/* initialize plane */
 struct drm_plane *omap_plane_init(struct drm_device *dev,
 		int idx, enum drm_plane_type type,
-		u32 possible_crtcs)
+		u32 possible_crtcs,
+		struct dispc_plane_mappings *plane_mappings)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	unsigned int num_planes = priv->dispc_ops->get_num_ovls();
 	struct drm_plane *plane;
 	struct omap_plane *omap_plane;
-	enum omap_plane_id id;
 	int ret;
 	u32 nformats;
 	const u32 *formats;
 
-	if (WARN_ON(idx >= ARRAY_SIZE(plane_idx_to_id)))
-		return ERR_PTR(-EINVAL);
-
-	id = plane_idx_to_id[idx];
+	if (plane_mappings->num_planes)
+		num_planes = plane_mappings->num_planes;
 
-	DBG("%s: type=%d", plane_id_to_name[id], type);
+	if (WARN_ON(idx >= num_planes))
+		return ERR_PTR(-EINVAL);
 
 	omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL);
 	if (!omap_plane)
 		return ERR_PTR(-ENOMEM);
 
-	formats = priv->dispc_ops->ovl_get_color_modes(id);
+	if (plane_mappings->num_planes) {
+		/* Use plane data from DT */
+		omap_plane->main_id = plane_mappings->plane[idx].main_id;
+		if (plane_mappings->plane[idx].is_virtual) {
+			omap_plane->name =
+				virtual_plane_id_to_name[omap_plane->main_id];
+			omap_plane->aux_id = plane_mappings->plane[idx].aux_id;
+			omap_plane->virtual_plane = true;
+		} else {
+			omap_plane->name =
+				plane_id_to_name[omap_plane->main_id];
+		}
+		if (plane_mappings->plane[idx].crtc_mask)
+			possible_crtcs = plane_mappings->plane[idx].crtc_mask;
+	} else {
+		/* Use legacy plane allocation */
+		omap_plane->main_id = idx;
+		omap_plane->name = plane_id_to_name[idx];
+	}
+
+	DBG("%s: type=%d", omap_plane->name, type);
+	DBG("	omap_plane->main_id: %d", omap_plane->main_id);
+	if (omap_plane->virtual_plane)
+		DBG("	omap_plane->aux_id: %d", omap_plane->aux_id);
+	DBG("	crtc_mask: 0x%04x", possible_crtcs);
+
+	formats = priv->dispc_ops->ovl_get_color_modes(omap_plane->main_id);
 	for (nformats = 0; formats[nformats]; ++nformats)
 		;
-	omap_plane->id = id;
-	omap_plane->name = plane_id_to_name[id];
 
 	plane = &omap_plane->base;
 
@@ -301,7 +374,7 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 
 error:
 	dev_err(dev->dev, "%s(): could not create plane: %s\n",
-		__func__, plane_id_to_name[id]);
+		__func__, omap_plane->name);
 
 	kfree(omap_plane);
 	return NULL;
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.h b/drivers/gpu/drm/omapdrm/omap_plane.h
index dc5e82ad061d..48815a05f4fe 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.h
+++ b/drivers/gpu/drm/omapdrm/omap_plane.h
@@ -30,8 +30,10 @@ struct drm_plane;
 
 struct drm_plane *omap_plane_init(struct drm_device *dev,
 		int idx, enum drm_plane_type type,
-		u32 possible_crtcs);
+		u32 possible_crtcs,
+		struct dispc_plane_mappings *plane_mappings);
 void omap_plane_install_properties(struct drm_plane *plane,
 		struct drm_mode_object *obj);
+bool is_omap_plane_virtual(struct drm_plane *plane);
 
 #endif /* __OMAPDRM_PLANE_H__ */
