diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 0a14d24..a6eec51 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1088,7 +1088,7 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
 	priv->dcrtc[dcrtc->num] = dcrtc;
 
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(dev, &dcrtc->crtc, primary, &armada_crtc_funcs);
+	drm_crtc_init(dev, &dcrtc->crtc, primary, NULL, &armada_crtc_funcs);
 	drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs);
 
 	drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop,
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index bd1e156..52415ca 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -634,7 +634,7 @@ static int ast_crtc_init(struct drm_device *dev)
 		return -ENOMEM;
 
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(dev, &crtc->base, primary, &ast_crtc_funcs);
+	drm_crtc_init(dev, &crtc->base, primary, NULL, &ast_crtc_funcs);
 	drm_mode_crtc_set_gamma_size(&crtc->base, 256);
 	drm_crtc_helper_add(&crtc->base, &ast_crtc_helper_funcs);
 
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index b67ad12..e88101a 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -132,7 +132,7 @@ static void bochs_crtc_init(struct drm_device *dev)
 	struct drm_plane *primary;
 
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(dev, crtc, primary, &bochs_crtc_funcs);
+	drm_crtc_init(dev, crtc, primary, NULL, &bochs_crtc_funcs);
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 	drm_crtc_helper_add(crtc, &bochs_helper_funcs);
 }
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
index 5291d2f..04a002b 100644
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -392,7 +392,8 @@ static void cirrus_crtc_init(struct drm_device *dev)
 		return;
 
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(dev, &cirrus_crtc->base, primary, &cirrus_crtc_funcs);
+	drm_crtc_init(dev, &cirrus_crtc->base, primary, NULL,
+		      &cirrus_crtc_funcs);
 
 	drm_mode_crtc_set_gamma_size(&cirrus_crtc->base, CIRRUS_LUT_SIZE);
 	cdev->mode_info.crtc = cirrus_crtc;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index fb8e493..e6e1f39 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -683,6 +683,7 @@ EXPORT_SYMBOL(drm_framebuffer_remove);
  * @dev: DRM device
  * @crtc: CRTC object to init
  * @primary: Primary plane for CRTC
+ * @cursor: Cursor plane for CRTC; may be NULL if no hardware cursor exists
  * @funcs: callbacks for the new CRTC
  *
  * Inits a new object created as base part of a driver crtc object.
@@ -692,6 +693,7 @@ EXPORT_SYMBOL(drm_framebuffer_remove);
  */
 int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
 		  struct drm_plane *primary,
