diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
index 46d65d39214d..a47784765217 100644
--- a/drivers/gpu/drm/tegra/Makefile
+++ b/drivers/gpu/drm/tegra/Makefile
@@ -5,6 +5,7 @@ tegra-drm-y := \
 	drm.o \
 	gem.o \
 	fb.o \
+	plane.o \
 	dc.o \
 	output.o \
 	rgb.o \
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 88b8d137726e..d2c7a3481022 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -19,38 +19,12 @@
 #include "dc.h"
 #include "drm.h"
 #include "gem.h"
+#include "plane.h"
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_plane_helper.h>
 
-struct tegra_plane {
-	struct drm_plane base;
-	unsigned int index;
-};
-
-static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
-{
-	return container_of(plane, struct tegra_plane, base);
-}
-
-struct tegra_plane_state {
-	struct drm_plane_state base;
-
-	struct tegra_bo_tiling tiling;
-	u32 format;
-	u32 swap;
-};
-
-static inline struct tegra_plane_state *
-to_tegra_plane_state(struct drm_plane_state *state)
-{
-	if (state)
-		return container_of(state, struct tegra_plane_state, base);
-
-	return NULL;
-}
-
 static void tegra_dc_stats_reset(struct tegra_dc_stats *stats)
 {
 	stats->frames = 0;
@@ -97,81 +71,6 @@ void tegra_dc_commit(struct tegra_dc *dc)
 	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
 }
 