+		  struct drm_plane *cursor,
 		  const struct drm_crtc_funcs *funcs)
 {
 	int ret;
@@ -716,6 +718,10 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
 	crtc->primary = primary;
 	primary->possible_crtcs = 1 << drm_crtc_index(crtc);
 
+	crtc->cursor = cursor;
+	if (cursor)
+		cursor->possible_crtcs = 1 << drm_crtc_index(crtc);
+
  out:
 	drm_modeset_unlock_all(dev);
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 507abd5..a17eb1d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -344,7 +344,7 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
 	private->crtc[nr] = crtc;
 
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(dev, crtc, primary, &exynos_crtc_funcs);
+	drm_crtc_init(dev, crtc, primary, NULL, &exynos_crtc_funcs);
 	drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
 
 	exynos_drm_crtc_attach_mode_property(crtc);
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c
index 25c174c..26a363e 100644
--- a/drivers/gpu/drm/gma500/psb_intel_display.c
+++ b/drivers/gpu/drm/gma500/psb_intel_display.c
@@ -513,7 +513,8 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 
 	/* Set the CRTC operations from the chip specific data */
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(dev, &gma_crtc->base, primary, dev_priv->ops->crtc_funcs);
+	drm_crtc_init(dev, &gma_crtc->base, primary, NULL,
+		      dev_priv->ops->crtc_funcs);
 
 	/* Set the CRTC clock functions from chip specific data */
 	gma_crtc->clock_funcs = dev_priv->ops->clock_funcs;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7d6878b..d43b31d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10722,7 +10722,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 		return;
 
 	primary = intel_primary_plane_create(dev, pipe);
-	ret = drm_crtc_init(dev, &intel_crtc->base, primary, &intel_crtc_funcs);
+	ret = drm_crtc_init(dev, &intel_crtc->base, primary, NULL,
+			    &intel_crtc_funcs);
 	if (ret) {
 		drm_crtc_cleanup(&intel_crtc->base);
 		kfree(intel_crtc);
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index f8c42b1..befa249 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1327,7 +1327,8 @@ static void mga_crtc_init(struct mga_device *mdev)
 		return;
 
 	primary = drm_primary_helper_create_plane(mdev->dev);
-	drm_crtc_init(mdev->dev, &mga_crtc->base, primary, &mga_crtc_funcs);
+	drm_crtc_init(mdev->dev, &mga_crtc->base, primary, NULL,
+		      &mga_crtc_funcs);
 
 	drm_mode_crtc_set_gamma_size(&mga_crtc->base, MGAG200_LUT_SIZE);
 	mdev->mode_info.crtc = mga_crtc;
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index f96497b..2dcd224 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -794,7 +794,7 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
 
 	INIT_FENCE_CB(&mdp4_crtc->pageflip_cb, pageflip_cb);
 
-	drm_crtc_init(dev, crtc, plane, &mdp4_crtc_funcs);
+	drm_crtc_init(dev, crtc, plane, NULL, &mdp4_crtc_funcs);
 	drm_crtc_helper_add(crtc, &mdp4_crtc_helper_funcs);
 
 	mdp4_plane_install_properties(mdp4_crtc->plane, &crtc->base);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index f200048..e74751f 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -562,7 +562,7 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
 
 	INIT_FENCE_CB(&mdp5_crtc->pageflip_cb, pageflip_cb);
 
-	drm_crtc_init(dev, crtc, plane, &mdp5_crtc_funcs);
+	drm_crtc_init(dev, crtc, plane, NULL, &mdp5_crtc_funcs);
 	drm_crtc_helper_add(crtc, &mdp5_crtc_helper_funcs);
 
 	mdp5_plane_install_properties(mdp5_crtc->plane, &crtc->base);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
index 2a5e9db..974babe 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
@@ -1124,7 +1124,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num)
 	nv_crtc->last_dpms = NV_DPMS_CLEARED;
 
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(dev, &nv_crtc->base, primary, &nv04_crtc_funcs);
+	drm_crtc_init(dev, &nv_crtc->base, primary, NULL, &nv04_crtc_funcs);
 	drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs);
 	drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
 
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index c744bf6..b1cc440 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1372,7 +1372,7 @@ nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index)
 
 	crtc = &head->base.base;
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(dev, crtc, primary, &nv50_crtc_func);
+	drm_crtc_init(dev, crtc, primary, NULL, &nv50_crtc_func);
 	drm_crtc_helper_add(crtc, &nv50_crtc_hfunc);
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index fdf9dc0..9623c6f 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -677,7 +677,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 	info->trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
 	info->trans_enabled = false;
 
-	drm_crtc_init(dev, crtc, plane, &omap_crtc_funcs);
+	drm_crtc_init(dev, crtc, plane, NULL, &omap_crtc_funcs);
 	drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs);
 
 	omap_plane_install_properties(omap_crtc->plane, &crtc->base);
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 5be0b87..50ad5fc 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -644,7 +644,7 @@ static int qdev_crtc_init(struct drm_device *dev, int crtc_id)
 		return -ENOMEM;
 
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(dev, &qxl_crtc->base, primary, &qxl_crtc_funcs);
+	drm_crtc_init(dev, &qxl_crtc->base, primary, NULL, &qxl_crtc_funcs);
 	qxl_crtc->index = crtc_id;
 	drm_mode_crtc_set_gamma_size(&qxl_crtc->base, 256);
 	drm_crtc_helper_add(&qxl_crtc->base, &qxl_crtc_helper_funcs);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 4e90049..1ef84c5 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -560,7 +560,8 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
 		return;
 
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(dev, &radeon_crtc->base, primary, &radeon_crtc_funcs);
+	drm_crtc_init(dev, &radeon_crtc->base, primary, NULL,
+		      &radeon_crtc_funcs);
 
 	drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256);
 	radeon_crtc->crtc_id = index;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 151ffaa..dca3c4c 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -570,7 +570,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
 	rcrtc->plane->crtc = crtc;
 
 	primary = drm_primary_helper_create_plane(dev);