-static int tegra_dc_format(u32 fourcc, u32 *format, u32 *swap)
-{
-	/* assume no swapping of fetched data */
-	if (swap)
-		*swap = BYTE_SWAP_NOSWAP;
-
-	switch (fourcc) {
-	case DRM_FORMAT_XBGR8888:
-		*format = WIN_COLOR_DEPTH_R8G8B8A8;
-		break;
-
-	case DRM_FORMAT_XRGB8888:
-		*format = WIN_COLOR_DEPTH_B8G8R8A8;
-		break;
-
-	case DRM_FORMAT_RGB565:
-		*format = WIN_COLOR_DEPTH_B5G6R5;
-		break;
-
-	case DRM_FORMAT_UYVY:
-		*format = WIN_COLOR_DEPTH_YCbCr422;
-		break;
-
-	case DRM_FORMAT_YUYV:
-		if (swap)
-			*swap = BYTE_SWAP_SWAP2;
-
-		*format = WIN_COLOR_DEPTH_YCbCr422;
-		break;
-
-	case DRM_FORMAT_YUV420:
-		*format = WIN_COLOR_DEPTH_YCbCr420P;
-		break;
-
-	case DRM_FORMAT_YUV422:
-		*format = WIN_COLOR_DEPTH_YCbCr422P;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static bool tegra_dc_format_is_yuv(unsigned int format, bool *planar)
-{
-	switch (format) {
-	case WIN_COLOR_DEPTH_YCbCr422:
-	case WIN_COLOR_DEPTH_YUV422:
-		if (planar)
-			*planar = false;
-
-		return true;
-
-	case WIN_COLOR_DEPTH_YCbCr420P:
-	case WIN_COLOR_DEPTH_YUV420P:
-	case WIN_COLOR_DEPTH_YCbCr422P:
-	case WIN_COLOR_DEPTH_YUV422P:
-	case WIN_COLOR_DEPTH_YCbCr422R:
-	case WIN_COLOR_DEPTH_YUV422R:
-	case WIN_COLOR_DEPTH_YCbCr422RA:
-	case WIN_COLOR_DEPTH_YUV422RA:
-		if (planar)
-			*planar = true;
-
-		return true;
-	}
-
-	if (planar)
-		*planar = false;
-
-	return false;
-}
-
 static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v,
 				  unsigned int bpp)
 {
@@ -223,7 +122,7 @@ static void tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
 	 * For YUV planar modes, the number of bytes per pixel takes into
 	 * account only the luma component and therefore is 1.
 	 */
-	yuv = tegra_dc_format_is_yuv(window->format, &planar);
+	yuv = tegra_plane_format_is_yuv(window->format, &planar);
 	if (!yuv)
 		bpp = window->bits_per_pixel / 8;
 	else
@@ -385,101 +284,12 @@ static void tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
 	spin_unlock_irqrestore(&dc->lock, flags);
 }
 
-static void tegra_plane_destroy(struct drm_plane *plane)
-{
-	struct tegra_plane *p = to_tegra_plane(plane);
-
-	drm_plane_cleanup(plane);
-	kfree(p);
-}
-
 static const u32 tegra_primary_plane_formats[] = {
 	DRM_FORMAT_XBGR8888,
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_RGB565,
 };
 
-static void tegra_plane_reset(struct drm_plane *plane)
-{
-	struct tegra_plane_state *state;
-
-	if (plane->state)
-		__drm_atomic_helper_plane_destroy_state(plane->state);
-
-	kfree(plane->state);
-	plane->state = NULL;
-
-	state = kzalloc(sizeof(*state), GFP_KERNEL);
-	if (state) {
-		plane->state = &state->base;
-		plane->state->plane = plane;
-	}
-}
-
-static struct drm_plane_state *tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
-{
-	struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
-	struct tegra_plane_state *copy;
-
-	copy = kmalloc(sizeof(*copy), GFP_KERNEL);
-	if (!copy)
-		return NULL;
-
-	__drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
-	copy->tiling = state->tiling;
-	copy->format = state->format;
-	copy->swap = state->swap;
-
-	return &copy->base;
-}
-
-static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
-					     struct drm_plane_state *state)
-{
-	__drm_atomic_helper_plane_destroy_state(state);
-	kfree(state);
-}
-
-static const struct drm_plane_funcs tegra_plane_funcs = {
-	.update_plane = drm_atomic_helper_update_plane,
-	.disable_plane = drm_atomic_helper_disable_plane,
-	.destroy = tegra_plane_destroy,
-	.reset = tegra_plane_reset,
-	.atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
-	.atomic_destroy_state = tegra_plane_atomic_destroy_state,
-};
-
-static int tegra_plane_state_add(struct tegra_plane *plane,
-				 struct drm_plane_state *state)
-{
-	struct drm_crtc_state *crtc_state;
-	struct tegra_dc_state *tegra;
-	struct drm_rect clip;
-	int err;
-
-	/* Propagate errors from allocation or locking failures. */
-	crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
-	if (IS_ERR(crtc_state))
-		return PTR_ERR(crtc_state);
-
-	clip.x1 = 0;
-	clip.y1 = 0;
-	clip.x2 = crtc_state->mode.hdisplay;
-	clip.y2 = crtc_state->mode.vdisplay;
-
-	/* Check plane state for visibility and calculate clipping bounds */
-	err = drm_plane_helper_check_state(state, &clip, 0, INT_MAX,
-					   true, true);
-	if (err < 0)
-		return err;
-
-	tegra = to_dc_state(crtc_state);
-
-	tegra->planes |= WIN_A_ACT_REQ << plane->index;
-
-	return 0;
-}
-
 static int tegra_plane_atomic_check(struct drm_plane *plane,
 				    struct drm_plane_state *state)
 {
@@ -493,8 +303,9 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
 	if (!state->crtc)
 		return 0;
 
-	err = tegra_dc_format(state->fb->format->format, &plane_state->format,
-			      &plane_state->swap);
+	err = tegra_plane_format(state->fb->format->format,
+				 &plane_state->format,
+				 &plane_state->swap);
 	if (err < 0)
 		return err;
 
diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
new file mode 100644
index 000000000000..1847d0204e46
--- /dev/null
+++ b/drivers/gpu/drm/tegra/plane.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2017 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include "dc.h"
+#include "plane.h"
+
+static void tegra_plane_destroy(struct drm_plane *plane)
+{
+	struct tegra_plane *p = to_tegra_plane(plane);
+
+	drm_plane_cleanup(plane);
+	kfree(p);
+}
+
+static void tegra_plane_reset(struct drm_plane *plane)
+{
+	struct tegra_plane_state *state;
+
+	if (plane->state)
+		__drm_atomic_helper_plane_destroy_state(plane->state);
+
+	kfree(plane->state);
+	plane->state = NULL;
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (state) {
+		plane->state = &state->base;
+		plane->state->plane = plane;
+	}
+}
+
+static struct drm_plane_state *
+tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
+{
+	struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
+	struct tegra_plane_state *copy;
+
+	copy = kmalloc(sizeof(*copy), GFP_KERNEL);
+	if (!copy)
+		return NULL;
+
+	__drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
+	copy->tiling = state->tiling;
+	copy->format = state->format;
+	copy->swap = state->swap;
+
+	return &copy->base;
+}
+
+static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
+					     struct drm_plane_state *state)
+{
+	__drm_atomic_helper_plane_destroy_state(state);
+	kfree(state);
+}
+
+const struct drm_plane_funcs tegra_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = tegra_plane_destroy,
+	.reset = tegra_plane_reset,
+	.atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
+	.atomic_destroy_state = tegra_plane_atomic_destroy_state,
+};
+
+int tegra_plane_state_add(struct tegra_plane *plane,
+			  struct drm_plane_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct tegra_dc_state *tegra;
+	struct drm_rect clip;
+	int err;
+
+	/* Propagate errors from allocation or locking failures. */
+	crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
+
+	clip.x1 = 0;
+	clip.y1 = 0;
+	clip.x2 = crtc_state->mode.hdisplay;
+	clip.y2 = crtc_state->mode.vdisplay;
+
+	/* Check plane state for visibility and calculate clipping bounds */
+	err = drm_plane_helper_check_state(state, &clip, 0, INT_MAX,
+					   true, true);
+	if (err < 0)
+		return err;
+
+	tegra = to_dc_state(crtc_state);
+
+	tegra->planes |= WIN_A_ACT_REQ << plane->index;
+
+	return 0;
+}
+
+int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap)
+{
+	/* assume no swapping of fetched data */
+	if (swap)
+		*swap = BYTE_SWAP_NOSWAP;
+
+	switch (fourcc) {
+	case DRM_FORMAT_XBGR8888:
+		*format = WIN_COLOR_DEPTH_R8G8B8A8;
+		break;
+
+	case DRM_FORMAT_XRGB8888:
+		*format = WIN_COLOR_DEPTH_B8G8R8A8;
+		break;
+
+	case DRM_FORMAT_RGB565:
+		*format = WIN_COLOR_DEPTH_B5G6R5;
+		break;
+
+	case DRM_FORMAT_UYVY:
+		*format = WIN_COLOR_DEPTH_YCbCr422;
+		break;
+
+	case DRM_FORMAT_YUYV:
+		if (!swap)
+			return -EINVAL;
+
+		*format = WIN_COLOR_DEPTH_YCbCr422;
+		*swap = BYTE_SWAP_SWAP2;
+		break;
+
+	case DRM_FORMAT_YUV420:
+		*format = WIN_COLOR_DEPTH_YCbCr420P;
+		break;
+
+	case DRM_FORMAT_YUV422:
+		*format = WIN_COLOR_DEPTH_YCbCr422P;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+bool tegra_plane_format_is_yuv(unsigned int format, bool *planar)
+{
+	switch (format) {
+	case WIN_COLOR_DEPTH_YCbCr422:
+	case WIN_COLOR_DEPTH_YUV422:
+		if (planar)
+			*planar = false;
+
+		return true;
+
+	case WIN_COLOR_DEPTH_YCbCr420P:
+	case WIN_COLOR_DEPTH_YUV420P:
+	case WIN_COLOR_DEPTH_YCbCr422P:
+	case WIN_COLOR_DEPTH_YUV422P:
+	case WIN_COLOR_DEPTH_YCbCr422R:
+	case WIN_COLOR_DEPTH_YUV422R:
+	case WIN_COLOR_DEPTH_YCbCr422RA:
+	case WIN_COLOR_DEPTH_YUV422RA:
+		if (planar)
+			*planar = true;
+
+		return true;
+	}
+
+	if (planar)
+		*planar = false;
+
+	return false;
+}
diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h
new file mode 100644
index 000000000000..8237b885acd7
--- /dev/null
+++ b/drivers/gpu/drm/tegra/plane.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef TEGRA_PLANE_H
+#define TEGRA_PLANE_H 1
+
+#include <drm/drm_plane.h>
+
+struct tegra_bo;
+
+struct tegra_plane {
+	struct drm_plane base;
+	unsigned int index;
+};
+
+struct tegra_cursor {
+	struct tegra_plane base;
+
+	struct tegra_bo *bo;
+	unsigned int width;
+	unsigned int height;
+};
+
+static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
+{
+	return container_of(plane, struct tegra_plane, base);
+}
+
+struct tegra_plane_state {
+	struct drm_plane_state base;
+
+	struct tegra_bo_tiling tiling;
+	u32 format;
+	u32 swap;
+};
+
+static inline struct tegra_plane_state *
+to_tegra_plane_state(struct drm_plane_state *state)
+{
+	if (state)
+		return container_of(state, struct tegra_plane_state, base);
+
+	return NULL;
+}
+
+extern const struct drm_plane_funcs tegra_plane_funcs;
+
+int tegra_plane_state_add(struct tegra_plane *plane,
+			  struct drm_plane_state *state);
+
+int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap);
+bool tegra_plane_format_is_yuv(unsigned int format, bool *planar);
+
+#endif /* TEGRA_PLANE_H */