-	ret = drm_crtc_init(rcdu->ddev, crtc, primary, &crtc_funcs);
+	ret = drm_crtc_init(rcdu->ddev, crtc, primary, NULL, &crtc_funcs);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
index e806553..dedbd33 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
@@ -517,7 +517,7 @@ int shmob_drm_crtc_create(struct shmob_drm_device *sdev)
 
 	sdev->crtc.dpms = DRM_MODE_DPMS_OFF;
 
-	ret = drm_crtc_init(sdev->ddev, crtc, primary, &crtc_funcs);
+	ret = drm_crtc_init(sdev->ddev, crtc, primary, NULL, &crtc_funcs);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 5e2ee9d..3b2e73f 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -1103,7 +1103,7 @@ static int tegra_dc_init(struct host1x_client *client)
 	int err;
 
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(tegra->drm, &dc->base, primary, &tegra_crtc_funcs);
+	drm_crtc_init(tegra->drm, &dc->base, primary, NULL, &tegra_crtc_funcs);
 	drm_mode_crtc_set_gamma_size(&dc->base, 256);
 	drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
 
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
index 310314c..002c88c 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -673,7 +673,7 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
 	}
 
 	primary = drm_primary_helper_create_plane(dev);
-	ret = drm_crtc_init(dev, crtc, primary, &tilcdc_crtc_funcs);
+	ret = drm_crtc_init(dev, crtc, primary, NULL, &tilcdc_crtc_funcs);
 	if (ret < 0)
 		goto fail;
 
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index c63b5e7..9490cf5 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -396,7 +396,7 @@ static int udl_crtc_init(struct drm_device *dev)
 		return -ENOMEM;
 
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(dev, crtc, primary, &udl_crtc_funcs);
+	drm_crtc_init(dev, crtc, primary, NULL, &udl_crtc_funcs);
 	drm_crtc_helper_add(crtc, &udl_helper_funcs);
 
 	return 0;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 08fdd7f..07888c5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -375,7 +375,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 	(void) drm_sysfs_connector_add(connector);
 
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(dev, crtc, primary, &vmw_legacy_crtc_funcs);
+	drm_crtc_init(dev, crtc, primary, NULL, &vmw_legacy_crtc_funcs);
 
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 46ea096..b1ad841 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -471,7 +471,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 	(void) drm_sysfs_connector_add(connector);
 
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(dev, crtc, primary, &vmw_screen_object_crtc_funcs);
+	drm_crtc_init(dev, crtc, primary, NULL, &vmw_screen_object_crtc_funcs);
 
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index 8c7b1d3..0710196 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -522,7 +522,7 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
 			imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
 
 	primary = drm_primary_helper_create_plane(dev);
-	drm_crtc_init(imxdrm->drm, crtc, primary,
+	drm_crtc_init(imxdrm->drm, crtc, primary, NULL,
 			imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
 
 	drm_mode_group_reinit(imxdrm->drm);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 9f7824d..1c9704b 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -271,6 +271,8 @@ struct drm_crtc_funcs {
  * @head: list management
  * @base: base KMS object for ID tracking etc.
  * @primary: primary plane for this CRTC
+ * @cursor: cursor plane for this CRTC; may be NULL if no cursor
+ *    is supported
  * @enabled: is this CRTC enabled?
  * @mode: current mode timings
  * @hwmode: mode timings as programmed to hw regs
@@ -309,6 +311,9 @@ struct drm_crtc {
 	/* primary plane for CRTC */
 	struct drm_plane *primary;
 
+	/* cursor plane for CRTC */
+	struct drm_plane *cursor;
+
 	/* Temporary tracking of the old fb while a modeset is ongoing. Used
 	 * by drm_mode_set_config_internal to implement correct refcounting. */
 	struct drm_framebuffer *old_fb;
@@ -909,6 +914,7 @@ extern void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
 extern int drm_crtc_init(struct drm_device *dev,
 			 struct drm_crtc *crtc,
 			 struct drm_plane *primary,
+			 struct drm_plane *cursor,
 			 const struct drm_crtc_funcs *funcs);
 extern void drm_crtc_cleanup(struct drm_crtc *crtc);
 extern unsigned int drm_crtc_index(struct drm_crtc *crtc);
