diff mbox

[RFCv3,08/14] drm: Replace crtc fb with primary plane fb (v2)

Message ID 1395188579-17191-9-git-send-email-matthew.d.roper@intel.com
State Superseded
Headers show

Commit Message

Matt Roper March 19, 2014, 12:22 a.m. UTC
Now that CRTC's have a primary plane, there's no need to track the
framebuffer in the CRTC.  Replace all references to the CRTC fb
with the primary plane's fb.

Also note that this simplifies framebuffer removal slightly; we no
longer need to scan all CRTC's and disable the ones that were using the
framebuffer since the existing loop over all planes will take care
of disabling the primary plane (and on most hardware, the CRTC by
extension).

v2: Fixup several lingering crtc->fb instances that were missed in the
    first patch iteration.

Tested-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/ast/ast_mode.c               |  12 +--
 drivers/gpu/drm/bochs/bochs_kms.c            |   4 +-
 drivers/gpu/drm/cirrus/cirrus_mode.c         |  10 +-
 drivers/gpu/drm/drm_crtc.c                   |  56 ++++------
 drivers/gpu/drm/drm_crtc_helper.c            |  21 ++--
 drivers/gpu/drm/drm_fb_helper.c              |   6 +-
 drivers/gpu/drm/gma500/cdv_intel_display.c   |   2 +-
 drivers/gpu/drm/gma500/cdv_intel_dp.c        |   2 +-
 drivers/gpu/drm/gma500/cdv_intel_hdmi.c      |   3 +-
 drivers/gpu/drm/gma500/cdv_intel_lvds.c      |   2 +-
 drivers/gpu/drm/gma500/gma_display.c         |  17 ++--
 drivers/gpu/drm/gma500/mdfld_dsi_output.c    |   2 +-
 drivers/gpu/drm/gma500/mdfld_intel_display.c |  17 ++--
 drivers/gpu/drm/gma500/oaktrail_crtc.c       |  13 +--
 drivers/gpu/drm/gma500/psb_intel_display.c   |   2 +-
 drivers/gpu/drm/gma500/psb_intel_lvds.c      |   2 +-
 drivers/gpu/drm/gma500/psb_intel_sdvo.c      |   2 +-
 drivers/gpu/drm/i915/i915_debugfs.c          |   4 +-
 drivers/gpu/drm/i915/i915_irq.c              |   4 +-
 drivers/gpu/drm/i915/intel_display.c         | 147 ++++++++++++++-------------
 drivers/gpu/drm/i915/intel_dp.c              |   5 +-
 drivers/gpu/drm/i915/intel_fbdev.c           |   6 +-
 drivers/gpu/drm/i915/intel_overlay.c         |   4 +-
 drivers/gpu/drm/i915/intel_pm.c              |  36 +++----
 drivers/gpu/drm/mgag200/mgag200_mode.c       |  28 ++---
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c     |  28 ++---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c     |  22 ++--
 drivers/gpu/drm/nouveau/dispnv04/crtc.c      |  20 ++--
 drivers/gpu/drm/nouveau/dispnv04/dfp.c       |   2 +-
 drivers/gpu/drm/nouveau/nouveau_display.c    |   8 +-
 drivers/gpu/drm/nouveau/nv50_display.c       |  17 ++--
 drivers/gpu/drm/qxl/qxl_display.c            |  11 +-
 drivers/gpu/drm/radeon/atombios_crtc.c       |  20 ++--
 drivers/gpu/drm/radeon/r100.c                |   4 +-
 drivers/gpu/drm/radeon/radeon_connectors.c   |   2 +-
 drivers/gpu/drm/radeon/radeon_device.c       |   3 +-
 drivers/gpu/drm/radeon/radeon_display.c      |   4 +-
 drivers/gpu/drm/radeon/radeon_legacy_crtc.c  |  16 +--
 drivers/gpu/drm/udl/udl_modeset.c            |   2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c          |  14 +--
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c          |   8 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c         |   8 +-
 include/drm/drm_crtc.h                       |   3 -
 43 files changed, 300 insertions(+), 299 deletions(-)

Comments

Daniel Vetter March 19, 2014, 11:57 a.m. UTC | #1
On Tue, Mar 18, 2014 at 05:22:53PM -0700, Matt Roper wrote:
> Now that CRTC's have a primary plane, there's no need to track the
> framebuffer in the CRTC.  Replace all references to the CRTC fb
> with the primary plane's fb.
> 
> Also note that this simplifies framebuffer removal slightly; we no
> longer need to scan all CRTC's and disable the ones that were using the
> framebuffer since the existing loop over all planes will take care
> of disabling the primary plane (and on most hardware, the CRTC by
> extension).
> 
> v2: Fixup several lingering crtc->fb instances that were missed in the
>     first patch iteration.
> 
> Tested-by: Rob Clark <robdclark@gmail.com>
> Signed-off-by: Matt Roper <matthew.d.roper@intel.com>

Giant patch again, and I don't think there's any sane way we can avoid
this big sed job. Put I think we can make it less intrusive.

First: Have you looked into cocinelle to do this? I'm not sure whether
cocinelle is sufficiently type aware, but the upside of using it is that
it's much easier to regenerate the patch.

In any case I think we need to split this into the usual 3 phases to avoid
flag days:

1) Switch to crtc->primary->fb all over the core, but keep crtc->fb fully
functional. I.e. update it before calling into drivers and use that to
update crtc->primary->fb on return (e.g. in the pageflip ioctl).

2) Switch drivers over to look at crtc->primary->fb. This way we can even
split up the patch into per-driver patches which gives driver maintainers
more wiggle room.

3) Kill crtc->fb.

Steps 2&3 don't block merging of the universal planes support at all. So
we could get the core support in all early for 3.16, then let driver
maintainers pick up patche for 2 and shortly before the 3.16 merge window
opens send a pull request with all the stragglers and step 3.

No comments on the actual patch, the few functional changes hidden in the
massive diff looked ok. But hard to review properly ;-)

Cheers, Daniel

> ---
>  drivers/gpu/drm/ast/ast_mode.c               |  12 +--
>  drivers/gpu/drm/bochs/bochs_kms.c            |   4 +-
>  drivers/gpu/drm/cirrus/cirrus_mode.c         |  10 +-
>  drivers/gpu/drm/drm_crtc.c                   |  56 ++++------
>  drivers/gpu/drm/drm_crtc_helper.c            |  21 ++--
>  drivers/gpu/drm/drm_fb_helper.c              |   6 +-
>  drivers/gpu/drm/gma500/cdv_intel_display.c   |   2 +-
>  drivers/gpu/drm/gma500/cdv_intel_dp.c        |   2 +-
>  drivers/gpu/drm/gma500/cdv_intel_hdmi.c      |   3 +-
>  drivers/gpu/drm/gma500/cdv_intel_lvds.c      |   2 +-
>  drivers/gpu/drm/gma500/gma_display.c         |  17 ++--
>  drivers/gpu/drm/gma500/mdfld_dsi_output.c    |   2 +-
>  drivers/gpu/drm/gma500/mdfld_intel_display.c |  17 ++--
>  drivers/gpu/drm/gma500/oaktrail_crtc.c       |  13 +--
>  drivers/gpu/drm/gma500/psb_intel_display.c   |   2 +-
>  drivers/gpu/drm/gma500/psb_intel_lvds.c      |   2 +-
>  drivers/gpu/drm/gma500/psb_intel_sdvo.c      |   2 +-
>  drivers/gpu/drm/i915/i915_debugfs.c          |   4 +-
>  drivers/gpu/drm/i915/i915_irq.c              |   4 +-
>  drivers/gpu/drm/i915/intel_display.c         | 147 ++++++++++++++-------------
>  drivers/gpu/drm/i915/intel_dp.c              |   5 +-
>  drivers/gpu/drm/i915/intel_fbdev.c           |   6 +-
>  drivers/gpu/drm/i915/intel_overlay.c         |   4 +-
>  drivers/gpu/drm/i915/intel_pm.c              |  36 +++----
>  drivers/gpu/drm/mgag200/mgag200_mode.c       |  28 ++---
>  drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c     |  28 ++---
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c     |  22 ++--
>  drivers/gpu/drm/nouveau/dispnv04/crtc.c      |  20 ++--
>  drivers/gpu/drm/nouveau/dispnv04/dfp.c       |   2 +-
>  drivers/gpu/drm/nouveau/nouveau_display.c    |   8 +-
>  drivers/gpu/drm/nouveau/nv50_display.c       |  17 ++--
>  drivers/gpu/drm/qxl/qxl_display.c            |  11 +-
>  drivers/gpu/drm/radeon/atombios_crtc.c       |  20 ++--
>  drivers/gpu/drm/radeon/r100.c                |   4 +-
>  drivers/gpu/drm/radeon/radeon_connectors.c   |   2 +-
>  drivers/gpu/drm/radeon/radeon_device.c       |   3 +-
>  drivers/gpu/drm/radeon/radeon_display.c      |   4 +-
>  drivers/gpu/drm/radeon/radeon_legacy_crtc.c  |  16 +--
>  drivers/gpu/drm/udl/udl_modeset.c            |   2 +-
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c          |  14 +--
>  drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c          |   8 +-
>  drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c         |   8 +-
>  include/drm/drm_crtc.h                       |   3 -
>  43 files changed, 300 insertions(+), 299 deletions(-)
> 
> diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
> index 44f0d32..bd1e156 100644
> --- a/drivers/gpu/drm/ast/ast_mode.c
> +++ b/drivers/gpu/drm/ast/ast_mode.c
> @@ -81,7 +81,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
>  	u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate;
>  	u32 hborder, vborder;
>  
> -	switch (crtc->fb->bits_per_pixel) {
> +	switch (crtc->primary->fb->bits_per_pixel) {
>  	case 8:
>  		vbios_mode->std_table = &vbios_stdtable[VGAModeIndex];
>  		color_index = VGAModeIndex - 1;
> @@ -176,7 +176,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
>  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff);
>  
>  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
> -		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->fb->bits_per_pixel);
> +		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->primary->fb->bits_per_pixel);
>  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000);
>  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay);
>  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8);
> @@ -340,7 +340,7 @@ static void ast_set_offset_reg(struct drm_crtc *crtc)
>  
>  	u16 offset;
>  
> -	offset = crtc->fb->pitches[0] >> 3;
> +	offset = crtc->primary->fb->pitches[0] >> 3;
>  	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff));
>  	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f);
>  }
> @@ -365,7 +365,7 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode
>  	struct ast_private *ast = crtc->dev->dev_private;
>  	u8 jregA0 = 0, jregA3 = 0, jregA8 = 0;
>  
> -	switch (crtc->fb->bits_per_pixel) {
> +	switch (crtc->primary->fb->bits_per_pixel) {
>  	case 8:
>  		jregA0 = 0x70;
>  		jregA3 = 0x01;
> @@ -418,7 +418,7 @@ static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mo
>  static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
>  		     struct ast_vbios_mode_info *vbios_mode)
>  {
> -	switch (crtc->fb->bits_per_pixel) {
> +	switch (crtc->primary->fb->bits_per_pixel) {
>  	case 8:
>  		break;
>  	default:
> @@ -490,7 +490,7 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc,
>  		ast_bo_unreserve(bo);
>  	}
>  
> -	ast_fb = to_ast_framebuffer(crtc->fb);
> +	ast_fb = to_ast_framebuffer(crtc->primary->fb);
>  	obj = ast_fb->obj;
>  	bo = gem_to_ast_bo(obj);
>  
> diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
> index 182f5c9..b67ad12 100644
> --- a/drivers/gpu/drm/bochs/bochs_kms.c
> +++ b/drivers/gpu/drm/bochs/bochs_kms.c
> @@ -62,10 +62,10 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
>  		}
>  	}
>  
> -	if (WARN_ON(crtc->fb == NULL))
> +	if (WARN_ON(crtc->primary->fb == NULL))
>  		return -EINVAL;
>  
> -	bochs_fb = to_bochs_framebuffer(crtc->fb);
> +	bochs_fb = to_bochs_framebuffer(crtc->primary->fb);
>  	bo = gem_to_bochs_bo(bochs_fb->obj);
>  	ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
>  	if (ret)
> diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
> index 449246f..5291d2f 100644
> --- a/drivers/gpu/drm/cirrus/cirrus_mode.c
> +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
> @@ -149,7 +149,7 @@ static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
>  		cirrus_bo_unreserve(bo);
>  	}
>  
> -	cirrus_fb = to_cirrus_framebuffer(crtc->fb);
> +	cirrus_fb = to_cirrus_framebuffer(crtc->primary->fb);
>  	obj = cirrus_fb->obj;
>  	bo = gem_to_cirrus_bo(obj);
>  
> @@ -268,7 +268,7 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
>  	sr07 = RREG8(SEQ_DATA);
>  	sr07 &= 0xe0;
>  	hdr = 0;
> -	switch (crtc->fb->bits_per_pixel) {
> +	switch (crtc->primary->fb->bits_per_pixel) {
>  	case 8:
>  		sr07 |= 0x11;
>  		break;
> @@ -291,13 +291,13 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
>  	WREG_SEQ(0x7, sr07);
>  
>  	/* Program the pitch */
> -	tmp = crtc->fb->pitches[0] / 8;
> +	tmp = crtc->primary->fb->pitches[0] / 8;
>  	WREG_CRT(VGA_CRTC_OFFSET, tmp);
>  
>  	/* Enable extended blanking and pitch bits, and enable full memory */
>  	tmp = 0x22;
> -	tmp |= (crtc->fb->pitches[0] >> 7) & 0x10;
> -	tmp |= (crtc->fb->pitches[0] >> 6) & 0x40;
> +	tmp |= (crtc->primary->fb->pitches[0] >> 7) & 0x10;
> +	tmp |= (crtc->primary->fb->pitches[0] >> 6) & 0x40;
>  	WREG_CRT(0x1b, tmp);
>  
>  	/* Enable high-colour modes */
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 0feb66cc..0c395e8 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -634,7 +634,7 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
>   * drm_framebuffer_remove - remove and unreference a framebuffer object
>   * @fb: framebuffer to remove
>   *
> - * Scans all the CRTCs and planes in @dev's mode_config.  If they're
> + * Scans all the planes in @dev's mode_config.  If they're
>   * using @fb, removes it, setting it to NULL. Then drops the reference to the
>   * passed-in framebuffer. Might take the modeset locks.
>   *
> @@ -645,10 +645,7 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
>  void drm_framebuffer_remove(struct drm_framebuffer *fb)
>  {
>  	struct drm_device *dev = fb->dev;
> -	struct drm_crtc *crtc;
>  	struct drm_plane *plane;
> -	struct drm_mode_set set;
> -	int ret;
>  
>  	WARN_ON(!list_empty(&fb->filp_head));
>  
> @@ -669,19 +666,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
>  	 */
>  	if (atomic_read(&fb->refcount.refcount) > 1) {
>  		drm_modeset_lock_all(dev);
> -		/* remove from any CRTC */
> -		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> -			if (crtc->fb == fb) {
> -				/* should turn off the crtc */
> -				memset(&set, 0, sizeof(struct drm_mode_set));
> -				set.crtc = crtc;
> -				set.fb = NULL;
> -				ret = drm_mode_set_config_internal(&set);
> -				if (ret)
> -					DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
> -			}
> -		}
> -
> +		/* remove from any plane */
>  		list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
>  			if (plane->fb == fb)
>  				drm_plane_force_disable(plane);
> @@ -1930,8 +1915,8 @@ int drm_mode_getcrtc(struct drm_device *dev,
>  	crtc_resp->x = crtc->x;
>  	crtc_resp->y = crtc->y;
>  	crtc_resp->gamma_size = crtc->gamma_size;
> -	if (crtc->fb)
> -		crtc_resp->fb_id = crtc->fb->base.id;
> +	if (crtc->primary->fb)
> +		crtc_resp->fb_id = crtc->primary->fb->base.id;
>  	else
>  		crtc_resp->fb_id = 0;
>  
> @@ -2438,7 +2423,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
>  	 * crtcs. Atomic modeset will have saner semantics ...
>  	 */
>  	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
> -		tmp->old_fb = tmp->fb;
> +		tmp->old_fb = tmp->primary->fb;
>  
>  	fb = set->fb;
>  
> @@ -2446,13 +2431,16 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
>  	if (ret == 0) {
>  		crtc->primary->crtc = crtc;
>  
> -		/* crtc->fb must be updated by ->set_config, enforces this. */
> -		WARN_ON(fb != crtc->fb);
> +		/*
> +		 * crtc->primary->fb must be updated by ->set_config,
> +		 * enforces this.
> +		 */
> +		WARN_ON(fb != crtc->primary->fb);
>  	}
>  
>  	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
> -		if (tmp->fb)
> -			drm_framebuffer_reference(tmp->fb);
> +		if (tmp->primary->fb)
> +			drm_framebuffer_reference(tmp->primary->fb);
>  		if (tmp->old_fb)
>  			drm_framebuffer_unreference(tmp->old_fb);
>  	}
> @@ -2511,12 +2499,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
>  		/* If we have a mode we need a framebuffer. */
>  		/* If we pass -1, set the mode with the currently bound fb */
>  		if (crtc_req->fb_id == -1) {
> -			if (!crtc->fb) {
> +			if (!crtc->primary->fb) {
>  				DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
>  				ret = -EINVAL;
>  				goto out;
>  			}
> -			fb = crtc->fb;
> +			fb = crtc->primary->fb;
>  			/* Make refcounting symmetric with the lookup path. */
>  			drm_framebuffer_reference(fb);
>  		} else {
> @@ -4309,7 +4297,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
>  	crtc = obj_to_crtc(obj);
>  
>  	mutex_lock(&crtc->mutex);
> -	if (crtc->fb == NULL) {
> +	if (crtc->primary->fb == NULL) {
>  		/* The framebuffer is currently unbound, presumably
>  		 * due to a hotplug event, that userspace has not
>  		 * yet discovered.
> @@ -4331,7 +4319,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
>  	if (ret)
>  		goto out;
>  
> -	if (crtc->fb->pixel_format != fb->pixel_format) {
> +	if (crtc->primary->fb->pixel_format != fb->pixel_format) {
>  		DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
>  		ret = -EINVAL;
>  		goto out;
> @@ -4364,7 +4352,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
>  			(void (*) (struct drm_pending_event *)) kfree;
>  	}
>  
> -	old_fb = crtc->fb;
> +	old_fb = crtc->primary->fb;
>  	ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
>  	if (ret) {
>  		if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
> @@ -4377,12 +4365,12 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
>  		old_fb = NULL;
>  	} else {
>  		/*
> -		 * Warn if the driver hasn't properly updated the crtc->fb
> -		 * field to reflect that the new framebuffer is now used.
> -		 * Failing to do so will screw with the reference counting
> -		 * on framebuffers.
> +		 * Warn if the driver hasn't properly updated the
> +		 * crtc->primary->fb field to reflect that the new framebuffer
> +		 * is now used.  Failing to do so will screw with the reference
> +		 * counting on framebuffers.
>  		 */
> -		WARN_ON(crtc->fb != fb);
> +		WARN_ON(crtc->primary->fb != fb);
>  		/* Unref only the old framebuffer. */
>  		fb = NULL;
>  	}
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index a855178..8825afb 100644
> --- a/drivers/gpu/drm/drm_crtc_helper.c
> +++ b/drivers/gpu/drm/drm_crtc_helper.c
> @@ -319,7 +319,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
>  				(*crtc_funcs->disable)(crtc);
>  			else
>  				(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
> -			crtc->fb = NULL;
> +			crtc->primary->fb = NULL;
>  		}
>  	}
>  }
> @@ -646,19 +646,19 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
>  	save_set.mode = &set->crtc->mode;
>  	save_set.x = set->crtc->x;
>  	save_set.y = set->crtc->y;
> -	save_set.fb = set->crtc->fb;
> +	save_set.fb = set->crtc->primary->fb;
>  
>  	/* We should be able to check here if the fb has the same properties
>  	 * and then just flip_or_move it */
> -	if (set->crtc->fb != set->fb) {
> +	if (set->crtc->primary->fb != set->fb) {
>  		/* If we have no fb then treat it as a full mode set */
> -		if (set->crtc->fb == NULL) {
> +		if (set->crtc->primary->fb == NULL) {
>  			DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
>  			mode_changed = true;
>  		} else if (set->fb == NULL) {
>  			mode_changed = true;
>  		} else if (set->fb->pixel_format !=
> -			   set->crtc->fb->pixel_format) {
> +			   set->crtc->primary->fb->pixel_format) {
>  			mode_changed = true;
>  		} else
>  			fb_changed = true;
> @@ -759,13 +759,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
>  			DRM_DEBUG_KMS("attempting to set mode from"
>  					" userspace\n");
>  			drm_mode_debug_printmodeline(set->mode);
> -			set->crtc->fb = set->fb;
> +			set->crtc->primary->fb = set->fb;
>  			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
>  						      set->x, set->y,
>  						      save_set.fb)) {
>  				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
>  					  set->crtc->base.id);
> -				set->crtc->fb = save_set.fb;
> +				set->crtc->primary->fb = save_set.fb;
>  				ret = -EINVAL;
>  				goto fail;
>  			}
> @@ -780,13 +780,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
>  	} else if (fb_changed) {
>  		set->crtc->x = set->x;
>  		set->crtc->y = set->y;
> -		set->crtc->fb = set->fb;
> +		set->crtc->primary->fb = set->fb;
>  		ret = crtc_funcs->mode_set_base(set->crtc,
>  						set->x, set->y, save_set.fb);
>  		if (ret != 0) {
>  			set->crtc->x = save_set.x;
>  			set->crtc->y = save_set.y;
> -			set->crtc->fb = save_set.fb;
> +			set->crtc->primary->fb = save_set.fb;
>  			goto fail;
>  		}
>  	}
> @@ -982,7 +982,8 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
>  			continue;
>  
>  		ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
> -					       crtc->x, crtc->y, crtc->fb);
> +					       crtc->x, crtc->y,
> +					       crtc->primary->fb);
>  
>  		/* Restoring the old config should never fail! */
>  		if (ret == false)
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index 9c6251f..e8e2b41 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -232,7 +232,7 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
>  
>  	list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
>  		if (crtc->base.id == c->base.id)
> -			return c->fb;
> +			return c->primary->fb;
>  	}
>  
>  	return NULL;
> @@ -366,9 +366,9 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
>  		return false;
>  
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> -		if (crtc->fb)
> +		if (crtc->primary->fb)
>  			crtcs_bound++;
> -		if (crtc->fb == fb_helper->fb)
> +		if (crtc->primary->fb == fb_helper->fb)
>  			bound++;
>  	}
>  
> diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c
> index 8fbfa06..1cddcf8 100644
> --- a/drivers/gpu/drm/gma500/cdv_intel_display.c
> +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c
> @@ -463,7 +463,7 @@ static bool cdv_intel_pipe_enabled(struct drm_device *dev, int pipe)
>  	crtc = dev_priv->pipe_to_crtc_mapping[pipe];
>  	gma_crtc = to_gma_crtc(crtc);
>  
> -	if (crtc->fb == NULL || !gma_crtc->active)
> +	if (crtc->primary->fb == NULL || !gma_crtc->active)
>  		return false;
>  	return true;
>  }
> diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
> index 0490ce3..9ff30c2 100644
> --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
> +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
> @@ -1693,7 +1693,7 @@ done:
>  		struct drm_crtc *crtc = encoder->base.crtc;
>  		drm_crtc_helper_set_mode(crtc, &crtc->mode,
>  					 crtc->x, crtc->y,
> -					 crtc->fb);
> +					 crtc->primary->fb);
>  	}
>  
>  	return 0;
> diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
> index 1c0d723..04956e6 100644
> --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
> +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
> @@ -199,7 +199,8 @@ static int cdv_hdmi_set_property(struct drm_connector *connector,
>  		    crtc->saved_mode.vdisplay != 0) {
>  			if (centre) {
>  				if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode,
> -					    encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
> +					    encoder->crtc->x, encoder->crtc->y,
> +					    encoder->crtc->primary->fb))
>  					return -1;
>  			} else {
>  				struct drm_encoder_helper_funcs *helpers
> diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
> index 20e08e6..58f11df 100644
> --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
> +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
> @@ -494,7 +494,7 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector,
>  						      &crtc->saved_mode,
>  						      encoder->crtc->x,
>  						      encoder->crtc->y,
> -						      encoder->crtc->fb))
> +						      encoder->crtc->primary->fb))
>  				return -1;
>  		}
>  	} else if (!strcmp(property->name, "backlight") && encoder) {
> diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
> index 386de2c..7b73dd1 100644
> --- a/drivers/gpu/drm/gma500/gma_display.c
> +++ b/drivers/gpu/drm/gma500/gma_display.c
> @@ -59,7 +59,7 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_psb_private *dev_priv = dev->dev_private;
>  	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
> -	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
> +	struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
>  	int pipe = gma_crtc->pipe;
>  	const struct psb_offset *map = &dev_priv->regmap[pipe];
>  	unsigned long start, offset;
> @@ -70,7 +70,7 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>  		return 0;
>  
>  	/* no fb bound */
> -	if (!crtc->fb) {
> +	if (!crtc->primary->fb) {
>  		dev_err(dev->dev, "No FB bound\n");
>  		goto gma_pipe_cleaner;
>  	}
> @@ -81,19 +81,20 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>  	if (ret < 0)
>  		goto gma_pipe_set_base_exit;
>  	start = psbfb->gtt->offset;
> -	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
> +	offset = y * crtc->primary->fb->pitches[0] +
> +		x * (crtc->primary->fb->bits_per_pixel / 8);
>  
> -	REG_WRITE(map->stride, crtc->fb->pitches[0]);
> +	REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
>  
>  	dspcntr = REG_READ(map->cntr);
>  	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
>  
> -	switch (crtc->fb->bits_per_pixel) {
> +	switch (crtc->primary->fb->bits_per_pixel) {
>  	case 8:
>  		dspcntr |= DISPPLANE_8BPP;
>  		break;
>  	case 16:
> -		if (crtc->fb->depth == 15)
> +		if (crtc->primary->fb->depth == 15)
>  			dspcntr |= DISPPLANE_15_16BPP;
>  		else
>  			dspcntr |= DISPPLANE_16BPP;
> @@ -511,8 +512,8 @@ void gma_crtc_disable(struct drm_crtc *crtc)
>  
>  	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
>  
> -	if (crtc->fb) {
> -		gt = to_psb_fb(crtc->fb)->gtt;
> +	if (crtc->primary->fb) {
> +		gt = to_psb_fb(crtc->primary->fb)->gtt;
>  		psb_gtt_unpin(gt);
>  	}
>  }
> diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> index 860a4ee..6e91b20 100644
> --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> @@ -287,7 +287,7 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
>  						&gma_crtc->saved_mode,
>  						encoder->crtc->x,
>  						encoder->crtc->y,
> -						encoder->crtc->fb))
> +						encoder->crtc->primary->fb))
>  					goto set_prop_error;
>  			} else {
>  				struct drm_encoder_helper_funcs *funcs =
> diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c
> index 321c00a..c54386a 100644
> --- a/drivers/gpu/drm/gma500/mdfld_intel_display.c
> +++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c
> @@ -166,7 +166,7 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_psb_private *dev_priv = dev->dev_private;
>  	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
> -	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
> +	struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
>  	int pipe = gma_crtc->pipe;
>  	const struct psb_offset *map = &dev_priv->regmap[pipe];
>  	unsigned long start, offset;
> @@ -178,12 +178,12 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>  	dev_dbg(dev->dev, "pipe = 0x%x.\n", pipe);
>  
>  	/* no fb bound */
> -	if (!crtc->fb) {
> +	if (!crtc->primary->fb) {
>  		dev_dbg(dev->dev, "No FB bound\n");
>  		return 0;
>  	}
>  
> -	ret = check_fb(crtc->fb);
> +	ret = check_fb(crtc->primary->fb);
>  	if (ret)
>  		return ret;
>  
> @@ -196,18 +196,19 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>  		return 0;
>  
>  	start = psbfb->gtt->offset;
> -	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
> +	offset = y * crtc->primary->fb->pitches[0] +
> +		x * (crtc->primary->fb->bits_per_pixel / 8);
>  
> -	REG_WRITE(map->stride, crtc->fb->pitches[0]);
> +	REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
>  	dspcntr = REG_READ(map->cntr);
>  	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
>  
> -	switch (crtc->fb->bits_per_pixel) {
> +	switch (crtc->primary->fb->bits_per_pixel) {
>  	case 8:
>  		dspcntr |= DISPPLANE_8BPP;
>  		break;
>  	case 16:
> -		if (crtc->fb->depth == 15)
> +		if (crtc->primary->fb->depth == 15)
>  			dspcntr |= DISPPLANE_15_16BPP;
>  		else
>  			dspcntr |= DISPPLANE_16BPP;
> @@ -700,7 +701,7 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
>  	}
>  #endif
>  
> -	ret = check_fb(crtc->fb);
> +	ret = check_fb(crtc->primary->fb);
>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c
> index 8195e85..b0fb42a 100644
> --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c
> +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c
> @@ -599,7 +599,7 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_psb_private *dev_priv = dev->dev_private;
>  	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
> -	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
> +	struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
>  	int pipe = gma_crtc->pipe;
>  	const struct psb_offset *map = &dev_priv->regmap[pipe];
>  	unsigned long start, offset;
> @@ -608,7 +608,7 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
>  	int ret = 0;
>  
>  	/* no fb bound */
> -	if (!crtc->fb) {
> +	if (!crtc->primary->fb) {
>  		dev_dbg(dev->dev, "No FB bound\n");
>  		return 0;
>  	}
> @@ -617,19 +617,20 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
>  		return 0;
>  
>  	start = psbfb->gtt->offset;
> -	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
> +	offset = y * crtc->primary->fb->pitches[0] +
> +		x * (crtc->primary->fb->bits_per_pixel / 8);
>  
> -	REG_WRITE(map->stride, crtc->fb->pitches[0]);
> +	REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
>  
>  	dspcntr = REG_READ(map->cntr);
>  	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
>  
> -	switch (crtc->fb->bits_per_pixel) {
> +	switch (crtc->primary->fb->bits_per_pixel) {
>  	case 8:
>  		dspcntr |= DISPPLANE_8BPP;
>  		break;
>  	case 16:
> -		if (crtc->fb->depth == 15)
> +		if (crtc->primary->fb->depth == 15)
>  			dspcntr |= DISPPLANE_15_16BPP;
>  		else
>  			dspcntr |= DISPPLANE_16BPP;
> diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c
> index c8f833d..25c174c 100644
> --- a/drivers/gpu/drm/gma500/psb_intel_display.c
> +++ b/drivers/gpu/drm/gma500/psb_intel_display.c
> @@ -120,7 +120,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
>  	const struct gma_limit_t *limit;
>  
>  	/* No scan out no play */
> -	if (crtc->fb == NULL) {
> +	if (crtc->primary->fb == NULL) {
>  		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
>  		return 0;
>  	}
> diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
> index 32342f6..dcdf70e 100644
> --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
> +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
> @@ -614,7 +614,7 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
>  						      &crtc->saved_mode,
>  						      encoder->crtc->x,
>  						      encoder->crtc->y,
> -						      encoder->crtc->fb))
> +						      encoder->crtc->primary->fb))
>  				goto set_prop_error;
>  		}
>  	} else if (!strcmp(property->name, "backlight")) {
> diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
> index 07d3a9e..1c0a2fb 100644
> --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
> +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
> @@ -1844,7 +1844,7 @@ done:
>  	if (psb_intel_sdvo->base.base.crtc) {
>  		struct drm_crtc *crtc = psb_intel_sdvo->base.base.crtc;
>  		drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
> -					 crtc->y, crtc->fb);
> +					 crtc->y, crtc->primary->fb);
>  	}
>  
>  	return 0;
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index d83d643..f00ba43 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2172,8 +2172,8 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc)
>  	struct intel_encoder *intel_encoder;
>  
>  	seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
> -		   crtc->fb->base.id, crtc->x, crtc->y,
> -		   crtc->fb->width, crtc->fb->height);
> +		   crtc->primary->fb->base.id, crtc->x, crtc->y,
> +		   crtc->primary->fb->width, crtc->primary->fb->height);
>  	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
>  		intel_encoder_info(m, intel_crtc, intel_encoder);
>  }
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 37f852d..e8b3f9f 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -2380,8 +2380,8 @@ static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, in
>  	} else {
>  		int dspaddr = DSPADDR(intel_crtc->plane);
>  		stall_detected = I915_READ(dspaddr) == (i915_gem_obj_ggtt_offset(obj) +
> -							crtc->y * crtc->fb->pitches[0] +
> -							crtc->x * crtc->fb->bits_per_pixel/8);
> +							crtc->y * crtc->primary->fb->pitches[0] +
> +							crtc->x * crtc->primary->fb->bits_per_pixel/8);
>  	}
>  
>  	spin_unlock_irqrestore(&dev->event_lock, flags);
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 21d12a9..c2f3730 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -744,7 +744,7 @@ bool intel_crtc_active(struct drm_crtc *crtc)
>  	 * We can ditch the crtc->fb check as soon as we can
>  	 * properly reconstruct framebuffers.
>  	 */
> -	return intel_crtc->active && crtc->fb &&
> +	return intel_crtc->active && crtc->primary->fb &&
>  		intel_crtc->config.adjusted_mode.crtc_clock;
>  }
>  
> @@ -2086,17 +2086,18 @@ static bool intel_alloc_plane_obj(struct intel_crtc *crtc,
>  
>  	if (plane_config->tiled) {
>  		obj->tiling_mode = I915_TILING_X;
> -		obj->stride = crtc->base.fb->pitches[0];
> +		obj->stride = crtc->base.primary->fb->pitches[0];
>  	}
>  
> -	mode_cmd.pixel_format = crtc->base.fb->pixel_format;
> -	mode_cmd.width = crtc->base.fb->width;
> -	mode_cmd.height = crtc->base.fb->height;
> -	mode_cmd.pitches[0] = crtc->base.fb->pitches[0];
> +	mode_cmd.pixel_format = crtc->base.primary->fb->pixel_format;
> +	mode_cmd.width = crtc->base.primary->fb->width;
> +	mode_cmd.height = crtc->base.primary->fb->height;
> +	mode_cmd.pitches[0] = crtc->base.primary->fb->pitches[0];
>  
>  	mutex_lock(&dev->struct_mutex);
>  
> -	if (intel_framebuffer_init(dev, to_intel_framebuffer(crtc->base.fb),
> +	if (intel_framebuffer_init(dev,
> +				   to_intel_framebuffer(crtc->base.primary->fb),
>  				   &mode_cmd, obj)) {
>  		DRM_DEBUG_KMS("intel fb init failed\n");
>  		goto out_unref_obj;
> @@ -2121,14 +2122,14 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
>  	struct intel_crtc *i;
>  	struct intel_framebuffer *fb;
>  
> -	if (!intel_crtc->base.fb)
> +	if (!intel_crtc->base.primary->fb)
>  		return;
>  
>  	if (intel_alloc_plane_obj(intel_crtc, plane_config))
>  		return;
>  
> -	kfree(intel_crtc->base.fb);
> -	intel_crtc->base.fb = NULL;
> +	kfree(intel_crtc->base.primary->fb);
> +	intel_crtc->base.primary->fb = NULL;
>  
>  	/*
>  	 * Failed to alloc the obj, check to see if we should share
> @@ -2140,13 +2141,13 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
>  		if (c == &intel_crtc->base)
>  			continue;
>  
> -		if (!i->active || !c->fb)
> +		if (!i->active || !c->primary->fb)
>  			continue;
>  
> -		fb = to_intel_framebuffer(c->fb);
> +		fb = to_intel_framebuffer(c->primary->fb);
>  		if (i915_gem_obj_ggtt_offset(fb->obj) == plane_config->base) {
> -			drm_framebuffer_reference(c->fb);
> -			intel_crtc->base.fb = c->fb;
> +			drm_framebuffer_reference(c->primary->fb);
> +			intel_crtc->base.primary->fb = c->primary->fb;
>  			break;
>  		}
>  	}
> @@ -2394,11 +2395,13 @@ void intel_display_handle_reset(struct drm_device *dev)
>  		/*
>  		 * FIXME: Once we have proper support for primary planes (and
>  		 * disabling them without disabling the entire crtc) allow again
> -		 * a NULL crtc->fb.
> +		 * a NULL crtc->primary->fb.
>  		 */
> -		if (intel_crtc->active && crtc->fb)
> -			dev_priv->display.update_plane(crtc, crtc->fb,
> -						       crtc->x, crtc->y);
> +		if (intel_crtc->active && crtc->primary->fb)
> +			dev_priv->display.update_plane(crtc,
> +						       crtc->primary->fb,
> +						       crtc->x,
> +						       crtc->y);
>  		mutex_unlock(&crtc->mutex);
>  	}
>  }
> @@ -2523,8 +2526,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>  		return ret;
>  	}
>  
> -	old_fb = crtc->fb;
> -	crtc->fb = fb;
> +	old_fb = crtc->primary->fb;
> +	crtc->primary->fb = fb;
>  	crtc->x = x;
>  	crtc->y = y;
>  
> @@ -3118,7 +3121,7 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  
> -	if (crtc->fb == NULL)
> +	if (crtc->primary->fb == NULL)
>  		return;
>  
>  	WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
> @@ -3127,7 +3130,7 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
>  		   !intel_crtc_has_pending_flip(crtc));
>  
>  	mutex_lock(&dev->struct_mutex);
> -	intel_finish_fb(crtc->fb);
> +	intel_finish_fb(crtc->primary->fb);
>  	mutex_unlock(&dev->struct_mutex);
>  }
>  
> @@ -4583,11 +4586,11 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
>  	assert_cursor_disabled(dev_priv, to_intel_crtc(crtc)->pipe);
>  	assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
>  
> -	if (crtc->fb) {
> +	if (crtc->primary->fb) {
>  		mutex_lock(&dev->struct_mutex);
> -		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
> +		intel_unpin_fb_obj(to_intel_framebuffer(crtc->primary->fb)->obj);
>  		mutex_unlock(&dev->struct_mutex);
> -		crtc->fb = NULL;
> +		crtc->primary->fb = NULL;
>  	}
>  
>  	/* Update computed state. */
> @@ -5738,8 +5741,9 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
>  	int fourcc, pixel_format;
>  	int aligned_height;
>  
> -	crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
> -	if (!crtc->base.fb) {
> +	crtc->base.primary->fb =
> +		kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
> +	if (!crtc->base.primary->fb) {
>  		DRM_DEBUG_KMS("failed to alloc fb\n");
>  		return;
>  	}
> @@ -5752,8 +5756,8 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
>  
>  	pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
>  	fourcc = intel_format_to_fourcc(pixel_format);
> -	crtc->base.fb->pixel_format = fourcc;
> -	crtc->base.fb->bits_per_pixel =
> +	crtc->base.primary->fb->pixel_format = fourcc;
> +	crtc->base.primary->fb->bits_per_pixel =
>  		drm_format_plane_cpp(fourcc, 0) * 8;
>  
>  	if (INTEL_INFO(dev)->gen >= 4) {
> @@ -5768,23 +5772,23 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
>  	plane_config->base = base;
>  
>  	val = I915_READ(PIPESRC(pipe));
> -	crtc->base.fb->width = ((val >> 16) & 0xfff) + 1;
> -	crtc->base.fb->height = ((val >> 0) & 0xfff) + 1;
> +	crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1;
> +	crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
>  
>  	val = I915_READ(DSPSTRIDE(pipe));
> -	crtc->base.fb->pitches[0] = val & 0xffffff80;
> +	crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
>  
> -	aligned_height = intel_align_height(dev, crtc->base.fb->height,
> +	aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
>  					    plane_config->tiled);
>  
> -	plane_config->size = ALIGN(crtc->base.fb->pitches[0] *
> +	plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
>  				   aligned_height, PAGE_SIZE);
>  
>  	DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
> -		      pipe, plane, crtc->base.fb->width,
> -		      crtc->base.fb->height,
> -		      crtc->base.fb->bits_per_pixel, base,
> -		      crtc->base.fb->pitches[0],
> +		      pipe, plane, crtc->base.primary->fb->width,
> +		      crtc->base.primary->fb->height,
> +		      crtc->base.primary->fb->bits_per_pixel, base,
> +		      crtc->base.primary->fb->pitches[0],
>  		      plane_config->size);
>  
>  }
> @@ -6746,8 +6750,9 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
>  	int fourcc, pixel_format;
>  	int aligned_height;
>  
> -	crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
> -	if (!crtc->base.fb) {
> +	crtc->base.primary->fb =
> +		kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
> +	if (!crtc->base.primary->fb) {
>  		DRM_DEBUG_KMS("failed to alloc fb\n");
>  		return;
>  	}
> @@ -6760,8 +6765,8 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
>  
>  	pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
>  	fourcc = intel_format_to_fourcc(pixel_format);
> -	crtc->base.fb->pixel_format = fourcc;
> -	crtc->base.fb->bits_per_pixel =
> +	crtc->base.primary->fb->pixel_format = fourcc;
> +	crtc->base.primary->fb->bits_per_pixel =
>  		drm_format_plane_cpp(fourcc, 0) * 8;
>  
>  	base = I915_READ(DSPSURF(plane)) & 0xfffff000;
> @@ -6776,23 +6781,23 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
>  	plane_config->base = base;
>  
>  	val = I915_READ(PIPESRC(pipe));
> -	crtc->base.fb->width = ((val >> 16) & 0xfff) + 1;
> -	crtc->base.fb->height = ((val >> 0) & 0xfff) + 1;
> +	crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1;
> +	crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
>  
>  	val = I915_READ(DSPSTRIDE(pipe));
> -	crtc->base.fb->pitches[0] = val & 0xffffff80;
> +	crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
>  
> -	aligned_height = intel_align_height(dev, crtc->base.fb->height,
> +	aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
>  					    plane_config->tiled);
>  
> -	plane_config->size = ALIGN(crtc->base.fb->pitches[0] *
> +	plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
>  				   aligned_height, PAGE_SIZE);
>  
>  	DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
> -		      pipe, plane, crtc->base.fb->width,
> -		      crtc->base.fb->height,
> -		      crtc->base.fb->bits_per_pixel, base,
> -		      crtc->base.fb->pitches[0],
> +		      pipe, plane, crtc->base.primary->fb->width,
> +		      crtc->base.primary->fb->height,
> +		      crtc->base.primary->fb->bits_per_pixel, base,
> +		      crtc->base.primary->fb->pitches[0],
>  		      plane_config->size);
>  }
>  
> @@ -8482,7 +8487,7 @@ void intel_mark_idle(struct drm_device *dev)
>  		goto out;
>  
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> -		if (!crtc->fb)
> +		if (!crtc->primary->fb)
>  			continue;
>  
>  		intel_decrease_pllclock(crtc);
> @@ -8505,10 +8510,10 @@ void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
>  		return;
>  
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> -		if (!crtc->fb)
> +		if (!crtc->primary->fb)
>  			continue;
>  
> -		if (to_intel_framebuffer(crtc->fb)->obj != obj)
> +		if (to_intel_framebuffer(crtc->primary->fb)->obj != obj)
>  			continue;
>  
>  		intel_increase_pllclock(crtc);
> @@ -8936,7 +8941,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct drm_framebuffer *old_fb = crtc->fb;
> +	struct drm_framebuffer *old_fb = crtc->primary->fb;
>  	struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>  	struct intel_unpin_work *work;
> @@ -8944,7 +8949,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
>  	int ret;
>  
>  	/* Can't change pixel format via MI display flips. */
> -	if (fb->pixel_format != crtc->fb->pixel_format)
> +	if (fb->pixel_format != crtc->primary->fb->pixel_format)
>  		return -EINVAL;
>  
>  	/*
> @@ -8952,8 +8957,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
>  	 * Note that pitch changes could also affect these register.
>  	 */
>  	if (INTEL_INFO(dev)->gen > 3 &&
> -	    (fb->offsets[0] != crtc->fb->offsets[0] ||
> -	     fb->pitches[0] != crtc->fb->pitches[0]))
> +	    (fb->offsets[0] != crtc->primary->fb->offsets[0] ||
> +	     fb->pitches[0] != crtc->primary->fb->pitches[0]))
>  		return -EINVAL;
>  
>  	if (i915_terminally_wedged(&dev_priv->gpu_error))
> @@ -8996,7 +9001,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
>  	drm_gem_object_reference(&work->old_fb_obj->base);
>  	drm_gem_object_reference(&obj->base);
>  
> -	crtc->fb = fb;
> +	crtc->primary->fb = fb;
>  
>  	work->pending_flip_obj = obj;
>  
> @@ -9019,7 +9024,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
>  
>  cleanup_pending:
>  	atomic_dec(&intel_crtc->unpin_work_count);
> -	crtc->fb = old_fb;
> +	crtc->primary->fb = old_fb;
>  	drm_gem_object_unreference(&work->old_fb_obj->base);
>  	drm_gem_object_unreference(&obj->base);
>  	mutex_unlock(&dev->struct_mutex);
> @@ -10060,7 +10065,7 @@ static int intel_set_mode(struct drm_crtc *crtc,
>  
>  void intel_crtc_restore_mode(struct drm_crtc *crtc)
>  {
> -	intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb);
> +	intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb);
>  }
>  
>  #undef for_each_intel_crtc_masked
> @@ -10184,9 +10189,9 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
>  	 * and then just flip_or_move it */
>  	if (is_crtc_connector_off(set)) {
>  		config->mode_changed = true;
> -	} else if (set->crtc->fb != set->fb) {
> +	} else if (set->crtc->primary->fb != set->fb) {
>  		/* If we have no fb then treat it as a full mode set */
> -		if (set->crtc->fb == NULL) {
> +		if (set->crtc->primary->fb == NULL) {
>  			struct intel_crtc *intel_crtc =
>  				to_intel_crtc(set->crtc);
>  
> @@ -10200,7 +10205,7 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
>  		} else if (set->fb == NULL) {
>  			config->mode_changed = true;
>  		} else if (set->fb->pixel_format !=
> -			   set->crtc->fb->pixel_format) {
> +			   set->crtc->primary->fb->pixel_format) {
>  			config->mode_changed = true;
>  		} else {
>  			config->fb_changed = true;
> @@ -10413,7 +10418,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  	save_set.mode = &set->crtc->mode;
>  	save_set.x = set->crtc->x;
>  	save_set.y = set->crtc->y;
> -	save_set.fb = set->crtc->fb;
> +	save_set.fb = set->crtc->primary->fb;
>  
>  	/* Compute whether we need a full modeset, only an fb base update or no
>  	 * change at all. In the future we might also check whether only the
> @@ -11755,7 +11760,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
>  				dev_priv->pipe_to_crtc_mapping[pipe];
>  
>  			__intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
> -					 crtc->fb);
> +					 crtc->primary->fb);
>  		}
>  	} else {
>  		intel_modeset_update_staged_output_state(dev);
> @@ -11780,15 +11785,15 @@ void intel_modeset_gem_init(struct drm_device *dev)
>  	 */
>  	mutex_lock(&dev->struct_mutex);
>  	list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
> -		if (!c->fb)
> +		if (!c->primary->fb)
>  			continue;
>  
> -		fb = to_intel_framebuffer(c->fb);
> +		fb = to_intel_framebuffer(c->primary->fb);
>  		if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL)) {
>  			DRM_ERROR("failed to pin boot fb on pipe %d\n",
>  				  to_intel_crtc(c)->pipe);
> -			drm_framebuffer_unreference(c->fb);
> -			c->fb = NULL;
> +			drm_framebuffer_unreference(c->primary->fb);
> +			c->primary->fb = NULL;
>  		}
>  	}
>  	mutex_unlock(&dev->struct_mutex);
> @@ -11827,7 +11832,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
>  
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
>  		/* Skip inactive CRTCs */
> -		if (!crtc->fb)
> +		if (!crtc->primary->fb)
>  			continue;
>  
>  		intel_increase_pllclock(crtc);
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 59ee4dc..05531bf 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1634,7 +1634,8 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct drm_crtc *crtc = dig_port->base.base.crtc;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -	struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
> +	struct drm_i915_gem_object *obj =
> +		to_intel_framebuffer(crtc->primary->fb)->obj;
>  	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
>  
>  	dev_priv->psr.source_ok = false;
> @@ -1667,7 +1668,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
>  		return false;
>  	}
>  
> -	obj = to_intel_framebuffer(crtc->fb)->obj;
> +	obj = to_intel_framebuffer(crtc->primary->fb)->obj;
>  	if (obj->tiling_mode != I915_TILING_X ||
>  	    obj->fence_reg == I915_FENCE_REG_NONE) {
>  		DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
> diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
> index d6d78c8..2b1d42d 100644
> --- a/drivers/gpu/drm/i915/intel_fbdev.c
> +++ b/drivers/gpu/drm/i915/intel_fbdev.c
> @@ -481,7 +481,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
>  		intel_crtc = to_intel_crtc(crtc);
>  
> -		if (!intel_crtc->active || !crtc->fb) {
> +		if (!intel_crtc->active || !crtc->primary->fb) {
>  			DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
>  				      pipe_name(intel_crtc->pipe));
>  			continue;
> @@ -491,7 +491,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
>  			DRM_DEBUG_KMS("found possible fb from plane %c\n",
>  				      pipe_name(intel_crtc->pipe));
>  			plane_config = &intel_crtc->plane_config;
> -			fb = to_intel_framebuffer(crtc->fb);
> +			fb = to_intel_framebuffer(crtc->primary->fb);
>  			max_size = plane_config->size;
>  		}
>  	}
> @@ -560,7 +560,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
>  		if (!intel_crtc->active)
>  			continue;
>  
> -		WARN(!crtc->fb,
> +		WARN(!crtc->primary->fb,
>  		     "re-used BIOS config but lost an fb on crtc %d\n",
>  		     crtc->base.id);
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
> index 312961a..623cd32 100644
> --- a/drivers/gpu/drm/i915/intel_overlay.c
> +++ b/drivers/gpu/drm/i915/intel_overlay.c
> @@ -606,14 +606,14 @@ static void update_colorkey(struct intel_overlay *overlay,
>  {
>  	u32 key = overlay->color_key;
>  
> -	switch (overlay->crtc->base.fb->bits_per_pixel) {
> +	switch (overlay->crtc->base.primary->fb->bits_per_pixel) {
>  	case 8:
>  		iowrite32(0, &regs->DCLRKV);
>  		iowrite32(CLK_RGB8I_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
>  		break;
>  
>  	case 16:
> -		if (overlay->crtc->base.fb->depth == 15) {
> +		if (overlay->crtc->base.primary->fb->depth == 15) {
>  			iowrite32(RGB15_TO_COLORKEY(key), &regs->DCLRKV);
>  			iowrite32(CLK_RGB15_MASK | DST_KEY_ENABLE,
>  				  &regs->DCLRKM);
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 3a1b569..e2d73f4 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -92,7 +92,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct drm_framebuffer *fb = crtc->fb;
> +	struct drm_framebuffer *fb = crtc->primary->fb;
>  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
>  	struct drm_i915_gem_object *obj = intel_fb->obj;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> @@ -149,7 +149,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct drm_framebuffer *fb = crtc->fb;
> +	struct drm_framebuffer *fb = crtc->primary->fb;
>  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
>  	struct drm_i915_gem_object *obj = intel_fb->obj;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> @@ -221,7 +221,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct drm_framebuffer *fb = crtc->fb;
> +	struct drm_framebuffer *fb = crtc->primary->fb;
>  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
>  	struct drm_i915_gem_object *obj = intel_fb->obj;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> @@ -277,7 +277,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct drm_framebuffer *fb = crtc->fb;
> +	struct drm_framebuffer *fb = crtc->primary->fb;
>  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
>  	struct drm_i915_gem_object *obj = intel_fb->obj;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> @@ -336,11 +336,11 @@ static void intel_fbc_work_fn(struct work_struct *__work)
>  		/* Double check that we haven't switched fb without cancelling
>  		 * the prior work.
>  		 */
> -		if (work->crtc->fb == work->fb) {
> +		if (work->crtc->primary->fb == work->fb) {
>  			dev_priv->display.enable_fbc(work->crtc);
>  
>  			dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane;
> -			dev_priv->fbc.fb_id = work->crtc->fb->base.id;
> +			dev_priv->fbc.fb_id = work->crtc->primary->fb->base.id;
>  			dev_priv->fbc.y = work->crtc->y;
>  		}
>  
> @@ -393,7 +393,7 @@ static void intel_enable_fbc(struct drm_crtc *crtc)
>  	}
>  
>  	work->crtc = crtc;
> -	work->fb = crtc->fb;
> +	work->fb = crtc->primary->fb;
>  	INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
>  
>  	dev_priv->fbc.fbc_work = work;
> @@ -499,14 +499,14 @@ void intel_update_fbc(struct drm_device *dev)
>  		}
>  	}
>  
> -	if (!crtc || crtc->fb == NULL) {
> +	if (!crtc || crtc->primary->fb == NULL) {
>  		if (set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT))
>  			DRM_DEBUG_KMS("no output, disabling\n");
>  		goto out_disable;
>  	}
>  
>  	intel_crtc = to_intel_crtc(crtc);
> -	fb = crtc->fb;
> +	fb = crtc->primary->fb;
>  	intel_fb = to_intel_framebuffer(fb);
>  	obj = intel_fb->obj;
>  	adjusted_mode = &intel_crtc->config.adjusted_mode;
> @@ -1041,7 +1041,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc)
>  	crtc = single_enabled_crtc(dev);
>  	if (crtc) {
>  		const struct drm_display_mode *adjusted_mode;
> -		int pixel_size = crtc->fb->bits_per_pixel / 8;
> +		int pixel_size = crtc->primary->fb->bits_per_pixel / 8;
>  		int clock;
>  
>  		adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
> @@ -1121,7 +1121,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
>  	clock = adjusted_mode->crtc_clock;
>  	htotal = adjusted_mode->crtc_htotal;
>  	hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
> -	pixel_size = crtc->fb->bits_per_pixel / 8;
> +	pixel_size = crtc->primary->fb->bits_per_pixel / 8;
>  
>  	/* Use the small buffer method to calculate plane watermark */
>  	entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
> @@ -1208,7 +1208,7 @@ static bool g4x_compute_srwm(struct drm_device *dev,
>  	clock = adjusted_mode->crtc_clock;
>  	htotal = adjusted_mode->crtc_htotal;
>  	hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
> -	pixel_size = crtc->fb->bits_per_pixel / 8;
> +	pixel_size = crtc->primary->fb->bits_per_pixel / 8;
>  
>  	line_time_us = max(htotal * 1000 / clock, 1);
>  	line_count = (latency_ns / line_time_us + 1000) / 1000;
> @@ -1247,7 +1247,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev,
>  		return false;
>  
>  	clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
> -	pixel_size = crtc->fb->bits_per_pixel / 8;	/* BPP */
> +	pixel_size = crtc->primary->fb->bits_per_pixel / 8;	/* BPP */
>  
>  	entries = (clock / 1000) * pixel_size;
>  	*plane_prec_mult = (entries > 256) ?
> @@ -1439,7 +1439,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
>  		int clock = adjusted_mode->crtc_clock;
>  		int htotal = adjusted_mode->crtc_htotal;
>  		int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
> -		int pixel_size = crtc->fb->bits_per_pixel / 8;
> +		int pixel_size = crtc->primary->fb->bits_per_pixel / 8;
>  		unsigned long line_time_us;
>  		int entries;
>  
> @@ -1512,7 +1512,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
>  	crtc = intel_get_crtc_for_plane(dev, 0);
>  	if (intel_crtc_active(crtc)) {
>  		const struct drm_display_mode *adjusted_mode;
> -		int cpp = crtc->fb->bits_per_pixel / 8;
> +		int cpp = crtc->primary->fb->bits_per_pixel / 8;
>  		if (IS_GEN2(dev))
>  			cpp = 4;
>  
> @@ -1528,7 +1528,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
>  	crtc = intel_get_crtc_for_plane(dev, 1);
>  	if (intel_crtc_active(crtc)) {
>  		const struct drm_display_mode *adjusted_mode;
> -		int cpp = crtc->fb->bits_per_pixel / 8;
> +		int cpp = crtc->primary->fb->bits_per_pixel / 8;
>  		if (IS_GEN2(dev))
>  			cpp = 4;
>  
> @@ -1565,7 +1565,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
>  		int clock = adjusted_mode->crtc_clock;
>  		int htotal = adjusted_mode->crtc_htotal;
>  		int hdisplay = to_intel_crtc(enabled)->config.pipe_src_w;
> -		int pixel_size = enabled->fb->bits_per_pixel / 8;
> +		int pixel_size = enabled->primary->fb->bits_per_pixel / 8;
>  		unsigned long line_time_us;
>  		int entries;
>  
> @@ -2117,7 +2117,7 @@ static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
>  	if (p->active) {
>  		p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_htotal;
>  		p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
> -		p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
> +		p->pri.bytes_per_pixel = crtc->primary->fb->bits_per_pixel / 8;
>  		p->cur.bytes_per_pixel = 4;
>  		p->pri.horiz_pixels = intel_crtc->config.pipe_src_w;
>  		p->cur.horiz_pixels = 64;
> diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
> index 1418414..f8c42b1 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_mode.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
> @@ -29,7 +29,7 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc)
>  	struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
>  	struct drm_device *dev = crtc->dev;
>  	struct mga_device *mdev = dev->dev_private;
> -	struct drm_framebuffer *fb = crtc->fb;
> +	struct drm_framebuffer *fb = crtc->primary->fb;
>  	int i;
>  
>  	if (!crtc->enabled)
> @@ -742,7 +742,7 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc,
>  		mgag200_bo_unreserve(bo);
>  	}
>  
> -	mga_fb = to_mga_framebuffer(crtc->fb);
> +	mga_fb = to_mga_framebuffer(crtc->primary->fb);
>  	obj = mga_fb->obj;
>  	bo = gem_to_mga_bo(obj);
>  
> @@ -805,7 +805,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
>  		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
>  	};
>  
> -	bppshift = mdev->bpp_shifts[(crtc->fb->bits_per_pixel >> 3) - 1];
> +	bppshift = mdev->bpp_shifts[(crtc->primary->fb->bits_per_pixel >> 3) - 1];
>  
>  	switch (mdev->type) {
>  	case G200_SE_A:
> @@ -843,12 +843,12 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
>  		break;
>  	}
>  
> -	switch (crtc->fb->bits_per_pixel) {
> +	switch (crtc->primary->fb->bits_per_pixel) {
>  	case 8:
>  		dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits;
>  		break;
>  	case 16:
> -		if (crtc->fb->depth == 15)
> +		if (crtc->primary->fb->depth == 15)
>  			dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_15bits;
>  		else
>  			dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_16bits;
> @@ -896,8 +896,9 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
>  	WREG_SEQ(3, 0);
>  	WREG_SEQ(4, 0xe);
>  
> -	pitch = crtc->fb->pitches[0] / (crtc->fb->bits_per_pixel / 8);
> -	if (crtc->fb->bits_per_pixel == 24)
> +	pitch = crtc->primary->fb->pitches[0] /
> +		(crtc->primary->fb->bits_per_pixel / 8);
> +	if (crtc->primary->fb->bits_per_pixel == 24)
>  		pitch = (pitch * 3) >> (4 - bppshift);
>  	else
>  		pitch = pitch >> (4 - bppshift);
> @@ -974,7 +975,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
>  		((vdisplay & 0xc00) >> 7) |
>  		((vsyncstart & 0xc00) >> 5) |
>  		((vdisplay & 0x400) >> 3);
> -	if (crtc->fb->bits_per_pixel == 24)
> +	if (crtc->primary->fb->bits_per_pixel == 24)
>  		ext_vga[3] = (((1 << bppshift) * 3) - 1) | 0x80;
>  	else
>  		ext_vga[3] = ((1 << bppshift) - 1) | 0x80;
> @@ -1034,9 +1035,9 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
>  			u32 bpp;
>  			u32 mb;
>  
> -			if (crtc->fb->bits_per_pixel > 16)
> +			if (crtc->primary->fb->bits_per_pixel > 16)
>  				bpp = 32;
> -			else if (crtc->fb->bits_per_pixel > 8)
> +			else if (crtc->primary->fb->bits_per_pixel > 8)
>  				bpp = 16;
>  			else
>  				bpp = 8;
> @@ -1277,8 +1278,9 @@ static void mga_crtc_disable(struct drm_crtc *crtc)
>  	int ret;
>  	DRM_DEBUG_KMS("\n");
>  	mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
> -	if (crtc->fb) {
> -		struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->fb);
> +	if (crtc->primary->fb) {
> +		struct mga_framebuffer *mga_fb =
> +			to_mga_framebuffer(crtc->primary->fb);
>  		struct drm_gem_object *obj = mga_fb->obj;
>  		struct mgag200_bo *bo = gem_to_mga_bo(obj);
>  		ret = mgag200_bo_reserve(bo, false);
> @@ -1287,7 +1289,7 @@ static void mga_crtc_disable(struct drm_crtc *crtc)
>  		mgag200_bo_push_sysram(bo);
>  		mgag200_bo_unreserve(bo);
>  	}
> -	crtc->fb = NULL;
> +	crtc->primary->fb = NULL;
>  }
>  
>  /* These provide the minimum set of functions required to handle a CRTC */
> diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
> index b10f681..f96497b 100644
> --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
> +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
> @@ -120,7 +120,7 @@ static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
>  
>  	/* grab reference to incoming scanout fb: */
>  	drm_framebuffer_reference(new_fb);
> -	mdp4_crtc->base.fb = new_fb;
> +	mdp4_crtc->base.primary->fb = new_fb;
>  	mdp4_crtc->fb = new_fb;
>  
>  	if (old_fb)
> @@ -182,7 +182,7 @@ static void pageflip_cb(struct msm_fence_cb *cb)
>  	struct mdp4_crtc *mdp4_crtc =
>  		container_of(cb, struct mdp4_crtc, pageflip_cb);
>  	struct drm_crtc *crtc = &mdp4_crtc->base;
> -	struct drm_framebuffer *fb = crtc->fb;
> +	struct drm_framebuffer *fb = crtc->primary->fb;
>  
>  	if (!fb)
>  		return;
> @@ -348,14 +348,14 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
>  			mode->type, mode->flags);
>  
>  	/* grab extra ref for update_scanout() */
> -	drm_framebuffer_reference(crtc->fb);
> +	drm_framebuffer_reference(crtc->primary->fb);
>  
> -	ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->fb,
> +	ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->primary->fb,
>  			0, 0, mode->hdisplay, mode->vdisplay,
>  			x << 16, y << 16,
>  			mode->hdisplay << 16, mode->vdisplay << 16);
>  	if (ret) {
> -		drm_framebuffer_unreference(crtc->fb);
> +		drm_framebuffer_unreference(crtc->primary->fb);
>  		dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
>  				mdp4_crtc->name, ret);
>  		return ret;
> @@ -368,7 +368,7 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
>  	/* take data from pipe: */
>  	mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_BASE(dma), 0);
>  	mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_STRIDE(dma),
> -			crtc->fb->pitches[0]);
> +			crtc->primary->fb->pitches[0]);
>  	mdp4_write(mdp4_kms, REG_MDP4_DMA_DST_SIZE(dma),
>  			MDP4_DMA_DST_SIZE_WIDTH(0) |
>  			MDP4_DMA_DST_SIZE_HEIGHT(0));
> @@ -378,7 +378,7 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
>  			MDP4_OVLP_SIZE_WIDTH(mode->hdisplay) |
>  			MDP4_OVLP_SIZE_HEIGHT(mode->vdisplay));
>  	mdp4_write(mdp4_kms, REG_MDP4_OVLP_STRIDE(ovlp),
> -			crtc->fb->pitches[0]);
> +			crtc->primary->fb->pitches[0]);
>  
>  	mdp4_write(mdp4_kms, REG_MDP4_OVLP_CFG(ovlp), 1);
>  
> @@ -388,8 +388,8 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
>  		mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(2), 0x00ff0000);
>  	}
>  
> -	update_fb(crtc, crtc->fb);
> -	update_scanout(crtc, crtc->fb);
> +	update_fb(crtc, crtc->primary->fb);
> +	update_scanout(crtc, crtc->primary->fb);
>  
>  	return 0;
>  }
> @@ -420,19 +420,19 @@ static int mdp4_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
>  	int ret;
>  
>  	/* grab extra ref for update_scanout() */
> -	drm_framebuffer_reference(crtc->fb);
> +	drm_framebuffer_reference(crtc->primary->fb);
>  
> -	ret = mdp4_plane_mode_set(plane, crtc, crtc->fb,
> +	ret = mdp4_plane_mode_set(plane, crtc, crtc->primary->fb,
>  			0, 0, mode->hdisplay, mode->vdisplay,
>  			x << 16, y << 16,
>  			mode->hdisplay << 16, mode->vdisplay << 16);
>  	if (ret) {
> -		drm_framebuffer_unreference(crtc->fb);
> +		drm_framebuffer_unreference(crtc->primary->fb);
>  		return ret;
>  	}
>  
> -	update_fb(crtc, crtc->fb);
> -	update_scanout(crtc, crtc->fb);
> +	update_fb(crtc, crtc->primary->fb);
> +	update_scanout(crtc, crtc->primary->fb);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
> index 7dc3d71..f200048 100644
> --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
> +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
> @@ -102,7 +102,7 @@ static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
>  
>  	/* grab reference to incoming scanout fb: */
>  	drm_framebuffer_reference(new_fb);
> -	mdp5_crtc->base.fb = new_fb;
> +	mdp5_crtc->base.primary->fb = new_fb;
>  	mdp5_crtc->fb = new_fb;
>  
>  	if (old_fb)
> @@ -289,14 +289,14 @@ static int mdp5_crtc_mode_set(struct drm_crtc *crtc,
>  			mode->type, mode->flags);
>  
>  	/* grab extra ref for update_scanout() */
> -	drm_framebuffer_reference(crtc->fb);
> +	drm_framebuffer_reference(crtc->primary->fb);
>  
> -	ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->fb,
> +	ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->primary->fb,
>  			0, 0, mode->hdisplay, mode->vdisplay,
>  			x << 16, y << 16,
>  			mode->hdisplay << 16, mode->vdisplay << 16);
>  	if (ret) {
> -		drm_framebuffer_unreference(crtc->fb);
> +		drm_framebuffer_unreference(crtc->primary->fb);
>  		dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
>  				mdp5_crtc->name, ret);
>  		return ret;
> @@ -306,8 +306,8 @@ static int mdp5_crtc_mode_set(struct drm_crtc *crtc,
>  			MDP5_LM_OUT_SIZE_WIDTH(mode->hdisplay) |
>  			MDP5_LM_OUT_SIZE_HEIGHT(mode->vdisplay));
>  
> -	update_fb(crtc, crtc->fb);
> -	update_scanout(crtc, crtc->fb);
> +	update_fb(crtc, crtc->primary->fb);
> +	update_scanout(crtc, crtc->primary->fb);
>  
>  	return 0;
>  }
> @@ -338,19 +338,19 @@ static int mdp5_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
>  	int ret;
>  
>  	/* grab extra ref for update_scanout() */
> -	drm_framebuffer_reference(crtc->fb);
> +	drm_framebuffer_reference(crtc->primary->fb);
>  
> -	ret = mdp5_plane_mode_set(plane, crtc, crtc->fb,
> +	ret = mdp5_plane_mode_set(plane, crtc, crtc->primary->fb,
>  			0, 0, mode->hdisplay, mode->vdisplay,
>  			x << 16, y << 16,
>  			mode->hdisplay << 16, mode->vdisplay << 16);
>  	if (ret) {
> -		drm_framebuffer_unreference(crtc->fb);
> +		drm_framebuffer_unreference(crtc->primary->fb);
>  		return ret;
>  	}
>  
> -	update_fb(crtc, crtc->fb);
> -	update_scanout(crtc, crtc->fb);
> +	update_fb(crtc, crtc->primary->fb);
> +	update_scanout(crtc, crtc->primary->fb);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
> index b55be84..2a5e9db 100644
> --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
> +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
> @@ -239,7 +239,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
>  	struct drm_device *dev = crtc->dev;
>  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
>  	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
> -	struct drm_framebuffer *fb = crtc->fb;
> +	struct drm_framebuffer *fb = crtc->primary->fb;
>  
>  	/* Calculate our timings */
>  	int horizDisplay	= (mode->crtc_hdisplay >> 3)		- 1;
> @@ -574,7 +574,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
>  		regp->CRTC[NV_CIO_CRE_86] = 0x1;
>  	}
>  
> -	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->fb->depth + 1) / 8;
> +	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->primary->fb->depth + 1) / 8;
>  	/* Enable slaved mode (called MODE_TV in nv4ref.h) */
>  	if (lvds_output || tmds_output || tv_output)
>  		regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7);
> @@ -588,7 +588,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
>  	regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS |
>  				NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL |
>  				NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON;
> -	if (crtc->fb->depth == 16)
> +	if (crtc->primary->fb->depth == 16)
>  		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
>  	if (nv_device(drm->device)->chipset >= 0x11)
>  		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG;
> @@ -609,7 +609,7 @@ static int
>  nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
>  {
>  	struct nv04_display *disp = nv04_display(crtc->dev);
> -	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
> +	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb);
>  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
>  	int ret;
>  
> @@ -808,7 +808,7 @@ nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
>  	 * mark the lut values as dirty by setting depth==0, and it'll be
>  	 * uploaded on the first mode_set_base()
>  	 */
> -	if (!nv_crtc->base.fb) {
> +	if (!nv_crtc->base.primary->fb) {
>  		nv_crtc->lut.depth = 0;
>  		return;
>  	}
> @@ -832,7 +832,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
>  	NV_DEBUG(drm, "index %d\n", nv_crtc->index);
>  
>  	/* no fb bound */
> -	if (!atomic && !crtc->fb) {
> +	if (!atomic && !crtc->primary->fb) {
>  		NV_DEBUG(drm, "No FB bound\n");
>  		return 0;
>  	}
> @@ -844,8 +844,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
>  		drm_fb = passed_fb;
>  		fb = nouveau_framebuffer(passed_fb);
>  	} else {
> -		drm_fb = crtc->fb;
> -		fb = nouveau_framebuffer(crtc->fb);
> +		drm_fb = crtc->primary->fb;
> +		fb = nouveau_framebuffer(crtc->primary->fb);
>  	}
>  
>  	nv_crtc->fb.offset = fb->nvbo->bo.offset;
> @@ -857,9 +857,9 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
>  
>  	/* Update the framebuffer format. */
>  	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] &= ~3;
> -	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->fb->depth + 1) / 8;
> +	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->primary->fb->depth + 1) / 8;
>  	regp->ramdac_gen_ctrl &= ~NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
> -	if (crtc->fb->depth == 16)
> +	if (crtc->primary->fb->depth == 16)
>  		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
>  	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_PIXEL_INDEX);
>  	NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL,
> diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
> index 7fdc51e..a2d669b 100644
> --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c
> +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
> @@ -415,7 +415,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder,
>  	/* Output property. */
>  	if ((nv_connector->dithering_mode == DITHERING_MODE_ON) ||
>  	    (nv_connector->dithering_mode == DITHERING_MODE_AUTO &&
> -	     encoder->crtc->fb->depth > connector->display_info.bpc * 3)) {
> +	     encoder->crtc->primary->fb->depth > connector->display_info.bpc * 3)) {
>  		if (nv_device(drm->device)->chipset == 0x11)
>  			regp->dither = savep->dither | 0x00010000;
>  		else {
> diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
> index 2401159..4e24c72 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_display.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_display.c
> @@ -569,7 +569,7 @@ nouveau_display_suspend(struct drm_device *dev)
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
>  		struct nouveau_framebuffer *nouveau_fb;
>  
> -		nouveau_fb = nouveau_framebuffer(crtc->fb);
> +		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
>  		if (!nouveau_fb || !nouveau_fb->nvbo)
>  			continue;
>  
> @@ -596,7 +596,7 @@ nouveau_display_repin(struct drm_device *dev)
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
>  		struct nouveau_framebuffer *nouveau_fb;
>  
> -		nouveau_fb = nouveau_framebuffer(crtc->fb);
> +		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
>  		if (!nouveau_fb || !nouveau_fb->nvbo)
>  			continue;
>  
> @@ -693,7 +693,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
>  	const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1;
>  	struct drm_device *dev = crtc->dev;
>  	struct nouveau_drm *drm = nouveau_drm(dev);
> -	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo;
> +	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo;
>  	struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
>  	struct nouveau_page_flip_state *s;
>  	struct nouveau_channel *chan = drm->channel;
> @@ -767,7 +767,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
>  		goto fail_unreserve;
>  
>  	/* Update the crtc struct and cleanup */
> -	crtc->fb = fb;
> +	crtc->primary->fb = fb;
>  
>  	nouveau_bo_fence(old_bo, fence);
>  	ttm_bo_unreserve(&old_bo->bo);
> diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
> index 5706842..c744bf6 100644
> --- a/drivers/gpu/drm/nouveau/nv50_display.c
> +++ b/drivers/gpu/drm/nouveau/nv50_display.c
> @@ -651,7 +651,7 @@ nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
>  	nv_connector = nouveau_crtc_connector_get(nv_crtc);
>  	connector = &nv_connector->base;
>  	if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) {
> -		if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3)
> +		if (nv_crtc->base.primary->fb->depth > connector->display_info.bpc * 3)
>  			mode = DITHERING_MODE_DYNAMIC2X2;
>  	} else {
>  		mode = nv_connector->dithering_mode;
> @@ -785,7 +785,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
>  
>  		if (update) {
>  			nv50_display_flip_stop(crtc);
> -			nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
> +			nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
>  		}
>  	}
>  
> @@ -1028,7 +1028,7 @@ nv50_crtc_commit(struct drm_crtc *crtc)
>  	}
>  
>  	nv50_crtc_cursor_show_hide(nv_crtc, nv_crtc->cursor.visible, true);
> -	nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
> +	nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
>  }
>  
>  static bool
> @@ -1042,7 +1042,8 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
>  static int
>  nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
>  {
> -	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
> +	struct nouveau_framebuffer *nvfb =
> +		nouveau_framebuffer(crtc->primary->fb);
>  	struct nv50_head *head = nv50_head(crtc);
>  	int ret;
>  
> @@ -1139,7 +1140,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
>  	nv50_crtc_set_dither(nv_crtc, false);
>  	nv50_crtc_set_scale(nv_crtc, false);
>  	nv50_crtc_set_color_vibrance(nv_crtc, false);
> -	nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, false);
> +	nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, false);
>  	return 0;
>  }
>  
> @@ -1151,7 +1152,7 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
>  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
>  	int ret;
>  
> -	if (!crtc->fb) {
> +	if (!crtc->primary->fb) {
>  		NV_DEBUG(drm, "No FB bound\n");
>  		return 0;
>  	}
> @@ -1161,8 +1162,8 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
>  		return ret;
>  
>  	nv50_display_flip_stop(crtc);
> -	nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, true);
> -	nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
> +	nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, true);
> +	nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
>  	return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
> index 24b6112..5be0b87 100644
> --- a/drivers/gpu/drm/qxl/qxl_display.c
> +++ b/drivers/gpu/drm/qxl/qxl_display.c
> @@ -527,7 +527,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
>  	bool recreate_primary = false;
>  	int ret;
>  	int surf_id;
> -	if (!crtc->fb) {
> +	if (!crtc->primary->fb) {
>  		DRM_DEBUG_KMS("No FB bound\n");
>  		return 0;
>  	}
> @@ -536,7 +536,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
>  		qfb = to_qxl_framebuffer(old_fb);
>  		old_bo = gem_to_qxl_bo(qfb->obj);
>  	}
> -	qfb = to_qxl_framebuffer(crtc->fb);
> +	qfb = to_qxl_framebuffer(crtc->primary->fb);
>  	bo = gem_to_qxl_bo(qfb->obj);
>  	if (!m)
>  		/* and do we care? */
> @@ -609,14 +609,15 @@ static void qxl_crtc_disable(struct drm_crtc *crtc)
>  	struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
>  	struct drm_device *dev = crtc->dev;
>  	struct qxl_device *qdev = dev->dev_private;
> -	if (crtc->fb) {
> -		struct qxl_framebuffer *qfb = to_qxl_framebuffer(crtc->fb);
> +	if (crtc->primary->fb) {
> +		struct qxl_framebuffer *qfb =
> +			to_qxl_framebuffer(crtc->primary->fb);
>  		struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
>  		int ret;
>  		ret = qxl_bo_reserve(bo, false);
>  		qxl_bo_unpin(bo);
>  		qxl_bo_unreserve(bo);
> -		crtc->fb = NULL;
> +		crtc->primary->fb = NULL;
>  	}
>  
>  	qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0);
> diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
> index daa4dd3..fb187c7 100644
> --- a/drivers/gpu/drm/radeon/atombios_crtc.c
> +++ b/drivers/gpu/drm/radeon/atombios_crtc.c
> @@ -1106,7 +1106,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
>  	int r;
>  
>  	/* no fb bound */
> -	if (!atomic && !crtc->fb) {
> +	if (!atomic && !crtc->primary->fb) {
>  		DRM_DEBUG_KMS("No FB bound\n");
>  		return 0;
>  	}
> @@ -1116,8 +1116,8 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
>  		target_fb = fb;
>  	}
>  	else {
> -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> -		target_fb = crtc->fb;
> +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> +		target_fb = crtc->primary->fb;
>  	}
>  
>  	/* If atomic, assume fb object is pinned & idle & fenced and
> @@ -1316,7 +1316,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
>  	/* set pageflip to happen anywhere in vblank interval */
>  	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
>  
> -	if (!atomic && fb && fb != crtc->fb) {
> +	if (!atomic && fb && fb != crtc->primary->fb) {
>  		radeon_fb = to_radeon_framebuffer(fb);
>  		rbo = gem_to_radeon_bo(radeon_fb->obj);
>  		r = radeon_bo_reserve(rbo, false);
> @@ -1350,7 +1350,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
>  	int r;
>  
>  	/* no fb bound */
> -	if (!atomic && !crtc->fb) {
> +	if (!atomic && !crtc->primary->fb) {
>  		DRM_DEBUG_KMS("No FB bound\n");
>  		return 0;
>  	}
> @@ -1360,8 +1360,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
>  		target_fb = fb;
>  	}
>  	else {
> -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> -		target_fb = crtc->fb;
> +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> +		target_fb = crtc->primary->fb;
>  	}
>  
>  	obj = radeon_fb->obj;
> @@ -1485,7 +1485,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
>  	/* set pageflip to happen anywhere in vblank interval */
>  	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
>  
> -	if (!atomic && fb && fb != crtc->fb) {
> +	if (!atomic && fb && fb != crtc->primary->fb) {
>  		radeon_fb = to_radeon_framebuffer(fb);
>  		rbo = gem_to_radeon_bo(radeon_fb->obj);
>  		r = radeon_bo_reserve(rbo, false);
> @@ -1972,12 +1972,12 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
>  	int i;
>  
>  	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
> -	if (crtc->fb) {
> +	if (crtc->primary->fb) {
>  		int r;
>  		struct radeon_framebuffer *radeon_fb;
>  		struct radeon_bo *rbo;
>  
> -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
>  		rbo = gem_to_radeon_bo(radeon_fb->obj);
>  		r = radeon_bo_reserve(rbo, false);
>  		if (unlikely(r))
> diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
> index 030f8e4..b6c3264 100644
> --- a/drivers/gpu/drm/radeon/r100.c
> +++ b/drivers/gpu/drm/radeon/r100.c
> @@ -3220,12 +3220,12 @@ void r100_bandwidth_update(struct radeon_device *rdev)
>  
>  	if (rdev->mode_info.crtcs[0]->base.enabled) {
>  		mode1 = &rdev->mode_info.crtcs[0]->base.mode;
> -		pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8;
> +		pixel_bytes1 = rdev->mode_info.crtcs[0]->base.primary->fb->bits_per_pixel / 8;
>  	}
>  	if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
>  		if (rdev->mode_info.crtcs[1]->base.enabled) {
>  			mode2 = &rdev->mode_info.crtcs[1]->base.mode;
> -			pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8;
> +			pixel_bytes2 = rdev->mode_info.crtcs[1]->base.primary->fb->bits_per_pixel / 8;
>  		}
>  	}
>  
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index 82d4f86..33b482b 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -89,7 +89,7 @@ static void radeon_property_change_mode(struct drm_encoder *encoder)
>  
>  	if (crtc && crtc->enabled) {
>  		drm_crtc_helper_set_mode(crtc, &crtc->mode,
> -					 crtc->x, crtc->y, crtc->fb);
> +					 crtc->x, crtc->y, crtc->primary->fb);
>  	}
>  }
>  
> diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
> index 2e72dcd..c524aba 100644
> --- a/drivers/gpu/drm/radeon/radeon_device.c
> +++ b/drivers/gpu/drm/radeon/radeon_device.c
> @@ -1424,7 +1424,8 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
>  
>  	/* unpin the front buffers */
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> -		struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
> +		struct radeon_framebuffer *rfb =
> +			to_radeon_framebuffer(crtc->primary->fb);
>  		struct radeon_bo *robj;
>  
>  		if (rfb == NULL || rfb->obj == NULL) {
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index a29d217..4e90049 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -369,7 +369,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
>  	work->event = event;
>  	work->rdev = rdev;
>  	work->crtc_id = radeon_crtc->crtc_id;
> -	old_radeon_fb = to_radeon_framebuffer(crtc->fb);
> +	old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
>  	new_radeon_fb = to_radeon_framebuffer(fb);
>  	/* schedule unpin of the old buffer */
>  	obj = old_radeon_fb->obj;
> @@ -460,7 +460,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
>  	spin_unlock_irqrestore(&dev->event_lock, flags);
>  
>  	/* update crtc fb */
> -	crtc->fb = fb;
> +	crtc->primary->fb = fb;
>  
>  	r = drm_vblank_get(dev, radeon_crtc->crtc_id);
>  	if (r) {
> diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
> index 0b158f9..cafb1cc 100644
> --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
> +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
> @@ -385,7 +385,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
>  
>  	DRM_DEBUG_KMS("\n");
>  	/* no fb bound */
> -	if (!atomic && !crtc->fb) {
> +	if (!atomic && !crtc->primary->fb) {
>  		DRM_DEBUG_KMS("No FB bound\n");
>  		return 0;
>  	}
> @@ -395,8 +395,8 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
>  		target_fb = fb;
>  	}
>  	else {
> -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> -		target_fb = crtc->fb;
> +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> +		target_fb = crtc->primary->fb;
>  	}
>  
>  	switch (target_fb->bits_per_pixel) {
> @@ -444,7 +444,7 @@ retry:
>  		 * We don't shutdown the display controller because new buffer
>  		 * will end up in same spot.
>  		 */
> -		if (!atomic && fb && fb != crtc->fb) {
> +		if (!atomic && fb && fb != crtc->primary->fb) {
>  			struct radeon_bo *old_rbo;
>  			unsigned long nsize, osize;
>  
> @@ -555,7 +555,7 @@ retry:
>  	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset);
>  	WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
>  
> -	if (!atomic && fb && fb != crtc->fb) {
> +	if (!atomic && fb && fb != crtc->primary->fb) {
>  		radeon_fb = to_radeon_framebuffer(fb);
>  		rbo = gem_to_radeon_bo(radeon_fb->obj);
>  		r = radeon_bo_reserve(rbo, false);
> @@ -599,7 +599,7 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
>  		}
>  	}
>  
> -	switch (crtc->fb->bits_per_pixel) {
> +	switch (crtc->primary->fb->bits_per_pixel) {
>  	case 8:
>  		format = 2;
>  		break;
> @@ -1087,12 +1087,12 @@ static void radeon_crtc_commit(struct drm_crtc *crtc)
>  static void radeon_crtc_disable(struct drm_crtc *crtc)
>  {
>  	radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
> -	if (crtc->fb) {
> +	if (crtc->primary->fb) {
>  		int r;
>  		struct radeon_framebuffer *radeon_fb;
>  		struct radeon_bo *rbo;
>  
> -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
>  		rbo = gem_to_radeon_bo(radeon_fb->obj);
>  		r = radeon_bo_reserve(rbo, false);
>  		if (unlikely(r))
> diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
> index 1255944..c63b5e7 100644
> --- a/drivers/gpu/drm/udl/udl_modeset.c
> +++ b/drivers/gpu/drm/udl/udl_modeset.c
> @@ -310,7 +310,7 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc,
>  
>  {
>  	struct drm_device *dev = crtc->dev;
> -	struct udl_framebuffer *ufb = to_udl_fb(crtc->fb);
> +	struct udl_framebuffer *ufb = to_udl_fb(crtc->primary->fb);
>  	struct udl_device *udl = dev->dev_private;
>  	char *buf;
>  	char *wrptr;
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index 8a65041..1d59ed3 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -468,7 +468,7 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv,
>  	num_units = 0;
>  	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list,
>  			    head) {
> -		if (crtc->fb != &framebuffer->base)
> +		if (crtc->primary->fb != &framebuffer->base)
>  			continue;
>  		units[num_units++] = vmw_crtc_to_du(crtc);
>  	}
> @@ -883,7 +883,7 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
>  
>  	num_units = 0;
>  	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
> -		if (crtc->fb != &framebuffer->base)
> +		if (crtc->primary->fb != &framebuffer->base)
>  			continue;
>  		units[num_units++] = vmw_crtc_to_du(crtc);
>  	}
> @@ -1245,7 +1245,7 @@ int vmw_kms_present(struct vmw_private *dev_priv,
>  
>  	num_units = 0;
>  	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
> -		if (crtc->fb != &vfb->base)
> +		if (crtc->primary->fb != &vfb->base)
>  			continue;
>  		units[num_units++] = vmw_crtc_to_du(crtc);
>  	}
> @@ -1382,7 +1382,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
>  
>  	num_units = 0;
>  	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
> -		if (crtc->fb != &vfb->base)
> +		if (crtc->primary->fb != &vfb->base)
>  			continue;
>  		units[num_units++] = vmw_crtc_to_du(crtc);
>  	}
> @@ -1725,7 +1725,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
>  		     uint32_t page_flip_flags)
>  {
>  	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> -	struct drm_framebuffer *old_fb = crtc->fb;
> +	struct drm_framebuffer *old_fb = crtc->primary->fb;
>  	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
>  	struct drm_file *file_priv ;
>  	struct vmw_fence_obj *fence = NULL;
> @@ -1743,7 +1743,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
>  	if (!vmw_kms_screen_object_flippable(dev_priv, crtc))
>  		return -EINVAL;
>  
> -	crtc->fb = fb;
> +	crtc->primary->fb = fb;
>  
>  	/* do a full screen dirty update */
>  	clips.x1 = clips.y1 = 0;
> @@ -1783,7 +1783,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
>  	return ret;
>  
>  out_no_fence:
> -	crtc->fb = old_fb;
> +	crtc->primary->fb = old_fb;
>  	return ret;
>  }
>  
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> index 001ec81..08fdd7f 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> @@ -93,7 +93,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
>  
>  		if (crtc == NULL)
>  			return 0;
> -		fb = entry->base.crtc.fb;
> +		fb = entry->base.crtc.primary->fb;
>  
>  		return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0],
>  					  fb->bits_per_pixel, fb->depth);
> @@ -101,7 +101,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
>  
>  	if (!list_empty(&lds->active)) {
>  		entry = list_entry(lds->active.next, typeof(*entry), active);
> -		fb = entry->base.crtc.fb;
> +		fb = entry->base.crtc.primary->fb;
>  
>  		vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0],
>  				   fb->bits_per_pixel, fb->depth);
> @@ -259,7 +259,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
>  
>  		connector->encoder = NULL;
>  		encoder->crtc = NULL;
> -		crtc->fb = NULL;
> +		crtc->primary->fb = NULL;
>  		crtc->enabled = false;
>  
>  		vmw_ldu_del_active(dev_priv, ldu);
> @@ -280,7 +280,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
>  
>  	vmw_fb_off(dev_priv);
>  
> -	crtc->fb = fb;
> +	crtc->primary->fb = fb;
>  	encoder->crtc = crtc;
>  	connector->encoder = encoder;
>  	crtc->x = set->x;
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> index 585da43..46ea096 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> @@ -307,7 +307,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
>  
>  		connector->encoder = NULL;
>  		encoder->crtc = NULL;
> -		crtc->fb = NULL;
> +		crtc->primary->fb = NULL;
>  		crtc->x = 0;
>  		crtc->y = 0;
>  		crtc->enabled = false;
> @@ -368,7 +368,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
>  
>  		connector->encoder = NULL;
>  		encoder->crtc = NULL;
> -		crtc->fb = NULL;
> +		crtc->primary->fb = NULL;
>  		crtc->x = 0;
>  		crtc->y = 0;
>  		crtc->enabled = false;
> @@ -381,7 +381,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
>  	connector->encoder = encoder;
>  	encoder->crtc = crtc;
>  	crtc->mode = *mode;
> -	crtc->fb = fb;
> +	crtc->primary->fb = fb;
>  	crtc->x = set->x;
>  	crtc->y = set->y;
>  	crtc->enabled = true;
> @@ -574,5 +574,5 @@ void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv,
>  	BUG_ON(!sou->base.is_implicit);
>  
>  	dev_priv->sou_priv->implicit_fb =
> -		vmw_framebuffer_to_vfb(sou->base.crtc.fb);
> +		vmw_framebuffer_to_vfb(sou->base.crtc.primary->fb);
>  }
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 4dc84f8..9f7824d 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -309,9 +309,6 @@ struct drm_crtc {
>  	/* primary plane for CRTC */
>  	struct drm_plane *primary;
>  
> -	/* framebuffer the connector is currently bound to */
> -	struct drm_framebuffer *fb;
> -
>  	/* 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;
> -- 
> 1.8.5.1
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
Matt Roper March 25, 2014, 1:20 a.m. UTC | #2
On Wed, Mar 19, 2014 at 12:57:21PM +0100, Daniel Vetter wrote:
> On Tue, Mar 18, 2014 at 05:22:53PM -0700, Matt Roper wrote:
> > Now that CRTC's have a primary plane, there's no need to track the
> > framebuffer in the CRTC.  Replace all references to the CRTC fb
> > with the primary plane's fb.
> > 
> > Also note that this simplifies framebuffer removal slightly; we no
> > longer need to scan all CRTC's and disable the ones that were using the
> > framebuffer since the existing loop over all planes will take care
> > of disabling the primary plane (and on most hardware, the CRTC by
> > extension).
> > 
> > v2: Fixup several lingering crtc->fb instances that were missed in the
> >     first patch iteration.
> > 
> > Tested-by: Rob Clark <robdclark@gmail.com>
> > Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> 
> Giant patch again, and I don't think there's any sane way we can avoid
> this big sed job. Put I think we can make it less intrusive.
> 
> First: Have you looked into cocinelle to do this? I'm not sure whether
> cocinelle is sufficiently type aware, but the upside of using it is that
> it's much easier to regenerate the patch.

Good idea!  Yeah, I think Coccinelle should do this pretty easily with
just:

        @@ struct drm_crtc *crtc; @@
        -   crtc->fb
        +   crtc->primary->fb

        @@ struct drm_crtc crtc; @@
        -   crtc.fb
        +   crtc.primary->fb

> In any case I think we need to split this into the usual 3 phases to avoid
> flag days:
> 
> 1) Switch to crtc->primary->fb all over the core, but keep crtc->fb fully
> functional. I.e. update it before calling into drivers and use that to
> update crtc->primary->fb on return (e.g. in the pageflip ioctl).

I'm starting to worry that this may be more tricky than it sounded when
I first read your email.  To be safe, it seems like we'll need to
sandwich all the various ->funcs-> driver calls in the core between
prepare_crtc_fbs() / finish_crtc_fbs() or similar since it's hard to
predict in a universal way when a driver might decide to go look at a
crtc's framebuffer (or even which crtcs it will decide to look at).
However even if we do that wrapping, there may be cases where the driver
calls back into a core helper function after modifying crtc->fb and the
core won't have that updated value unless we throw in extra sync-up
points.  

Is this pretty much what you had in mind or am I overlooking a much
simpler way to accomplish this?


Matt

> 
> 2) Switch drivers over to look at crtc->primary->fb. This way we can even
> split up the patch into per-driver patches which gives driver maintainers
> more wiggle room.
> 
> 3) Kill crtc->fb.
> 
> Steps 2&3 don't block merging of the universal planes support at all. So
> we could get the core support in all early for 3.16, then let driver
> maintainers pick up patche for 2 and shortly before the 3.16 merge window
> opens send a pull request with all the stragglers and step 3.
> 
> No comments on the actual patch, the few functional changes hidden in the
> massive diff looked ok. But hard to review properly ;-)
> 
> Cheers, Daniel
> 
> > ---
> >  drivers/gpu/drm/ast/ast_mode.c               |  12 +--
> >  drivers/gpu/drm/bochs/bochs_kms.c            |   4 +-
> >  drivers/gpu/drm/cirrus/cirrus_mode.c         |  10 +-
> >  drivers/gpu/drm/drm_crtc.c                   |  56 ++++------
> >  drivers/gpu/drm/drm_crtc_helper.c            |  21 ++--
> >  drivers/gpu/drm/drm_fb_helper.c              |   6 +-
> >  drivers/gpu/drm/gma500/cdv_intel_display.c   |   2 +-
> >  drivers/gpu/drm/gma500/cdv_intel_dp.c        |   2 +-
> >  drivers/gpu/drm/gma500/cdv_intel_hdmi.c      |   3 +-
> >  drivers/gpu/drm/gma500/cdv_intel_lvds.c      |   2 +-
> >  drivers/gpu/drm/gma500/gma_display.c         |  17 ++--
> >  drivers/gpu/drm/gma500/mdfld_dsi_output.c    |   2 +-
> >  drivers/gpu/drm/gma500/mdfld_intel_display.c |  17 ++--
> >  drivers/gpu/drm/gma500/oaktrail_crtc.c       |  13 +--
> >  drivers/gpu/drm/gma500/psb_intel_display.c   |   2 +-
> >  drivers/gpu/drm/gma500/psb_intel_lvds.c      |   2 +-
> >  drivers/gpu/drm/gma500/psb_intel_sdvo.c      |   2 +-
> >  drivers/gpu/drm/i915/i915_debugfs.c          |   4 +-
> >  drivers/gpu/drm/i915/i915_irq.c              |   4 +-
> >  drivers/gpu/drm/i915/intel_display.c         | 147 ++++++++++++++-------------
> >  drivers/gpu/drm/i915/intel_dp.c              |   5 +-
> >  drivers/gpu/drm/i915/intel_fbdev.c           |   6 +-
> >  drivers/gpu/drm/i915/intel_overlay.c         |   4 +-
> >  drivers/gpu/drm/i915/intel_pm.c              |  36 +++----
> >  drivers/gpu/drm/mgag200/mgag200_mode.c       |  28 ++---
> >  drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c     |  28 ++---
> >  drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c     |  22 ++--
> >  drivers/gpu/drm/nouveau/dispnv04/crtc.c      |  20 ++--
> >  drivers/gpu/drm/nouveau/dispnv04/dfp.c       |   2 +-
> >  drivers/gpu/drm/nouveau/nouveau_display.c    |   8 +-
> >  drivers/gpu/drm/nouveau/nv50_display.c       |  17 ++--
> >  drivers/gpu/drm/qxl/qxl_display.c            |  11 +-
> >  drivers/gpu/drm/radeon/atombios_crtc.c       |  20 ++--
> >  drivers/gpu/drm/radeon/r100.c                |   4 +-
> >  drivers/gpu/drm/radeon/radeon_connectors.c   |   2 +-
> >  drivers/gpu/drm/radeon/radeon_device.c       |   3 +-
> >  drivers/gpu/drm/radeon/radeon_display.c      |   4 +-
> >  drivers/gpu/drm/radeon/radeon_legacy_crtc.c  |  16 +--
> >  drivers/gpu/drm/udl/udl_modeset.c            |   2 +-
> >  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c          |  14 +--
> >  drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c          |   8 +-
> >  drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c         |   8 +-
> >  include/drm/drm_crtc.h                       |   3 -
> >  43 files changed, 300 insertions(+), 299 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
> > index 44f0d32..bd1e156 100644
> > --- a/drivers/gpu/drm/ast/ast_mode.c
> > +++ b/drivers/gpu/drm/ast/ast_mode.c
> > @@ -81,7 +81,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
> >  	u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate;
> >  	u32 hborder, vborder;
> >  
> > -	switch (crtc->fb->bits_per_pixel) {
> > +	switch (crtc->primary->fb->bits_per_pixel) {
> >  	case 8:
> >  		vbios_mode->std_table = &vbios_stdtable[VGAModeIndex];
> >  		color_index = VGAModeIndex - 1;
> > @@ -176,7 +176,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
> >  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff);
> >  
> >  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
> > -		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->fb->bits_per_pixel);
> > +		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->primary->fb->bits_per_pixel);
> >  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000);
> >  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay);
> >  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8);
> > @@ -340,7 +340,7 @@ static void ast_set_offset_reg(struct drm_crtc *crtc)
> >  
> >  	u16 offset;
> >  
> > -	offset = crtc->fb->pitches[0] >> 3;
> > +	offset = crtc->primary->fb->pitches[0] >> 3;
> >  	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff));
> >  	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f);
> >  }
> > @@ -365,7 +365,7 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode
> >  	struct ast_private *ast = crtc->dev->dev_private;
> >  	u8 jregA0 = 0, jregA3 = 0, jregA8 = 0;
> >  
> > -	switch (crtc->fb->bits_per_pixel) {
> > +	switch (crtc->primary->fb->bits_per_pixel) {
> >  	case 8:
> >  		jregA0 = 0x70;
> >  		jregA3 = 0x01;
> > @@ -418,7 +418,7 @@ static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mo
> >  static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
> >  		     struct ast_vbios_mode_info *vbios_mode)
> >  {
> > -	switch (crtc->fb->bits_per_pixel) {
> > +	switch (crtc->primary->fb->bits_per_pixel) {
> >  	case 8:
> >  		break;
> >  	default:
> > @@ -490,7 +490,7 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc,
> >  		ast_bo_unreserve(bo);
> >  	}
> >  
> > -	ast_fb = to_ast_framebuffer(crtc->fb);
> > +	ast_fb = to_ast_framebuffer(crtc->primary->fb);
> >  	obj = ast_fb->obj;
> >  	bo = gem_to_ast_bo(obj);
> >  
> > diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
> > index 182f5c9..b67ad12 100644
> > --- a/drivers/gpu/drm/bochs/bochs_kms.c
> > +++ b/drivers/gpu/drm/bochs/bochs_kms.c
> > @@ -62,10 +62,10 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> >  		}
> >  	}
> >  
> > -	if (WARN_ON(crtc->fb == NULL))
> > +	if (WARN_ON(crtc->primary->fb == NULL))
> >  		return -EINVAL;
> >  
> > -	bochs_fb = to_bochs_framebuffer(crtc->fb);
> > +	bochs_fb = to_bochs_framebuffer(crtc->primary->fb);
> >  	bo = gem_to_bochs_bo(bochs_fb->obj);
> >  	ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
> >  	if (ret)
> > diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
> > index 449246f..5291d2f 100644
> > --- a/drivers/gpu/drm/cirrus/cirrus_mode.c
> > +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
> > @@ -149,7 +149,7 @@ static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
> >  		cirrus_bo_unreserve(bo);
> >  	}
> >  
> > -	cirrus_fb = to_cirrus_framebuffer(crtc->fb);
> > +	cirrus_fb = to_cirrus_framebuffer(crtc->primary->fb);
> >  	obj = cirrus_fb->obj;
> >  	bo = gem_to_cirrus_bo(obj);
> >  
> > @@ -268,7 +268,7 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
> >  	sr07 = RREG8(SEQ_DATA);
> >  	sr07 &= 0xe0;
> >  	hdr = 0;
> > -	switch (crtc->fb->bits_per_pixel) {
> > +	switch (crtc->primary->fb->bits_per_pixel) {
> >  	case 8:
> >  		sr07 |= 0x11;
> >  		break;
> > @@ -291,13 +291,13 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
> >  	WREG_SEQ(0x7, sr07);
> >  
> >  	/* Program the pitch */
> > -	tmp = crtc->fb->pitches[0] / 8;
> > +	tmp = crtc->primary->fb->pitches[0] / 8;
> >  	WREG_CRT(VGA_CRTC_OFFSET, tmp);
> >  
> >  	/* Enable extended blanking and pitch bits, and enable full memory */
> >  	tmp = 0x22;
> > -	tmp |= (crtc->fb->pitches[0] >> 7) & 0x10;
> > -	tmp |= (crtc->fb->pitches[0] >> 6) & 0x40;
> > +	tmp |= (crtc->primary->fb->pitches[0] >> 7) & 0x10;
> > +	tmp |= (crtc->primary->fb->pitches[0] >> 6) & 0x40;
> >  	WREG_CRT(0x1b, tmp);
> >  
> >  	/* Enable high-colour modes */
> > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> > index 0feb66cc..0c395e8 100644
> > --- a/drivers/gpu/drm/drm_crtc.c
> > +++ b/drivers/gpu/drm/drm_crtc.c
> > @@ -634,7 +634,7 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
> >   * drm_framebuffer_remove - remove and unreference a framebuffer object
> >   * @fb: framebuffer to remove
> >   *
> > - * Scans all the CRTCs and planes in @dev's mode_config.  If they're
> > + * Scans all the planes in @dev's mode_config.  If they're
> >   * using @fb, removes it, setting it to NULL. Then drops the reference to the
> >   * passed-in framebuffer. Might take the modeset locks.
> >   *
> > @@ -645,10 +645,7 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
> >  void drm_framebuffer_remove(struct drm_framebuffer *fb)
> >  {
> >  	struct drm_device *dev = fb->dev;
> > -	struct drm_crtc *crtc;
> >  	struct drm_plane *plane;
> > -	struct drm_mode_set set;
> > -	int ret;
> >  
> >  	WARN_ON(!list_empty(&fb->filp_head));
> >  
> > @@ -669,19 +666,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
> >  	 */
> >  	if (atomic_read(&fb->refcount.refcount) > 1) {
> >  		drm_modeset_lock_all(dev);
> > -		/* remove from any CRTC */
> > -		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > -			if (crtc->fb == fb) {
> > -				/* should turn off the crtc */
> > -				memset(&set, 0, sizeof(struct drm_mode_set));
> > -				set.crtc = crtc;
> > -				set.fb = NULL;
> > -				ret = drm_mode_set_config_internal(&set);
> > -				if (ret)
> > -					DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
> > -			}
> > -		}
> > -
> > +		/* remove from any plane */
> >  		list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
> >  			if (plane->fb == fb)
> >  				drm_plane_force_disable(plane);
> > @@ -1930,8 +1915,8 @@ int drm_mode_getcrtc(struct drm_device *dev,
> >  	crtc_resp->x = crtc->x;
> >  	crtc_resp->y = crtc->y;
> >  	crtc_resp->gamma_size = crtc->gamma_size;
> > -	if (crtc->fb)
> > -		crtc_resp->fb_id = crtc->fb->base.id;
> > +	if (crtc->primary->fb)
> > +		crtc_resp->fb_id = crtc->primary->fb->base.id;
> >  	else
> >  		crtc_resp->fb_id = 0;
> >  
> > @@ -2438,7 +2423,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
> >  	 * crtcs. Atomic modeset will have saner semantics ...
> >  	 */
> >  	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
> > -		tmp->old_fb = tmp->fb;
> > +		tmp->old_fb = tmp->primary->fb;
> >  
> >  	fb = set->fb;
> >  
> > @@ -2446,13 +2431,16 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
> >  	if (ret == 0) {
> >  		crtc->primary->crtc = crtc;
> >  
> > -		/* crtc->fb must be updated by ->set_config, enforces this. */
> > -		WARN_ON(fb != crtc->fb);
> > +		/*
> > +		 * crtc->primary->fb must be updated by ->set_config,
> > +		 * enforces this.
> > +		 */
> > +		WARN_ON(fb != crtc->primary->fb);
> >  	}
> >  
> >  	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
> > -		if (tmp->fb)
> > -			drm_framebuffer_reference(tmp->fb);
> > +		if (tmp->primary->fb)
> > +			drm_framebuffer_reference(tmp->primary->fb);
> >  		if (tmp->old_fb)
> >  			drm_framebuffer_unreference(tmp->old_fb);
> >  	}
> > @@ -2511,12 +2499,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
> >  		/* If we have a mode we need a framebuffer. */
> >  		/* If we pass -1, set the mode with the currently bound fb */
> >  		if (crtc_req->fb_id == -1) {
> > -			if (!crtc->fb) {
> > +			if (!crtc->primary->fb) {
> >  				DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
> >  				ret = -EINVAL;
> >  				goto out;
> >  			}
> > -			fb = crtc->fb;
> > +			fb = crtc->primary->fb;
> >  			/* Make refcounting symmetric with the lookup path. */
> >  			drm_framebuffer_reference(fb);
> >  		} else {
> > @@ -4309,7 +4297,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
> >  	crtc = obj_to_crtc(obj);
> >  
> >  	mutex_lock(&crtc->mutex);
> > -	if (crtc->fb == NULL) {
> > +	if (crtc->primary->fb == NULL) {
> >  		/* The framebuffer is currently unbound, presumably
> >  		 * due to a hotplug event, that userspace has not
> >  		 * yet discovered.
> > @@ -4331,7 +4319,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
> >  	if (ret)
> >  		goto out;
> >  
> > -	if (crtc->fb->pixel_format != fb->pixel_format) {
> > +	if (crtc->primary->fb->pixel_format != fb->pixel_format) {
> >  		DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
> >  		ret = -EINVAL;
> >  		goto out;
> > @@ -4364,7 +4352,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
> >  			(void (*) (struct drm_pending_event *)) kfree;
> >  	}
> >  
> > -	old_fb = crtc->fb;
> > +	old_fb = crtc->primary->fb;
> >  	ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
> >  	if (ret) {
> >  		if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
> > @@ -4377,12 +4365,12 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
> >  		old_fb = NULL;
> >  	} else {
> >  		/*
> > -		 * Warn if the driver hasn't properly updated the crtc->fb
> > -		 * field to reflect that the new framebuffer is now used.
> > -		 * Failing to do so will screw with the reference counting
> > -		 * on framebuffers.
> > +		 * Warn if the driver hasn't properly updated the
> > +		 * crtc->primary->fb field to reflect that the new framebuffer
> > +		 * is now used.  Failing to do so will screw with the reference
> > +		 * counting on framebuffers.
> >  		 */
> > -		WARN_ON(crtc->fb != fb);
> > +		WARN_ON(crtc->primary->fb != fb);
> >  		/* Unref only the old framebuffer. */
> >  		fb = NULL;
> >  	}
> > diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> > index a855178..8825afb 100644
> > --- a/drivers/gpu/drm/drm_crtc_helper.c
> > +++ b/drivers/gpu/drm/drm_crtc_helper.c
> > @@ -319,7 +319,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
> >  				(*crtc_funcs->disable)(crtc);
> >  			else
> >  				(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
> > -			crtc->fb = NULL;
> > +			crtc->primary->fb = NULL;
> >  		}
> >  	}
> >  }
> > @@ -646,19 +646,19 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
> >  	save_set.mode = &set->crtc->mode;
> >  	save_set.x = set->crtc->x;
> >  	save_set.y = set->crtc->y;
> > -	save_set.fb = set->crtc->fb;
> > +	save_set.fb = set->crtc->primary->fb;
> >  
> >  	/* We should be able to check here if the fb has the same properties
> >  	 * and then just flip_or_move it */
> > -	if (set->crtc->fb != set->fb) {
> > +	if (set->crtc->primary->fb != set->fb) {
> >  		/* If we have no fb then treat it as a full mode set */
> > -		if (set->crtc->fb == NULL) {
> > +		if (set->crtc->primary->fb == NULL) {
> >  			DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
> >  			mode_changed = true;
> >  		} else if (set->fb == NULL) {
> >  			mode_changed = true;
> >  		} else if (set->fb->pixel_format !=
> > -			   set->crtc->fb->pixel_format) {
> > +			   set->crtc->primary->fb->pixel_format) {
> >  			mode_changed = true;
> >  		} else
> >  			fb_changed = true;
> > @@ -759,13 +759,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
> >  			DRM_DEBUG_KMS("attempting to set mode from"
> >  					" userspace\n");
> >  			drm_mode_debug_printmodeline(set->mode);
> > -			set->crtc->fb = set->fb;
> > +			set->crtc->primary->fb = set->fb;
> >  			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
> >  						      set->x, set->y,
> >  						      save_set.fb)) {
> >  				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
> >  					  set->crtc->base.id);
> > -				set->crtc->fb = save_set.fb;
> > +				set->crtc->primary->fb = save_set.fb;
> >  				ret = -EINVAL;
> >  				goto fail;
> >  			}
> > @@ -780,13 +780,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
> >  	} else if (fb_changed) {
> >  		set->crtc->x = set->x;
> >  		set->crtc->y = set->y;
> > -		set->crtc->fb = set->fb;
> > +		set->crtc->primary->fb = set->fb;
> >  		ret = crtc_funcs->mode_set_base(set->crtc,
> >  						set->x, set->y, save_set.fb);
> >  		if (ret != 0) {
> >  			set->crtc->x = save_set.x;
> >  			set->crtc->y = save_set.y;
> > -			set->crtc->fb = save_set.fb;
> > +			set->crtc->primary->fb = save_set.fb;
> >  			goto fail;
> >  		}
> >  	}
> > @@ -982,7 +982,8 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
> >  			continue;
> >  
> >  		ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
> > -					       crtc->x, crtc->y, crtc->fb);
> > +					       crtc->x, crtc->y,
> > +					       crtc->primary->fb);
> >  
> >  		/* Restoring the old config should never fail! */
> >  		if (ret == false)
> > diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> > index 9c6251f..e8e2b41 100644
> > --- a/drivers/gpu/drm/drm_fb_helper.c
> > +++ b/drivers/gpu/drm/drm_fb_helper.c
> > @@ -232,7 +232,7 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
> >  
> >  	list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
> >  		if (crtc->base.id == c->base.id)
> > -			return c->fb;
> > +			return c->primary->fb;
> >  	}
> >  
> >  	return NULL;
> > @@ -366,9 +366,9 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
> >  		return false;
> >  
> >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > -		if (crtc->fb)
> > +		if (crtc->primary->fb)
> >  			crtcs_bound++;
> > -		if (crtc->fb == fb_helper->fb)
> > +		if (crtc->primary->fb == fb_helper->fb)
> >  			bound++;
> >  	}
> >  
> > diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c
> > index 8fbfa06..1cddcf8 100644
> > --- a/drivers/gpu/drm/gma500/cdv_intel_display.c
> > +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c
> > @@ -463,7 +463,7 @@ static bool cdv_intel_pipe_enabled(struct drm_device *dev, int pipe)
> >  	crtc = dev_priv->pipe_to_crtc_mapping[pipe];
> >  	gma_crtc = to_gma_crtc(crtc);
> >  
> > -	if (crtc->fb == NULL || !gma_crtc->active)
> > +	if (crtc->primary->fb == NULL || !gma_crtc->active)
> >  		return false;
> >  	return true;
> >  }
> > diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
> > index 0490ce3..9ff30c2 100644
> > --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
> > +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
> > @@ -1693,7 +1693,7 @@ done:
> >  		struct drm_crtc *crtc = encoder->base.crtc;
> >  		drm_crtc_helper_set_mode(crtc, &crtc->mode,
> >  					 crtc->x, crtc->y,
> > -					 crtc->fb);
> > +					 crtc->primary->fb);
> >  	}
> >  
> >  	return 0;
> > diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
> > index 1c0d723..04956e6 100644
> > --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
> > +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
> > @@ -199,7 +199,8 @@ static int cdv_hdmi_set_property(struct drm_connector *connector,
> >  		    crtc->saved_mode.vdisplay != 0) {
> >  			if (centre) {
> >  				if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode,
> > -					    encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
> > +					    encoder->crtc->x, encoder->crtc->y,
> > +					    encoder->crtc->primary->fb))
> >  					return -1;
> >  			} else {
> >  				struct drm_encoder_helper_funcs *helpers
> > diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
> > index 20e08e6..58f11df 100644
> > --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
> > +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
> > @@ -494,7 +494,7 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector,
> >  						      &crtc->saved_mode,
> >  						      encoder->crtc->x,
> >  						      encoder->crtc->y,
> > -						      encoder->crtc->fb))
> > +						      encoder->crtc->primary->fb))
> >  				return -1;
> >  		}
> >  	} else if (!strcmp(property->name, "backlight") && encoder) {
> > diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
> > index 386de2c..7b73dd1 100644
> > --- a/drivers/gpu/drm/gma500/gma_display.c
> > +++ b/drivers/gpu/drm/gma500/gma_display.c
> > @@ -59,7 +59,7 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> >  	struct drm_device *dev = crtc->dev;
> >  	struct drm_psb_private *dev_priv = dev->dev_private;
> >  	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
> > -	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
> > +	struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
> >  	int pipe = gma_crtc->pipe;
> >  	const struct psb_offset *map = &dev_priv->regmap[pipe];
> >  	unsigned long start, offset;
> > @@ -70,7 +70,7 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> >  		return 0;
> >  
> >  	/* no fb bound */
> > -	if (!crtc->fb) {
> > +	if (!crtc->primary->fb) {
> >  		dev_err(dev->dev, "No FB bound\n");
> >  		goto gma_pipe_cleaner;
> >  	}
> > @@ -81,19 +81,20 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> >  	if (ret < 0)
> >  		goto gma_pipe_set_base_exit;
> >  	start = psbfb->gtt->offset;
> > -	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
> > +	offset = y * crtc->primary->fb->pitches[0] +
> > +		x * (crtc->primary->fb->bits_per_pixel / 8);
> >  
> > -	REG_WRITE(map->stride, crtc->fb->pitches[0]);
> > +	REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
> >  
> >  	dspcntr = REG_READ(map->cntr);
> >  	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
> >  
> > -	switch (crtc->fb->bits_per_pixel) {
> > +	switch (crtc->primary->fb->bits_per_pixel) {
> >  	case 8:
> >  		dspcntr |= DISPPLANE_8BPP;
> >  		break;
> >  	case 16:
> > -		if (crtc->fb->depth == 15)
> > +		if (crtc->primary->fb->depth == 15)
> >  			dspcntr |= DISPPLANE_15_16BPP;
> >  		else
> >  			dspcntr |= DISPPLANE_16BPP;
> > @@ -511,8 +512,8 @@ void gma_crtc_disable(struct drm_crtc *crtc)
> >  
> >  	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
> >  
> > -	if (crtc->fb) {
> > -		gt = to_psb_fb(crtc->fb)->gtt;
> > +	if (crtc->primary->fb) {
> > +		gt = to_psb_fb(crtc->primary->fb)->gtt;
> >  		psb_gtt_unpin(gt);
> >  	}
> >  }
> > diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> > index 860a4ee..6e91b20 100644
> > --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> > +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> > @@ -287,7 +287,7 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
> >  						&gma_crtc->saved_mode,
> >  						encoder->crtc->x,
> >  						encoder->crtc->y,
> > -						encoder->crtc->fb))
> > +						encoder->crtc->primary->fb))
> >  					goto set_prop_error;
> >  			} else {
> >  				struct drm_encoder_helper_funcs *funcs =
> > diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c
> > index 321c00a..c54386a 100644
> > --- a/drivers/gpu/drm/gma500/mdfld_intel_display.c
> > +++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c
> > @@ -166,7 +166,7 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> >  	struct drm_device *dev = crtc->dev;
> >  	struct drm_psb_private *dev_priv = dev->dev_private;
> >  	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
> > -	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
> > +	struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
> >  	int pipe = gma_crtc->pipe;
> >  	const struct psb_offset *map = &dev_priv->regmap[pipe];
> >  	unsigned long start, offset;
> > @@ -178,12 +178,12 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> >  	dev_dbg(dev->dev, "pipe = 0x%x.\n", pipe);
> >  
> >  	/* no fb bound */
> > -	if (!crtc->fb) {
> > +	if (!crtc->primary->fb) {
> >  		dev_dbg(dev->dev, "No FB bound\n");
> >  		return 0;
> >  	}
> >  
> > -	ret = check_fb(crtc->fb);
> > +	ret = check_fb(crtc->primary->fb);
> >  	if (ret)
> >  		return ret;
> >  
> > @@ -196,18 +196,19 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> >  		return 0;
> >  
> >  	start = psbfb->gtt->offset;
> > -	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
> > +	offset = y * crtc->primary->fb->pitches[0] +
> > +		x * (crtc->primary->fb->bits_per_pixel / 8);
> >  
> > -	REG_WRITE(map->stride, crtc->fb->pitches[0]);
> > +	REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
> >  	dspcntr = REG_READ(map->cntr);
> >  	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
> >  
> > -	switch (crtc->fb->bits_per_pixel) {
> > +	switch (crtc->primary->fb->bits_per_pixel) {
> >  	case 8:
> >  		dspcntr |= DISPPLANE_8BPP;
> >  		break;
> >  	case 16:
> > -		if (crtc->fb->depth == 15)
> > +		if (crtc->primary->fb->depth == 15)
> >  			dspcntr |= DISPPLANE_15_16BPP;
> >  		else
> >  			dspcntr |= DISPPLANE_16BPP;
> > @@ -700,7 +701,7 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
> >  	}
> >  #endif
> >  
> > -	ret = check_fb(crtc->fb);
> > +	ret = check_fb(crtc->primary->fb);
> >  	if (ret)
> >  		return ret;
> >  
> > diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c
> > index 8195e85..b0fb42a 100644
> > --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c
> > +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c
> > @@ -599,7 +599,7 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
> >  	struct drm_device *dev = crtc->dev;
> >  	struct drm_psb_private *dev_priv = dev->dev_private;
> >  	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
> > -	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
> > +	struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
> >  	int pipe = gma_crtc->pipe;
> >  	const struct psb_offset *map = &dev_priv->regmap[pipe];
> >  	unsigned long start, offset;
> > @@ -608,7 +608,7 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
> >  	int ret = 0;
> >  
> >  	/* no fb bound */
> > -	if (!crtc->fb) {
> > +	if (!crtc->primary->fb) {
> >  		dev_dbg(dev->dev, "No FB bound\n");
> >  		return 0;
> >  	}
> > @@ -617,19 +617,20 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
> >  		return 0;
> >  
> >  	start = psbfb->gtt->offset;
> > -	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
> > +	offset = y * crtc->primary->fb->pitches[0] +
> > +		x * (crtc->primary->fb->bits_per_pixel / 8);
> >  
> > -	REG_WRITE(map->stride, crtc->fb->pitches[0]);
> > +	REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
> >  
> >  	dspcntr = REG_READ(map->cntr);
> >  	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
> >  
> > -	switch (crtc->fb->bits_per_pixel) {
> > +	switch (crtc->primary->fb->bits_per_pixel) {
> >  	case 8:
> >  		dspcntr |= DISPPLANE_8BPP;
> >  		break;
> >  	case 16:
> > -		if (crtc->fb->depth == 15)
> > +		if (crtc->primary->fb->depth == 15)
> >  			dspcntr |= DISPPLANE_15_16BPP;
> >  		else
> >  			dspcntr |= DISPPLANE_16BPP;
> > diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c
> > index c8f833d..25c174c 100644
> > --- a/drivers/gpu/drm/gma500/psb_intel_display.c
> > +++ b/drivers/gpu/drm/gma500/psb_intel_display.c
> > @@ -120,7 +120,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
> >  	const struct gma_limit_t *limit;
> >  
> >  	/* No scan out no play */
> > -	if (crtc->fb == NULL) {
> > +	if (crtc->primary->fb == NULL) {
> >  		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
> >  		return 0;
> >  	}
> > diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
> > index 32342f6..dcdf70e 100644
> > --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
> > +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
> > @@ -614,7 +614,7 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
> >  						      &crtc->saved_mode,
> >  						      encoder->crtc->x,
> >  						      encoder->crtc->y,
> > -						      encoder->crtc->fb))
> > +						      encoder->crtc->primary->fb))
> >  				goto set_prop_error;
> >  		}
> >  	} else if (!strcmp(property->name, "backlight")) {
> > diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
> > index 07d3a9e..1c0a2fb 100644
> > --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
> > +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
> > @@ -1844,7 +1844,7 @@ done:
> >  	if (psb_intel_sdvo->base.base.crtc) {
> >  		struct drm_crtc *crtc = psb_intel_sdvo->base.base.crtc;
> >  		drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
> > -					 crtc->y, crtc->fb);
> > +					 crtc->y, crtc->primary->fb);
> >  	}
> >  
> >  	return 0;
> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> > index d83d643..f00ba43 100644
> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > @@ -2172,8 +2172,8 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc)
> >  	struct intel_encoder *intel_encoder;
> >  
> >  	seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
> > -		   crtc->fb->base.id, crtc->x, crtc->y,
> > -		   crtc->fb->width, crtc->fb->height);
> > +		   crtc->primary->fb->base.id, crtc->x, crtc->y,
> > +		   crtc->primary->fb->width, crtc->primary->fb->height);
> >  	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
> >  		intel_encoder_info(m, intel_crtc, intel_encoder);
> >  }
> > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > index 37f852d..e8b3f9f 100644
> > --- a/drivers/gpu/drm/i915/i915_irq.c
> > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > @@ -2380,8 +2380,8 @@ static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, in
> >  	} else {
> >  		int dspaddr = DSPADDR(intel_crtc->plane);
> >  		stall_detected = I915_READ(dspaddr) == (i915_gem_obj_ggtt_offset(obj) +
> > -							crtc->y * crtc->fb->pitches[0] +
> > -							crtc->x * crtc->fb->bits_per_pixel/8);
> > +							crtc->y * crtc->primary->fb->pitches[0] +
> > +							crtc->x * crtc->primary->fb->bits_per_pixel/8);
> >  	}
> >  
> >  	spin_unlock_irqrestore(&dev->event_lock, flags);
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 21d12a9..c2f3730 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -744,7 +744,7 @@ bool intel_crtc_active(struct drm_crtc *crtc)
> >  	 * We can ditch the crtc->fb check as soon as we can
> >  	 * properly reconstruct framebuffers.
> >  	 */
> > -	return intel_crtc->active && crtc->fb &&
> > +	return intel_crtc->active && crtc->primary->fb &&
> >  		intel_crtc->config.adjusted_mode.crtc_clock;
> >  }
> >  
> > @@ -2086,17 +2086,18 @@ static bool intel_alloc_plane_obj(struct intel_crtc *crtc,
> >  
> >  	if (plane_config->tiled) {
> >  		obj->tiling_mode = I915_TILING_X;
> > -		obj->stride = crtc->base.fb->pitches[0];
> > +		obj->stride = crtc->base.primary->fb->pitches[0];
> >  	}
> >  
> > -	mode_cmd.pixel_format = crtc->base.fb->pixel_format;
> > -	mode_cmd.width = crtc->base.fb->width;
> > -	mode_cmd.height = crtc->base.fb->height;
> > -	mode_cmd.pitches[0] = crtc->base.fb->pitches[0];
> > +	mode_cmd.pixel_format = crtc->base.primary->fb->pixel_format;
> > +	mode_cmd.width = crtc->base.primary->fb->width;
> > +	mode_cmd.height = crtc->base.primary->fb->height;
> > +	mode_cmd.pitches[0] = crtc->base.primary->fb->pitches[0];
> >  
> >  	mutex_lock(&dev->struct_mutex);
> >  
> > -	if (intel_framebuffer_init(dev, to_intel_framebuffer(crtc->base.fb),
> > +	if (intel_framebuffer_init(dev,
> > +				   to_intel_framebuffer(crtc->base.primary->fb),
> >  				   &mode_cmd, obj)) {
> >  		DRM_DEBUG_KMS("intel fb init failed\n");
> >  		goto out_unref_obj;
> > @@ -2121,14 +2122,14 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
> >  	struct intel_crtc *i;
> >  	struct intel_framebuffer *fb;
> >  
> > -	if (!intel_crtc->base.fb)
> > +	if (!intel_crtc->base.primary->fb)
> >  		return;
> >  
> >  	if (intel_alloc_plane_obj(intel_crtc, plane_config))
> >  		return;
> >  
> > -	kfree(intel_crtc->base.fb);
> > -	intel_crtc->base.fb = NULL;
> > +	kfree(intel_crtc->base.primary->fb);
> > +	intel_crtc->base.primary->fb = NULL;
> >  
> >  	/*
> >  	 * Failed to alloc the obj, check to see if we should share
> > @@ -2140,13 +2141,13 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
> >  		if (c == &intel_crtc->base)
> >  			continue;
> >  
> > -		if (!i->active || !c->fb)
> > +		if (!i->active || !c->primary->fb)
> >  			continue;
> >  
> > -		fb = to_intel_framebuffer(c->fb);
> > +		fb = to_intel_framebuffer(c->primary->fb);
> >  		if (i915_gem_obj_ggtt_offset(fb->obj) == plane_config->base) {
> > -			drm_framebuffer_reference(c->fb);
> > -			intel_crtc->base.fb = c->fb;
> > +			drm_framebuffer_reference(c->primary->fb);
> > +			intel_crtc->base.primary->fb = c->primary->fb;
> >  			break;
> >  		}
> >  	}
> > @@ -2394,11 +2395,13 @@ void intel_display_handle_reset(struct drm_device *dev)
> >  		/*
> >  		 * FIXME: Once we have proper support for primary planes (and
> >  		 * disabling them without disabling the entire crtc) allow again
> > -		 * a NULL crtc->fb.
> > +		 * a NULL crtc->primary->fb.
> >  		 */
> > -		if (intel_crtc->active && crtc->fb)
> > -			dev_priv->display.update_plane(crtc, crtc->fb,
> > -						       crtc->x, crtc->y);
> > +		if (intel_crtc->active && crtc->primary->fb)
> > +			dev_priv->display.update_plane(crtc,
> > +						       crtc->primary->fb,
> > +						       crtc->x,
> > +						       crtc->y);
> >  		mutex_unlock(&crtc->mutex);
> >  	}
> >  }
> > @@ -2523,8 +2526,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> >  		return ret;
> >  	}
> >  
> > -	old_fb = crtc->fb;
> > -	crtc->fb = fb;
> > +	old_fb = crtc->primary->fb;
> > +	crtc->primary->fb = fb;
> >  	crtc->x = x;
> >  	crtc->y = y;
> >  
> > @@ -3118,7 +3121,7 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
> >  	struct drm_device *dev = crtc->dev;
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> >  
> > -	if (crtc->fb == NULL)
> > +	if (crtc->primary->fb == NULL)
> >  		return;
> >  
> >  	WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
> > @@ -3127,7 +3130,7 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
> >  		   !intel_crtc_has_pending_flip(crtc));
> >  
> >  	mutex_lock(&dev->struct_mutex);
> > -	intel_finish_fb(crtc->fb);
> > +	intel_finish_fb(crtc->primary->fb);
> >  	mutex_unlock(&dev->struct_mutex);
> >  }
> >  
> > @@ -4583,11 +4586,11 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
> >  	assert_cursor_disabled(dev_priv, to_intel_crtc(crtc)->pipe);
> >  	assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
> >  
> > -	if (crtc->fb) {
> > +	if (crtc->primary->fb) {
> >  		mutex_lock(&dev->struct_mutex);
> > -		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
> > +		intel_unpin_fb_obj(to_intel_framebuffer(crtc->primary->fb)->obj);
> >  		mutex_unlock(&dev->struct_mutex);
> > -		crtc->fb = NULL;
> > +		crtc->primary->fb = NULL;
> >  	}
> >  
> >  	/* Update computed state. */
> > @@ -5738,8 +5741,9 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
> >  	int fourcc, pixel_format;
> >  	int aligned_height;
> >  
> > -	crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
> > -	if (!crtc->base.fb) {
> > +	crtc->base.primary->fb =
> > +		kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
> > +	if (!crtc->base.primary->fb) {
> >  		DRM_DEBUG_KMS("failed to alloc fb\n");
> >  		return;
> >  	}
> > @@ -5752,8 +5756,8 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
> >  
> >  	pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
> >  	fourcc = intel_format_to_fourcc(pixel_format);
> > -	crtc->base.fb->pixel_format = fourcc;
> > -	crtc->base.fb->bits_per_pixel =
> > +	crtc->base.primary->fb->pixel_format = fourcc;
> > +	crtc->base.primary->fb->bits_per_pixel =
> >  		drm_format_plane_cpp(fourcc, 0) * 8;
> >  
> >  	if (INTEL_INFO(dev)->gen >= 4) {
> > @@ -5768,23 +5772,23 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
> >  	plane_config->base = base;
> >  
> >  	val = I915_READ(PIPESRC(pipe));
> > -	crtc->base.fb->width = ((val >> 16) & 0xfff) + 1;
> > -	crtc->base.fb->height = ((val >> 0) & 0xfff) + 1;
> > +	crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1;
> > +	crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
> >  
> >  	val = I915_READ(DSPSTRIDE(pipe));
> > -	crtc->base.fb->pitches[0] = val & 0xffffff80;
> > +	crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
> >  
> > -	aligned_height = intel_align_height(dev, crtc->base.fb->height,
> > +	aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
> >  					    plane_config->tiled);
> >  
> > -	plane_config->size = ALIGN(crtc->base.fb->pitches[0] *
> > +	plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
> >  				   aligned_height, PAGE_SIZE);
> >  
> >  	DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
> > -		      pipe, plane, crtc->base.fb->width,
> > -		      crtc->base.fb->height,
> > -		      crtc->base.fb->bits_per_pixel, base,
> > -		      crtc->base.fb->pitches[0],
> > +		      pipe, plane, crtc->base.primary->fb->width,
> > +		      crtc->base.primary->fb->height,
> > +		      crtc->base.primary->fb->bits_per_pixel, base,
> > +		      crtc->base.primary->fb->pitches[0],
> >  		      plane_config->size);
> >  
> >  }
> > @@ -6746,8 +6750,9 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
> >  	int fourcc, pixel_format;
> >  	int aligned_height;
> >  
> > -	crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
> > -	if (!crtc->base.fb) {
> > +	crtc->base.primary->fb =
> > +		kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
> > +	if (!crtc->base.primary->fb) {
> >  		DRM_DEBUG_KMS("failed to alloc fb\n");
> >  		return;
> >  	}
> > @@ -6760,8 +6765,8 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
> >  
> >  	pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
> >  	fourcc = intel_format_to_fourcc(pixel_format);
> > -	crtc->base.fb->pixel_format = fourcc;
> > -	crtc->base.fb->bits_per_pixel =
> > +	crtc->base.primary->fb->pixel_format = fourcc;
> > +	crtc->base.primary->fb->bits_per_pixel =
> >  		drm_format_plane_cpp(fourcc, 0) * 8;
> >  
> >  	base = I915_READ(DSPSURF(plane)) & 0xfffff000;
> > @@ -6776,23 +6781,23 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
> >  	plane_config->base = base;
> >  
> >  	val = I915_READ(PIPESRC(pipe));
> > -	crtc->base.fb->width = ((val >> 16) & 0xfff) + 1;
> > -	crtc->base.fb->height = ((val >> 0) & 0xfff) + 1;
> > +	crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1;
> > +	crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
> >  
> >  	val = I915_READ(DSPSTRIDE(pipe));
> > -	crtc->base.fb->pitches[0] = val & 0xffffff80;
> > +	crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
> >  
> > -	aligned_height = intel_align_height(dev, crtc->base.fb->height,
> > +	aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
> >  					    plane_config->tiled);
> >  
> > -	plane_config->size = ALIGN(crtc->base.fb->pitches[0] *
> > +	plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
> >  				   aligned_height, PAGE_SIZE);
> >  
> >  	DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
> > -		      pipe, plane, crtc->base.fb->width,
> > -		      crtc->base.fb->height,
> > -		      crtc->base.fb->bits_per_pixel, base,
> > -		      crtc->base.fb->pitches[0],
> > +		      pipe, plane, crtc->base.primary->fb->width,
> > +		      crtc->base.primary->fb->height,
> > +		      crtc->base.primary->fb->bits_per_pixel, base,
> > +		      crtc->base.primary->fb->pitches[0],
> >  		      plane_config->size);
> >  }
> >  
> > @@ -8482,7 +8487,7 @@ void intel_mark_idle(struct drm_device *dev)
> >  		goto out;
> >  
> >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > -		if (!crtc->fb)
> > +		if (!crtc->primary->fb)
> >  			continue;
> >  
> >  		intel_decrease_pllclock(crtc);
> > @@ -8505,10 +8510,10 @@ void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
> >  		return;
> >  
> >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > -		if (!crtc->fb)
> > +		if (!crtc->primary->fb)
> >  			continue;
> >  
> > -		if (to_intel_framebuffer(crtc->fb)->obj != obj)
> > +		if (to_intel_framebuffer(crtc->primary->fb)->obj != obj)
> >  			continue;
> >  
> >  		intel_increase_pllclock(crtc);
> > @@ -8936,7 +8941,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> >  {
> >  	struct drm_device *dev = crtc->dev;
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > -	struct drm_framebuffer *old_fb = crtc->fb;
> > +	struct drm_framebuffer *old_fb = crtc->primary->fb;
> >  	struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
> >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >  	struct intel_unpin_work *work;
> > @@ -8944,7 +8949,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> >  	int ret;
> >  
> >  	/* Can't change pixel format via MI display flips. */
> > -	if (fb->pixel_format != crtc->fb->pixel_format)
> > +	if (fb->pixel_format != crtc->primary->fb->pixel_format)
> >  		return -EINVAL;
> >  
> >  	/*
> > @@ -8952,8 +8957,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> >  	 * Note that pitch changes could also affect these register.
> >  	 */
> >  	if (INTEL_INFO(dev)->gen > 3 &&
> > -	    (fb->offsets[0] != crtc->fb->offsets[0] ||
> > -	     fb->pitches[0] != crtc->fb->pitches[0]))
> > +	    (fb->offsets[0] != crtc->primary->fb->offsets[0] ||
> > +	     fb->pitches[0] != crtc->primary->fb->pitches[0]))
> >  		return -EINVAL;
> >  
> >  	if (i915_terminally_wedged(&dev_priv->gpu_error))
> > @@ -8996,7 +9001,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> >  	drm_gem_object_reference(&work->old_fb_obj->base);
> >  	drm_gem_object_reference(&obj->base);
> >  
> > -	crtc->fb = fb;
> > +	crtc->primary->fb = fb;
> >  
> >  	work->pending_flip_obj = obj;
> >  
> > @@ -9019,7 +9024,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> >  
> >  cleanup_pending:
> >  	atomic_dec(&intel_crtc->unpin_work_count);
> > -	crtc->fb = old_fb;
> > +	crtc->primary->fb = old_fb;
> >  	drm_gem_object_unreference(&work->old_fb_obj->base);
> >  	drm_gem_object_unreference(&obj->base);
> >  	mutex_unlock(&dev->struct_mutex);
> > @@ -10060,7 +10065,7 @@ static int intel_set_mode(struct drm_crtc *crtc,
> >  
> >  void intel_crtc_restore_mode(struct drm_crtc *crtc)
> >  {
> > -	intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb);
> > +	intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb);
> >  }
> >  
> >  #undef for_each_intel_crtc_masked
> > @@ -10184,9 +10189,9 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
> >  	 * and then just flip_or_move it */
> >  	if (is_crtc_connector_off(set)) {
> >  		config->mode_changed = true;
> > -	} else if (set->crtc->fb != set->fb) {
> > +	} else if (set->crtc->primary->fb != set->fb) {
> >  		/* If we have no fb then treat it as a full mode set */
> > -		if (set->crtc->fb == NULL) {
> > +		if (set->crtc->primary->fb == NULL) {
> >  			struct intel_crtc *intel_crtc =
> >  				to_intel_crtc(set->crtc);
> >  
> > @@ -10200,7 +10205,7 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
> >  		} else if (set->fb == NULL) {
> >  			config->mode_changed = true;
> >  		} else if (set->fb->pixel_format !=
> > -			   set->crtc->fb->pixel_format) {
> > +			   set->crtc->primary->fb->pixel_format) {
> >  			config->mode_changed = true;
> >  		} else {
> >  			config->fb_changed = true;
> > @@ -10413,7 +10418,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
> >  	save_set.mode = &set->crtc->mode;
> >  	save_set.x = set->crtc->x;
> >  	save_set.y = set->crtc->y;
> > -	save_set.fb = set->crtc->fb;
> > +	save_set.fb = set->crtc->primary->fb;
> >  
> >  	/* Compute whether we need a full modeset, only an fb base update or no
> >  	 * change at all. In the future we might also check whether only the
> > @@ -11755,7 +11760,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
> >  				dev_priv->pipe_to_crtc_mapping[pipe];
> >  
> >  			__intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
> > -					 crtc->fb);
> > +					 crtc->primary->fb);
> >  		}
> >  	} else {
> >  		intel_modeset_update_staged_output_state(dev);
> > @@ -11780,15 +11785,15 @@ void intel_modeset_gem_init(struct drm_device *dev)
> >  	 */
> >  	mutex_lock(&dev->struct_mutex);
> >  	list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
> > -		if (!c->fb)
> > +		if (!c->primary->fb)
> >  			continue;
> >  
> > -		fb = to_intel_framebuffer(c->fb);
> > +		fb = to_intel_framebuffer(c->primary->fb);
> >  		if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL)) {
> >  			DRM_ERROR("failed to pin boot fb on pipe %d\n",
> >  				  to_intel_crtc(c)->pipe);
> > -			drm_framebuffer_unreference(c->fb);
> > -			c->fb = NULL;
> > +			drm_framebuffer_unreference(c->primary->fb);
> > +			c->primary->fb = NULL;
> >  		}
> >  	}
> >  	mutex_unlock(&dev->struct_mutex);
> > @@ -11827,7 +11832,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
> >  
> >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> >  		/* Skip inactive CRTCs */
> > -		if (!crtc->fb)
> > +		if (!crtc->primary->fb)
> >  			continue;
> >  
> >  		intel_increase_pllclock(crtc);
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 59ee4dc..05531bf 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -1634,7 +1634,8 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> >  	struct drm_crtc *crtc = dig_port->base.base.crtc;
> >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > -	struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
> > +	struct drm_i915_gem_object *obj =
> > +		to_intel_framebuffer(crtc->primary->fb)->obj;
> >  	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
> >  
> >  	dev_priv->psr.source_ok = false;
> > @@ -1667,7 +1668,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
> >  		return false;
> >  	}
> >  
> > -	obj = to_intel_framebuffer(crtc->fb)->obj;
> > +	obj = to_intel_framebuffer(crtc->primary->fb)->obj;
> >  	if (obj->tiling_mode != I915_TILING_X ||
> >  	    obj->fence_reg == I915_FENCE_REG_NONE) {
> >  		DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
> > diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
> > index d6d78c8..2b1d42d 100644
> > --- a/drivers/gpu/drm/i915/intel_fbdev.c
> > +++ b/drivers/gpu/drm/i915/intel_fbdev.c
> > @@ -481,7 +481,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
> >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> >  		intel_crtc = to_intel_crtc(crtc);
> >  
> > -		if (!intel_crtc->active || !crtc->fb) {
> > +		if (!intel_crtc->active || !crtc->primary->fb) {
> >  			DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
> >  				      pipe_name(intel_crtc->pipe));
> >  			continue;
> > @@ -491,7 +491,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
> >  			DRM_DEBUG_KMS("found possible fb from plane %c\n",
> >  				      pipe_name(intel_crtc->pipe));
> >  			plane_config = &intel_crtc->plane_config;
> > -			fb = to_intel_framebuffer(crtc->fb);
> > +			fb = to_intel_framebuffer(crtc->primary->fb);
> >  			max_size = plane_config->size;
> >  		}
> >  	}
> > @@ -560,7 +560,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
> >  		if (!intel_crtc->active)
> >  			continue;
> >  
> > -		WARN(!crtc->fb,
> > +		WARN(!crtc->primary->fb,
> >  		     "re-used BIOS config but lost an fb on crtc %d\n",
> >  		     crtc->base.id);
> >  	}
> > diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
> > index 312961a..623cd32 100644
> > --- a/drivers/gpu/drm/i915/intel_overlay.c
> > +++ b/drivers/gpu/drm/i915/intel_overlay.c
> > @@ -606,14 +606,14 @@ static void update_colorkey(struct intel_overlay *overlay,
> >  {
> >  	u32 key = overlay->color_key;
> >  
> > -	switch (overlay->crtc->base.fb->bits_per_pixel) {
> > +	switch (overlay->crtc->base.primary->fb->bits_per_pixel) {
> >  	case 8:
> >  		iowrite32(0, &regs->DCLRKV);
> >  		iowrite32(CLK_RGB8I_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
> >  		break;
> >  
> >  	case 16:
> > -		if (overlay->crtc->base.fb->depth == 15) {
> > +		if (overlay->crtc->base.primary->fb->depth == 15) {
> >  			iowrite32(RGB15_TO_COLORKEY(key), &regs->DCLRKV);
> >  			iowrite32(CLK_RGB15_MASK | DST_KEY_ENABLE,
> >  				  &regs->DCLRKM);
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 3a1b569..e2d73f4 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -92,7 +92,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc)
> >  {
> >  	struct drm_device *dev = crtc->dev;
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > -	struct drm_framebuffer *fb = crtc->fb;
> > +	struct drm_framebuffer *fb = crtc->primary->fb;
> >  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> >  	struct drm_i915_gem_object *obj = intel_fb->obj;
> >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > @@ -149,7 +149,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc)
> >  {
> >  	struct drm_device *dev = crtc->dev;
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > -	struct drm_framebuffer *fb = crtc->fb;
> > +	struct drm_framebuffer *fb = crtc->primary->fb;
> >  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> >  	struct drm_i915_gem_object *obj = intel_fb->obj;
> >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > @@ -221,7 +221,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc)
> >  {
> >  	struct drm_device *dev = crtc->dev;
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > -	struct drm_framebuffer *fb = crtc->fb;
> > +	struct drm_framebuffer *fb = crtc->primary->fb;
> >  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> >  	struct drm_i915_gem_object *obj = intel_fb->obj;
> >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > @@ -277,7 +277,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc)
> >  {
> >  	struct drm_device *dev = crtc->dev;
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > -	struct drm_framebuffer *fb = crtc->fb;
> > +	struct drm_framebuffer *fb = crtc->primary->fb;
> >  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> >  	struct drm_i915_gem_object *obj = intel_fb->obj;
> >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > @@ -336,11 +336,11 @@ static void intel_fbc_work_fn(struct work_struct *__work)
> >  		/* Double check that we haven't switched fb without cancelling
> >  		 * the prior work.
> >  		 */
> > -		if (work->crtc->fb == work->fb) {
> > +		if (work->crtc->primary->fb == work->fb) {
> >  			dev_priv->display.enable_fbc(work->crtc);
> >  
> >  			dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane;
> > -			dev_priv->fbc.fb_id = work->crtc->fb->base.id;
> > +			dev_priv->fbc.fb_id = work->crtc->primary->fb->base.id;
> >  			dev_priv->fbc.y = work->crtc->y;
> >  		}
> >  
> > @@ -393,7 +393,7 @@ static void intel_enable_fbc(struct drm_crtc *crtc)
> >  	}
> >  
> >  	work->crtc = crtc;
> > -	work->fb = crtc->fb;
> > +	work->fb = crtc->primary->fb;
> >  	INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
> >  
> >  	dev_priv->fbc.fbc_work = work;
> > @@ -499,14 +499,14 @@ void intel_update_fbc(struct drm_device *dev)
> >  		}
> >  	}
> >  
> > -	if (!crtc || crtc->fb == NULL) {
> > +	if (!crtc || crtc->primary->fb == NULL) {
> >  		if (set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT))
> >  			DRM_DEBUG_KMS("no output, disabling\n");
> >  		goto out_disable;
> >  	}
> >  
> >  	intel_crtc = to_intel_crtc(crtc);
> > -	fb = crtc->fb;
> > +	fb = crtc->primary->fb;
> >  	intel_fb = to_intel_framebuffer(fb);
> >  	obj = intel_fb->obj;
> >  	adjusted_mode = &intel_crtc->config.adjusted_mode;
> > @@ -1041,7 +1041,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc)
> >  	crtc = single_enabled_crtc(dev);
> >  	if (crtc) {
> >  		const struct drm_display_mode *adjusted_mode;
> > -		int pixel_size = crtc->fb->bits_per_pixel / 8;
> > +		int pixel_size = crtc->primary->fb->bits_per_pixel / 8;
> >  		int clock;
> >  
> >  		adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
> > @@ -1121,7 +1121,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
> >  	clock = adjusted_mode->crtc_clock;
> >  	htotal = adjusted_mode->crtc_htotal;
> >  	hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
> > -	pixel_size = crtc->fb->bits_per_pixel / 8;
> > +	pixel_size = crtc->primary->fb->bits_per_pixel / 8;
> >  
> >  	/* Use the small buffer method to calculate plane watermark */
> >  	entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
> > @@ -1208,7 +1208,7 @@ static bool g4x_compute_srwm(struct drm_device *dev,
> >  	clock = adjusted_mode->crtc_clock;
> >  	htotal = adjusted_mode->crtc_htotal;
> >  	hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
> > -	pixel_size = crtc->fb->bits_per_pixel / 8;
> > +	pixel_size = crtc->primary->fb->bits_per_pixel / 8;
> >  
> >  	line_time_us = max(htotal * 1000 / clock, 1);
> >  	line_count = (latency_ns / line_time_us + 1000) / 1000;
> > @@ -1247,7 +1247,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev,
> >  		return false;
> >  
> >  	clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
> > -	pixel_size = crtc->fb->bits_per_pixel / 8;	/* BPP */
> > +	pixel_size = crtc->primary->fb->bits_per_pixel / 8;	/* BPP */
> >  
> >  	entries = (clock / 1000) * pixel_size;
> >  	*plane_prec_mult = (entries > 256) ?
> > @@ -1439,7 +1439,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
> >  		int clock = adjusted_mode->crtc_clock;
> >  		int htotal = adjusted_mode->crtc_htotal;
> >  		int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
> > -		int pixel_size = crtc->fb->bits_per_pixel / 8;
> > +		int pixel_size = crtc->primary->fb->bits_per_pixel / 8;
> >  		unsigned long line_time_us;
> >  		int entries;
> >  
> > @@ -1512,7 +1512,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
> >  	crtc = intel_get_crtc_for_plane(dev, 0);
> >  	if (intel_crtc_active(crtc)) {
> >  		const struct drm_display_mode *adjusted_mode;
> > -		int cpp = crtc->fb->bits_per_pixel / 8;
> > +		int cpp = crtc->primary->fb->bits_per_pixel / 8;
> >  		if (IS_GEN2(dev))
> >  			cpp = 4;
> >  
> > @@ -1528,7 +1528,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
> >  	crtc = intel_get_crtc_for_plane(dev, 1);
> >  	if (intel_crtc_active(crtc)) {
> >  		const struct drm_display_mode *adjusted_mode;
> > -		int cpp = crtc->fb->bits_per_pixel / 8;
> > +		int cpp = crtc->primary->fb->bits_per_pixel / 8;
> >  		if (IS_GEN2(dev))
> >  			cpp = 4;
> >  
> > @@ -1565,7 +1565,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
> >  		int clock = adjusted_mode->crtc_clock;
> >  		int htotal = adjusted_mode->crtc_htotal;
> >  		int hdisplay = to_intel_crtc(enabled)->config.pipe_src_w;
> > -		int pixel_size = enabled->fb->bits_per_pixel / 8;
> > +		int pixel_size = enabled->primary->fb->bits_per_pixel / 8;
> >  		unsigned long line_time_us;
> >  		int entries;
> >  
> > @@ -2117,7 +2117,7 @@ static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
> >  	if (p->active) {
> >  		p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_htotal;
> >  		p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
> > -		p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
> > +		p->pri.bytes_per_pixel = crtc->primary->fb->bits_per_pixel / 8;
> >  		p->cur.bytes_per_pixel = 4;
> >  		p->pri.horiz_pixels = intel_crtc->config.pipe_src_w;
> >  		p->cur.horiz_pixels = 64;
> > diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
> > index 1418414..f8c42b1 100644
> > --- a/drivers/gpu/drm/mgag200/mgag200_mode.c
> > +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
> > @@ -29,7 +29,7 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc)
> >  	struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
> >  	struct drm_device *dev = crtc->dev;
> >  	struct mga_device *mdev = dev->dev_private;
> > -	struct drm_framebuffer *fb = crtc->fb;
> > +	struct drm_framebuffer *fb = crtc->primary->fb;
> >  	int i;
> >  
> >  	if (!crtc->enabled)
> > @@ -742,7 +742,7 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc,
> >  		mgag200_bo_unreserve(bo);
> >  	}
> >  
> > -	mga_fb = to_mga_framebuffer(crtc->fb);
> > +	mga_fb = to_mga_framebuffer(crtc->primary->fb);
> >  	obj = mga_fb->obj;
> >  	bo = gem_to_mga_bo(obj);
> >  
> > @@ -805,7 +805,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
> >  		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
> >  	};
> >  
> > -	bppshift = mdev->bpp_shifts[(crtc->fb->bits_per_pixel >> 3) - 1];
> > +	bppshift = mdev->bpp_shifts[(crtc->primary->fb->bits_per_pixel >> 3) - 1];
> >  
> >  	switch (mdev->type) {
> >  	case G200_SE_A:
> > @@ -843,12 +843,12 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
> >  		break;
> >  	}
> >  
> > -	switch (crtc->fb->bits_per_pixel) {
> > +	switch (crtc->primary->fb->bits_per_pixel) {
> >  	case 8:
> >  		dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits;
> >  		break;
> >  	case 16:
> > -		if (crtc->fb->depth == 15)
> > +		if (crtc->primary->fb->depth == 15)
> >  			dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_15bits;
> >  		else
> >  			dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_16bits;
> > @@ -896,8 +896,9 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
> >  	WREG_SEQ(3, 0);
> >  	WREG_SEQ(4, 0xe);
> >  
> > -	pitch = crtc->fb->pitches[0] / (crtc->fb->bits_per_pixel / 8);
> > -	if (crtc->fb->bits_per_pixel == 24)
> > +	pitch = crtc->primary->fb->pitches[0] /
> > +		(crtc->primary->fb->bits_per_pixel / 8);
> > +	if (crtc->primary->fb->bits_per_pixel == 24)
> >  		pitch = (pitch * 3) >> (4 - bppshift);
> >  	else
> >  		pitch = pitch >> (4 - bppshift);
> > @@ -974,7 +975,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
> >  		((vdisplay & 0xc00) >> 7) |
> >  		((vsyncstart & 0xc00) >> 5) |
> >  		((vdisplay & 0x400) >> 3);
> > -	if (crtc->fb->bits_per_pixel == 24)
> > +	if (crtc->primary->fb->bits_per_pixel == 24)
> >  		ext_vga[3] = (((1 << bppshift) * 3) - 1) | 0x80;
> >  	else
> >  		ext_vga[3] = ((1 << bppshift) - 1) | 0x80;
> > @@ -1034,9 +1035,9 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
> >  			u32 bpp;
> >  			u32 mb;
> >  
> > -			if (crtc->fb->bits_per_pixel > 16)
> > +			if (crtc->primary->fb->bits_per_pixel > 16)
> >  				bpp = 32;
> > -			else if (crtc->fb->bits_per_pixel > 8)
> > +			else if (crtc->primary->fb->bits_per_pixel > 8)
> >  				bpp = 16;
> >  			else
> >  				bpp = 8;
> > @@ -1277,8 +1278,9 @@ static void mga_crtc_disable(struct drm_crtc *crtc)
> >  	int ret;
> >  	DRM_DEBUG_KMS("\n");
> >  	mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
> > -	if (crtc->fb) {
> > -		struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->fb);
> > +	if (crtc->primary->fb) {
> > +		struct mga_framebuffer *mga_fb =
> > +			to_mga_framebuffer(crtc->primary->fb);
> >  		struct drm_gem_object *obj = mga_fb->obj;
> >  		struct mgag200_bo *bo = gem_to_mga_bo(obj);
> >  		ret = mgag200_bo_reserve(bo, false);
> > @@ -1287,7 +1289,7 @@ static void mga_crtc_disable(struct drm_crtc *crtc)
> >  		mgag200_bo_push_sysram(bo);
> >  		mgag200_bo_unreserve(bo);
> >  	}
> > -	crtc->fb = NULL;
> > +	crtc->primary->fb = NULL;
> >  }
> >  
> >  /* These provide the minimum set of functions required to handle a CRTC */
> > diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
> > index b10f681..f96497b 100644
> > --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
> > +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
> > @@ -120,7 +120,7 @@ static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
> >  
> >  	/* grab reference to incoming scanout fb: */
> >  	drm_framebuffer_reference(new_fb);
> > -	mdp4_crtc->base.fb = new_fb;
> > +	mdp4_crtc->base.primary->fb = new_fb;
> >  	mdp4_crtc->fb = new_fb;
> >  
> >  	if (old_fb)
> > @@ -182,7 +182,7 @@ static void pageflip_cb(struct msm_fence_cb *cb)
> >  	struct mdp4_crtc *mdp4_crtc =
> >  		container_of(cb, struct mdp4_crtc, pageflip_cb);
> >  	struct drm_crtc *crtc = &mdp4_crtc->base;
> > -	struct drm_framebuffer *fb = crtc->fb;
> > +	struct drm_framebuffer *fb = crtc->primary->fb;
> >  
> >  	if (!fb)
> >  		return;
> > @@ -348,14 +348,14 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
> >  			mode->type, mode->flags);
> >  
> >  	/* grab extra ref for update_scanout() */
> > -	drm_framebuffer_reference(crtc->fb);
> > +	drm_framebuffer_reference(crtc->primary->fb);
> >  
> > -	ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->fb,
> > +	ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->primary->fb,
> >  			0, 0, mode->hdisplay, mode->vdisplay,
> >  			x << 16, y << 16,
> >  			mode->hdisplay << 16, mode->vdisplay << 16);
> >  	if (ret) {
> > -		drm_framebuffer_unreference(crtc->fb);
> > +		drm_framebuffer_unreference(crtc->primary->fb);
> >  		dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
> >  				mdp4_crtc->name, ret);
> >  		return ret;
> > @@ -368,7 +368,7 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
> >  	/* take data from pipe: */
> >  	mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_BASE(dma), 0);
> >  	mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_STRIDE(dma),
> > -			crtc->fb->pitches[0]);
> > +			crtc->primary->fb->pitches[0]);
> >  	mdp4_write(mdp4_kms, REG_MDP4_DMA_DST_SIZE(dma),
> >  			MDP4_DMA_DST_SIZE_WIDTH(0) |
> >  			MDP4_DMA_DST_SIZE_HEIGHT(0));
> > @@ -378,7 +378,7 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
> >  			MDP4_OVLP_SIZE_WIDTH(mode->hdisplay) |
> >  			MDP4_OVLP_SIZE_HEIGHT(mode->vdisplay));
> >  	mdp4_write(mdp4_kms, REG_MDP4_OVLP_STRIDE(ovlp),
> > -			crtc->fb->pitches[0]);
> > +			crtc->primary->fb->pitches[0]);
> >  
> >  	mdp4_write(mdp4_kms, REG_MDP4_OVLP_CFG(ovlp), 1);
> >  
> > @@ -388,8 +388,8 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
> >  		mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(2), 0x00ff0000);
> >  	}
> >  
> > -	update_fb(crtc, crtc->fb);
> > -	update_scanout(crtc, crtc->fb);
> > +	update_fb(crtc, crtc->primary->fb);
> > +	update_scanout(crtc, crtc->primary->fb);
> >  
> >  	return 0;
> >  }
> > @@ -420,19 +420,19 @@ static int mdp4_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> >  	int ret;
> >  
> >  	/* grab extra ref for update_scanout() */
> > -	drm_framebuffer_reference(crtc->fb);
> > +	drm_framebuffer_reference(crtc->primary->fb);
> >  
> > -	ret = mdp4_plane_mode_set(plane, crtc, crtc->fb,
> > +	ret = mdp4_plane_mode_set(plane, crtc, crtc->primary->fb,
> >  			0, 0, mode->hdisplay, mode->vdisplay,
> >  			x << 16, y << 16,
> >  			mode->hdisplay << 16, mode->vdisplay << 16);
> >  	if (ret) {
> > -		drm_framebuffer_unreference(crtc->fb);
> > +		drm_framebuffer_unreference(crtc->primary->fb);
> >  		return ret;
> >  	}
> >  
> > -	update_fb(crtc, crtc->fb);
> > -	update_scanout(crtc, crtc->fb);
> > +	update_fb(crtc, crtc->primary->fb);
> > +	update_scanout(crtc, crtc->primary->fb);
> >  
> >  	return 0;
> >  }
> > diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
> > index 7dc3d71..f200048 100644
> > --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
> > +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
> > @@ -102,7 +102,7 @@ static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
> >  
> >  	/* grab reference to incoming scanout fb: */
> >  	drm_framebuffer_reference(new_fb);
> > -	mdp5_crtc->base.fb = new_fb;
> > +	mdp5_crtc->base.primary->fb = new_fb;
> >  	mdp5_crtc->fb = new_fb;
> >  
> >  	if (old_fb)
> > @@ -289,14 +289,14 @@ static int mdp5_crtc_mode_set(struct drm_crtc *crtc,
> >  			mode->type, mode->flags);
> >  
> >  	/* grab extra ref for update_scanout() */
> > -	drm_framebuffer_reference(crtc->fb);
> > +	drm_framebuffer_reference(crtc->primary->fb);
> >  
> > -	ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->fb,
> > +	ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->primary->fb,
> >  			0, 0, mode->hdisplay, mode->vdisplay,
> >  			x << 16, y << 16,
> >  			mode->hdisplay << 16, mode->vdisplay << 16);
> >  	if (ret) {
> > -		drm_framebuffer_unreference(crtc->fb);
> > +		drm_framebuffer_unreference(crtc->primary->fb);
> >  		dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
> >  				mdp5_crtc->name, ret);
> >  		return ret;
> > @@ -306,8 +306,8 @@ static int mdp5_crtc_mode_set(struct drm_crtc *crtc,
> >  			MDP5_LM_OUT_SIZE_WIDTH(mode->hdisplay) |
> >  			MDP5_LM_OUT_SIZE_HEIGHT(mode->vdisplay));
> >  
> > -	update_fb(crtc, crtc->fb);
> > -	update_scanout(crtc, crtc->fb);
> > +	update_fb(crtc, crtc->primary->fb);
> > +	update_scanout(crtc, crtc->primary->fb);
> >  
> >  	return 0;
> >  }
> > @@ -338,19 +338,19 @@ static int mdp5_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> >  	int ret;
> >  
> >  	/* grab extra ref for update_scanout() */
> > -	drm_framebuffer_reference(crtc->fb);
> > +	drm_framebuffer_reference(crtc->primary->fb);
> >  
> > -	ret = mdp5_plane_mode_set(plane, crtc, crtc->fb,
> > +	ret = mdp5_plane_mode_set(plane, crtc, crtc->primary->fb,
> >  			0, 0, mode->hdisplay, mode->vdisplay,
> >  			x << 16, y << 16,
> >  			mode->hdisplay << 16, mode->vdisplay << 16);
> >  	if (ret) {
> > -		drm_framebuffer_unreference(crtc->fb);
> > +		drm_framebuffer_unreference(crtc->primary->fb);
> >  		return ret;
> >  	}
> >  
> > -	update_fb(crtc, crtc->fb);
> > -	update_scanout(crtc, crtc->fb);
> > +	update_fb(crtc, crtc->primary->fb);
> > +	update_scanout(crtc, crtc->primary->fb);
> >  
> >  	return 0;
> >  }
> > diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
> > index b55be84..2a5e9db 100644
> > --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
> > +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
> > @@ -239,7 +239,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
> >  	struct drm_device *dev = crtc->dev;
> >  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
> >  	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
> > -	struct drm_framebuffer *fb = crtc->fb;
> > +	struct drm_framebuffer *fb = crtc->primary->fb;
> >  
> >  	/* Calculate our timings */
> >  	int horizDisplay	= (mode->crtc_hdisplay >> 3)		- 1;
> > @@ -574,7 +574,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
> >  		regp->CRTC[NV_CIO_CRE_86] = 0x1;
> >  	}
> >  
> > -	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->fb->depth + 1) / 8;
> > +	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->primary->fb->depth + 1) / 8;
> >  	/* Enable slaved mode (called MODE_TV in nv4ref.h) */
> >  	if (lvds_output || tmds_output || tv_output)
> >  		regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7);
> > @@ -588,7 +588,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
> >  	regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS |
> >  				NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL |
> >  				NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON;
> > -	if (crtc->fb->depth == 16)
> > +	if (crtc->primary->fb->depth == 16)
> >  		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
> >  	if (nv_device(drm->device)->chipset >= 0x11)
> >  		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG;
> > @@ -609,7 +609,7 @@ static int
> >  nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
> >  {
> >  	struct nv04_display *disp = nv04_display(crtc->dev);
> > -	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
> > +	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb);
> >  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
> >  	int ret;
> >  
> > @@ -808,7 +808,7 @@ nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
> >  	 * mark the lut values as dirty by setting depth==0, and it'll be
> >  	 * uploaded on the first mode_set_base()
> >  	 */
> > -	if (!nv_crtc->base.fb) {
> > +	if (!nv_crtc->base.primary->fb) {
> >  		nv_crtc->lut.depth = 0;
> >  		return;
> >  	}
> > @@ -832,7 +832,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
> >  	NV_DEBUG(drm, "index %d\n", nv_crtc->index);
> >  
> >  	/* no fb bound */
> > -	if (!atomic && !crtc->fb) {
> > +	if (!atomic && !crtc->primary->fb) {
> >  		NV_DEBUG(drm, "No FB bound\n");
> >  		return 0;
> >  	}
> > @@ -844,8 +844,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
> >  		drm_fb = passed_fb;
> >  		fb = nouveau_framebuffer(passed_fb);
> >  	} else {
> > -		drm_fb = crtc->fb;
> > -		fb = nouveau_framebuffer(crtc->fb);
> > +		drm_fb = crtc->primary->fb;
> > +		fb = nouveau_framebuffer(crtc->primary->fb);
> >  	}
> >  
> >  	nv_crtc->fb.offset = fb->nvbo->bo.offset;
> > @@ -857,9 +857,9 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
> >  
> >  	/* Update the framebuffer format. */
> >  	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] &= ~3;
> > -	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->fb->depth + 1) / 8;
> > +	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->primary->fb->depth + 1) / 8;
> >  	regp->ramdac_gen_ctrl &= ~NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
> > -	if (crtc->fb->depth == 16)
> > +	if (crtc->primary->fb->depth == 16)
> >  		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
> >  	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_PIXEL_INDEX);
> >  	NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL,
> > diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
> > index 7fdc51e..a2d669b 100644
> > --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c
> > +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
> > @@ -415,7 +415,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder,
> >  	/* Output property. */
> >  	if ((nv_connector->dithering_mode == DITHERING_MODE_ON) ||
> >  	    (nv_connector->dithering_mode == DITHERING_MODE_AUTO &&
> > -	     encoder->crtc->fb->depth > connector->display_info.bpc * 3)) {
> > +	     encoder->crtc->primary->fb->depth > connector->display_info.bpc * 3)) {
> >  		if (nv_device(drm->device)->chipset == 0x11)
> >  			regp->dither = savep->dither | 0x00010000;
> >  		else {
> > diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
> > index 2401159..4e24c72 100644
> > --- a/drivers/gpu/drm/nouveau/nouveau_display.c
> > +++ b/drivers/gpu/drm/nouveau/nouveau_display.c
> > @@ -569,7 +569,7 @@ nouveau_display_suspend(struct drm_device *dev)
> >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> >  		struct nouveau_framebuffer *nouveau_fb;
> >  
> > -		nouveau_fb = nouveau_framebuffer(crtc->fb);
> > +		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
> >  		if (!nouveau_fb || !nouveau_fb->nvbo)
> >  			continue;
> >  
> > @@ -596,7 +596,7 @@ nouveau_display_repin(struct drm_device *dev)
> >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> >  		struct nouveau_framebuffer *nouveau_fb;
> >  
> > -		nouveau_fb = nouveau_framebuffer(crtc->fb);
> > +		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
> >  		if (!nouveau_fb || !nouveau_fb->nvbo)
> >  			continue;
> >  
> > @@ -693,7 +693,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
> >  	const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1;
> >  	struct drm_device *dev = crtc->dev;
> >  	struct nouveau_drm *drm = nouveau_drm(dev);
> > -	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo;
> > +	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo;
> >  	struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
> >  	struct nouveau_page_flip_state *s;
> >  	struct nouveau_channel *chan = drm->channel;
> > @@ -767,7 +767,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
> >  		goto fail_unreserve;
> >  
> >  	/* Update the crtc struct and cleanup */
> > -	crtc->fb = fb;
> > +	crtc->primary->fb = fb;
> >  
> >  	nouveau_bo_fence(old_bo, fence);
> >  	ttm_bo_unreserve(&old_bo->bo);
> > diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
> > index 5706842..c744bf6 100644
> > --- a/drivers/gpu/drm/nouveau/nv50_display.c
> > +++ b/drivers/gpu/drm/nouveau/nv50_display.c
> > @@ -651,7 +651,7 @@ nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
> >  	nv_connector = nouveau_crtc_connector_get(nv_crtc);
> >  	connector = &nv_connector->base;
> >  	if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) {
> > -		if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3)
> > +		if (nv_crtc->base.primary->fb->depth > connector->display_info.bpc * 3)
> >  			mode = DITHERING_MODE_DYNAMIC2X2;
> >  	} else {
> >  		mode = nv_connector->dithering_mode;
> > @@ -785,7 +785,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
> >  
> >  		if (update) {
> >  			nv50_display_flip_stop(crtc);
> > -			nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
> > +			nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
> >  		}
> >  	}
> >  
> > @@ -1028,7 +1028,7 @@ nv50_crtc_commit(struct drm_crtc *crtc)
> >  	}
> >  
> >  	nv50_crtc_cursor_show_hide(nv_crtc, nv_crtc->cursor.visible, true);
> > -	nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
> > +	nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
> >  }
> >  
> >  static bool
> > @@ -1042,7 +1042,8 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
> >  static int
> >  nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
> >  {
> > -	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
> > +	struct nouveau_framebuffer *nvfb =
> > +		nouveau_framebuffer(crtc->primary->fb);
> >  	struct nv50_head *head = nv50_head(crtc);
> >  	int ret;
> >  
> > @@ -1139,7 +1140,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
> >  	nv50_crtc_set_dither(nv_crtc, false);
> >  	nv50_crtc_set_scale(nv_crtc, false);
> >  	nv50_crtc_set_color_vibrance(nv_crtc, false);
> > -	nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, false);
> > +	nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, false);
> >  	return 0;
> >  }
> >  
> > @@ -1151,7 +1152,7 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> >  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
> >  	int ret;
> >  
> > -	if (!crtc->fb) {
> > +	if (!crtc->primary->fb) {
> >  		NV_DEBUG(drm, "No FB bound\n");
> >  		return 0;
> >  	}
> > @@ -1161,8 +1162,8 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> >  		return ret;
> >  
> >  	nv50_display_flip_stop(crtc);
> > -	nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, true);
> > -	nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
> > +	nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, true);
> > +	nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
> >  	return 0;
> >  }
> >  
> > diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
> > index 24b6112..5be0b87 100644
> > --- a/drivers/gpu/drm/qxl/qxl_display.c
> > +++ b/drivers/gpu/drm/qxl/qxl_display.c
> > @@ -527,7 +527,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
> >  	bool recreate_primary = false;
> >  	int ret;
> >  	int surf_id;
> > -	if (!crtc->fb) {
> > +	if (!crtc->primary->fb) {
> >  		DRM_DEBUG_KMS("No FB bound\n");
> >  		return 0;
> >  	}
> > @@ -536,7 +536,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
> >  		qfb = to_qxl_framebuffer(old_fb);
> >  		old_bo = gem_to_qxl_bo(qfb->obj);
> >  	}
> > -	qfb = to_qxl_framebuffer(crtc->fb);
> > +	qfb = to_qxl_framebuffer(crtc->primary->fb);
> >  	bo = gem_to_qxl_bo(qfb->obj);
> >  	if (!m)
> >  		/* and do we care? */
> > @@ -609,14 +609,15 @@ static void qxl_crtc_disable(struct drm_crtc *crtc)
> >  	struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
> >  	struct drm_device *dev = crtc->dev;
> >  	struct qxl_device *qdev = dev->dev_private;
> > -	if (crtc->fb) {
> > -		struct qxl_framebuffer *qfb = to_qxl_framebuffer(crtc->fb);
> > +	if (crtc->primary->fb) {
> > +		struct qxl_framebuffer *qfb =
> > +			to_qxl_framebuffer(crtc->primary->fb);
> >  		struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
> >  		int ret;
> >  		ret = qxl_bo_reserve(bo, false);
> >  		qxl_bo_unpin(bo);
> >  		qxl_bo_unreserve(bo);
> > -		crtc->fb = NULL;
> > +		crtc->primary->fb = NULL;
> >  	}
> >  
> >  	qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0);
> > diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
> > index daa4dd3..fb187c7 100644
> > --- a/drivers/gpu/drm/radeon/atombios_crtc.c
> > +++ b/drivers/gpu/drm/radeon/atombios_crtc.c
> > @@ -1106,7 +1106,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
> >  	int r;
> >  
> >  	/* no fb bound */
> > -	if (!atomic && !crtc->fb) {
> > +	if (!atomic && !crtc->primary->fb) {
> >  		DRM_DEBUG_KMS("No FB bound\n");
> >  		return 0;
> >  	}
> > @@ -1116,8 +1116,8 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
> >  		target_fb = fb;
> >  	}
> >  	else {
> > -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> > -		target_fb = crtc->fb;
> > +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> > +		target_fb = crtc->primary->fb;
> >  	}
> >  
> >  	/* If atomic, assume fb object is pinned & idle & fenced and
> > @@ -1316,7 +1316,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
> >  	/* set pageflip to happen anywhere in vblank interval */
> >  	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> >  
> > -	if (!atomic && fb && fb != crtc->fb) {
> > +	if (!atomic && fb && fb != crtc->primary->fb) {
> >  		radeon_fb = to_radeon_framebuffer(fb);
> >  		rbo = gem_to_radeon_bo(radeon_fb->obj);
> >  		r = radeon_bo_reserve(rbo, false);
> > @@ -1350,7 +1350,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
> >  	int r;
> >  
> >  	/* no fb bound */
> > -	if (!atomic && !crtc->fb) {
> > +	if (!atomic && !crtc->primary->fb) {
> >  		DRM_DEBUG_KMS("No FB bound\n");
> >  		return 0;
> >  	}
> > @@ -1360,8 +1360,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
> >  		target_fb = fb;
> >  	}
> >  	else {
> > -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> > -		target_fb = crtc->fb;
> > +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> > +		target_fb = crtc->primary->fb;
> >  	}
> >  
> >  	obj = radeon_fb->obj;
> > @@ -1485,7 +1485,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
> >  	/* set pageflip to happen anywhere in vblank interval */
> >  	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> >  
> > -	if (!atomic && fb && fb != crtc->fb) {
> > +	if (!atomic && fb && fb != crtc->primary->fb) {
> >  		radeon_fb = to_radeon_framebuffer(fb);
> >  		rbo = gem_to_radeon_bo(radeon_fb->obj);
> >  		r = radeon_bo_reserve(rbo, false);
> > @@ -1972,12 +1972,12 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
> >  	int i;
> >  
> >  	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
> > -	if (crtc->fb) {
> > +	if (crtc->primary->fb) {
> >  		int r;
> >  		struct radeon_framebuffer *radeon_fb;
> >  		struct radeon_bo *rbo;
> >  
> > -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> > +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> >  		rbo = gem_to_radeon_bo(radeon_fb->obj);
> >  		r = radeon_bo_reserve(rbo, false);
> >  		if (unlikely(r))
> > diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
> > index 030f8e4..b6c3264 100644
> > --- a/drivers/gpu/drm/radeon/r100.c
> > +++ b/drivers/gpu/drm/radeon/r100.c
> > @@ -3220,12 +3220,12 @@ void r100_bandwidth_update(struct radeon_device *rdev)
> >  
> >  	if (rdev->mode_info.crtcs[0]->base.enabled) {
> >  		mode1 = &rdev->mode_info.crtcs[0]->base.mode;
> > -		pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8;
> > +		pixel_bytes1 = rdev->mode_info.crtcs[0]->base.primary->fb->bits_per_pixel / 8;
> >  	}
> >  	if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
> >  		if (rdev->mode_info.crtcs[1]->base.enabled) {
> >  			mode2 = &rdev->mode_info.crtcs[1]->base.mode;
> > -			pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8;
> > +			pixel_bytes2 = rdev->mode_info.crtcs[1]->base.primary->fb->bits_per_pixel / 8;
> >  		}
> >  	}
> >  
> > diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> > index 82d4f86..33b482b 100644
> > --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> > +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> > @@ -89,7 +89,7 @@ static void radeon_property_change_mode(struct drm_encoder *encoder)
> >  
> >  	if (crtc && crtc->enabled) {
> >  		drm_crtc_helper_set_mode(crtc, &crtc->mode,
> > -					 crtc->x, crtc->y, crtc->fb);
> > +					 crtc->x, crtc->y, crtc->primary->fb);
> >  	}
> >  }
> >  
> > diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
> > index 2e72dcd..c524aba 100644
> > --- a/drivers/gpu/drm/radeon/radeon_device.c
> > +++ b/drivers/gpu/drm/radeon/radeon_device.c
> > @@ -1424,7 +1424,8 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
> >  
> >  	/* unpin the front buffers */
> >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > -		struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
> > +		struct radeon_framebuffer *rfb =
> > +			to_radeon_framebuffer(crtc->primary->fb);
> >  		struct radeon_bo *robj;
> >  
> >  		if (rfb == NULL || rfb->obj == NULL) {
> > diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> > index a29d217..4e90049 100644
> > --- a/drivers/gpu/drm/radeon/radeon_display.c
> > +++ b/drivers/gpu/drm/radeon/radeon_display.c
> > @@ -369,7 +369,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
> >  	work->event = event;
> >  	work->rdev = rdev;
> >  	work->crtc_id = radeon_crtc->crtc_id;
> > -	old_radeon_fb = to_radeon_framebuffer(crtc->fb);
> > +	old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> >  	new_radeon_fb = to_radeon_framebuffer(fb);
> >  	/* schedule unpin of the old buffer */
> >  	obj = old_radeon_fb->obj;
> > @@ -460,7 +460,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
> >  	spin_unlock_irqrestore(&dev->event_lock, flags);
> >  
> >  	/* update crtc fb */
> > -	crtc->fb = fb;
> > +	crtc->primary->fb = fb;
> >  
> >  	r = drm_vblank_get(dev, radeon_crtc->crtc_id);
> >  	if (r) {
> > diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
> > index 0b158f9..cafb1cc 100644
> > --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
> > +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
> > @@ -385,7 +385,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
> >  
> >  	DRM_DEBUG_KMS("\n");
> >  	/* no fb bound */
> > -	if (!atomic && !crtc->fb) {
> > +	if (!atomic && !crtc->primary->fb) {
> >  		DRM_DEBUG_KMS("No FB bound\n");
> >  		return 0;
> >  	}
> > @@ -395,8 +395,8 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
> >  		target_fb = fb;
> >  	}
> >  	else {
> > -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> > -		target_fb = crtc->fb;
> > +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> > +		target_fb = crtc->primary->fb;
> >  	}
> >  
> >  	switch (target_fb->bits_per_pixel) {
> > @@ -444,7 +444,7 @@ retry:
> >  		 * We don't shutdown the display controller because new buffer
> >  		 * will end up in same spot.
> >  		 */
> > -		if (!atomic && fb && fb != crtc->fb) {
> > +		if (!atomic && fb && fb != crtc->primary->fb) {
> >  			struct radeon_bo *old_rbo;
> >  			unsigned long nsize, osize;
> >  
> > @@ -555,7 +555,7 @@ retry:
> >  	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset);
> >  	WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
> >  
> > -	if (!atomic && fb && fb != crtc->fb) {
> > +	if (!atomic && fb && fb != crtc->primary->fb) {
> >  		radeon_fb = to_radeon_framebuffer(fb);
> >  		rbo = gem_to_radeon_bo(radeon_fb->obj);
> >  		r = radeon_bo_reserve(rbo, false);
> > @@ -599,7 +599,7 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
> >  		}
> >  	}
> >  
> > -	switch (crtc->fb->bits_per_pixel) {
> > +	switch (crtc->primary->fb->bits_per_pixel) {
> >  	case 8:
> >  		format = 2;
> >  		break;
> > @@ -1087,12 +1087,12 @@ static void radeon_crtc_commit(struct drm_crtc *crtc)
> >  static void radeon_crtc_disable(struct drm_crtc *crtc)
> >  {
> >  	radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
> > -	if (crtc->fb) {
> > +	if (crtc->primary->fb) {
> >  		int r;
> >  		struct radeon_framebuffer *radeon_fb;
> >  		struct radeon_bo *rbo;
> >  
> > -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> > +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> >  		rbo = gem_to_radeon_bo(radeon_fb->obj);
> >  		r = radeon_bo_reserve(rbo, false);
> >  		if (unlikely(r))
> > diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
> > index 1255944..c63b5e7 100644
> > --- a/drivers/gpu/drm/udl/udl_modeset.c
> > +++ b/drivers/gpu/drm/udl/udl_modeset.c
> > @@ -310,7 +310,7 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc,
> >  
> >  {
> >  	struct drm_device *dev = crtc->dev;
> > -	struct udl_framebuffer *ufb = to_udl_fb(crtc->fb);
> > +	struct udl_framebuffer *ufb = to_udl_fb(crtc->primary->fb);
> >  	struct udl_device *udl = dev->dev_private;
> >  	char *buf;
> >  	char *wrptr;
> > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > index 8a65041..1d59ed3 100644
> > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > @@ -468,7 +468,7 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv,
> >  	num_units = 0;
> >  	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list,
> >  			    head) {
> > -		if (crtc->fb != &framebuffer->base)
> > +		if (crtc->primary->fb != &framebuffer->base)
> >  			continue;
> >  		units[num_units++] = vmw_crtc_to_du(crtc);
> >  	}
> > @@ -883,7 +883,7 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
> >  
> >  	num_units = 0;
> >  	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
> > -		if (crtc->fb != &framebuffer->base)
> > +		if (crtc->primary->fb != &framebuffer->base)
> >  			continue;
> >  		units[num_units++] = vmw_crtc_to_du(crtc);
> >  	}
> > @@ -1245,7 +1245,7 @@ int vmw_kms_present(struct vmw_private *dev_priv,
> >  
> >  	num_units = 0;
> >  	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
> > -		if (crtc->fb != &vfb->base)
> > +		if (crtc->primary->fb != &vfb->base)
> >  			continue;
> >  		units[num_units++] = vmw_crtc_to_du(crtc);
> >  	}
> > @@ -1382,7 +1382,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
> >  
> >  	num_units = 0;
> >  	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
> > -		if (crtc->fb != &vfb->base)
> > +		if (crtc->primary->fb != &vfb->base)
> >  			continue;
> >  		units[num_units++] = vmw_crtc_to_du(crtc);
> >  	}
> > @@ -1725,7 +1725,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
> >  		     uint32_t page_flip_flags)
> >  {
> >  	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> > -	struct drm_framebuffer *old_fb = crtc->fb;
> > +	struct drm_framebuffer *old_fb = crtc->primary->fb;
> >  	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
> >  	struct drm_file *file_priv ;
> >  	struct vmw_fence_obj *fence = NULL;
> > @@ -1743,7 +1743,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
> >  	if (!vmw_kms_screen_object_flippable(dev_priv, crtc))
> >  		return -EINVAL;
> >  
> > -	crtc->fb = fb;
> > +	crtc->primary->fb = fb;
> >  
> >  	/* do a full screen dirty update */
> >  	clips.x1 = clips.y1 = 0;
> > @@ -1783,7 +1783,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
> >  	return ret;
> >  
> >  out_no_fence:
> > -	crtc->fb = old_fb;
> > +	crtc->primary->fb = old_fb;
> >  	return ret;
> >  }
> >  
> > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> > index 001ec81..08fdd7f 100644
> > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> > @@ -93,7 +93,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
> >  
> >  		if (crtc == NULL)
> >  			return 0;
> > -		fb = entry->base.crtc.fb;
> > +		fb = entry->base.crtc.primary->fb;
> >  
> >  		return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0],
> >  					  fb->bits_per_pixel, fb->depth);
> > @@ -101,7 +101,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
> >  
> >  	if (!list_empty(&lds->active)) {
> >  		entry = list_entry(lds->active.next, typeof(*entry), active);
> > -		fb = entry->base.crtc.fb;
> > +		fb = entry->base.crtc.primary->fb;
> >  
> >  		vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0],
> >  				   fb->bits_per_pixel, fb->depth);
> > @@ -259,7 +259,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
> >  
> >  		connector->encoder = NULL;
> >  		encoder->crtc = NULL;
> > -		crtc->fb = NULL;
> > +		crtc->primary->fb = NULL;
> >  		crtc->enabled = false;
> >  
> >  		vmw_ldu_del_active(dev_priv, ldu);
> > @@ -280,7 +280,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
> >  
> >  	vmw_fb_off(dev_priv);
> >  
> > -	crtc->fb = fb;
> > +	crtc->primary->fb = fb;
> >  	encoder->crtc = crtc;
> >  	connector->encoder = encoder;
> >  	crtc->x = set->x;
> > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> > index 585da43..46ea096 100644
> > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> > @@ -307,7 +307,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
> >  
> >  		connector->encoder = NULL;
> >  		encoder->crtc = NULL;
> > -		crtc->fb = NULL;
> > +		crtc->primary->fb = NULL;
> >  		crtc->x = 0;
> >  		crtc->y = 0;
> >  		crtc->enabled = false;
> > @@ -368,7 +368,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
> >  
> >  		connector->encoder = NULL;
> >  		encoder->crtc = NULL;
> > -		crtc->fb = NULL;
> > +		crtc->primary->fb = NULL;
> >  		crtc->x = 0;
> >  		crtc->y = 0;
> >  		crtc->enabled = false;
> > @@ -381,7 +381,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
> >  	connector->encoder = encoder;
> >  	encoder->crtc = crtc;
> >  	crtc->mode = *mode;
> > -	crtc->fb = fb;
> > +	crtc->primary->fb = fb;
> >  	crtc->x = set->x;
> >  	crtc->y = set->y;
> >  	crtc->enabled = true;
> > @@ -574,5 +574,5 @@ void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv,
> >  	BUG_ON(!sou->base.is_implicit);
> >  
> >  	dev_priv->sou_priv->implicit_fb =
> > -		vmw_framebuffer_to_vfb(sou->base.crtc.fb);
> > +		vmw_framebuffer_to_vfb(sou->base.crtc.primary->fb);
> >  }
> > diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> > index 4dc84f8..9f7824d 100644
> > --- a/include/drm/drm_crtc.h
> > +++ b/include/drm/drm_crtc.h
> > @@ -309,9 +309,6 @@ struct drm_crtc {
> >  	/* primary plane for CRTC */
> >  	struct drm_plane *primary;
> >  
> > -	/* framebuffer the connector is currently bound to */
> > -	struct drm_framebuffer *fb;
> > -
> >  	/* 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;
> > -- 
> > 1.8.5.1
> > 
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/dri-devel
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Daniel Vetter March 25, 2014, 10:32 a.m. UTC | #3
On Mon, Mar 24, 2014 at 06:20:35PM -0700, Matt Roper wrote:
> On Wed, Mar 19, 2014 at 12:57:21PM +0100, Daniel Vetter wrote:
> > On Tue, Mar 18, 2014 at 05:22:53PM -0700, Matt Roper wrote:
> > > Now that CRTC's have a primary plane, there's no need to track the
> > > framebuffer in the CRTC.  Replace all references to the CRTC fb
> > > with the primary plane's fb.
> > > 
> > > Also note that this simplifies framebuffer removal slightly; we no
> > > longer need to scan all CRTC's and disable the ones that were using the
> > > framebuffer since the existing loop over all planes will take care
> > > of disabling the primary plane (and on most hardware, the CRTC by
> > > extension).
> > > 
> > > v2: Fixup several lingering crtc->fb instances that were missed in the
> > >     first patch iteration.
> > > 
> > > Tested-by: Rob Clark <robdclark@gmail.com>
> > > Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> > 
> > Giant patch again, and I don't think there's any sane way we can avoid
> > this big sed job. Put I think we can make it less intrusive.
> > 
> > First: Have you looked into cocinelle to do this? I'm not sure whether
> > cocinelle is sufficiently type aware, but the upside of using it is that
> > it's much easier to regenerate the patch.
> 
> Good idea!  Yeah, I think Coccinelle should do this pretty easily with
> just:
> 
>         @@ struct drm_crtc *crtc; @@
>         -   crtc->fb
>         +   crtc->primary->fb
> 
>         @@ struct drm_crtc crtc; @@
>         -   crtc.fb
>         +   crtc.primary->fb
> 
> > In any case I think we need to split this into the usual 3 phases to avoid
> > flag days:
> > 
> > 1) Switch to crtc->primary->fb all over the core, but keep crtc->fb fully
> > functional. I.e. update it before calling into drivers and use that to
> > update crtc->primary->fb on return (e.g. in the pageflip ioctl).
> 
> I'm starting to worry that this may be more tricky than it sounded when
> I first read your email.  To be safe, it seems like we'll need to
> sandwich all the various ->funcs-> driver calls in the core between
> prepare_crtc_fbs() / finish_crtc_fbs() or similar since it's hard to
> predict in a universal way when a driver might decide to go look at a
> crtc's framebuffer (or even which crtcs it will decide to look at).
> However even if we do that wrapping, there may be cases where the driver
> calls back into a core helper function after modifying crtc->fb and the
> core won't have that updated value unless we throw in extra sync-up
> points.  
> 
> Is this pretty much what you had in mind or am I overlooking a much
> simpler way to accomplish this?

Hm, you're right that drivers can call back into crtc helpers (not the
core itself), which means doing that in stages is tricky. Which still
covers all the drivers except i915, so doesn't really buy us much. New
transition idea, unfortunately a bit longer.

1) Add crtc->primary and everywhere where we set (i.e. core, crtc helpers,
drivers) crtc->fb also add an assignement for crtc->primary->fb. No
transition assignment like crtc->primary->fb = crtc->fb and the other way
round in the core.

This should help a lot since we have about 300 places which look at
crtc->fb, but only 30 which change crtc->fb. Most of them in the core +
crct helpers, i915 (our own modeset infrastructure) and vmwgfx. So this
should be much simpler to get in without a giant mess.

2) Transition all parts to look at crtc->primary->fb at least, but keep
assigning to both.

3) Once 2) is complete, rip out the crtc->fb assignments and remove
crtc->fb.

Does this one here sound more workable? It's still a bit a flag day thing
but easier to manage than one massive subsystem wide sed job touching 300
places ...

One downside is that we can't enlist the compilers help for 1), but if you
have the entire patch-series ready (with the patches in 2) generated with
cocinelle) we can still compile-check the end-result, which should be good
enough to catch everything.

Cheers, Daniel
> 
> 
> Matt
> 
> > 
> > 2) Switch drivers over to look at crtc->primary->fb. This way we can even
> > split up the patch into per-driver patches which gives driver maintainers
> > more wiggle room.
> > 
> > 3) Kill crtc->fb.
> > 
> > Steps 2&3 don't block merging of the universal planes support at all. So
> > we could get the core support in all early for 3.16, then let driver
> > maintainers pick up patche for 2 and shortly before the 3.16 merge window
> > opens send a pull request with all the stragglers and step 3.
> > 
> > No comments on the actual patch, the few functional changes hidden in the
> > massive diff looked ok. But hard to review properly ;-)
> > 
> > Cheers, Daniel
> > 
> > > ---
> > >  drivers/gpu/drm/ast/ast_mode.c               |  12 +--
> > >  drivers/gpu/drm/bochs/bochs_kms.c            |   4 +-
> > >  drivers/gpu/drm/cirrus/cirrus_mode.c         |  10 +-
> > >  drivers/gpu/drm/drm_crtc.c                   |  56 ++++------
> > >  drivers/gpu/drm/drm_crtc_helper.c            |  21 ++--
> > >  drivers/gpu/drm/drm_fb_helper.c              |   6 +-
> > >  drivers/gpu/drm/gma500/cdv_intel_display.c   |   2 +-
> > >  drivers/gpu/drm/gma500/cdv_intel_dp.c        |   2 +-
> > >  drivers/gpu/drm/gma500/cdv_intel_hdmi.c      |   3 +-
> > >  drivers/gpu/drm/gma500/cdv_intel_lvds.c      |   2 +-
> > >  drivers/gpu/drm/gma500/gma_display.c         |  17 ++--
> > >  drivers/gpu/drm/gma500/mdfld_dsi_output.c    |   2 +-
> > >  drivers/gpu/drm/gma500/mdfld_intel_display.c |  17 ++--
> > >  drivers/gpu/drm/gma500/oaktrail_crtc.c       |  13 +--
> > >  drivers/gpu/drm/gma500/psb_intel_display.c   |   2 +-
> > >  drivers/gpu/drm/gma500/psb_intel_lvds.c      |   2 +-
> > >  drivers/gpu/drm/gma500/psb_intel_sdvo.c      |   2 +-
> > >  drivers/gpu/drm/i915/i915_debugfs.c          |   4 +-
> > >  drivers/gpu/drm/i915/i915_irq.c              |   4 +-
> > >  drivers/gpu/drm/i915/intel_display.c         | 147 ++++++++++++++-------------
> > >  drivers/gpu/drm/i915/intel_dp.c              |   5 +-
> > >  drivers/gpu/drm/i915/intel_fbdev.c           |   6 +-
> > >  drivers/gpu/drm/i915/intel_overlay.c         |   4 +-
> > >  drivers/gpu/drm/i915/intel_pm.c              |  36 +++----
> > >  drivers/gpu/drm/mgag200/mgag200_mode.c       |  28 ++---
> > >  drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c     |  28 ++---
> > >  drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c     |  22 ++--
> > >  drivers/gpu/drm/nouveau/dispnv04/crtc.c      |  20 ++--
> > >  drivers/gpu/drm/nouveau/dispnv04/dfp.c       |   2 +-
> > >  drivers/gpu/drm/nouveau/nouveau_display.c    |   8 +-
> > >  drivers/gpu/drm/nouveau/nv50_display.c       |  17 ++--
> > >  drivers/gpu/drm/qxl/qxl_display.c            |  11 +-
> > >  drivers/gpu/drm/radeon/atombios_crtc.c       |  20 ++--
> > >  drivers/gpu/drm/radeon/r100.c                |   4 +-
> > >  drivers/gpu/drm/radeon/radeon_connectors.c   |   2 +-
> > >  drivers/gpu/drm/radeon/radeon_device.c       |   3 +-
> > >  drivers/gpu/drm/radeon/radeon_display.c      |   4 +-
> > >  drivers/gpu/drm/radeon/radeon_legacy_crtc.c  |  16 +--
> > >  drivers/gpu/drm/udl/udl_modeset.c            |   2 +-
> > >  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c          |  14 +--
> > >  drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c          |   8 +-
> > >  drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c         |   8 +-
> > >  include/drm/drm_crtc.h                       |   3 -
> > >  43 files changed, 300 insertions(+), 299 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
> > > index 44f0d32..bd1e156 100644
> > > --- a/drivers/gpu/drm/ast/ast_mode.c
> > > +++ b/drivers/gpu/drm/ast/ast_mode.c
> > > @@ -81,7 +81,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
> > >  	u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate;
> > >  	u32 hborder, vborder;
> > >  
> > > -	switch (crtc->fb->bits_per_pixel) {
> > > +	switch (crtc->primary->fb->bits_per_pixel) {
> > >  	case 8:
> > >  		vbios_mode->std_table = &vbios_stdtable[VGAModeIndex];
> > >  		color_index = VGAModeIndex - 1;
> > > @@ -176,7 +176,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
> > >  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff);
> > >  
> > >  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
> > > -		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->fb->bits_per_pixel);
> > > +		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->primary->fb->bits_per_pixel);
> > >  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000);
> > >  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay);
> > >  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8);
> > > @@ -340,7 +340,7 @@ static void ast_set_offset_reg(struct drm_crtc *crtc)
> > >  
> > >  	u16 offset;
> > >  
> > > -	offset = crtc->fb->pitches[0] >> 3;
> > > +	offset = crtc->primary->fb->pitches[0] >> 3;
> > >  	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff));
> > >  	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f);
> > >  }
> > > @@ -365,7 +365,7 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode
> > >  	struct ast_private *ast = crtc->dev->dev_private;
> > >  	u8 jregA0 = 0, jregA3 = 0, jregA8 = 0;
> > >  
> > > -	switch (crtc->fb->bits_per_pixel) {
> > > +	switch (crtc->primary->fb->bits_per_pixel) {
> > >  	case 8:
> > >  		jregA0 = 0x70;
> > >  		jregA3 = 0x01;
> > > @@ -418,7 +418,7 @@ static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mo
> > >  static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
> > >  		     struct ast_vbios_mode_info *vbios_mode)
> > >  {
> > > -	switch (crtc->fb->bits_per_pixel) {
> > > +	switch (crtc->primary->fb->bits_per_pixel) {
> > >  	case 8:
> > >  		break;
> > >  	default:
> > > @@ -490,7 +490,7 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc,
> > >  		ast_bo_unreserve(bo);
> > >  	}
> > >  
> > > -	ast_fb = to_ast_framebuffer(crtc->fb);
> > > +	ast_fb = to_ast_framebuffer(crtc->primary->fb);
> > >  	obj = ast_fb->obj;
> > >  	bo = gem_to_ast_bo(obj);
> > >  
> > > diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
> > > index 182f5c9..b67ad12 100644
> > > --- a/drivers/gpu/drm/bochs/bochs_kms.c
> > > +++ b/drivers/gpu/drm/bochs/bochs_kms.c
> > > @@ -62,10 +62,10 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> > >  		}
> > >  	}
> > >  
> > > -	if (WARN_ON(crtc->fb == NULL))
> > > +	if (WARN_ON(crtc->primary->fb == NULL))
> > >  		return -EINVAL;
> > >  
> > > -	bochs_fb = to_bochs_framebuffer(crtc->fb);
> > > +	bochs_fb = to_bochs_framebuffer(crtc->primary->fb);
> > >  	bo = gem_to_bochs_bo(bochs_fb->obj);
> > >  	ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
> > >  	if (ret)
> > > diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
> > > index 449246f..5291d2f 100644
> > > --- a/drivers/gpu/drm/cirrus/cirrus_mode.c
> > > +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
> > > @@ -149,7 +149,7 @@ static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
> > >  		cirrus_bo_unreserve(bo);
> > >  	}
> > >  
> > > -	cirrus_fb = to_cirrus_framebuffer(crtc->fb);
> > > +	cirrus_fb = to_cirrus_framebuffer(crtc->primary->fb);
> > >  	obj = cirrus_fb->obj;
> > >  	bo = gem_to_cirrus_bo(obj);
> > >  
> > > @@ -268,7 +268,7 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
> > >  	sr07 = RREG8(SEQ_DATA);
> > >  	sr07 &= 0xe0;
> > >  	hdr = 0;
> > > -	switch (crtc->fb->bits_per_pixel) {
> > > +	switch (crtc->primary->fb->bits_per_pixel) {
> > >  	case 8:
> > >  		sr07 |= 0x11;
> > >  		break;
> > > @@ -291,13 +291,13 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
> > >  	WREG_SEQ(0x7, sr07);
> > >  
> > >  	/* Program the pitch */
> > > -	tmp = crtc->fb->pitches[0] / 8;
> > > +	tmp = crtc->primary->fb->pitches[0] / 8;
> > >  	WREG_CRT(VGA_CRTC_OFFSET, tmp);
> > >  
> > >  	/* Enable extended blanking and pitch bits, and enable full memory */
> > >  	tmp = 0x22;
> > > -	tmp |= (crtc->fb->pitches[0] >> 7) & 0x10;
> > > -	tmp |= (crtc->fb->pitches[0] >> 6) & 0x40;
> > > +	tmp |= (crtc->primary->fb->pitches[0] >> 7) & 0x10;
> > > +	tmp |= (crtc->primary->fb->pitches[0] >> 6) & 0x40;
> > >  	WREG_CRT(0x1b, tmp);
> > >  
> > >  	/* Enable high-colour modes */
> > > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> > > index 0feb66cc..0c395e8 100644
> > > --- a/drivers/gpu/drm/drm_crtc.c
> > > +++ b/drivers/gpu/drm/drm_crtc.c
> > > @@ -634,7 +634,7 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
> > >   * drm_framebuffer_remove - remove and unreference a framebuffer object
> > >   * @fb: framebuffer to remove
> > >   *
> > > - * Scans all the CRTCs and planes in @dev's mode_config.  If they're
> > > + * Scans all the planes in @dev's mode_config.  If they're
> > >   * using @fb, removes it, setting it to NULL. Then drops the reference to the
> > >   * passed-in framebuffer. Might take the modeset locks.
> > >   *
> > > @@ -645,10 +645,7 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
> > >  void drm_framebuffer_remove(struct drm_framebuffer *fb)
> > >  {
> > >  	struct drm_device *dev = fb->dev;
> > > -	struct drm_crtc *crtc;
> > >  	struct drm_plane *plane;
> > > -	struct drm_mode_set set;
> > > -	int ret;
> > >  
> > >  	WARN_ON(!list_empty(&fb->filp_head));
> > >  
> > > @@ -669,19 +666,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
> > >  	 */
> > >  	if (atomic_read(&fb->refcount.refcount) > 1) {
> > >  		drm_modeset_lock_all(dev);
> > > -		/* remove from any CRTC */
> > > -		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > > -			if (crtc->fb == fb) {
> > > -				/* should turn off the crtc */
> > > -				memset(&set, 0, sizeof(struct drm_mode_set));
> > > -				set.crtc = crtc;
> > > -				set.fb = NULL;
> > > -				ret = drm_mode_set_config_internal(&set);
> > > -				if (ret)
> > > -					DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
> > > -			}
> > > -		}
> > > -
> > > +		/* remove from any plane */
> > >  		list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
> > >  			if (plane->fb == fb)
> > >  				drm_plane_force_disable(plane);
> > > @@ -1930,8 +1915,8 @@ int drm_mode_getcrtc(struct drm_device *dev,
> > >  	crtc_resp->x = crtc->x;
> > >  	crtc_resp->y = crtc->y;
> > >  	crtc_resp->gamma_size = crtc->gamma_size;
> > > -	if (crtc->fb)
> > > -		crtc_resp->fb_id = crtc->fb->base.id;
> > > +	if (crtc->primary->fb)
> > > +		crtc_resp->fb_id = crtc->primary->fb->base.id;
> > >  	else
> > >  		crtc_resp->fb_id = 0;
> > >  
> > > @@ -2438,7 +2423,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
> > >  	 * crtcs. Atomic modeset will have saner semantics ...
> > >  	 */
> > >  	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
> > > -		tmp->old_fb = tmp->fb;
> > > +		tmp->old_fb = tmp->primary->fb;
> > >  
> > >  	fb = set->fb;
> > >  
> > > @@ -2446,13 +2431,16 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
> > >  	if (ret == 0) {
> > >  		crtc->primary->crtc = crtc;
> > >  
> > > -		/* crtc->fb must be updated by ->set_config, enforces this. */
> > > -		WARN_ON(fb != crtc->fb);
> > > +		/*
> > > +		 * crtc->primary->fb must be updated by ->set_config,
> > > +		 * enforces this.
> > > +		 */
> > > +		WARN_ON(fb != crtc->primary->fb);
> > >  	}
> > >  
> > >  	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
> > > -		if (tmp->fb)
> > > -			drm_framebuffer_reference(tmp->fb);
> > > +		if (tmp->primary->fb)
> > > +			drm_framebuffer_reference(tmp->primary->fb);
> > >  		if (tmp->old_fb)
> > >  			drm_framebuffer_unreference(tmp->old_fb);
> > >  	}
> > > @@ -2511,12 +2499,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
> > >  		/* If we have a mode we need a framebuffer. */
> > >  		/* If we pass -1, set the mode with the currently bound fb */
> > >  		if (crtc_req->fb_id == -1) {
> > > -			if (!crtc->fb) {
> > > +			if (!crtc->primary->fb) {
> > >  				DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
> > >  				ret = -EINVAL;
> > >  				goto out;
> > >  			}
> > > -			fb = crtc->fb;
> > > +			fb = crtc->primary->fb;
> > >  			/* Make refcounting symmetric with the lookup path. */
> > >  			drm_framebuffer_reference(fb);
> > >  		} else {
> > > @@ -4309,7 +4297,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
> > >  	crtc = obj_to_crtc(obj);
> > >  
> > >  	mutex_lock(&crtc->mutex);
> > > -	if (crtc->fb == NULL) {
> > > +	if (crtc->primary->fb == NULL) {
> > >  		/* The framebuffer is currently unbound, presumably
> > >  		 * due to a hotplug event, that userspace has not
> > >  		 * yet discovered.
> > > @@ -4331,7 +4319,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
> > >  	if (ret)
> > >  		goto out;
> > >  
> > > -	if (crtc->fb->pixel_format != fb->pixel_format) {
> > > +	if (crtc->primary->fb->pixel_format != fb->pixel_format) {
> > >  		DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
> > >  		ret = -EINVAL;
> > >  		goto out;
> > > @@ -4364,7 +4352,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
> > >  			(void (*) (struct drm_pending_event *)) kfree;
> > >  	}
> > >  
> > > -	old_fb = crtc->fb;
> > > +	old_fb = crtc->primary->fb;
> > >  	ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
> > >  	if (ret) {
> > >  		if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
> > > @@ -4377,12 +4365,12 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
> > >  		old_fb = NULL;
> > >  	} else {
> > >  		/*
> > > -		 * Warn if the driver hasn't properly updated the crtc->fb
> > > -		 * field to reflect that the new framebuffer is now used.
> > > -		 * Failing to do so will screw with the reference counting
> > > -		 * on framebuffers.
> > > +		 * Warn if the driver hasn't properly updated the
> > > +		 * crtc->primary->fb field to reflect that the new framebuffer
> > > +		 * is now used.  Failing to do so will screw with the reference
> > > +		 * counting on framebuffers.
> > >  		 */
> > > -		WARN_ON(crtc->fb != fb);
> > > +		WARN_ON(crtc->primary->fb != fb);
> > >  		/* Unref only the old framebuffer. */
> > >  		fb = NULL;
> > >  	}
> > > diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> > > index a855178..8825afb 100644
> > > --- a/drivers/gpu/drm/drm_crtc_helper.c
> > > +++ b/drivers/gpu/drm/drm_crtc_helper.c
> > > @@ -319,7 +319,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
> > >  				(*crtc_funcs->disable)(crtc);
> > >  			else
> > >  				(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
> > > -			crtc->fb = NULL;
> > > +			crtc->primary->fb = NULL;
> > >  		}
> > >  	}
> > >  }
> > > @@ -646,19 +646,19 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
> > >  	save_set.mode = &set->crtc->mode;
> > >  	save_set.x = set->crtc->x;
> > >  	save_set.y = set->crtc->y;
> > > -	save_set.fb = set->crtc->fb;
> > > +	save_set.fb = set->crtc->primary->fb;
> > >  
> > >  	/* We should be able to check here if the fb has the same properties
> > >  	 * and then just flip_or_move it */
> > > -	if (set->crtc->fb != set->fb) {
> > > +	if (set->crtc->primary->fb != set->fb) {
> > >  		/* If we have no fb then treat it as a full mode set */
> > > -		if (set->crtc->fb == NULL) {
> > > +		if (set->crtc->primary->fb == NULL) {
> > >  			DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
> > >  			mode_changed = true;
> > >  		} else if (set->fb == NULL) {
> > >  			mode_changed = true;
> > >  		} else if (set->fb->pixel_format !=
> > > -			   set->crtc->fb->pixel_format) {
> > > +			   set->crtc->primary->fb->pixel_format) {
> > >  			mode_changed = true;
> > >  		} else
> > >  			fb_changed = true;
> > > @@ -759,13 +759,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
> > >  			DRM_DEBUG_KMS("attempting to set mode from"
> > >  					" userspace\n");
> > >  			drm_mode_debug_printmodeline(set->mode);
> > > -			set->crtc->fb = set->fb;
> > > +			set->crtc->primary->fb = set->fb;
> > >  			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
> > >  						      set->x, set->y,
> > >  						      save_set.fb)) {
> > >  				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
> > >  					  set->crtc->base.id);
> > > -				set->crtc->fb = save_set.fb;
> > > +				set->crtc->primary->fb = save_set.fb;
> > >  				ret = -EINVAL;
> > >  				goto fail;
> > >  			}
> > > @@ -780,13 +780,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
> > >  	} else if (fb_changed) {
> > >  		set->crtc->x = set->x;
> > >  		set->crtc->y = set->y;
> > > -		set->crtc->fb = set->fb;
> > > +		set->crtc->primary->fb = set->fb;
> > >  		ret = crtc_funcs->mode_set_base(set->crtc,
> > >  						set->x, set->y, save_set.fb);
> > >  		if (ret != 0) {
> > >  			set->crtc->x = save_set.x;
> > >  			set->crtc->y = save_set.y;
> > > -			set->crtc->fb = save_set.fb;
> > > +			set->crtc->primary->fb = save_set.fb;
> > >  			goto fail;
> > >  		}
> > >  	}
> > > @@ -982,7 +982,8 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
> > >  			continue;
> > >  
> > >  		ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
> > > -					       crtc->x, crtc->y, crtc->fb);
> > > +					       crtc->x, crtc->y,
> > > +					       crtc->primary->fb);
> > >  
> > >  		/* Restoring the old config should never fail! */
> > >  		if (ret == false)
> > > diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> > > index 9c6251f..e8e2b41 100644
> > > --- a/drivers/gpu/drm/drm_fb_helper.c
> > > +++ b/drivers/gpu/drm/drm_fb_helper.c
> > > @@ -232,7 +232,7 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
> > >  
> > >  	list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
> > >  		if (crtc->base.id == c->base.id)
> > > -			return c->fb;
> > > +			return c->primary->fb;
> > >  	}
> > >  
> > >  	return NULL;
> > > @@ -366,9 +366,9 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
> > >  		return false;
> > >  
> > >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > > -		if (crtc->fb)
> > > +		if (crtc->primary->fb)
> > >  			crtcs_bound++;
> > > -		if (crtc->fb == fb_helper->fb)
> > > +		if (crtc->primary->fb == fb_helper->fb)
> > >  			bound++;
> > >  	}
> > >  
> > > diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c
> > > index 8fbfa06..1cddcf8 100644
> > > --- a/drivers/gpu/drm/gma500/cdv_intel_display.c
> > > +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c
> > > @@ -463,7 +463,7 @@ static bool cdv_intel_pipe_enabled(struct drm_device *dev, int pipe)
> > >  	crtc = dev_priv->pipe_to_crtc_mapping[pipe];
> > >  	gma_crtc = to_gma_crtc(crtc);
> > >  
> > > -	if (crtc->fb == NULL || !gma_crtc->active)
> > > +	if (crtc->primary->fb == NULL || !gma_crtc->active)
> > >  		return false;
> > >  	return true;
> > >  }
> > > diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
> > > index 0490ce3..9ff30c2 100644
> > > --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
> > > +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
> > > @@ -1693,7 +1693,7 @@ done:
> > >  		struct drm_crtc *crtc = encoder->base.crtc;
> > >  		drm_crtc_helper_set_mode(crtc, &crtc->mode,
> > >  					 crtc->x, crtc->y,
> > > -					 crtc->fb);
> > > +					 crtc->primary->fb);
> > >  	}
> > >  
> > >  	return 0;
> > > diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
> > > index 1c0d723..04956e6 100644
> > > --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
> > > +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
> > > @@ -199,7 +199,8 @@ static int cdv_hdmi_set_property(struct drm_connector *connector,
> > >  		    crtc->saved_mode.vdisplay != 0) {
> > >  			if (centre) {
> > >  				if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode,
> > > -					    encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
> > > +					    encoder->crtc->x, encoder->crtc->y,
> > > +					    encoder->crtc->primary->fb))
> > >  					return -1;
> > >  			} else {
> > >  				struct drm_encoder_helper_funcs *helpers
> > > diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
> > > index 20e08e6..58f11df 100644
> > > --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
> > > +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
> > > @@ -494,7 +494,7 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector,
> > >  						      &crtc->saved_mode,
> > >  						      encoder->crtc->x,
> > >  						      encoder->crtc->y,
> > > -						      encoder->crtc->fb))
> > > +						      encoder->crtc->primary->fb))
> > >  				return -1;
> > >  		}
> > >  	} else if (!strcmp(property->name, "backlight") && encoder) {
> > > diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
> > > index 386de2c..7b73dd1 100644
> > > --- a/drivers/gpu/drm/gma500/gma_display.c
> > > +++ b/drivers/gpu/drm/gma500/gma_display.c
> > > @@ -59,7 +59,7 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct drm_psb_private *dev_priv = dev->dev_private;
> > >  	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
> > > -	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
> > > +	struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
> > >  	int pipe = gma_crtc->pipe;
> > >  	const struct psb_offset *map = &dev_priv->regmap[pipe];
> > >  	unsigned long start, offset;
> > > @@ -70,7 +70,7 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> > >  		return 0;
> > >  
> > >  	/* no fb bound */
> > > -	if (!crtc->fb) {
> > > +	if (!crtc->primary->fb) {
> > >  		dev_err(dev->dev, "No FB bound\n");
> > >  		goto gma_pipe_cleaner;
> > >  	}
> > > @@ -81,19 +81,20 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> > >  	if (ret < 0)
> > >  		goto gma_pipe_set_base_exit;
> > >  	start = psbfb->gtt->offset;
> > > -	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
> > > +	offset = y * crtc->primary->fb->pitches[0] +
> > > +		x * (crtc->primary->fb->bits_per_pixel / 8);
> > >  
> > > -	REG_WRITE(map->stride, crtc->fb->pitches[0]);
> > > +	REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
> > >  
> > >  	dspcntr = REG_READ(map->cntr);
> > >  	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
> > >  
> > > -	switch (crtc->fb->bits_per_pixel) {
> > > +	switch (crtc->primary->fb->bits_per_pixel) {
> > >  	case 8:
> > >  		dspcntr |= DISPPLANE_8BPP;
> > >  		break;
> > >  	case 16:
> > > -		if (crtc->fb->depth == 15)
> > > +		if (crtc->primary->fb->depth == 15)
> > >  			dspcntr |= DISPPLANE_15_16BPP;
> > >  		else
> > >  			dspcntr |= DISPPLANE_16BPP;
> > > @@ -511,8 +512,8 @@ void gma_crtc_disable(struct drm_crtc *crtc)
> > >  
> > >  	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
> > >  
> > > -	if (crtc->fb) {
> > > -		gt = to_psb_fb(crtc->fb)->gtt;
> > > +	if (crtc->primary->fb) {
> > > +		gt = to_psb_fb(crtc->primary->fb)->gtt;
> > >  		psb_gtt_unpin(gt);
> > >  	}
> > >  }
> > > diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> > > index 860a4ee..6e91b20 100644
> > > --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> > > +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> > > @@ -287,7 +287,7 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
> > >  						&gma_crtc->saved_mode,
> > >  						encoder->crtc->x,
> > >  						encoder->crtc->y,
> > > -						encoder->crtc->fb))
> > > +						encoder->crtc->primary->fb))
> > >  					goto set_prop_error;
> > >  			} else {
> > >  				struct drm_encoder_helper_funcs *funcs =
> > > diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c
> > > index 321c00a..c54386a 100644
> > > --- a/drivers/gpu/drm/gma500/mdfld_intel_display.c
> > > +++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c
> > > @@ -166,7 +166,7 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct drm_psb_private *dev_priv = dev->dev_private;
> > >  	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
> > > -	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
> > > +	struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
> > >  	int pipe = gma_crtc->pipe;
> > >  	const struct psb_offset *map = &dev_priv->regmap[pipe];
> > >  	unsigned long start, offset;
> > > @@ -178,12 +178,12 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> > >  	dev_dbg(dev->dev, "pipe = 0x%x.\n", pipe);
> > >  
> > >  	/* no fb bound */
> > > -	if (!crtc->fb) {
> > > +	if (!crtc->primary->fb) {
> > >  		dev_dbg(dev->dev, "No FB bound\n");
> > >  		return 0;
> > >  	}
> > >  
> > > -	ret = check_fb(crtc->fb);
> > > +	ret = check_fb(crtc->primary->fb);
> > >  	if (ret)
> > >  		return ret;
> > >  
> > > @@ -196,18 +196,19 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> > >  		return 0;
> > >  
> > >  	start = psbfb->gtt->offset;
> > > -	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
> > > +	offset = y * crtc->primary->fb->pitches[0] +
> > > +		x * (crtc->primary->fb->bits_per_pixel / 8);
> > >  
> > > -	REG_WRITE(map->stride, crtc->fb->pitches[0]);
> > > +	REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
> > >  	dspcntr = REG_READ(map->cntr);
> > >  	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
> > >  
> > > -	switch (crtc->fb->bits_per_pixel) {
> > > +	switch (crtc->primary->fb->bits_per_pixel) {
> > >  	case 8:
> > >  		dspcntr |= DISPPLANE_8BPP;
> > >  		break;
> > >  	case 16:
> > > -		if (crtc->fb->depth == 15)
> > > +		if (crtc->primary->fb->depth == 15)
> > >  			dspcntr |= DISPPLANE_15_16BPP;
> > >  		else
> > >  			dspcntr |= DISPPLANE_16BPP;
> > > @@ -700,7 +701,7 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
> > >  	}
> > >  #endif
> > >  
> > > -	ret = check_fb(crtc->fb);
> > > +	ret = check_fb(crtc->primary->fb);
> > >  	if (ret)
> > >  		return ret;
> > >  
> > > diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c
> > > index 8195e85..b0fb42a 100644
> > > --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c
> > > +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c
> > > @@ -599,7 +599,7 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct drm_psb_private *dev_priv = dev->dev_private;
> > >  	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
> > > -	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
> > > +	struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
> > >  	int pipe = gma_crtc->pipe;
> > >  	const struct psb_offset *map = &dev_priv->regmap[pipe];
> > >  	unsigned long start, offset;
> > > @@ -608,7 +608,7 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
> > >  	int ret = 0;
> > >  
> > >  	/* no fb bound */
> > > -	if (!crtc->fb) {
> > > +	if (!crtc->primary->fb) {
> > >  		dev_dbg(dev->dev, "No FB bound\n");
> > >  		return 0;
> > >  	}
> > > @@ -617,19 +617,20 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
> > >  		return 0;
> > >  
> > >  	start = psbfb->gtt->offset;
> > > -	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
> > > +	offset = y * crtc->primary->fb->pitches[0] +
> > > +		x * (crtc->primary->fb->bits_per_pixel / 8);
> > >  
> > > -	REG_WRITE(map->stride, crtc->fb->pitches[0]);
> > > +	REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
> > >  
> > >  	dspcntr = REG_READ(map->cntr);
> > >  	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
> > >  
> > > -	switch (crtc->fb->bits_per_pixel) {
> > > +	switch (crtc->primary->fb->bits_per_pixel) {
> > >  	case 8:
> > >  		dspcntr |= DISPPLANE_8BPP;
> > >  		break;
> > >  	case 16:
> > > -		if (crtc->fb->depth == 15)
> > > +		if (crtc->primary->fb->depth == 15)
> > >  			dspcntr |= DISPPLANE_15_16BPP;
> > >  		else
> > >  			dspcntr |= DISPPLANE_16BPP;
> > > diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c
> > > index c8f833d..25c174c 100644
> > > --- a/drivers/gpu/drm/gma500/psb_intel_display.c
> > > +++ b/drivers/gpu/drm/gma500/psb_intel_display.c
> > > @@ -120,7 +120,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
> > >  	const struct gma_limit_t *limit;
> > >  
> > >  	/* No scan out no play */
> > > -	if (crtc->fb == NULL) {
> > > +	if (crtc->primary->fb == NULL) {
> > >  		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
> > >  		return 0;
> > >  	}
> > > diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
> > > index 32342f6..dcdf70e 100644
> > > --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
> > > +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
> > > @@ -614,7 +614,7 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
> > >  						      &crtc->saved_mode,
> > >  						      encoder->crtc->x,
> > >  						      encoder->crtc->y,
> > > -						      encoder->crtc->fb))
> > > +						      encoder->crtc->primary->fb))
> > >  				goto set_prop_error;
> > >  		}
> > >  	} else if (!strcmp(property->name, "backlight")) {
> > > diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
> > > index 07d3a9e..1c0a2fb 100644
> > > --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
> > > +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
> > > @@ -1844,7 +1844,7 @@ done:
> > >  	if (psb_intel_sdvo->base.base.crtc) {
> > >  		struct drm_crtc *crtc = psb_intel_sdvo->base.base.crtc;
> > >  		drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
> > > -					 crtc->y, crtc->fb);
> > > +					 crtc->y, crtc->primary->fb);
> > >  	}
> > >  
> > >  	return 0;
> > > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> > > index d83d643..f00ba43 100644
> > > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > > @@ -2172,8 +2172,8 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc)
> > >  	struct intel_encoder *intel_encoder;
> > >  
> > >  	seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
> > > -		   crtc->fb->base.id, crtc->x, crtc->y,
> > > -		   crtc->fb->width, crtc->fb->height);
> > > +		   crtc->primary->fb->base.id, crtc->x, crtc->y,
> > > +		   crtc->primary->fb->width, crtc->primary->fb->height);
> > >  	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
> > >  		intel_encoder_info(m, intel_crtc, intel_encoder);
> > >  }
> > > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > > index 37f852d..e8b3f9f 100644
> > > --- a/drivers/gpu/drm/i915/i915_irq.c
> > > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > > @@ -2380,8 +2380,8 @@ static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, in
> > >  	} else {
> > >  		int dspaddr = DSPADDR(intel_crtc->plane);
> > >  		stall_detected = I915_READ(dspaddr) == (i915_gem_obj_ggtt_offset(obj) +
> > > -							crtc->y * crtc->fb->pitches[0] +
> > > -							crtc->x * crtc->fb->bits_per_pixel/8);
> > > +							crtc->y * crtc->primary->fb->pitches[0] +
> > > +							crtc->x * crtc->primary->fb->bits_per_pixel/8);
> > >  	}
> > >  
> > >  	spin_unlock_irqrestore(&dev->event_lock, flags);
> > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > > index 21d12a9..c2f3730 100644
> > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > @@ -744,7 +744,7 @@ bool intel_crtc_active(struct drm_crtc *crtc)
> > >  	 * We can ditch the crtc->fb check as soon as we can
> > >  	 * properly reconstruct framebuffers.
> > >  	 */
> > > -	return intel_crtc->active && crtc->fb &&
> > > +	return intel_crtc->active && crtc->primary->fb &&
> > >  		intel_crtc->config.adjusted_mode.crtc_clock;
> > >  }
> > >  
> > > @@ -2086,17 +2086,18 @@ static bool intel_alloc_plane_obj(struct intel_crtc *crtc,
> > >  
> > >  	if (plane_config->tiled) {
> > >  		obj->tiling_mode = I915_TILING_X;
> > > -		obj->stride = crtc->base.fb->pitches[0];
> > > +		obj->stride = crtc->base.primary->fb->pitches[0];
> > >  	}
> > >  
> > > -	mode_cmd.pixel_format = crtc->base.fb->pixel_format;
> > > -	mode_cmd.width = crtc->base.fb->width;
> > > -	mode_cmd.height = crtc->base.fb->height;
> > > -	mode_cmd.pitches[0] = crtc->base.fb->pitches[0];
> > > +	mode_cmd.pixel_format = crtc->base.primary->fb->pixel_format;
> > > +	mode_cmd.width = crtc->base.primary->fb->width;
> > > +	mode_cmd.height = crtc->base.primary->fb->height;
> > > +	mode_cmd.pitches[0] = crtc->base.primary->fb->pitches[0];
> > >  
> > >  	mutex_lock(&dev->struct_mutex);
> > >  
> > > -	if (intel_framebuffer_init(dev, to_intel_framebuffer(crtc->base.fb),
> > > +	if (intel_framebuffer_init(dev,
> > > +				   to_intel_framebuffer(crtc->base.primary->fb),
> > >  				   &mode_cmd, obj)) {
> > >  		DRM_DEBUG_KMS("intel fb init failed\n");
> > >  		goto out_unref_obj;
> > > @@ -2121,14 +2122,14 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
> > >  	struct intel_crtc *i;
> > >  	struct intel_framebuffer *fb;
> > >  
> > > -	if (!intel_crtc->base.fb)
> > > +	if (!intel_crtc->base.primary->fb)
> > >  		return;
> > >  
> > >  	if (intel_alloc_plane_obj(intel_crtc, plane_config))
> > >  		return;
> > >  
> > > -	kfree(intel_crtc->base.fb);
> > > -	intel_crtc->base.fb = NULL;
> > > +	kfree(intel_crtc->base.primary->fb);
> > > +	intel_crtc->base.primary->fb = NULL;
> > >  
> > >  	/*
> > >  	 * Failed to alloc the obj, check to see if we should share
> > > @@ -2140,13 +2141,13 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
> > >  		if (c == &intel_crtc->base)
> > >  			continue;
> > >  
> > > -		if (!i->active || !c->fb)
> > > +		if (!i->active || !c->primary->fb)
> > >  			continue;
> > >  
> > > -		fb = to_intel_framebuffer(c->fb);
> > > +		fb = to_intel_framebuffer(c->primary->fb);
> > >  		if (i915_gem_obj_ggtt_offset(fb->obj) == plane_config->base) {
> > > -			drm_framebuffer_reference(c->fb);
> > > -			intel_crtc->base.fb = c->fb;
> > > +			drm_framebuffer_reference(c->primary->fb);
> > > +			intel_crtc->base.primary->fb = c->primary->fb;
> > >  			break;
> > >  		}
> > >  	}
> > > @@ -2394,11 +2395,13 @@ void intel_display_handle_reset(struct drm_device *dev)
> > >  		/*
> > >  		 * FIXME: Once we have proper support for primary planes (and
> > >  		 * disabling them without disabling the entire crtc) allow again
> > > -		 * a NULL crtc->fb.
> > > +		 * a NULL crtc->primary->fb.
> > >  		 */
> > > -		if (intel_crtc->active && crtc->fb)
> > > -			dev_priv->display.update_plane(crtc, crtc->fb,
> > > -						       crtc->x, crtc->y);
> > > +		if (intel_crtc->active && crtc->primary->fb)
> > > +			dev_priv->display.update_plane(crtc,
> > > +						       crtc->primary->fb,
> > > +						       crtc->x,
> > > +						       crtc->y);
> > >  		mutex_unlock(&crtc->mutex);
> > >  	}
> > >  }
> > > @@ -2523,8 +2526,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> > >  		return ret;
> > >  	}
> > >  
> > > -	old_fb = crtc->fb;
> > > -	crtc->fb = fb;
> > > +	old_fb = crtc->primary->fb;
> > > +	crtc->primary->fb = fb;
> > >  	crtc->x = x;
> > >  	crtc->y = y;
> > >  
> > > @@ -3118,7 +3121,7 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > >  
> > > -	if (crtc->fb == NULL)
> > > +	if (crtc->primary->fb == NULL)
> > >  		return;
> > >  
> > >  	WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
> > > @@ -3127,7 +3130,7 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
> > >  		   !intel_crtc_has_pending_flip(crtc));
> > >  
> > >  	mutex_lock(&dev->struct_mutex);
> > > -	intel_finish_fb(crtc->fb);
> > > +	intel_finish_fb(crtc->primary->fb);
> > >  	mutex_unlock(&dev->struct_mutex);
> > >  }
> > >  
> > > @@ -4583,11 +4586,11 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
> > >  	assert_cursor_disabled(dev_priv, to_intel_crtc(crtc)->pipe);
> > >  	assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
> > >  
> > > -	if (crtc->fb) {
> > > +	if (crtc->primary->fb) {
> > >  		mutex_lock(&dev->struct_mutex);
> > > -		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
> > > +		intel_unpin_fb_obj(to_intel_framebuffer(crtc->primary->fb)->obj);
> > >  		mutex_unlock(&dev->struct_mutex);
> > > -		crtc->fb = NULL;
> > > +		crtc->primary->fb = NULL;
> > >  	}
> > >  
> > >  	/* Update computed state. */
> > > @@ -5738,8 +5741,9 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
> > >  	int fourcc, pixel_format;
> > >  	int aligned_height;
> > >  
> > > -	crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
> > > -	if (!crtc->base.fb) {
> > > +	crtc->base.primary->fb =
> > > +		kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
> > > +	if (!crtc->base.primary->fb) {
> > >  		DRM_DEBUG_KMS("failed to alloc fb\n");
> > >  		return;
> > >  	}
> > > @@ -5752,8 +5756,8 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
> > >  
> > >  	pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
> > >  	fourcc = intel_format_to_fourcc(pixel_format);
> > > -	crtc->base.fb->pixel_format = fourcc;
> > > -	crtc->base.fb->bits_per_pixel =
> > > +	crtc->base.primary->fb->pixel_format = fourcc;
> > > +	crtc->base.primary->fb->bits_per_pixel =
> > >  		drm_format_plane_cpp(fourcc, 0) * 8;
> > >  
> > >  	if (INTEL_INFO(dev)->gen >= 4) {
> > > @@ -5768,23 +5772,23 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
> > >  	plane_config->base = base;
> > >  
> > >  	val = I915_READ(PIPESRC(pipe));
> > > -	crtc->base.fb->width = ((val >> 16) & 0xfff) + 1;
> > > -	crtc->base.fb->height = ((val >> 0) & 0xfff) + 1;
> > > +	crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1;
> > > +	crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
> > >  
> > >  	val = I915_READ(DSPSTRIDE(pipe));
> > > -	crtc->base.fb->pitches[0] = val & 0xffffff80;
> > > +	crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
> > >  
> > > -	aligned_height = intel_align_height(dev, crtc->base.fb->height,
> > > +	aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
> > >  					    plane_config->tiled);
> > >  
> > > -	plane_config->size = ALIGN(crtc->base.fb->pitches[0] *
> > > +	plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
> > >  				   aligned_height, PAGE_SIZE);
> > >  
> > >  	DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
> > > -		      pipe, plane, crtc->base.fb->width,
> > > -		      crtc->base.fb->height,
> > > -		      crtc->base.fb->bits_per_pixel, base,
> > > -		      crtc->base.fb->pitches[0],
> > > +		      pipe, plane, crtc->base.primary->fb->width,
> > > +		      crtc->base.primary->fb->height,
> > > +		      crtc->base.primary->fb->bits_per_pixel, base,
> > > +		      crtc->base.primary->fb->pitches[0],
> > >  		      plane_config->size);
> > >  
> > >  }
> > > @@ -6746,8 +6750,9 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
> > >  	int fourcc, pixel_format;
> > >  	int aligned_height;
> > >  
> > > -	crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
> > > -	if (!crtc->base.fb) {
> > > +	crtc->base.primary->fb =
> > > +		kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
> > > +	if (!crtc->base.primary->fb) {
> > >  		DRM_DEBUG_KMS("failed to alloc fb\n");
> > >  		return;
> > >  	}
> > > @@ -6760,8 +6765,8 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
> > >  
> > >  	pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
> > >  	fourcc = intel_format_to_fourcc(pixel_format);
> > > -	crtc->base.fb->pixel_format = fourcc;
> > > -	crtc->base.fb->bits_per_pixel =
> > > +	crtc->base.primary->fb->pixel_format = fourcc;
> > > +	crtc->base.primary->fb->bits_per_pixel =
> > >  		drm_format_plane_cpp(fourcc, 0) * 8;
> > >  
> > >  	base = I915_READ(DSPSURF(plane)) & 0xfffff000;
> > > @@ -6776,23 +6781,23 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
> > >  	plane_config->base = base;
> > >  
> > >  	val = I915_READ(PIPESRC(pipe));
> > > -	crtc->base.fb->width = ((val >> 16) & 0xfff) + 1;
> > > -	crtc->base.fb->height = ((val >> 0) & 0xfff) + 1;
> > > +	crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1;
> > > +	crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
> > >  
> > >  	val = I915_READ(DSPSTRIDE(pipe));
> > > -	crtc->base.fb->pitches[0] = val & 0xffffff80;
> > > +	crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
> > >  
> > > -	aligned_height = intel_align_height(dev, crtc->base.fb->height,
> > > +	aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
> > >  					    plane_config->tiled);
> > >  
> > > -	plane_config->size = ALIGN(crtc->base.fb->pitches[0] *
> > > +	plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
> > >  				   aligned_height, PAGE_SIZE);
> > >  
> > >  	DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
> > > -		      pipe, plane, crtc->base.fb->width,
> > > -		      crtc->base.fb->height,
> > > -		      crtc->base.fb->bits_per_pixel, base,
> > > -		      crtc->base.fb->pitches[0],
> > > +		      pipe, plane, crtc->base.primary->fb->width,
> > > +		      crtc->base.primary->fb->height,
> > > +		      crtc->base.primary->fb->bits_per_pixel, base,
> > > +		      crtc->base.primary->fb->pitches[0],
> > >  		      plane_config->size);
> > >  }
> > >  
> > > @@ -8482,7 +8487,7 @@ void intel_mark_idle(struct drm_device *dev)
> > >  		goto out;
> > >  
> > >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > > -		if (!crtc->fb)
> > > +		if (!crtc->primary->fb)
> > >  			continue;
> > >  
> > >  		intel_decrease_pllclock(crtc);
> > > @@ -8505,10 +8510,10 @@ void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
> > >  		return;
> > >  
> > >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > > -		if (!crtc->fb)
> > > +		if (!crtc->primary->fb)
> > >  			continue;
> > >  
> > > -		if (to_intel_framebuffer(crtc->fb)->obj != obj)
> > > +		if (to_intel_framebuffer(crtc->primary->fb)->obj != obj)
> > >  			continue;
> > >  
> > >  		intel_increase_pllclock(crtc);
> > > @@ -8936,7 +8941,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> > >  {
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > > -	struct drm_framebuffer *old_fb = crtc->fb;
> > > +	struct drm_framebuffer *old_fb = crtc->primary->fb;
> > >  	struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
> > >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > >  	struct intel_unpin_work *work;
> > > @@ -8944,7 +8949,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> > >  	int ret;
> > >  
> > >  	/* Can't change pixel format via MI display flips. */
> > > -	if (fb->pixel_format != crtc->fb->pixel_format)
> > > +	if (fb->pixel_format != crtc->primary->fb->pixel_format)
> > >  		return -EINVAL;
> > >  
> > >  	/*
> > > @@ -8952,8 +8957,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> > >  	 * Note that pitch changes could also affect these register.
> > >  	 */
> > >  	if (INTEL_INFO(dev)->gen > 3 &&
> > > -	    (fb->offsets[0] != crtc->fb->offsets[0] ||
> > > -	     fb->pitches[0] != crtc->fb->pitches[0]))
> > > +	    (fb->offsets[0] != crtc->primary->fb->offsets[0] ||
> > > +	     fb->pitches[0] != crtc->primary->fb->pitches[0]))
> > >  		return -EINVAL;
> > >  
> > >  	if (i915_terminally_wedged(&dev_priv->gpu_error))
> > > @@ -8996,7 +9001,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> > >  	drm_gem_object_reference(&work->old_fb_obj->base);
> > >  	drm_gem_object_reference(&obj->base);
> > >  
> > > -	crtc->fb = fb;
> > > +	crtc->primary->fb = fb;
> > >  
> > >  	work->pending_flip_obj = obj;
> > >  
> > > @@ -9019,7 +9024,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> > >  
> > >  cleanup_pending:
> > >  	atomic_dec(&intel_crtc->unpin_work_count);
> > > -	crtc->fb = old_fb;
> > > +	crtc->primary->fb = old_fb;
> > >  	drm_gem_object_unreference(&work->old_fb_obj->base);
> > >  	drm_gem_object_unreference(&obj->base);
> > >  	mutex_unlock(&dev->struct_mutex);
> > > @@ -10060,7 +10065,7 @@ static int intel_set_mode(struct drm_crtc *crtc,
> > >  
> > >  void intel_crtc_restore_mode(struct drm_crtc *crtc)
> > >  {
> > > -	intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb);
> > > +	intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb);
> > >  }
> > >  
> > >  #undef for_each_intel_crtc_masked
> > > @@ -10184,9 +10189,9 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
> > >  	 * and then just flip_or_move it */
> > >  	if (is_crtc_connector_off(set)) {
> > >  		config->mode_changed = true;
> > > -	} else if (set->crtc->fb != set->fb) {
> > > +	} else if (set->crtc->primary->fb != set->fb) {
> > >  		/* If we have no fb then treat it as a full mode set */
> > > -		if (set->crtc->fb == NULL) {
> > > +		if (set->crtc->primary->fb == NULL) {
> > >  			struct intel_crtc *intel_crtc =
> > >  				to_intel_crtc(set->crtc);
> > >  
> > > @@ -10200,7 +10205,7 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
> > >  		} else if (set->fb == NULL) {
> > >  			config->mode_changed = true;
> > >  		} else if (set->fb->pixel_format !=
> > > -			   set->crtc->fb->pixel_format) {
> > > +			   set->crtc->primary->fb->pixel_format) {
> > >  			config->mode_changed = true;
> > >  		} else {
> > >  			config->fb_changed = true;
> > > @@ -10413,7 +10418,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
> > >  	save_set.mode = &set->crtc->mode;
> > >  	save_set.x = set->crtc->x;
> > >  	save_set.y = set->crtc->y;
> > > -	save_set.fb = set->crtc->fb;
> > > +	save_set.fb = set->crtc->primary->fb;
> > >  
> > >  	/* Compute whether we need a full modeset, only an fb base update or no
> > >  	 * change at all. In the future we might also check whether only the
> > > @@ -11755,7 +11760,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
> > >  				dev_priv->pipe_to_crtc_mapping[pipe];
> > >  
> > >  			__intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
> > > -					 crtc->fb);
> > > +					 crtc->primary->fb);
> > >  		}
> > >  	} else {
> > >  		intel_modeset_update_staged_output_state(dev);
> > > @@ -11780,15 +11785,15 @@ void intel_modeset_gem_init(struct drm_device *dev)
> > >  	 */
> > >  	mutex_lock(&dev->struct_mutex);
> > >  	list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
> > > -		if (!c->fb)
> > > +		if (!c->primary->fb)
> > >  			continue;
> > >  
> > > -		fb = to_intel_framebuffer(c->fb);
> > > +		fb = to_intel_framebuffer(c->primary->fb);
> > >  		if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL)) {
> > >  			DRM_ERROR("failed to pin boot fb on pipe %d\n",
> > >  				  to_intel_crtc(c)->pipe);
> > > -			drm_framebuffer_unreference(c->fb);
> > > -			c->fb = NULL;
> > > +			drm_framebuffer_unreference(c->primary->fb);
> > > +			c->primary->fb = NULL;
> > >  		}
> > >  	}
> > >  	mutex_unlock(&dev->struct_mutex);
> > > @@ -11827,7 +11832,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
> > >  
> > >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > >  		/* Skip inactive CRTCs */
> > > -		if (!crtc->fb)
> > > +		if (!crtc->primary->fb)
> > >  			continue;
> > >  
> > >  		intel_increase_pllclock(crtc);
> > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > index 59ee4dc..05531bf 100644
> > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > @@ -1634,7 +1634,8 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
> > >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > >  	struct drm_crtc *crtc = dig_port->base.base.crtc;
> > >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > > -	struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
> > > +	struct drm_i915_gem_object *obj =
> > > +		to_intel_framebuffer(crtc->primary->fb)->obj;
> > >  	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
> > >  
> > >  	dev_priv->psr.source_ok = false;
> > > @@ -1667,7 +1668,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
> > >  		return false;
> > >  	}
> > >  
> > > -	obj = to_intel_framebuffer(crtc->fb)->obj;
> > > +	obj = to_intel_framebuffer(crtc->primary->fb)->obj;
> > >  	if (obj->tiling_mode != I915_TILING_X ||
> > >  	    obj->fence_reg == I915_FENCE_REG_NONE) {
> > >  		DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
> > > diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
> > > index d6d78c8..2b1d42d 100644
> > > --- a/drivers/gpu/drm/i915/intel_fbdev.c
> > > +++ b/drivers/gpu/drm/i915/intel_fbdev.c
> > > @@ -481,7 +481,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
> > >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > >  		intel_crtc = to_intel_crtc(crtc);
> > >  
> > > -		if (!intel_crtc->active || !crtc->fb) {
> > > +		if (!intel_crtc->active || !crtc->primary->fb) {
> > >  			DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
> > >  				      pipe_name(intel_crtc->pipe));
> > >  			continue;
> > > @@ -491,7 +491,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
> > >  			DRM_DEBUG_KMS("found possible fb from plane %c\n",
> > >  				      pipe_name(intel_crtc->pipe));
> > >  			plane_config = &intel_crtc->plane_config;
> > > -			fb = to_intel_framebuffer(crtc->fb);
> > > +			fb = to_intel_framebuffer(crtc->primary->fb);
> > >  			max_size = plane_config->size;
> > >  		}
> > >  	}
> > > @@ -560,7 +560,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
> > >  		if (!intel_crtc->active)
> > >  			continue;
> > >  
> > > -		WARN(!crtc->fb,
> > > +		WARN(!crtc->primary->fb,
> > >  		     "re-used BIOS config but lost an fb on crtc %d\n",
> > >  		     crtc->base.id);
> > >  	}
> > > diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
> > > index 312961a..623cd32 100644
> > > --- a/drivers/gpu/drm/i915/intel_overlay.c
> > > +++ b/drivers/gpu/drm/i915/intel_overlay.c
> > > @@ -606,14 +606,14 @@ static void update_colorkey(struct intel_overlay *overlay,
> > >  {
> > >  	u32 key = overlay->color_key;
> > >  
> > > -	switch (overlay->crtc->base.fb->bits_per_pixel) {
> > > +	switch (overlay->crtc->base.primary->fb->bits_per_pixel) {
> > >  	case 8:
> > >  		iowrite32(0, &regs->DCLRKV);
> > >  		iowrite32(CLK_RGB8I_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
> > >  		break;
> > >  
> > >  	case 16:
> > > -		if (overlay->crtc->base.fb->depth == 15) {
> > > +		if (overlay->crtc->base.primary->fb->depth == 15) {
> > >  			iowrite32(RGB15_TO_COLORKEY(key), &regs->DCLRKV);
> > >  			iowrite32(CLK_RGB15_MASK | DST_KEY_ENABLE,
> > >  				  &regs->DCLRKM);
> > > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > > index 3a1b569..e2d73f4 100644
> > > --- a/drivers/gpu/drm/i915/intel_pm.c
> > > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > > @@ -92,7 +92,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc)
> > >  {
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > > -	struct drm_framebuffer *fb = crtc->fb;
> > > +	struct drm_framebuffer *fb = crtc->primary->fb;
> > >  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > >  	struct drm_i915_gem_object *obj = intel_fb->obj;
> > >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > > @@ -149,7 +149,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc)
> > >  {
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > > -	struct drm_framebuffer *fb = crtc->fb;
> > > +	struct drm_framebuffer *fb = crtc->primary->fb;
> > >  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > >  	struct drm_i915_gem_object *obj = intel_fb->obj;
> > >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > > @@ -221,7 +221,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc)
> > >  {
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > > -	struct drm_framebuffer *fb = crtc->fb;
> > > +	struct drm_framebuffer *fb = crtc->primary->fb;
> > >  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > >  	struct drm_i915_gem_object *obj = intel_fb->obj;
> > >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > > @@ -277,7 +277,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc)
> > >  {
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > > -	struct drm_framebuffer *fb = crtc->fb;
> > > +	struct drm_framebuffer *fb = crtc->primary->fb;
> > >  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > >  	struct drm_i915_gem_object *obj = intel_fb->obj;
> > >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > > @@ -336,11 +336,11 @@ static void intel_fbc_work_fn(struct work_struct *__work)
> > >  		/* Double check that we haven't switched fb without cancelling
> > >  		 * the prior work.
> > >  		 */
> > > -		if (work->crtc->fb == work->fb) {
> > > +		if (work->crtc->primary->fb == work->fb) {
> > >  			dev_priv->display.enable_fbc(work->crtc);
> > >  
> > >  			dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane;
> > > -			dev_priv->fbc.fb_id = work->crtc->fb->base.id;
> > > +			dev_priv->fbc.fb_id = work->crtc->primary->fb->base.id;
> > >  			dev_priv->fbc.y = work->crtc->y;
> > >  		}
> > >  
> > > @@ -393,7 +393,7 @@ static void intel_enable_fbc(struct drm_crtc *crtc)
> > >  	}
> > >  
> > >  	work->crtc = crtc;
> > > -	work->fb = crtc->fb;
> > > +	work->fb = crtc->primary->fb;
> > >  	INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
> > >  
> > >  	dev_priv->fbc.fbc_work = work;
> > > @@ -499,14 +499,14 @@ void intel_update_fbc(struct drm_device *dev)
> > >  		}
> > >  	}
> > >  
> > > -	if (!crtc || crtc->fb == NULL) {
> > > +	if (!crtc || crtc->primary->fb == NULL) {
> > >  		if (set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT))
> > >  			DRM_DEBUG_KMS("no output, disabling\n");
> > >  		goto out_disable;
> > >  	}
> > >  
> > >  	intel_crtc = to_intel_crtc(crtc);
> > > -	fb = crtc->fb;
> > > +	fb = crtc->primary->fb;
> > >  	intel_fb = to_intel_framebuffer(fb);
> > >  	obj = intel_fb->obj;
> > >  	adjusted_mode = &intel_crtc->config.adjusted_mode;
> > > @@ -1041,7 +1041,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc)
> > >  	crtc = single_enabled_crtc(dev);
> > >  	if (crtc) {
> > >  		const struct drm_display_mode *adjusted_mode;
> > > -		int pixel_size = crtc->fb->bits_per_pixel / 8;
> > > +		int pixel_size = crtc->primary->fb->bits_per_pixel / 8;
> > >  		int clock;
> > >  
> > >  		adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
> > > @@ -1121,7 +1121,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
> > >  	clock = adjusted_mode->crtc_clock;
> > >  	htotal = adjusted_mode->crtc_htotal;
> > >  	hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
> > > -	pixel_size = crtc->fb->bits_per_pixel / 8;
> > > +	pixel_size = crtc->primary->fb->bits_per_pixel / 8;
> > >  
> > >  	/* Use the small buffer method to calculate plane watermark */
> > >  	entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
> > > @@ -1208,7 +1208,7 @@ static bool g4x_compute_srwm(struct drm_device *dev,
> > >  	clock = adjusted_mode->crtc_clock;
> > >  	htotal = adjusted_mode->crtc_htotal;
> > >  	hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
> > > -	pixel_size = crtc->fb->bits_per_pixel / 8;
> > > +	pixel_size = crtc->primary->fb->bits_per_pixel / 8;
> > >  
> > >  	line_time_us = max(htotal * 1000 / clock, 1);
> > >  	line_count = (latency_ns / line_time_us + 1000) / 1000;
> > > @@ -1247,7 +1247,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev,
> > >  		return false;
> > >  
> > >  	clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
> > > -	pixel_size = crtc->fb->bits_per_pixel / 8;	/* BPP */
> > > +	pixel_size = crtc->primary->fb->bits_per_pixel / 8;	/* BPP */
> > >  
> > >  	entries = (clock / 1000) * pixel_size;
> > >  	*plane_prec_mult = (entries > 256) ?
> > > @@ -1439,7 +1439,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
> > >  		int clock = adjusted_mode->crtc_clock;
> > >  		int htotal = adjusted_mode->crtc_htotal;
> > >  		int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
> > > -		int pixel_size = crtc->fb->bits_per_pixel / 8;
> > > +		int pixel_size = crtc->primary->fb->bits_per_pixel / 8;
> > >  		unsigned long line_time_us;
> > >  		int entries;
> > >  
> > > @@ -1512,7 +1512,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
> > >  	crtc = intel_get_crtc_for_plane(dev, 0);
> > >  	if (intel_crtc_active(crtc)) {
> > >  		const struct drm_display_mode *adjusted_mode;
> > > -		int cpp = crtc->fb->bits_per_pixel / 8;
> > > +		int cpp = crtc->primary->fb->bits_per_pixel / 8;
> > >  		if (IS_GEN2(dev))
> > >  			cpp = 4;
> > >  
> > > @@ -1528,7 +1528,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
> > >  	crtc = intel_get_crtc_for_plane(dev, 1);
> > >  	if (intel_crtc_active(crtc)) {
> > >  		const struct drm_display_mode *adjusted_mode;
> > > -		int cpp = crtc->fb->bits_per_pixel / 8;
> > > +		int cpp = crtc->primary->fb->bits_per_pixel / 8;
> > >  		if (IS_GEN2(dev))
> > >  			cpp = 4;
> > >  
> > > @@ -1565,7 +1565,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
> > >  		int clock = adjusted_mode->crtc_clock;
> > >  		int htotal = adjusted_mode->crtc_htotal;
> > >  		int hdisplay = to_intel_crtc(enabled)->config.pipe_src_w;
> > > -		int pixel_size = enabled->fb->bits_per_pixel / 8;
> > > +		int pixel_size = enabled->primary->fb->bits_per_pixel / 8;
> > >  		unsigned long line_time_us;
> > >  		int entries;
> > >  
> > > @@ -2117,7 +2117,7 @@ static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
> > >  	if (p->active) {
> > >  		p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_htotal;
> > >  		p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
> > > -		p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
> > > +		p->pri.bytes_per_pixel = crtc->primary->fb->bits_per_pixel / 8;
> > >  		p->cur.bytes_per_pixel = 4;
> > >  		p->pri.horiz_pixels = intel_crtc->config.pipe_src_w;
> > >  		p->cur.horiz_pixels = 64;
> > > diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
> > > index 1418414..f8c42b1 100644
> > > --- a/drivers/gpu/drm/mgag200/mgag200_mode.c
> > > +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
> > > @@ -29,7 +29,7 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc)
> > >  	struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct mga_device *mdev = dev->dev_private;
> > > -	struct drm_framebuffer *fb = crtc->fb;
> > > +	struct drm_framebuffer *fb = crtc->primary->fb;
> > >  	int i;
> > >  
> > >  	if (!crtc->enabled)
> > > @@ -742,7 +742,7 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc,
> > >  		mgag200_bo_unreserve(bo);
> > >  	}
> > >  
> > > -	mga_fb = to_mga_framebuffer(crtc->fb);
> > > +	mga_fb = to_mga_framebuffer(crtc->primary->fb);
> > >  	obj = mga_fb->obj;
> > >  	bo = gem_to_mga_bo(obj);
> > >  
> > > @@ -805,7 +805,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
> > >  		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
> > >  	};
> > >  
> > > -	bppshift = mdev->bpp_shifts[(crtc->fb->bits_per_pixel >> 3) - 1];
> > > +	bppshift = mdev->bpp_shifts[(crtc->primary->fb->bits_per_pixel >> 3) - 1];
> > >  
> > >  	switch (mdev->type) {
> > >  	case G200_SE_A:
> > > @@ -843,12 +843,12 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
> > >  		break;
> > >  	}
> > >  
> > > -	switch (crtc->fb->bits_per_pixel) {
> > > +	switch (crtc->primary->fb->bits_per_pixel) {
> > >  	case 8:
> > >  		dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits;
> > >  		break;
> > >  	case 16:
> > > -		if (crtc->fb->depth == 15)
> > > +		if (crtc->primary->fb->depth == 15)
> > >  			dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_15bits;
> > >  		else
> > >  			dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_16bits;
> > > @@ -896,8 +896,9 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
> > >  	WREG_SEQ(3, 0);
> > >  	WREG_SEQ(4, 0xe);
> > >  
> > > -	pitch = crtc->fb->pitches[0] / (crtc->fb->bits_per_pixel / 8);
> > > -	if (crtc->fb->bits_per_pixel == 24)
> > > +	pitch = crtc->primary->fb->pitches[0] /
> > > +		(crtc->primary->fb->bits_per_pixel / 8);
> > > +	if (crtc->primary->fb->bits_per_pixel == 24)
> > >  		pitch = (pitch * 3) >> (4 - bppshift);
> > >  	else
> > >  		pitch = pitch >> (4 - bppshift);
> > > @@ -974,7 +975,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
> > >  		((vdisplay & 0xc00) >> 7) |
> > >  		((vsyncstart & 0xc00) >> 5) |
> > >  		((vdisplay & 0x400) >> 3);
> > > -	if (crtc->fb->bits_per_pixel == 24)
> > > +	if (crtc->primary->fb->bits_per_pixel == 24)
> > >  		ext_vga[3] = (((1 << bppshift) * 3) - 1) | 0x80;
> > >  	else
> > >  		ext_vga[3] = ((1 << bppshift) - 1) | 0x80;
> > > @@ -1034,9 +1035,9 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
> > >  			u32 bpp;
> > >  			u32 mb;
> > >  
> > > -			if (crtc->fb->bits_per_pixel > 16)
> > > +			if (crtc->primary->fb->bits_per_pixel > 16)
> > >  				bpp = 32;
> > > -			else if (crtc->fb->bits_per_pixel > 8)
> > > +			else if (crtc->primary->fb->bits_per_pixel > 8)
> > >  				bpp = 16;
> > >  			else
> > >  				bpp = 8;
> > > @@ -1277,8 +1278,9 @@ static void mga_crtc_disable(struct drm_crtc *crtc)
> > >  	int ret;
> > >  	DRM_DEBUG_KMS("\n");
> > >  	mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
> > > -	if (crtc->fb) {
> > > -		struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->fb);
> > > +	if (crtc->primary->fb) {
> > > +		struct mga_framebuffer *mga_fb =
> > > +			to_mga_framebuffer(crtc->primary->fb);
> > >  		struct drm_gem_object *obj = mga_fb->obj;
> > >  		struct mgag200_bo *bo = gem_to_mga_bo(obj);
> > >  		ret = mgag200_bo_reserve(bo, false);
> > > @@ -1287,7 +1289,7 @@ static void mga_crtc_disable(struct drm_crtc *crtc)
> > >  		mgag200_bo_push_sysram(bo);
> > >  		mgag200_bo_unreserve(bo);
> > >  	}
> > > -	crtc->fb = NULL;
> > > +	crtc->primary->fb = NULL;
> > >  }
> > >  
> > >  /* These provide the minimum set of functions required to handle a CRTC */
> > > diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
> > > index b10f681..f96497b 100644
> > > --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
> > > +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
> > > @@ -120,7 +120,7 @@ static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
> > >  
> > >  	/* grab reference to incoming scanout fb: */
> > >  	drm_framebuffer_reference(new_fb);
> > > -	mdp4_crtc->base.fb = new_fb;
> > > +	mdp4_crtc->base.primary->fb = new_fb;
> > >  	mdp4_crtc->fb = new_fb;
> > >  
> > >  	if (old_fb)
> > > @@ -182,7 +182,7 @@ static void pageflip_cb(struct msm_fence_cb *cb)
> > >  	struct mdp4_crtc *mdp4_crtc =
> > >  		container_of(cb, struct mdp4_crtc, pageflip_cb);
> > >  	struct drm_crtc *crtc = &mdp4_crtc->base;
> > > -	struct drm_framebuffer *fb = crtc->fb;
> > > +	struct drm_framebuffer *fb = crtc->primary->fb;
> > >  
> > >  	if (!fb)
> > >  		return;
> > > @@ -348,14 +348,14 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
> > >  			mode->type, mode->flags);
> > >  
> > >  	/* grab extra ref for update_scanout() */
> > > -	drm_framebuffer_reference(crtc->fb);
> > > +	drm_framebuffer_reference(crtc->primary->fb);
> > >  
> > > -	ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->fb,
> > > +	ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->primary->fb,
> > >  			0, 0, mode->hdisplay, mode->vdisplay,
> > >  			x << 16, y << 16,
> > >  			mode->hdisplay << 16, mode->vdisplay << 16);
> > >  	if (ret) {
> > > -		drm_framebuffer_unreference(crtc->fb);
> > > +		drm_framebuffer_unreference(crtc->primary->fb);
> > >  		dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
> > >  				mdp4_crtc->name, ret);
> > >  		return ret;
> > > @@ -368,7 +368,7 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
> > >  	/* take data from pipe: */
> > >  	mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_BASE(dma), 0);
> > >  	mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_STRIDE(dma),
> > > -			crtc->fb->pitches[0]);
> > > +			crtc->primary->fb->pitches[0]);
> > >  	mdp4_write(mdp4_kms, REG_MDP4_DMA_DST_SIZE(dma),
> > >  			MDP4_DMA_DST_SIZE_WIDTH(0) |
> > >  			MDP4_DMA_DST_SIZE_HEIGHT(0));
> > > @@ -378,7 +378,7 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
> > >  			MDP4_OVLP_SIZE_WIDTH(mode->hdisplay) |
> > >  			MDP4_OVLP_SIZE_HEIGHT(mode->vdisplay));
> > >  	mdp4_write(mdp4_kms, REG_MDP4_OVLP_STRIDE(ovlp),
> > > -			crtc->fb->pitches[0]);
> > > +			crtc->primary->fb->pitches[0]);
> > >  
> > >  	mdp4_write(mdp4_kms, REG_MDP4_OVLP_CFG(ovlp), 1);
> > >  
> > > @@ -388,8 +388,8 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
> > >  		mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(2), 0x00ff0000);
> > >  	}
> > >  
> > > -	update_fb(crtc, crtc->fb);
> > > -	update_scanout(crtc, crtc->fb);
> > > +	update_fb(crtc, crtc->primary->fb);
> > > +	update_scanout(crtc, crtc->primary->fb);
> > >  
> > >  	return 0;
> > >  }
> > > @@ -420,19 +420,19 @@ static int mdp4_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> > >  	int ret;
> > >  
> > >  	/* grab extra ref for update_scanout() */
> > > -	drm_framebuffer_reference(crtc->fb);
> > > +	drm_framebuffer_reference(crtc->primary->fb);
> > >  
> > > -	ret = mdp4_plane_mode_set(plane, crtc, crtc->fb,
> > > +	ret = mdp4_plane_mode_set(plane, crtc, crtc->primary->fb,
> > >  			0, 0, mode->hdisplay, mode->vdisplay,
> > >  			x << 16, y << 16,
> > >  			mode->hdisplay << 16, mode->vdisplay << 16);
> > >  	if (ret) {
> > > -		drm_framebuffer_unreference(crtc->fb);
> > > +		drm_framebuffer_unreference(crtc->primary->fb);
> > >  		return ret;
> > >  	}
> > >  
> > > -	update_fb(crtc, crtc->fb);
> > > -	update_scanout(crtc, crtc->fb);
> > > +	update_fb(crtc, crtc->primary->fb);
> > > +	update_scanout(crtc, crtc->primary->fb);
> > >  
> > >  	return 0;
> > >  }
> > > diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
> > > index 7dc3d71..f200048 100644
> > > --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
> > > +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
> > > @@ -102,7 +102,7 @@ static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
> > >  
> > >  	/* grab reference to incoming scanout fb: */
> > >  	drm_framebuffer_reference(new_fb);
> > > -	mdp5_crtc->base.fb = new_fb;
> > > +	mdp5_crtc->base.primary->fb = new_fb;
> > >  	mdp5_crtc->fb = new_fb;
> > >  
> > >  	if (old_fb)
> > > @@ -289,14 +289,14 @@ static int mdp5_crtc_mode_set(struct drm_crtc *crtc,
> > >  			mode->type, mode->flags);
> > >  
> > >  	/* grab extra ref for update_scanout() */
> > > -	drm_framebuffer_reference(crtc->fb);
> > > +	drm_framebuffer_reference(crtc->primary->fb);
> > >  
> > > -	ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->fb,
> > > +	ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->primary->fb,
> > >  			0, 0, mode->hdisplay, mode->vdisplay,
> > >  			x << 16, y << 16,
> > >  			mode->hdisplay << 16, mode->vdisplay << 16);
> > >  	if (ret) {
> > > -		drm_framebuffer_unreference(crtc->fb);
> > > +		drm_framebuffer_unreference(crtc->primary->fb);
> > >  		dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
> > >  				mdp5_crtc->name, ret);
> > >  		return ret;
> > > @@ -306,8 +306,8 @@ static int mdp5_crtc_mode_set(struct drm_crtc *crtc,
> > >  			MDP5_LM_OUT_SIZE_WIDTH(mode->hdisplay) |
> > >  			MDP5_LM_OUT_SIZE_HEIGHT(mode->vdisplay));
> > >  
> > > -	update_fb(crtc, crtc->fb);
> > > -	update_scanout(crtc, crtc->fb);
> > > +	update_fb(crtc, crtc->primary->fb);
> > > +	update_scanout(crtc, crtc->primary->fb);
> > >  
> > >  	return 0;
> > >  }
> > > @@ -338,19 +338,19 @@ static int mdp5_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> > >  	int ret;
> > >  
> > >  	/* grab extra ref for update_scanout() */
> > > -	drm_framebuffer_reference(crtc->fb);
> > > +	drm_framebuffer_reference(crtc->primary->fb);
> > >  
> > > -	ret = mdp5_plane_mode_set(plane, crtc, crtc->fb,
> > > +	ret = mdp5_plane_mode_set(plane, crtc, crtc->primary->fb,
> > >  			0, 0, mode->hdisplay, mode->vdisplay,
> > >  			x << 16, y << 16,
> > >  			mode->hdisplay << 16, mode->vdisplay << 16);
> > >  	if (ret) {
> > > -		drm_framebuffer_unreference(crtc->fb);
> > > +		drm_framebuffer_unreference(crtc->primary->fb);
> > >  		return ret;
> > >  	}
> > >  
> > > -	update_fb(crtc, crtc->fb);
> > > -	update_scanout(crtc, crtc->fb);
> > > +	update_fb(crtc, crtc->primary->fb);
> > > +	update_scanout(crtc, crtc->primary->fb);
> > >  
> > >  	return 0;
> > >  }
> > > diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
> > > index b55be84..2a5e9db 100644
> > > --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
> > > +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
> > > @@ -239,7 +239,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
> > >  	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
> > > -	struct drm_framebuffer *fb = crtc->fb;
> > > +	struct drm_framebuffer *fb = crtc->primary->fb;
> > >  
> > >  	/* Calculate our timings */
> > >  	int horizDisplay	= (mode->crtc_hdisplay >> 3)		- 1;
> > > @@ -574,7 +574,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
> > >  		regp->CRTC[NV_CIO_CRE_86] = 0x1;
> > >  	}
> > >  
> > > -	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->fb->depth + 1) / 8;
> > > +	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->primary->fb->depth + 1) / 8;
> > >  	/* Enable slaved mode (called MODE_TV in nv4ref.h) */
> > >  	if (lvds_output || tmds_output || tv_output)
> > >  		regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7);
> > > @@ -588,7 +588,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
> > >  	regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS |
> > >  				NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL |
> > >  				NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON;
> > > -	if (crtc->fb->depth == 16)
> > > +	if (crtc->primary->fb->depth == 16)
> > >  		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
> > >  	if (nv_device(drm->device)->chipset >= 0x11)
> > >  		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG;
> > > @@ -609,7 +609,7 @@ static int
> > >  nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
> > >  {
> > >  	struct nv04_display *disp = nv04_display(crtc->dev);
> > > -	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
> > > +	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb);
> > >  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
> > >  	int ret;
> > >  
> > > @@ -808,7 +808,7 @@ nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
> > >  	 * mark the lut values as dirty by setting depth==0, and it'll be
> > >  	 * uploaded on the first mode_set_base()
> > >  	 */
> > > -	if (!nv_crtc->base.fb) {
> > > +	if (!nv_crtc->base.primary->fb) {
> > >  		nv_crtc->lut.depth = 0;
> > >  		return;
> > >  	}
> > > @@ -832,7 +832,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
> > >  	NV_DEBUG(drm, "index %d\n", nv_crtc->index);
> > >  
> > >  	/* no fb bound */
> > > -	if (!atomic && !crtc->fb) {
> > > +	if (!atomic && !crtc->primary->fb) {
> > >  		NV_DEBUG(drm, "No FB bound\n");
> > >  		return 0;
> > >  	}
> > > @@ -844,8 +844,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
> > >  		drm_fb = passed_fb;
> > >  		fb = nouveau_framebuffer(passed_fb);
> > >  	} else {
> > > -		drm_fb = crtc->fb;
> > > -		fb = nouveau_framebuffer(crtc->fb);
> > > +		drm_fb = crtc->primary->fb;
> > > +		fb = nouveau_framebuffer(crtc->primary->fb);
> > >  	}
> > >  
> > >  	nv_crtc->fb.offset = fb->nvbo->bo.offset;
> > > @@ -857,9 +857,9 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
> > >  
> > >  	/* Update the framebuffer format. */
> > >  	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] &= ~3;
> > > -	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->fb->depth + 1) / 8;
> > > +	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->primary->fb->depth + 1) / 8;
> > >  	regp->ramdac_gen_ctrl &= ~NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
> > > -	if (crtc->fb->depth == 16)
> > > +	if (crtc->primary->fb->depth == 16)
> > >  		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
> > >  	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_PIXEL_INDEX);
> > >  	NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL,
> > > diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
> > > index 7fdc51e..a2d669b 100644
> > > --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c
> > > +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
> > > @@ -415,7 +415,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder,
> > >  	/* Output property. */
> > >  	if ((nv_connector->dithering_mode == DITHERING_MODE_ON) ||
> > >  	    (nv_connector->dithering_mode == DITHERING_MODE_AUTO &&
> > > -	     encoder->crtc->fb->depth > connector->display_info.bpc * 3)) {
> > > +	     encoder->crtc->primary->fb->depth > connector->display_info.bpc * 3)) {
> > >  		if (nv_device(drm->device)->chipset == 0x11)
> > >  			regp->dither = savep->dither | 0x00010000;
> > >  		else {
> > > diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
> > > index 2401159..4e24c72 100644
> > > --- a/drivers/gpu/drm/nouveau/nouveau_display.c
> > > +++ b/drivers/gpu/drm/nouveau/nouveau_display.c
> > > @@ -569,7 +569,7 @@ nouveau_display_suspend(struct drm_device *dev)
> > >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > >  		struct nouveau_framebuffer *nouveau_fb;
> > >  
> > > -		nouveau_fb = nouveau_framebuffer(crtc->fb);
> > > +		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
> > >  		if (!nouveau_fb || !nouveau_fb->nvbo)
> > >  			continue;
> > >  
> > > @@ -596,7 +596,7 @@ nouveau_display_repin(struct drm_device *dev)
> > >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > >  		struct nouveau_framebuffer *nouveau_fb;
> > >  
> > > -		nouveau_fb = nouveau_framebuffer(crtc->fb);
> > > +		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
> > >  		if (!nouveau_fb || !nouveau_fb->nvbo)
> > >  			continue;
> > >  
> > > @@ -693,7 +693,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
> > >  	const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1;
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct nouveau_drm *drm = nouveau_drm(dev);
> > > -	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo;
> > > +	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo;
> > >  	struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
> > >  	struct nouveau_page_flip_state *s;
> > >  	struct nouveau_channel *chan = drm->channel;
> > > @@ -767,7 +767,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
> > >  		goto fail_unreserve;
> > >  
> > >  	/* Update the crtc struct and cleanup */
> > > -	crtc->fb = fb;
> > > +	crtc->primary->fb = fb;
> > >  
> > >  	nouveau_bo_fence(old_bo, fence);
> > >  	ttm_bo_unreserve(&old_bo->bo);
> > > diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
> > > index 5706842..c744bf6 100644
> > > --- a/drivers/gpu/drm/nouveau/nv50_display.c
> > > +++ b/drivers/gpu/drm/nouveau/nv50_display.c
> > > @@ -651,7 +651,7 @@ nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
> > >  	nv_connector = nouveau_crtc_connector_get(nv_crtc);
> > >  	connector = &nv_connector->base;
> > >  	if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) {
> > > -		if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3)
> > > +		if (nv_crtc->base.primary->fb->depth > connector->display_info.bpc * 3)
> > >  			mode = DITHERING_MODE_DYNAMIC2X2;
> > >  	} else {
> > >  		mode = nv_connector->dithering_mode;
> > > @@ -785,7 +785,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
> > >  
> > >  		if (update) {
> > >  			nv50_display_flip_stop(crtc);
> > > -			nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
> > > +			nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
> > >  		}
> > >  	}
> > >  
> > > @@ -1028,7 +1028,7 @@ nv50_crtc_commit(struct drm_crtc *crtc)
> > >  	}
> > >  
> > >  	nv50_crtc_cursor_show_hide(nv_crtc, nv_crtc->cursor.visible, true);
> > > -	nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
> > > +	nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
> > >  }
> > >  
> > >  static bool
> > > @@ -1042,7 +1042,8 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
> > >  static int
> > >  nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
> > >  {
> > > -	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
> > > +	struct nouveau_framebuffer *nvfb =
> > > +		nouveau_framebuffer(crtc->primary->fb);
> > >  	struct nv50_head *head = nv50_head(crtc);
> > >  	int ret;
> > >  
> > > @@ -1139,7 +1140,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
> > >  	nv50_crtc_set_dither(nv_crtc, false);
> > >  	nv50_crtc_set_scale(nv_crtc, false);
> > >  	nv50_crtc_set_color_vibrance(nv_crtc, false);
> > > -	nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, false);
> > > +	nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, false);
> > >  	return 0;
> > >  }
> > >  
> > > @@ -1151,7 +1152,7 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> > >  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
> > >  	int ret;
> > >  
> > > -	if (!crtc->fb) {
> > > +	if (!crtc->primary->fb) {
> > >  		NV_DEBUG(drm, "No FB bound\n");
> > >  		return 0;
> > >  	}
> > > @@ -1161,8 +1162,8 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
> > >  		return ret;
> > >  
> > >  	nv50_display_flip_stop(crtc);
> > > -	nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, true);
> > > -	nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
> > > +	nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, true);
> > > +	nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
> > >  	return 0;
> > >  }
> > >  
> > > diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
> > > index 24b6112..5be0b87 100644
> > > --- a/drivers/gpu/drm/qxl/qxl_display.c
> > > +++ b/drivers/gpu/drm/qxl/qxl_display.c
> > > @@ -527,7 +527,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
> > >  	bool recreate_primary = false;
> > >  	int ret;
> > >  	int surf_id;
> > > -	if (!crtc->fb) {
> > > +	if (!crtc->primary->fb) {
> > >  		DRM_DEBUG_KMS("No FB bound\n");
> > >  		return 0;
> > >  	}
> > > @@ -536,7 +536,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
> > >  		qfb = to_qxl_framebuffer(old_fb);
> > >  		old_bo = gem_to_qxl_bo(qfb->obj);
> > >  	}
> > > -	qfb = to_qxl_framebuffer(crtc->fb);
> > > +	qfb = to_qxl_framebuffer(crtc->primary->fb);
> > >  	bo = gem_to_qxl_bo(qfb->obj);
> > >  	if (!m)
> > >  		/* and do we care? */
> > > @@ -609,14 +609,15 @@ static void qxl_crtc_disable(struct drm_crtc *crtc)
> > >  	struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct qxl_device *qdev = dev->dev_private;
> > > -	if (crtc->fb) {
> > > -		struct qxl_framebuffer *qfb = to_qxl_framebuffer(crtc->fb);
> > > +	if (crtc->primary->fb) {
> > > +		struct qxl_framebuffer *qfb =
> > > +			to_qxl_framebuffer(crtc->primary->fb);
> > >  		struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
> > >  		int ret;
> > >  		ret = qxl_bo_reserve(bo, false);
> > >  		qxl_bo_unpin(bo);
> > >  		qxl_bo_unreserve(bo);
> > > -		crtc->fb = NULL;
> > > +		crtc->primary->fb = NULL;
> > >  	}
> > >  
> > >  	qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0);
> > > diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
> > > index daa4dd3..fb187c7 100644
> > > --- a/drivers/gpu/drm/radeon/atombios_crtc.c
> > > +++ b/drivers/gpu/drm/radeon/atombios_crtc.c
> > > @@ -1106,7 +1106,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
> > >  	int r;
> > >  
> > >  	/* no fb bound */
> > > -	if (!atomic && !crtc->fb) {
> > > +	if (!atomic && !crtc->primary->fb) {
> > >  		DRM_DEBUG_KMS("No FB bound\n");
> > >  		return 0;
> > >  	}
> > > @@ -1116,8 +1116,8 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
> > >  		target_fb = fb;
> > >  	}
> > >  	else {
> > > -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> > > -		target_fb = crtc->fb;
> > > +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> > > +		target_fb = crtc->primary->fb;
> > >  	}
> > >  
> > >  	/* If atomic, assume fb object is pinned & idle & fenced and
> > > @@ -1316,7 +1316,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
> > >  	/* set pageflip to happen anywhere in vblank interval */
> > >  	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> > >  
> > > -	if (!atomic && fb && fb != crtc->fb) {
> > > +	if (!atomic && fb && fb != crtc->primary->fb) {
> > >  		radeon_fb = to_radeon_framebuffer(fb);
> > >  		rbo = gem_to_radeon_bo(radeon_fb->obj);
> > >  		r = radeon_bo_reserve(rbo, false);
> > > @@ -1350,7 +1350,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
> > >  	int r;
> > >  
> > >  	/* no fb bound */
> > > -	if (!atomic && !crtc->fb) {
> > > +	if (!atomic && !crtc->primary->fb) {
> > >  		DRM_DEBUG_KMS("No FB bound\n");
> > >  		return 0;
> > >  	}
> > > @@ -1360,8 +1360,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
> > >  		target_fb = fb;
> > >  	}
> > >  	else {
> > > -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> > > -		target_fb = crtc->fb;
> > > +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> > > +		target_fb = crtc->primary->fb;
> > >  	}
> > >  
> > >  	obj = radeon_fb->obj;
> > > @@ -1485,7 +1485,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
> > >  	/* set pageflip to happen anywhere in vblank interval */
> > >  	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> > >  
> > > -	if (!atomic && fb && fb != crtc->fb) {
> > > +	if (!atomic && fb && fb != crtc->primary->fb) {
> > >  		radeon_fb = to_radeon_framebuffer(fb);
> > >  		rbo = gem_to_radeon_bo(radeon_fb->obj);
> > >  		r = radeon_bo_reserve(rbo, false);
> > > @@ -1972,12 +1972,12 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
> > >  	int i;
> > >  
> > >  	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
> > > -	if (crtc->fb) {
> > > +	if (crtc->primary->fb) {
> > >  		int r;
> > >  		struct radeon_framebuffer *radeon_fb;
> > >  		struct radeon_bo *rbo;
> > >  
> > > -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> > > +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> > >  		rbo = gem_to_radeon_bo(radeon_fb->obj);
> > >  		r = radeon_bo_reserve(rbo, false);
> > >  		if (unlikely(r))
> > > diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
> > > index 030f8e4..b6c3264 100644
> > > --- a/drivers/gpu/drm/radeon/r100.c
> > > +++ b/drivers/gpu/drm/radeon/r100.c
> > > @@ -3220,12 +3220,12 @@ void r100_bandwidth_update(struct radeon_device *rdev)
> > >  
> > >  	if (rdev->mode_info.crtcs[0]->base.enabled) {
> > >  		mode1 = &rdev->mode_info.crtcs[0]->base.mode;
> > > -		pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8;
> > > +		pixel_bytes1 = rdev->mode_info.crtcs[0]->base.primary->fb->bits_per_pixel / 8;
> > >  	}
> > >  	if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
> > >  		if (rdev->mode_info.crtcs[1]->base.enabled) {
> > >  			mode2 = &rdev->mode_info.crtcs[1]->base.mode;
> > > -			pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8;
> > > +			pixel_bytes2 = rdev->mode_info.crtcs[1]->base.primary->fb->bits_per_pixel / 8;
> > >  		}
> > >  	}
> > >  
> > > diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> > > index 82d4f86..33b482b 100644
> > > --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> > > +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> > > @@ -89,7 +89,7 @@ static void radeon_property_change_mode(struct drm_encoder *encoder)
> > >  
> > >  	if (crtc && crtc->enabled) {
> > >  		drm_crtc_helper_set_mode(crtc, &crtc->mode,
> > > -					 crtc->x, crtc->y, crtc->fb);
> > > +					 crtc->x, crtc->y, crtc->primary->fb);
> > >  	}
> > >  }
> > >  
> > > diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
> > > index 2e72dcd..c524aba 100644
> > > --- a/drivers/gpu/drm/radeon/radeon_device.c
> > > +++ b/drivers/gpu/drm/radeon/radeon_device.c
> > > @@ -1424,7 +1424,8 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
> > >  
> > >  	/* unpin the front buffers */
> > >  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> > > -		struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
> > > +		struct radeon_framebuffer *rfb =
> > > +			to_radeon_framebuffer(crtc->primary->fb);
> > >  		struct radeon_bo *robj;
> > >  
> > >  		if (rfb == NULL || rfb->obj == NULL) {
> > > diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> > > index a29d217..4e90049 100644
> > > --- a/drivers/gpu/drm/radeon/radeon_display.c
> > > +++ b/drivers/gpu/drm/radeon/radeon_display.c
> > > @@ -369,7 +369,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
> > >  	work->event = event;
> > >  	work->rdev = rdev;
> > >  	work->crtc_id = radeon_crtc->crtc_id;
> > > -	old_radeon_fb = to_radeon_framebuffer(crtc->fb);
> > > +	old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> > >  	new_radeon_fb = to_radeon_framebuffer(fb);
> > >  	/* schedule unpin of the old buffer */
> > >  	obj = old_radeon_fb->obj;
> > > @@ -460,7 +460,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
> > >  	spin_unlock_irqrestore(&dev->event_lock, flags);
> > >  
> > >  	/* update crtc fb */
> > > -	crtc->fb = fb;
> > > +	crtc->primary->fb = fb;
> > >  
> > >  	r = drm_vblank_get(dev, radeon_crtc->crtc_id);
> > >  	if (r) {
> > > diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
> > > index 0b158f9..cafb1cc 100644
> > > --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
> > > +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
> > > @@ -385,7 +385,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
> > >  
> > >  	DRM_DEBUG_KMS("\n");
> > >  	/* no fb bound */
> > > -	if (!atomic && !crtc->fb) {
> > > +	if (!atomic && !crtc->primary->fb) {
> > >  		DRM_DEBUG_KMS("No FB bound\n");
> > >  		return 0;
> > >  	}
> > > @@ -395,8 +395,8 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
> > >  		target_fb = fb;
> > >  	}
> > >  	else {
> > > -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> > > -		target_fb = crtc->fb;
> > > +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> > > +		target_fb = crtc->primary->fb;
> > >  	}
> > >  
> > >  	switch (target_fb->bits_per_pixel) {
> > > @@ -444,7 +444,7 @@ retry:
> > >  		 * We don't shutdown the display controller because new buffer
> > >  		 * will end up in same spot.
> > >  		 */
> > > -		if (!atomic && fb && fb != crtc->fb) {
> > > +		if (!atomic && fb && fb != crtc->primary->fb) {
> > >  			struct radeon_bo *old_rbo;
> > >  			unsigned long nsize, osize;
> > >  
> > > @@ -555,7 +555,7 @@ retry:
> > >  	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset);
> > >  	WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
> > >  
> > > -	if (!atomic && fb && fb != crtc->fb) {
> > > +	if (!atomic && fb && fb != crtc->primary->fb) {
> > >  		radeon_fb = to_radeon_framebuffer(fb);
> > >  		rbo = gem_to_radeon_bo(radeon_fb->obj);
> > >  		r = radeon_bo_reserve(rbo, false);
> > > @@ -599,7 +599,7 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
> > >  		}
> > >  	}
> > >  
> > > -	switch (crtc->fb->bits_per_pixel) {
> > > +	switch (crtc->primary->fb->bits_per_pixel) {
> > >  	case 8:
> > >  		format = 2;
> > >  		break;
> > > @@ -1087,12 +1087,12 @@ static void radeon_crtc_commit(struct drm_crtc *crtc)
> > >  static void radeon_crtc_disable(struct drm_crtc *crtc)
> > >  {
> > >  	radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
> > > -	if (crtc->fb) {
> > > +	if (crtc->primary->fb) {
> > >  		int r;
> > >  		struct radeon_framebuffer *radeon_fb;
> > >  		struct radeon_bo *rbo;
> > >  
> > > -		radeon_fb = to_radeon_framebuffer(crtc->fb);
> > > +		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> > >  		rbo = gem_to_radeon_bo(radeon_fb->obj);
> > >  		r = radeon_bo_reserve(rbo, false);
> > >  		if (unlikely(r))
> > > diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
> > > index 1255944..c63b5e7 100644
> > > --- a/drivers/gpu/drm/udl/udl_modeset.c
> > > +++ b/drivers/gpu/drm/udl/udl_modeset.c
> > > @@ -310,7 +310,7 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc,
> > >  
> > >  {
> > >  	struct drm_device *dev = crtc->dev;
> > > -	struct udl_framebuffer *ufb = to_udl_fb(crtc->fb);
> > > +	struct udl_framebuffer *ufb = to_udl_fb(crtc->primary->fb);
> > >  	struct udl_device *udl = dev->dev_private;
> > >  	char *buf;
> > >  	char *wrptr;
> > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > > index 8a65041..1d59ed3 100644
> > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > > @@ -468,7 +468,7 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv,
> > >  	num_units = 0;
> > >  	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list,
> > >  			    head) {
> > > -		if (crtc->fb != &framebuffer->base)
> > > +		if (crtc->primary->fb != &framebuffer->base)
> > >  			continue;
> > >  		units[num_units++] = vmw_crtc_to_du(crtc);
> > >  	}
> > > @@ -883,7 +883,7 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
> > >  
> > >  	num_units = 0;
> > >  	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
> > > -		if (crtc->fb != &framebuffer->base)
> > > +		if (crtc->primary->fb != &framebuffer->base)
> > >  			continue;
> > >  		units[num_units++] = vmw_crtc_to_du(crtc);
> > >  	}
> > > @@ -1245,7 +1245,7 @@ int vmw_kms_present(struct vmw_private *dev_priv,
> > >  
> > >  	num_units = 0;
> > >  	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
> > > -		if (crtc->fb != &vfb->base)
> > > +		if (crtc->primary->fb != &vfb->base)
> > >  			continue;
> > >  		units[num_units++] = vmw_crtc_to_du(crtc);
> > >  	}
> > > @@ -1382,7 +1382,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
> > >  
> > >  	num_units = 0;
> > >  	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
> > > -		if (crtc->fb != &vfb->base)
> > > +		if (crtc->primary->fb != &vfb->base)
> > >  			continue;
> > >  		units[num_units++] = vmw_crtc_to_du(crtc);
> > >  	}
> > > @@ -1725,7 +1725,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
> > >  		     uint32_t page_flip_flags)
> > >  {
> > >  	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> > > -	struct drm_framebuffer *old_fb = crtc->fb;
> > > +	struct drm_framebuffer *old_fb = crtc->primary->fb;
> > >  	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
> > >  	struct drm_file *file_priv ;
> > >  	struct vmw_fence_obj *fence = NULL;
> > > @@ -1743,7 +1743,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
> > >  	if (!vmw_kms_screen_object_flippable(dev_priv, crtc))
> > >  		return -EINVAL;
> > >  
> > > -	crtc->fb = fb;
> > > +	crtc->primary->fb = fb;
> > >  
> > >  	/* do a full screen dirty update */
> > >  	clips.x1 = clips.y1 = 0;
> > > @@ -1783,7 +1783,7 @@ int vmw_du_page_flip(struct drm_crtc *crtc,
> > >  	return ret;
> > >  
> > >  out_no_fence:
> > > -	crtc->fb = old_fb;
> > > +	crtc->primary->fb = old_fb;
> > >  	return ret;
> > >  }
> > >  
> > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> > > index 001ec81..08fdd7f 100644
> > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> > > @@ -93,7 +93,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
> > >  
> > >  		if (crtc == NULL)
> > >  			return 0;
> > > -		fb = entry->base.crtc.fb;
> > > +		fb = entry->base.crtc.primary->fb;
> > >  
> > >  		return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0],
> > >  					  fb->bits_per_pixel, fb->depth);
> > > @@ -101,7 +101,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
> > >  
> > >  	if (!list_empty(&lds->active)) {
> > >  		entry = list_entry(lds->active.next, typeof(*entry), active);
> > > -		fb = entry->base.crtc.fb;
> > > +		fb = entry->base.crtc.primary->fb;
> > >  
> > >  		vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0],
> > >  				   fb->bits_per_pixel, fb->depth);
> > > @@ -259,7 +259,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
> > >  
> > >  		connector->encoder = NULL;
> > >  		encoder->crtc = NULL;
> > > -		crtc->fb = NULL;
> > > +		crtc->primary->fb = NULL;
> > >  		crtc->enabled = false;
> > >  
> > >  		vmw_ldu_del_active(dev_priv, ldu);
> > > @@ -280,7 +280,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
> > >  
> > >  	vmw_fb_off(dev_priv);
> > >  
> > > -	crtc->fb = fb;
> > > +	crtc->primary->fb = fb;
> > >  	encoder->crtc = crtc;
> > >  	connector->encoder = encoder;
> > >  	crtc->x = set->x;
> > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> > > index 585da43..46ea096 100644
> > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> > > @@ -307,7 +307,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
> > >  
> > >  		connector->encoder = NULL;
> > >  		encoder->crtc = NULL;
> > > -		crtc->fb = NULL;
> > > +		crtc->primary->fb = NULL;
> > >  		crtc->x = 0;
> > >  		crtc->y = 0;
> > >  		crtc->enabled = false;
> > > @@ -368,7 +368,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
> > >  
> > >  		connector->encoder = NULL;
> > >  		encoder->crtc = NULL;
> > > -		crtc->fb = NULL;
> > > +		crtc->primary->fb = NULL;
> > >  		crtc->x = 0;
> > >  		crtc->y = 0;
> > >  		crtc->enabled = false;
> > > @@ -381,7 +381,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
> > >  	connector->encoder = encoder;
> > >  	encoder->crtc = crtc;
> > >  	crtc->mode = *mode;
> > > -	crtc->fb = fb;
> > > +	crtc->primary->fb = fb;
> > >  	crtc->x = set->x;
> > >  	crtc->y = set->y;
> > >  	crtc->enabled = true;
> > > @@ -574,5 +574,5 @@ void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv,
> > >  	BUG_ON(!sou->base.is_implicit);
> > >  
> > >  	dev_priv->sou_priv->implicit_fb =
> > > -		vmw_framebuffer_to_vfb(sou->base.crtc.fb);
> > > +		vmw_framebuffer_to_vfb(sou->base.crtc.primary->fb);
> > >  }
> > > diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> > > index 4dc84f8..9f7824d 100644
> > > --- a/include/drm/drm_crtc.h
> > > +++ b/include/drm/drm_crtc.h
> > > @@ -309,9 +309,6 @@ struct drm_crtc {
> > >  	/* primary plane for CRTC */
> > >  	struct drm_plane *primary;
> > >  
> > > -	/* framebuffer the connector is currently bound to */
> > > -	struct drm_framebuffer *fb;
> > > -
> > >  	/* 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;
> > > -- 
> > > 1.8.5.1
> > > 
> > > _______________________________________________
> > > dri-devel mailing list
> > > dri-devel@lists.freedesktop.org
> > > http://lists.freedesktop.org/mailman/listinfo/dri-devel
> > 
> > -- 
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > +41 (0) 79 365 57 48 - http://blog.ffwll.ch
> 
> -- 
> Matt Roper
> Graphics Software Engineer
> ISG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
diff mbox

Patch

diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 44f0d32..bd1e156 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -81,7 +81,7 @@  static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
 	u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate;
 	u32 hborder, vborder;
 
-	switch (crtc->fb->bits_per_pixel) {
+	switch (crtc->primary->fb->bits_per_pixel) {
 	case 8:
 		vbios_mode->std_table = &vbios_stdtable[VGAModeIndex];
 		color_index = VGAModeIndex - 1;
@@ -176,7 +176,7 @@  static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff);
 
 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
-		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->fb->bits_per_pixel);
+		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->primary->fb->bits_per_pixel);
 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000);
 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay);
 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8);
@@ -340,7 +340,7 @@  static void ast_set_offset_reg(struct drm_crtc *crtc)
 
 	u16 offset;
 
-	offset = crtc->fb->pitches[0] >> 3;
+	offset = crtc->primary->fb->pitches[0] >> 3;
 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff));
 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f);
 }
@@ -365,7 +365,7 @@  static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode
 	struct ast_private *ast = crtc->dev->dev_private;
 	u8 jregA0 = 0, jregA3 = 0, jregA8 = 0;
 
-	switch (crtc->fb->bits_per_pixel) {
+	switch (crtc->primary->fb->bits_per_pixel) {
 	case 8:
 		jregA0 = 0x70;
 		jregA3 = 0x01;
@@ -418,7 +418,7 @@  static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mo
 static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		     struct ast_vbios_mode_info *vbios_mode)
 {
-	switch (crtc->fb->bits_per_pixel) {
+	switch (crtc->primary->fb->bits_per_pixel) {
 	case 8:
 		break;
 	default:
@@ -490,7 +490,7 @@  static int ast_crtc_do_set_base(struct drm_crtc *crtc,
 		ast_bo_unreserve(bo);
 	}
 
-	ast_fb = to_ast_framebuffer(crtc->fb);
+	ast_fb = to_ast_framebuffer(crtc->primary->fb);
 	obj = ast_fb->obj;
 	bo = gem_to_ast_bo(obj);
 
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index 182f5c9..b67ad12 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -62,10 +62,10 @@  static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 		}
 	}
 
-	if (WARN_ON(crtc->fb == NULL))
+	if (WARN_ON(crtc->primary->fb == NULL))
 		return -EINVAL;
 
-	bochs_fb = to_bochs_framebuffer(crtc->fb);
+	bochs_fb = to_bochs_framebuffer(crtc->primary->fb);
 	bo = gem_to_bochs_bo(bochs_fb->obj);
 	ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
 	if (ret)
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
index 449246f..5291d2f 100644
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -149,7 +149,7 @@  static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
 		cirrus_bo_unreserve(bo);
 	}
 
-	cirrus_fb = to_cirrus_framebuffer(crtc->fb);
+	cirrus_fb = to_cirrus_framebuffer(crtc->primary->fb);
 	obj = cirrus_fb->obj;
 	bo = gem_to_cirrus_bo(obj);
 
@@ -268,7 +268,7 @@  static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
 	sr07 = RREG8(SEQ_DATA);
 	sr07 &= 0xe0;
 	hdr = 0;
-	switch (crtc->fb->bits_per_pixel) {
+	switch (crtc->primary->fb->bits_per_pixel) {
 	case 8:
 		sr07 |= 0x11;
 		break;
@@ -291,13 +291,13 @@  static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
 	WREG_SEQ(0x7, sr07);
 
 	/* Program the pitch */
-	tmp = crtc->fb->pitches[0] / 8;
+	tmp = crtc->primary->fb->pitches[0] / 8;
 	WREG_CRT(VGA_CRTC_OFFSET, tmp);
 
 	/* Enable extended blanking and pitch bits, and enable full memory */
 	tmp = 0x22;
-	tmp |= (crtc->fb->pitches[0] >> 7) & 0x10;
-	tmp |= (crtc->fb->pitches[0] >> 6) & 0x40;
+	tmp |= (crtc->primary->fb->pitches[0] >> 7) & 0x10;
+	tmp |= (crtc->primary->fb->pitches[0] >> 6) & 0x40;
 	WREG_CRT(0x1b, tmp);
 
 	/* Enable high-colour modes */
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 0feb66cc..0c395e8 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -634,7 +634,7 @@  EXPORT_SYMBOL(drm_framebuffer_cleanup);
  * drm_framebuffer_remove - remove and unreference a framebuffer object
  * @fb: framebuffer to remove
  *
- * Scans all the CRTCs and planes in @dev's mode_config.  If they're
+ * Scans all the planes in @dev's mode_config.  If they're
  * using @fb, removes it, setting it to NULL. Then drops the reference to the
  * passed-in framebuffer. Might take the modeset locks.
  *
@@ -645,10 +645,7 @@  EXPORT_SYMBOL(drm_framebuffer_cleanup);
 void drm_framebuffer_remove(struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = fb->dev;
-	struct drm_crtc *crtc;
 	struct drm_plane *plane;
-	struct drm_mode_set set;
-	int ret;
 
 	WARN_ON(!list_empty(&fb->filp_head));
 
@@ -669,19 +666,7 @@  void drm_framebuffer_remove(struct drm_framebuffer *fb)
 	 */
 	if (atomic_read(&fb->refcount.refcount) > 1) {
 		drm_modeset_lock_all(dev);
-		/* remove from any CRTC */
-		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-			if (crtc->fb == fb) {
-				/* should turn off the crtc */
-				memset(&set, 0, sizeof(struct drm_mode_set));
-				set.crtc = crtc;
-				set.fb = NULL;
-				ret = drm_mode_set_config_internal(&set);
-				if (ret)
-					DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
-			}
-		}
-
+		/* remove from any plane */
 		list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
 			if (plane->fb == fb)
 				drm_plane_force_disable(plane);
@@ -1930,8 +1915,8 @@  int drm_mode_getcrtc(struct drm_device *dev,
 	crtc_resp->x = crtc->x;
 	crtc_resp->y = crtc->y;
 	crtc_resp->gamma_size = crtc->gamma_size;
-	if (crtc->fb)
-		crtc_resp->fb_id = crtc->fb->base.id;
+	if (crtc->primary->fb)
+		crtc_resp->fb_id = crtc->primary->fb->base.id;
 	else
 		crtc_resp->fb_id = 0;
 
@@ -2438,7 +2423,7 @@  int drm_mode_set_config_internal(struct drm_mode_set *set)
 	 * crtcs. Atomic modeset will have saner semantics ...
 	 */
 	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
-		tmp->old_fb = tmp->fb;
+		tmp->old_fb = tmp->primary->fb;
 
 	fb = set->fb;
 
@@ -2446,13 +2431,16 @@  int drm_mode_set_config_internal(struct drm_mode_set *set)
 	if (ret == 0) {
 		crtc->primary->crtc = crtc;
 
-		/* crtc->fb must be updated by ->set_config, enforces this. */
-		WARN_ON(fb != crtc->fb);
+		/*
+		 * crtc->primary->fb must be updated by ->set_config,
+		 * enforces this.
+		 */
+		WARN_ON(fb != crtc->primary->fb);
 	}
 
 	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
-		if (tmp->fb)
-			drm_framebuffer_reference(tmp->fb);
+		if (tmp->primary->fb)
+			drm_framebuffer_reference(tmp->primary->fb);
 		if (tmp->old_fb)
 			drm_framebuffer_unreference(tmp->old_fb);
 	}
@@ -2511,12 +2499,12 @@  int drm_mode_setcrtc(struct drm_device *dev, void *data,
 		/* If we have a mode we need a framebuffer. */
 		/* If we pass -1, set the mode with the currently bound fb */
 		if (crtc_req->fb_id == -1) {
-			if (!crtc->fb) {
+			if (!crtc->primary->fb) {
 				DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
 				ret = -EINVAL;
 				goto out;
 			}
-			fb = crtc->fb;
+			fb = crtc->primary->fb;
 			/* Make refcounting symmetric with the lookup path. */
 			drm_framebuffer_reference(fb);
 		} else {
@@ -4309,7 +4297,7 @@  int drm_mode_page_flip_ioctl(struct drm_device *dev,
 	crtc = obj_to_crtc(obj);
 
 	mutex_lock(&crtc->mutex);
-	if (crtc->fb == NULL) {
+	if (crtc->primary->fb == NULL) {
 		/* The framebuffer is currently unbound, presumably
 		 * due to a hotplug event, that userspace has not
 		 * yet discovered.
@@ -4331,7 +4319,7 @@  int drm_mode_page_flip_ioctl(struct drm_device *dev,
 	if (ret)
 		goto out;
 
-	if (crtc->fb->pixel_format != fb->pixel_format) {
+	if (crtc->primary->fb->pixel_format != fb->pixel_format) {
 		DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
 		ret = -EINVAL;
 		goto out;
@@ -4364,7 +4352,7 @@  int drm_mode_page_flip_ioctl(struct drm_device *dev,
 			(void (*) (struct drm_pending_event *)) kfree;
 	}
 
-	old_fb = crtc->fb;
+	old_fb = crtc->primary->fb;
 	ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
 	if (ret) {
 		if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
@@ -4377,12 +4365,12 @@  int drm_mode_page_flip_ioctl(struct drm_device *dev,
 		old_fb = NULL;
 	} else {
 		/*
-		 * Warn if the driver hasn't properly updated the crtc->fb
-		 * field to reflect that the new framebuffer is now used.
-		 * Failing to do so will screw with the reference counting
-		 * on framebuffers.
+		 * Warn if the driver hasn't properly updated the
+		 * crtc->primary->fb field to reflect that the new framebuffer
+		 * is now used.  Failing to do so will screw with the reference
+		 * counting on framebuffers.
 		 */
-		WARN_ON(crtc->fb != fb);
+		WARN_ON(crtc->primary->fb != fb);
 		/* Unref only the old framebuffer. */
 		fb = NULL;
 	}
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index a855178..8825afb 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -319,7 +319,7 @@  void drm_helper_disable_unused_functions(struct drm_device *dev)
 				(*crtc_funcs->disable)(crtc);
 			else
 				(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
-			crtc->fb = NULL;
+			crtc->primary->fb = NULL;
 		}
 	}
 }
@@ -646,19 +646,19 @@  int drm_crtc_helper_set_config(struct drm_mode_set *set)
 	save_set.mode = &set->crtc->mode;
 	save_set.x = set->crtc->x;
 	save_set.y = set->crtc->y;
-	save_set.fb = set->crtc->fb;
+	save_set.fb = set->crtc->primary->fb;
 
 	/* We should be able to check here if the fb has the same properties
 	 * and then just flip_or_move it */
-	if (set->crtc->fb != set->fb) {
+	if (set->crtc->primary->fb != set->fb) {
 		/* If we have no fb then treat it as a full mode set */
-		if (set->crtc->fb == NULL) {
+		if (set->crtc->primary->fb == NULL) {
 			DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
 			mode_changed = true;
 		} else if (set->fb == NULL) {
 			mode_changed = true;
 		} else if (set->fb->pixel_format !=
-			   set->crtc->fb->pixel_format) {
+			   set->crtc->primary->fb->pixel_format) {
 			mode_changed = true;
 		} else
 			fb_changed = true;
@@ -759,13 +759,13 @@  int drm_crtc_helper_set_config(struct drm_mode_set *set)
 			DRM_DEBUG_KMS("attempting to set mode from"
 					" userspace\n");
 			drm_mode_debug_printmodeline(set->mode);
-			set->crtc->fb = set->fb;
+			set->crtc->primary->fb = set->fb;
 			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
 						      set->x, set->y,
 						      save_set.fb)) {
 				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
 					  set->crtc->base.id);
-				set->crtc->fb = save_set.fb;
+				set->crtc->primary->fb = save_set.fb;
 				ret = -EINVAL;
 				goto fail;
 			}
@@ -780,13 +780,13 @@  int drm_crtc_helper_set_config(struct drm_mode_set *set)
 	} else if (fb_changed) {
 		set->crtc->x = set->x;
 		set->crtc->y = set->y;
-		set->crtc->fb = set->fb;
+		set->crtc->primary->fb = set->fb;
 		ret = crtc_funcs->mode_set_base(set->crtc,
 						set->x, set->y, save_set.fb);
 		if (ret != 0) {
 			set->crtc->x = save_set.x;
 			set->crtc->y = save_set.y;
-			set->crtc->fb = save_set.fb;
+			set->crtc->primary->fb = save_set.fb;
 			goto fail;
 		}
 	}
@@ -982,7 +982,8 @@  void drm_helper_resume_force_mode(struct drm_device *dev)
 			continue;
 
 		ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
-					       crtc->x, crtc->y, crtc->fb);
+					       crtc->x, crtc->y,
+					       crtc->primary->fb);
 
 		/* Restoring the old config should never fail! */
 		if (ret == false)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 9c6251f..e8e2b41 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -232,7 +232,7 @@  static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
 
 	list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
 		if (crtc->base.id == c->base.id)
-			return c->fb;
+			return c->primary->fb;
 	}
 
 	return NULL;
@@ -366,9 +366,9 @@  static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
 		return false;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		if (crtc->fb)
+		if (crtc->primary->fb)
 			crtcs_bound++;
-		if (crtc->fb == fb_helper->fb)
+		if (crtc->primary->fb == fb_helper->fb)
 			bound++;
 	}
 
diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c
index 8fbfa06..1cddcf8 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_display.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_display.c
@@ -463,7 +463,7 @@  static bool cdv_intel_pipe_enabled(struct drm_device *dev, int pipe)
 	crtc = dev_priv->pipe_to_crtc_mapping[pipe];
 	gma_crtc = to_gma_crtc(crtc);
 
-	if (crtc->fb == NULL || !gma_crtc->active)
+	if (crtc->primary->fb == NULL || !gma_crtc->active)
 		return false;
 	return true;
 }
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
index 0490ce3..9ff30c2 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -1693,7 +1693,7 @@  done:
 		struct drm_crtc *crtc = encoder->base.crtc;
 		drm_crtc_helper_set_mode(crtc, &crtc->mode,
 					 crtc->x, crtc->y,
-					 crtc->fb);
+					 crtc->primary->fb);
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
index 1c0d723..04956e6 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
@@ -199,7 +199,8 @@  static int cdv_hdmi_set_property(struct drm_connector *connector,
 		    crtc->saved_mode.vdisplay != 0) {
 			if (centre) {
 				if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode,
-					    encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
+					    encoder->crtc->x, encoder->crtc->y,
+					    encoder->crtc->primary->fb))
 					return -1;
 			} else {
 				struct drm_encoder_helper_funcs *helpers
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index 20e08e6..58f11df 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -494,7 +494,7 @@  static int cdv_intel_lvds_set_property(struct drm_connector *connector,
 						      &crtc->saved_mode,
 						      encoder->crtc->x,
 						      encoder->crtc->y,
-						      encoder->crtc->fb))
+						      encoder->crtc->primary->fb))
 				return -1;
 		}
 	} else if (!strcmp(property->name, "backlight") && encoder) {
diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
index 386de2c..7b73dd1 100644
--- a/drivers/gpu/drm/gma500/gma_display.c
+++ b/drivers/gpu/drm/gma500/gma_display.c
@@ -59,7 +59,7 @@  int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 	struct drm_device *dev = crtc->dev;
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
-	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
+	struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
 	int pipe = gma_crtc->pipe;
 	const struct psb_offset *map = &dev_priv->regmap[pipe];
 	unsigned long start, offset;
@@ -70,7 +70,7 @@  int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		return 0;
 
 	/* no fb bound */
-	if (!crtc->fb) {
+	if (!crtc->primary->fb) {
 		dev_err(dev->dev, "No FB bound\n");
 		goto gma_pipe_cleaner;
 	}
@@ -81,19 +81,20 @@  int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 	if (ret < 0)
 		goto gma_pipe_set_base_exit;
 	start = psbfb->gtt->offset;
-	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
+	offset = y * crtc->primary->fb->pitches[0] +
+		x * (crtc->primary->fb->bits_per_pixel / 8);
 
-	REG_WRITE(map->stride, crtc->fb->pitches[0]);
+	REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
 
 	dspcntr = REG_READ(map->cntr);
 	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
 
-	switch (crtc->fb->bits_per_pixel) {
+	switch (crtc->primary->fb->bits_per_pixel) {
 	case 8:
 		dspcntr |= DISPPLANE_8BPP;
 		break;
 	case 16:
-		if (crtc->fb->depth == 15)
+		if (crtc->primary->fb->depth == 15)
 			dspcntr |= DISPPLANE_15_16BPP;
 		else
 			dspcntr |= DISPPLANE_16BPP;
@@ -511,8 +512,8 @@  void gma_crtc_disable(struct drm_crtc *crtc)
 
 	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
 
-	if (crtc->fb) {
-		gt = to_psb_fb(crtc->fb)->gtt;
+	if (crtc->primary->fb) {
+		gt = to_psb_fb(crtc->primary->fb)->gtt;
 		psb_gtt_unpin(gt);
 	}
 }
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
index 860a4ee..6e91b20 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
@@ -287,7 +287,7 @@  static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
 						&gma_crtc->saved_mode,
 						encoder->crtc->x,
 						encoder->crtc->y,
-						encoder->crtc->fb))
+						encoder->crtc->primary->fb))
 					goto set_prop_error;
 			} else {
 				struct drm_encoder_helper_funcs *funcs =
diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c
index 321c00a..c54386a 100644
--- a/drivers/gpu/drm/gma500/mdfld_intel_display.c
+++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c
@@ -166,7 +166,7 @@  static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 	struct drm_device *dev = crtc->dev;
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
-	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
+	struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
 	int pipe = gma_crtc->pipe;
 	const struct psb_offset *map = &dev_priv->regmap[pipe];
 	unsigned long start, offset;
@@ -178,12 +178,12 @@  static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 	dev_dbg(dev->dev, "pipe = 0x%x.\n", pipe);
 
 	/* no fb bound */
-	if (!crtc->fb) {
+	if (!crtc->primary->fb) {
 		dev_dbg(dev->dev, "No FB bound\n");
 		return 0;
 	}
 
-	ret = check_fb(crtc->fb);
+	ret = check_fb(crtc->primary->fb);
 	if (ret)
 		return ret;
 
@@ -196,18 +196,19 @@  static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		return 0;
 
 	start = psbfb->gtt->offset;
-	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
+	offset = y * crtc->primary->fb->pitches[0] +
+		x * (crtc->primary->fb->bits_per_pixel / 8);
 
-	REG_WRITE(map->stride, crtc->fb->pitches[0]);
+	REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
 	dspcntr = REG_READ(map->cntr);
 	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
 
-	switch (crtc->fb->bits_per_pixel) {
+	switch (crtc->primary->fb->bits_per_pixel) {
 	case 8:
 		dspcntr |= DISPPLANE_8BPP;
 		break;
 	case 16:
-		if (crtc->fb->depth == 15)
+		if (crtc->primary->fb->depth == 15)
 			dspcntr |= DISPPLANE_15_16BPP;
 		else
 			dspcntr |= DISPPLANE_16BPP;
@@ -700,7 +701,7 @@  static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
 	}
 #endif
 
-	ret = check_fb(crtc->fb);
+	ret = check_fb(crtc->primary->fb);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c
index 8195e85..b0fb42a 100644
--- a/drivers/gpu/drm/gma500/oaktrail_crtc.c
+++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c
@@ -599,7 +599,7 @@  static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
-	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
+	struct psb_framebuffer *psbfb = to_psb_fb(crtc->primary->fb);
 	int pipe = gma_crtc->pipe;
 	const struct psb_offset *map = &dev_priv->regmap[pipe];
 	unsigned long start, offset;
@@ -608,7 +608,7 @@  static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
 	int ret = 0;
 
 	/* no fb bound */
-	if (!crtc->fb) {
+	if (!crtc->primary->fb) {
 		dev_dbg(dev->dev, "No FB bound\n");
 		return 0;
 	}
@@ -617,19 +617,20 @@  static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
 		return 0;
 
 	start = psbfb->gtt->offset;
-	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
+	offset = y * crtc->primary->fb->pitches[0] +
+		x * (crtc->primary->fb->bits_per_pixel / 8);
 
-	REG_WRITE(map->stride, crtc->fb->pitches[0]);
+	REG_WRITE(map->stride, crtc->primary->fb->pitches[0]);
 
 	dspcntr = REG_READ(map->cntr);
 	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
 
-	switch (crtc->fb->bits_per_pixel) {
+	switch (crtc->primary->fb->bits_per_pixel) {
 	case 8:
 		dspcntr |= DISPPLANE_8BPP;
 		break;
 	case 16:
-		if (crtc->fb->depth == 15)
+		if (crtc->primary->fb->depth == 15)
 			dspcntr |= DISPPLANE_15_16BPP;
 		else
 			dspcntr |= DISPPLANE_16BPP;
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c
index c8f833d..25c174c 100644
--- a/drivers/gpu/drm/gma500/psb_intel_display.c
+++ b/drivers/gpu/drm/gma500/psb_intel_display.c
@@ -120,7 +120,7 @@  static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 	const struct gma_limit_t *limit;
 
 	/* No scan out no play */
-	if (crtc->fb == NULL) {
+	if (crtc->primary->fb == NULL) {
 		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
 		return 0;
 	}
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index 32342f6..dcdf70e 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -614,7 +614,7 @@  int psb_intel_lvds_set_property(struct drm_connector *connector,
 						      &crtc->saved_mode,
 						      encoder->crtc->x,
 						      encoder->crtc->y,
-						      encoder->crtc->fb))
+						      encoder->crtc->primary->fb))
 				goto set_prop_error;
 		}
 	} else if (!strcmp(property->name, "backlight")) {
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
index 07d3a9e..1c0a2fb 100644
--- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
+++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
@@ -1844,7 +1844,7 @@  done:
 	if (psb_intel_sdvo->base.base.crtc) {
 		struct drm_crtc *crtc = psb_intel_sdvo->base.base.crtc;
 		drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
-					 crtc->y, crtc->fb);
+					 crtc->y, crtc->primary->fb);
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index d83d643..f00ba43 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2172,8 +2172,8 @@  static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc)
 	struct intel_encoder *intel_encoder;
 
 	seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
-		   crtc->fb->base.id, crtc->x, crtc->y,
-		   crtc->fb->width, crtc->fb->height);
+		   crtc->primary->fb->base.id, crtc->x, crtc->y,
+		   crtc->primary->fb->width, crtc->primary->fb->height);
 	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
 		intel_encoder_info(m, intel_crtc, intel_encoder);
 }
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 37f852d..e8b3f9f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2380,8 +2380,8 @@  static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, in
 	} else {
 		int dspaddr = DSPADDR(intel_crtc->plane);
 		stall_detected = I915_READ(dspaddr) == (i915_gem_obj_ggtt_offset(obj) +
-							crtc->y * crtc->fb->pitches[0] +
-							crtc->x * crtc->fb->bits_per_pixel/8);
+							crtc->y * crtc->primary->fb->pitches[0] +
+							crtc->x * crtc->primary->fb->bits_per_pixel/8);
 	}
 
 	spin_unlock_irqrestore(&dev->event_lock, flags);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 21d12a9..c2f3730 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -744,7 +744,7 @@  bool intel_crtc_active(struct drm_crtc *crtc)
 	 * We can ditch the crtc->fb check as soon as we can
 	 * properly reconstruct framebuffers.
 	 */
-	return intel_crtc->active && crtc->fb &&
+	return intel_crtc->active && crtc->primary->fb &&
 		intel_crtc->config.adjusted_mode.crtc_clock;
 }
 
@@ -2086,17 +2086,18 @@  static bool intel_alloc_plane_obj(struct intel_crtc *crtc,
 
 	if (plane_config->tiled) {
 		obj->tiling_mode = I915_TILING_X;
-		obj->stride = crtc->base.fb->pitches[0];
+		obj->stride = crtc->base.primary->fb->pitches[0];
 	}
 
-	mode_cmd.pixel_format = crtc->base.fb->pixel_format;
-	mode_cmd.width = crtc->base.fb->width;
-	mode_cmd.height = crtc->base.fb->height;
-	mode_cmd.pitches[0] = crtc->base.fb->pitches[0];
+	mode_cmd.pixel_format = crtc->base.primary->fb->pixel_format;
+	mode_cmd.width = crtc->base.primary->fb->width;
+	mode_cmd.height = crtc->base.primary->fb->height;
+	mode_cmd.pitches[0] = crtc->base.primary->fb->pitches[0];
 
 	mutex_lock(&dev->struct_mutex);
 
-	if (intel_framebuffer_init(dev, to_intel_framebuffer(crtc->base.fb),
+	if (intel_framebuffer_init(dev,
+				   to_intel_framebuffer(crtc->base.primary->fb),
 				   &mode_cmd, obj)) {
 		DRM_DEBUG_KMS("intel fb init failed\n");
 		goto out_unref_obj;
@@ -2121,14 +2122,14 @@  static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
 	struct intel_crtc *i;
 	struct intel_framebuffer *fb;
 
-	if (!intel_crtc->base.fb)
+	if (!intel_crtc->base.primary->fb)
 		return;
 
 	if (intel_alloc_plane_obj(intel_crtc, plane_config))
 		return;
 
-	kfree(intel_crtc->base.fb);
-	intel_crtc->base.fb = NULL;
+	kfree(intel_crtc->base.primary->fb);
+	intel_crtc->base.primary->fb = NULL;
 
 	/*
 	 * Failed to alloc the obj, check to see if we should share
@@ -2140,13 +2141,13 @@  static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
 		if (c == &intel_crtc->base)
 			continue;
 
-		if (!i->active || !c->fb)
+		if (!i->active || !c->primary->fb)
 			continue;
 
-		fb = to_intel_framebuffer(c->fb);
+		fb = to_intel_framebuffer(c->primary->fb);
 		if (i915_gem_obj_ggtt_offset(fb->obj) == plane_config->base) {
-			drm_framebuffer_reference(c->fb);
-			intel_crtc->base.fb = c->fb;
+			drm_framebuffer_reference(c->primary->fb);
+			intel_crtc->base.primary->fb = c->primary->fb;
 			break;
 		}
 	}
@@ -2394,11 +2395,13 @@  void intel_display_handle_reset(struct drm_device *dev)
 		/*
 		 * FIXME: Once we have proper support for primary planes (and
 		 * disabling them without disabling the entire crtc) allow again
-		 * a NULL crtc->fb.
+		 * a NULL crtc->primary->fb.
 		 */
-		if (intel_crtc->active && crtc->fb)
-			dev_priv->display.update_plane(crtc, crtc->fb,
-						       crtc->x, crtc->y);
+		if (intel_crtc->active && crtc->primary->fb)
+			dev_priv->display.update_plane(crtc,
+						       crtc->primary->fb,
+						       crtc->x,
+						       crtc->y);
 		mutex_unlock(&crtc->mutex);
 	}
 }
@@ -2523,8 +2526,8 @@  intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		return ret;
 	}
 
-	old_fb = crtc->fb;
-	crtc->fb = fb;
+	old_fb = crtc->primary->fb;
+	crtc->primary->fb = fb;
 	crtc->x = x;
 	crtc->y = y;
 
@@ -3118,7 +3121,7 @@  static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (crtc->fb == NULL)
+	if (crtc->primary->fb == NULL)
 		return;
 
 	WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
@@ -3127,7 +3130,7 @@  static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
 		   !intel_crtc_has_pending_flip(crtc));
 
 	mutex_lock(&dev->struct_mutex);
-	intel_finish_fb(crtc->fb);
+	intel_finish_fb(crtc->primary->fb);
 	mutex_unlock(&dev->struct_mutex);
 }
 
@@ -4583,11 +4586,11 @@  static void intel_crtc_disable(struct drm_crtc *crtc)
 	assert_cursor_disabled(dev_priv, to_intel_crtc(crtc)->pipe);
 	assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
 
-	if (crtc->fb) {
+	if (crtc->primary->fb) {
 		mutex_lock(&dev->struct_mutex);
-		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
+		intel_unpin_fb_obj(to_intel_framebuffer(crtc->primary->fb)->obj);
 		mutex_unlock(&dev->struct_mutex);
-		crtc->fb = NULL;
+		crtc->primary->fb = NULL;
 	}
 
 	/* Update computed state. */
@@ -5738,8 +5741,9 @@  static void i9xx_get_plane_config(struct intel_crtc *crtc,
 	int fourcc, pixel_format;
 	int aligned_height;
 
-	crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
-	if (!crtc->base.fb) {
+	crtc->base.primary->fb =
+		kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
+	if (!crtc->base.primary->fb) {
 		DRM_DEBUG_KMS("failed to alloc fb\n");
 		return;
 	}
@@ -5752,8 +5756,8 @@  static void i9xx_get_plane_config(struct intel_crtc *crtc,
 
 	pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
 	fourcc = intel_format_to_fourcc(pixel_format);
-	crtc->base.fb->pixel_format = fourcc;
-	crtc->base.fb->bits_per_pixel =
+	crtc->base.primary->fb->pixel_format = fourcc;
+	crtc->base.primary->fb->bits_per_pixel =
 		drm_format_plane_cpp(fourcc, 0) * 8;
 
 	if (INTEL_INFO(dev)->gen >= 4) {
@@ -5768,23 +5772,23 @@  static void i9xx_get_plane_config(struct intel_crtc *crtc,
 	plane_config->base = base;
 
 	val = I915_READ(PIPESRC(pipe));
-	crtc->base.fb->width = ((val >> 16) & 0xfff) + 1;
-	crtc->base.fb->height = ((val >> 0) & 0xfff) + 1;
+	crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1;
+	crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
 
 	val = I915_READ(DSPSTRIDE(pipe));
-	crtc->base.fb->pitches[0] = val & 0xffffff80;
+	crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
 
-	aligned_height = intel_align_height(dev, crtc->base.fb->height,
+	aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
 					    plane_config->tiled);
 
-	plane_config->size = ALIGN(crtc->base.fb->pitches[0] *
+	plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
 				   aligned_height, PAGE_SIZE);
 
 	DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
-		      pipe, plane, crtc->base.fb->width,
-		      crtc->base.fb->height,
-		      crtc->base.fb->bits_per_pixel, base,
-		      crtc->base.fb->pitches[0],
+		      pipe, plane, crtc->base.primary->fb->width,
+		      crtc->base.primary->fb->height,
+		      crtc->base.primary->fb->bits_per_pixel, base,
+		      crtc->base.primary->fb->pitches[0],
 		      plane_config->size);
 
 }
@@ -6746,8 +6750,9 @@  static void ironlake_get_plane_config(struct intel_crtc *crtc,
 	int fourcc, pixel_format;
 	int aligned_height;
 
-	crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
-	if (!crtc->base.fb) {
+	crtc->base.primary->fb =
+		kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
+	if (!crtc->base.primary->fb) {
 		DRM_DEBUG_KMS("failed to alloc fb\n");
 		return;
 	}
@@ -6760,8 +6765,8 @@  static void ironlake_get_plane_config(struct intel_crtc *crtc,
 
 	pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
 	fourcc = intel_format_to_fourcc(pixel_format);
-	crtc->base.fb->pixel_format = fourcc;
-	crtc->base.fb->bits_per_pixel =
+	crtc->base.primary->fb->pixel_format = fourcc;
+	crtc->base.primary->fb->bits_per_pixel =
 		drm_format_plane_cpp(fourcc, 0) * 8;
 
 	base = I915_READ(DSPSURF(plane)) & 0xfffff000;
@@ -6776,23 +6781,23 @@  static void ironlake_get_plane_config(struct intel_crtc *crtc,
 	plane_config->base = base;
 
 	val = I915_READ(PIPESRC(pipe));
-	crtc->base.fb->width = ((val >> 16) & 0xfff) + 1;
-	crtc->base.fb->height = ((val >> 0) & 0xfff) + 1;
+	crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1;
+	crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
 
 	val = I915_READ(DSPSTRIDE(pipe));
-	crtc->base.fb->pitches[0] = val & 0xffffff80;
+	crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
 
-	aligned_height = intel_align_height(dev, crtc->base.fb->height,
+	aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
 					    plane_config->tiled);
 
-	plane_config->size = ALIGN(crtc->base.fb->pitches[0] *
+	plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
 				   aligned_height, PAGE_SIZE);
 
 	DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
-		      pipe, plane, crtc->base.fb->width,
-		      crtc->base.fb->height,
-		      crtc->base.fb->bits_per_pixel, base,
-		      crtc->base.fb->pitches[0],
+		      pipe, plane, crtc->base.primary->fb->width,
+		      crtc->base.primary->fb->height,
+		      crtc->base.primary->fb->bits_per_pixel, base,
+		      crtc->base.primary->fb->pitches[0],
 		      plane_config->size);
 }
 
@@ -8482,7 +8487,7 @@  void intel_mark_idle(struct drm_device *dev)
 		goto out;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		if (!crtc->fb)
+		if (!crtc->primary->fb)
 			continue;
 
 		intel_decrease_pllclock(crtc);
@@ -8505,10 +8510,10 @@  void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
 		return;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		if (!crtc->fb)
+		if (!crtc->primary->fb)
 			continue;
 
-		if (to_intel_framebuffer(crtc->fb)->obj != obj)
+		if (to_intel_framebuffer(crtc->primary->fb)->obj != obj)
 			continue;
 
 		intel_increase_pllclock(crtc);
@@ -8936,7 +8941,7 @@  static int intel_crtc_page_flip(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_framebuffer *old_fb = crtc->fb;
+	struct drm_framebuffer *old_fb = crtc->primary->fb;
 	struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_unpin_work *work;
@@ -8944,7 +8949,7 @@  static int intel_crtc_page_flip(struct drm_crtc *crtc,
 	int ret;
 
 	/* Can't change pixel format via MI display flips. */
-	if (fb->pixel_format != crtc->fb->pixel_format)
+	if (fb->pixel_format != crtc->primary->fb->pixel_format)
 		return -EINVAL;
 
 	/*
@@ -8952,8 +8957,8 @@  static int intel_crtc_page_flip(struct drm_crtc *crtc,
 	 * Note that pitch changes could also affect these register.
 	 */
 	if (INTEL_INFO(dev)->gen > 3 &&
-	    (fb->offsets[0] != crtc->fb->offsets[0] ||
-	     fb->pitches[0] != crtc->fb->pitches[0]))
+	    (fb->offsets[0] != crtc->primary->fb->offsets[0] ||
+	     fb->pitches[0] != crtc->primary->fb->pitches[0]))
 		return -EINVAL;
 
 	if (i915_terminally_wedged(&dev_priv->gpu_error))
@@ -8996,7 +9001,7 @@  static int intel_crtc_page_flip(struct drm_crtc *crtc,
 	drm_gem_object_reference(&work->old_fb_obj->base);
 	drm_gem_object_reference(&obj->base);
 
-	crtc->fb = fb;
+	crtc->primary->fb = fb;
 
 	work->pending_flip_obj = obj;
 
@@ -9019,7 +9024,7 @@  static int intel_crtc_page_flip(struct drm_crtc *crtc,
 
 cleanup_pending:
 	atomic_dec(&intel_crtc->unpin_work_count);
-	crtc->fb = old_fb;
+	crtc->primary->fb = old_fb;
 	drm_gem_object_unreference(&work->old_fb_obj->base);
 	drm_gem_object_unreference(&obj->base);
 	mutex_unlock(&dev->struct_mutex);
@@ -10060,7 +10065,7 @@  static int intel_set_mode(struct drm_crtc *crtc,
 
 void intel_crtc_restore_mode(struct drm_crtc *crtc)
 {
-	intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb);
+	intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb);
 }
 
 #undef for_each_intel_crtc_masked
@@ -10184,9 +10189,9 @@  intel_set_config_compute_mode_changes(struct drm_mode_set *set,
 	 * and then just flip_or_move it */
 	if (is_crtc_connector_off(set)) {
 		config->mode_changed = true;
-	} else if (set->crtc->fb != set->fb) {
+	} else if (set->crtc->primary->fb != set->fb) {
 		/* If we have no fb then treat it as a full mode set */
-		if (set->crtc->fb == NULL) {
+		if (set->crtc->primary->fb == NULL) {
 			struct intel_crtc *intel_crtc =
 				to_intel_crtc(set->crtc);
 
@@ -10200,7 +10205,7 @@  intel_set_config_compute_mode_changes(struct drm_mode_set *set,
 		} else if (set->fb == NULL) {
 			config->mode_changed = true;
 		} else if (set->fb->pixel_format !=
-			   set->crtc->fb->pixel_format) {
+			   set->crtc->primary->fb->pixel_format) {
 			config->mode_changed = true;
 		} else {
 			config->fb_changed = true;
@@ -10413,7 +10418,7 @@  static int intel_crtc_set_config(struct drm_mode_set *set)
 	save_set.mode = &set->crtc->mode;
 	save_set.x = set->crtc->x;
 	save_set.y = set->crtc->y;
-	save_set.fb = set->crtc->fb;
+	save_set.fb = set->crtc->primary->fb;
 
 	/* Compute whether we need a full modeset, only an fb base update or no
 	 * change at all. In the future we might also check whether only the
@@ -11755,7 +11760,7 @@  void intel_modeset_setup_hw_state(struct drm_device *dev,
 				dev_priv->pipe_to_crtc_mapping[pipe];
 
 			__intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
-					 crtc->fb);
+					 crtc->primary->fb);
 		}
 	} else {
 		intel_modeset_update_staged_output_state(dev);
@@ -11780,15 +11785,15 @@  void intel_modeset_gem_init(struct drm_device *dev)
 	 */
 	mutex_lock(&dev->struct_mutex);
 	list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
-		if (!c->fb)
+		if (!c->primary->fb)
 			continue;
 
-		fb = to_intel_framebuffer(c->fb);
+		fb = to_intel_framebuffer(c->primary->fb);
 		if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL)) {
 			DRM_ERROR("failed to pin boot fb on pipe %d\n",
 				  to_intel_crtc(c)->pipe);
-			drm_framebuffer_unreference(c->fb);
-			c->fb = NULL;
+			drm_framebuffer_unreference(c->primary->fb);
+			c->primary->fb = NULL;
 		}
 	}
 	mutex_unlock(&dev->struct_mutex);
@@ -11827,7 +11832,7 @@  void intel_modeset_cleanup(struct drm_device *dev)
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		/* Skip inactive CRTCs */
-		if (!crtc->fb)
+		if (!crtc->primary->fb)
 			continue;
 
 		intel_increase_pllclock(crtc);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 59ee4dc..05531bf 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1634,7 +1634,8 @@  static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc = dig_port->base.base.crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
+	struct drm_i915_gem_object *obj =
+		to_intel_framebuffer(crtc->primary->fb)->obj;
 	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
 
 	dev_priv->psr.source_ok = false;
@@ -1667,7 +1668,7 @@  static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
 		return false;
 	}
 
-	obj = to_intel_framebuffer(crtc->fb)->obj;
+	obj = to_intel_framebuffer(crtc->primary->fb)->obj;
 	if (obj->tiling_mode != I915_TILING_X ||
 	    obj->fence_reg == I915_FENCE_REG_NONE) {
 		DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index d6d78c8..2b1d42d 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -481,7 +481,7 @@  static bool intel_fbdev_init_bios(struct drm_device *dev,
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		intel_crtc = to_intel_crtc(crtc);
 
-		if (!intel_crtc->active || !crtc->fb) {
+		if (!intel_crtc->active || !crtc->primary->fb) {
 			DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
 				      pipe_name(intel_crtc->pipe));
 			continue;
@@ -491,7 +491,7 @@  static bool intel_fbdev_init_bios(struct drm_device *dev,
 			DRM_DEBUG_KMS("found possible fb from plane %c\n",
 				      pipe_name(intel_crtc->pipe));
 			plane_config = &intel_crtc->plane_config;
-			fb = to_intel_framebuffer(crtc->fb);
+			fb = to_intel_framebuffer(crtc->primary->fb);
 			max_size = plane_config->size;
 		}
 	}
@@ -560,7 +560,7 @@  static bool intel_fbdev_init_bios(struct drm_device *dev,
 		if (!intel_crtc->active)
 			continue;
 
-		WARN(!crtc->fb,
+		WARN(!crtc->primary->fb,
 		     "re-used BIOS config but lost an fb on crtc %d\n",
 		     crtc->base.id);
 	}
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 312961a..623cd32 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -606,14 +606,14 @@  static void update_colorkey(struct intel_overlay *overlay,
 {
 	u32 key = overlay->color_key;
 
-	switch (overlay->crtc->base.fb->bits_per_pixel) {
+	switch (overlay->crtc->base.primary->fb->bits_per_pixel) {
 	case 8:
 		iowrite32(0, &regs->DCLRKV);
 		iowrite32(CLK_RGB8I_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
 		break;
 
 	case 16:
-		if (overlay->crtc->base.fb->depth == 15) {
+		if (overlay->crtc->base.primary->fb->depth == 15) {
 			iowrite32(RGB15_TO_COLORKEY(key), &regs->DCLRKV);
 			iowrite32(CLK_RGB15_MASK | DST_KEY_ENABLE,
 				  &regs->DCLRKM);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 3a1b569..e2d73f4 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -92,7 +92,7 @@  static void i8xx_enable_fbc(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_framebuffer *fb = crtc->fb;
+	struct drm_framebuffer *fb = crtc->primary->fb;
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -149,7 +149,7 @@  static void g4x_enable_fbc(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_framebuffer *fb = crtc->fb;
+	struct drm_framebuffer *fb = crtc->primary->fb;
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -221,7 +221,7 @@  static void ironlake_enable_fbc(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_framebuffer *fb = crtc->fb;
+	struct drm_framebuffer *fb = crtc->primary->fb;
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -277,7 +277,7 @@  static void gen7_enable_fbc(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_framebuffer *fb = crtc->fb;
+	struct drm_framebuffer *fb = crtc->primary->fb;
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -336,11 +336,11 @@  static void intel_fbc_work_fn(struct work_struct *__work)
 		/* Double check that we haven't switched fb without cancelling
 		 * the prior work.
 		 */
-		if (work->crtc->fb == work->fb) {
+		if (work->crtc->primary->fb == work->fb) {
 			dev_priv->display.enable_fbc(work->crtc);
 
 			dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane;
-			dev_priv->fbc.fb_id = work->crtc->fb->base.id;
+			dev_priv->fbc.fb_id = work->crtc->primary->fb->base.id;
 			dev_priv->fbc.y = work->crtc->y;
 		}
 
@@ -393,7 +393,7 @@  static void intel_enable_fbc(struct drm_crtc *crtc)
 	}
 
 	work->crtc = crtc;
-	work->fb = crtc->fb;
+	work->fb = crtc->primary->fb;
 	INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
 
 	dev_priv->fbc.fbc_work = work;
@@ -499,14 +499,14 @@  void intel_update_fbc(struct drm_device *dev)
 		}
 	}
 
-	if (!crtc || crtc->fb == NULL) {
+	if (!crtc || crtc->primary->fb == NULL) {
 		if (set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT))
 			DRM_DEBUG_KMS("no output, disabling\n");
 		goto out_disable;
 	}
 
 	intel_crtc = to_intel_crtc(crtc);
-	fb = crtc->fb;
+	fb = crtc->primary->fb;
 	intel_fb = to_intel_framebuffer(fb);
 	obj = intel_fb->obj;
 	adjusted_mode = &intel_crtc->config.adjusted_mode;
@@ -1041,7 +1041,7 @@  static void pineview_update_wm(struct drm_crtc *unused_crtc)
 	crtc = single_enabled_crtc(dev);
 	if (crtc) {
 		const struct drm_display_mode *adjusted_mode;
-		int pixel_size = crtc->fb->bits_per_pixel / 8;
+		int pixel_size = crtc->primary->fb->bits_per_pixel / 8;
 		int clock;
 
 		adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
@@ -1121,7 +1121,7 @@  static bool g4x_compute_wm0(struct drm_device *dev,
 	clock = adjusted_mode->crtc_clock;
 	htotal = adjusted_mode->crtc_htotal;
 	hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
-	pixel_size = crtc->fb->bits_per_pixel / 8;
+	pixel_size = crtc->primary->fb->bits_per_pixel / 8;
 
 	/* Use the small buffer method to calculate plane watermark */
 	entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
@@ -1208,7 +1208,7 @@  static bool g4x_compute_srwm(struct drm_device *dev,
 	clock = adjusted_mode->crtc_clock;
 	htotal = adjusted_mode->crtc_htotal;
 	hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
-	pixel_size = crtc->fb->bits_per_pixel / 8;
+	pixel_size = crtc->primary->fb->bits_per_pixel / 8;
 
 	line_time_us = max(htotal * 1000 / clock, 1);
 	line_count = (latency_ns / line_time_us + 1000) / 1000;
@@ -1247,7 +1247,7 @@  static bool vlv_compute_drain_latency(struct drm_device *dev,
 		return false;
 
 	clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
-	pixel_size = crtc->fb->bits_per_pixel / 8;	/* BPP */
+	pixel_size = crtc->primary->fb->bits_per_pixel / 8;	/* BPP */
 
 	entries = (clock / 1000) * pixel_size;
 	*plane_prec_mult = (entries > 256) ?
@@ -1439,7 +1439,7 @@  static void i965_update_wm(struct drm_crtc *unused_crtc)
 		int clock = adjusted_mode->crtc_clock;
 		int htotal = adjusted_mode->crtc_htotal;
 		int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
-		int pixel_size = crtc->fb->bits_per_pixel / 8;
+		int pixel_size = crtc->primary->fb->bits_per_pixel / 8;
 		unsigned long line_time_us;
 		int entries;
 
@@ -1512,7 +1512,7 @@  static void i9xx_update_wm(struct drm_crtc *unused_crtc)
 	crtc = intel_get_crtc_for_plane(dev, 0);
 	if (intel_crtc_active(crtc)) {
 		const struct drm_display_mode *adjusted_mode;
-		int cpp = crtc->fb->bits_per_pixel / 8;
+		int cpp = crtc->primary->fb->bits_per_pixel / 8;
 		if (IS_GEN2(dev))
 			cpp = 4;
 
@@ -1528,7 +1528,7 @@  static void i9xx_update_wm(struct drm_crtc *unused_crtc)
 	crtc = intel_get_crtc_for_plane(dev, 1);
 	if (intel_crtc_active(crtc)) {
 		const struct drm_display_mode *adjusted_mode;
-		int cpp = crtc->fb->bits_per_pixel / 8;
+		int cpp = crtc->primary->fb->bits_per_pixel / 8;
 		if (IS_GEN2(dev))
 			cpp = 4;
 
@@ -1565,7 +1565,7 @@  static void i9xx_update_wm(struct drm_crtc *unused_crtc)
 		int clock = adjusted_mode->crtc_clock;
 		int htotal = adjusted_mode->crtc_htotal;
 		int hdisplay = to_intel_crtc(enabled)->config.pipe_src_w;
-		int pixel_size = enabled->fb->bits_per_pixel / 8;
+		int pixel_size = enabled->primary->fb->bits_per_pixel / 8;
 		unsigned long line_time_us;
 		int entries;
 
@@ -2117,7 +2117,7 @@  static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
 	if (p->active) {
 		p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_htotal;
 		p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
-		p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
+		p->pri.bytes_per_pixel = crtc->primary->fb->bits_per_pixel / 8;
 		p->cur.bytes_per_pixel = 4;
 		p->pri.horiz_pixels = intel_crtc->config.pipe_src_w;
 		p->cur.horiz_pixels = 64;
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 1418414..f8c42b1 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -29,7 +29,7 @@  static void mga_crtc_load_lut(struct drm_crtc *crtc)
 	struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct mga_device *mdev = dev->dev_private;
-	struct drm_framebuffer *fb = crtc->fb;
+	struct drm_framebuffer *fb = crtc->primary->fb;
 	int i;
 
 	if (!crtc->enabled)
@@ -742,7 +742,7 @@  static int mga_crtc_do_set_base(struct drm_crtc *crtc,
 		mgag200_bo_unreserve(bo);
 	}
 
-	mga_fb = to_mga_framebuffer(crtc->fb);
+	mga_fb = to_mga_framebuffer(crtc->primary->fb);
 	obj = mga_fb->obj;
 	bo = gem_to_mga_bo(obj);
 
@@ -805,7 +805,7 @@  static int mga_crtc_mode_set(struct drm_crtc *crtc,
 		/* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
 	};
 
-	bppshift = mdev->bpp_shifts[(crtc->fb->bits_per_pixel >> 3) - 1];
+	bppshift = mdev->bpp_shifts[(crtc->primary->fb->bits_per_pixel >> 3) - 1];
 
 	switch (mdev->type) {
 	case G200_SE_A:
@@ -843,12 +843,12 @@  static int mga_crtc_mode_set(struct drm_crtc *crtc,
 		break;
 	}
 
-	switch (crtc->fb->bits_per_pixel) {
+	switch (crtc->primary->fb->bits_per_pixel) {
 	case 8:
 		dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits;
 		break;
 	case 16:
-		if (crtc->fb->depth == 15)
+		if (crtc->primary->fb->depth == 15)
 			dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_15bits;
 		else
 			dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_16bits;
@@ -896,8 +896,9 @@  static int mga_crtc_mode_set(struct drm_crtc *crtc,
 	WREG_SEQ(3, 0);
 	WREG_SEQ(4, 0xe);
 
-	pitch = crtc->fb->pitches[0] / (crtc->fb->bits_per_pixel / 8);
-	if (crtc->fb->bits_per_pixel == 24)
+	pitch = crtc->primary->fb->pitches[0] /
+		(crtc->primary->fb->bits_per_pixel / 8);
+	if (crtc->primary->fb->bits_per_pixel == 24)
 		pitch = (pitch * 3) >> (4 - bppshift);
 	else
 		pitch = pitch >> (4 - bppshift);
@@ -974,7 +975,7 @@  static int mga_crtc_mode_set(struct drm_crtc *crtc,
 		((vdisplay & 0xc00) >> 7) |
 		((vsyncstart & 0xc00) >> 5) |
 		((vdisplay & 0x400) >> 3);
-	if (crtc->fb->bits_per_pixel == 24)
+	if (crtc->primary->fb->bits_per_pixel == 24)
 		ext_vga[3] = (((1 << bppshift) * 3) - 1) | 0x80;
 	else
 		ext_vga[3] = ((1 << bppshift) - 1) | 0x80;
@@ -1034,9 +1035,9 @@  static int mga_crtc_mode_set(struct drm_crtc *crtc,
 			u32 bpp;
 			u32 mb;
 
-			if (crtc->fb->bits_per_pixel > 16)
+			if (crtc->primary->fb->bits_per_pixel > 16)
 				bpp = 32;
-			else if (crtc->fb->bits_per_pixel > 8)
+			else if (crtc->primary->fb->bits_per_pixel > 8)
 				bpp = 16;
 			else
 				bpp = 8;
@@ -1277,8 +1278,9 @@  static void mga_crtc_disable(struct drm_crtc *crtc)
 	int ret;
 	DRM_DEBUG_KMS("\n");
 	mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-	if (crtc->fb) {
-		struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->fb);
+	if (crtc->primary->fb) {
+		struct mga_framebuffer *mga_fb =
+			to_mga_framebuffer(crtc->primary->fb);
 		struct drm_gem_object *obj = mga_fb->obj;
 		struct mgag200_bo *bo = gem_to_mga_bo(obj);
 		ret = mgag200_bo_reserve(bo, false);
@@ -1287,7 +1289,7 @@  static void mga_crtc_disable(struct drm_crtc *crtc)
 		mgag200_bo_push_sysram(bo);
 		mgag200_bo_unreserve(bo);
 	}
-	crtc->fb = NULL;
+	crtc->primary->fb = NULL;
 }
 
 /* These provide the minimum set of functions required to handle a CRTC */
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index b10f681..f96497b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -120,7 +120,7 @@  static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
 
 	/* grab reference to incoming scanout fb: */
 	drm_framebuffer_reference(new_fb);
-	mdp4_crtc->base.fb = new_fb;
+	mdp4_crtc->base.primary->fb = new_fb;
 	mdp4_crtc->fb = new_fb;
 
 	if (old_fb)
@@ -182,7 +182,7 @@  static void pageflip_cb(struct msm_fence_cb *cb)
 	struct mdp4_crtc *mdp4_crtc =
 		container_of(cb, struct mdp4_crtc, pageflip_cb);
 	struct drm_crtc *crtc = &mdp4_crtc->base;
-	struct drm_framebuffer *fb = crtc->fb;
+	struct drm_framebuffer *fb = crtc->primary->fb;
 
 	if (!fb)
 		return;
@@ -348,14 +348,14 @@  static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
 			mode->type, mode->flags);
 
 	/* grab extra ref for update_scanout() */
-	drm_framebuffer_reference(crtc->fb);
+	drm_framebuffer_reference(crtc->primary->fb);
 
-	ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->fb,
+	ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->primary->fb,
 			0, 0, mode->hdisplay, mode->vdisplay,
 			x << 16, y << 16,
 			mode->hdisplay << 16, mode->vdisplay << 16);
 	if (ret) {
-		drm_framebuffer_unreference(crtc->fb);
+		drm_framebuffer_unreference(crtc->primary->fb);
 		dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
 				mdp4_crtc->name, ret);
 		return ret;
@@ -368,7 +368,7 @@  static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
 	/* take data from pipe: */
 	mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_BASE(dma), 0);
 	mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_STRIDE(dma),
-			crtc->fb->pitches[0]);
+			crtc->primary->fb->pitches[0]);
 	mdp4_write(mdp4_kms, REG_MDP4_DMA_DST_SIZE(dma),
 			MDP4_DMA_DST_SIZE_WIDTH(0) |
 			MDP4_DMA_DST_SIZE_HEIGHT(0));
@@ -378,7 +378,7 @@  static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
 			MDP4_OVLP_SIZE_WIDTH(mode->hdisplay) |
 			MDP4_OVLP_SIZE_HEIGHT(mode->vdisplay));
 	mdp4_write(mdp4_kms, REG_MDP4_OVLP_STRIDE(ovlp),
-			crtc->fb->pitches[0]);
+			crtc->primary->fb->pitches[0]);
 
 	mdp4_write(mdp4_kms, REG_MDP4_OVLP_CFG(ovlp), 1);
 
@@ -388,8 +388,8 @@  static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
 		mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(2), 0x00ff0000);
 	}
 
-	update_fb(crtc, crtc->fb);
-	update_scanout(crtc, crtc->fb);
+	update_fb(crtc, crtc->primary->fb);
+	update_scanout(crtc, crtc->primary->fb);
 
 	return 0;
 }
@@ -420,19 +420,19 @@  static int mdp4_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 	int ret;
 
 	/* grab extra ref for update_scanout() */
-	drm_framebuffer_reference(crtc->fb);
+	drm_framebuffer_reference(crtc->primary->fb);
 
-	ret = mdp4_plane_mode_set(plane, crtc, crtc->fb,
+	ret = mdp4_plane_mode_set(plane, crtc, crtc->primary->fb,
 			0, 0, mode->hdisplay, mode->vdisplay,
 			x << 16, y << 16,
 			mode->hdisplay << 16, mode->vdisplay << 16);
 	if (ret) {
-		drm_framebuffer_unreference(crtc->fb);
+		drm_framebuffer_unreference(crtc->primary->fb);
 		return ret;
 	}
 
-	update_fb(crtc, crtc->fb);
-	update_scanout(crtc, crtc->fb);
+	update_fb(crtc, crtc->primary->fb);
+	update_scanout(crtc, crtc->primary->fb);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 7dc3d71..f200048 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -102,7 +102,7 @@  static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
 
 	/* grab reference to incoming scanout fb: */
 	drm_framebuffer_reference(new_fb);
-	mdp5_crtc->base.fb = new_fb;
+	mdp5_crtc->base.primary->fb = new_fb;
 	mdp5_crtc->fb = new_fb;
 
 	if (old_fb)
@@ -289,14 +289,14 @@  static int mdp5_crtc_mode_set(struct drm_crtc *crtc,
 			mode->type, mode->flags);
 
 	/* grab extra ref for update_scanout() */
-	drm_framebuffer_reference(crtc->fb);
+	drm_framebuffer_reference(crtc->primary->fb);
 
-	ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->fb,
+	ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->primary->fb,
 			0, 0, mode->hdisplay, mode->vdisplay,
 			x << 16, y << 16,
 			mode->hdisplay << 16, mode->vdisplay << 16);
 	if (ret) {
-		drm_framebuffer_unreference(crtc->fb);
+		drm_framebuffer_unreference(crtc->primary->fb);
 		dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
 				mdp5_crtc->name, ret);
 		return ret;
@@ -306,8 +306,8 @@  static int mdp5_crtc_mode_set(struct drm_crtc *crtc,
 			MDP5_LM_OUT_SIZE_WIDTH(mode->hdisplay) |
 			MDP5_LM_OUT_SIZE_HEIGHT(mode->vdisplay));
 
-	update_fb(crtc, crtc->fb);
-	update_scanout(crtc, crtc->fb);
+	update_fb(crtc, crtc->primary->fb);
+	update_scanout(crtc, crtc->primary->fb);
 
 	return 0;
 }
@@ -338,19 +338,19 @@  static int mdp5_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 	int ret;
 
 	/* grab extra ref for update_scanout() */
-	drm_framebuffer_reference(crtc->fb);
+	drm_framebuffer_reference(crtc->primary->fb);
 
-	ret = mdp5_plane_mode_set(plane, crtc, crtc->fb,
+	ret = mdp5_plane_mode_set(plane, crtc, crtc->primary->fb,
 			0, 0, mode->hdisplay, mode->vdisplay,
 			x << 16, y << 16,
 			mode->hdisplay << 16, mode->vdisplay << 16);
 	if (ret) {
-		drm_framebuffer_unreference(crtc->fb);
+		drm_framebuffer_unreference(crtc->primary->fb);
 		return ret;
 	}
 
-	update_fb(crtc, crtc->fb);
-	update_scanout(crtc, crtc->fb);
+	update_fb(crtc, crtc->primary->fb);
+	update_scanout(crtc, crtc->primary->fb);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
index b55be84..2a5e9db 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
@@ -239,7 +239,7 @@  nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
 	struct drm_device *dev = crtc->dev;
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
-	struct drm_framebuffer *fb = crtc->fb;
+	struct drm_framebuffer *fb = crtc->primary->fb;
 
 	/* Calculate our timings */
 	int horizDisplay	= (mode->crtc_hdisplay >> 3)		- 1;
@@ -574,7 +574,7 @@  nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
 		regp->CRTC[NV_CIO_CRE_86] = 0x1;
 	}
 
-	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->fb->depth + 1) / 8;
+	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->primary->fb->depth + 1) / 8;
 	/* Enable slaved mode (called MODE_TV in nv4ref.h) */
 	if (lvds_output || tmds_output || tv_output)
 		regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7);
@@ -588,7 +588,7 @@  nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
 	regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS |
 				NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL |
 				NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON;
-	if (crtc->fb->depth == 16)
+	if (crtc->primary->fb->depth == 16)
 		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
 	if (nv_device(drm->device)->chipset >= 0x11)
 		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG;
@@ -609,7 +609,7 @@  static int
 nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
 {
 	struct nv04_display *disp = nv04_display(crtc->dev);
-	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
+	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	int ret;
 
@@ -808,7 +808,7 @@  nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
 	 * mark the lut values as dirty by setting depth==0, and it'll be
 	 * uploaded on the first mode_set_base()
 	 */
-	if (!nv_crtc->base.fb) {
+	if (!nv_crtc->base.primary->fb) {
 		nv_crtc->lut.depth = 0;
 		return;
 	}
@@ -832,7 +832,7 @@  nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
 	NV_DEBUG(drm, "index %d\n", nv_crtc->index);
 
 	/* no fb bound */
-	if (!atomic && !crtc->fb) {
+	if (!atomic && !crtc->primary->fb) {
 		NV_DEBUG(drm, "No FB bound\n");
 		return 0;
 	}
@@ -844,8 +844,8 @@  nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
 		drm_fb = passed_fb;
 		fb = nouveau_framebuffer(passed_fb);
 	} else {
-		drm_fb = crtc->fb;
-		fb = nouveau_framebuffer(crtc->fb);
+		drm_fb = crtc->primary->fb;
+		fb = nouveau_framebuffer(crtc->primary->fb);
 	}
 
 	nv_crtc->fb.offset = fb->nvbo->bo.offset;
@@ -857,9 +857,9 @@  nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
 
 	/* Update the framebuffer format. */
 	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] &= ~3;
-	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->fb->depth + 1) / 8;
+	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->primary->fb->depth + 1) / 8;
 	regp->ramdac_gen_ctrl &= ~NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
-	if (crtc->fb->depth == 16)
+	if (crtc->primary->fb->depth == 16)
 		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_PIXEL_INDEX);
 	NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL,
diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
index 7fdc51e..a2d669b 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
@@ -415,7 +415,7 @@  static void nv04_dfp_mode_set(struct drm_encoder *encoder,
 	/* Output property. */
 	if ((nv_connector->dithering_mode == DITHERING_MODE_ON) ||
 	    (nv_connector->dithering_mode == DITHERING_MODE_AUTO &&
-	     encoder->crtc->fb->depth > connector->display_info.bpc * 3)) {
+	     encoder->crtc->primary->fb->depth > connector->display_info.bpc * 3)) {
 		if (nv_device(drm->device)->chipset == 0x11)
 			regp->dither = savep->dither | 0x00010000;
 		else {
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 2401159..4e24c72 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -569,7 +569,7 @@  nouveau_display_suspend(struct drm_device *dev)
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct nouveau_framebuffer *nouveau_fb;
 
-		nouveau_fb = nouveau_framebuffer(crtc->fb);
+		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
 		if (!nouveau_fb || !nouveau_fb->nvbo)
 			continue;
 
@@ -596,7 +596,7 @@  nouveau_display_repin(struct drm_device *dev)
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct nouveau_framebuffer *nouveau_fb;
 
-		nouveau_fb = nouveau_framebuffer(crtc->fb);
+		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
 		if (!nouveau_fb || !nouveau_fb->nvbo)
 			continue;
 
@@ -693,7 +693,7 @@  nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 	const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1;
 	struct drm_device *dev = crtc->dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo;
+	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo;
 	struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
 	struct nouveau_page_flip_state *s;
 	struct nouveau_channel *chan = drm->channel;
@@ -767,7 +767,7 @@  nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 		goto fail_unreserve;
 
 	/* Update the crtc struct and cleanup */
-	crtc->fb = fb;
+	crtc->primary->fb = fb;
 
 	nouveau_bo_fence(old_bo, fence);
 	ttm_bo_unreserve(&old_bo->bo);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 5706842..c744bf6 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -651,7 +651,7 @@  nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
 	nv_connector = nouveau_crtc_connector_get(nv_crtc);
 	connector = &nv_connector->base;
 	if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) {
-		if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3)
+		if (nv_crtc->base.primary->fb->depth > connector->display_info.bpc * 3)
 			mode = DITHERING_MODE_DYNAMIC2X2;
 	} else {
 		mode = nv_connector->dithering_mode;
@@ -785,7 +785,7 @@  nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
 
 		if (update) {
 			nv50_display_flip_stop(crtc);
-			nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
+			nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
 		}
 	}
 
@@ -1028,7 +1028,7 @@  nv50_crtc_commit(struct drm_crtc *crtc)
 	}
 
 	nv50_crtc_cursor_show_hide(nv_crtc, nv_crtc->cursor.visible, true);
-	nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
+	nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
 }
 
 static bool
@@ -1042,7 +1042,8 @@  nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
 static int
 nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
 {
-	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
+	struct nouveau_framebuffer *nvfb =
+		nouveau_framebuffer(crtc->primary->fb);
 	struct nv50_head *head = nv50_head(crtc);
 	int ret;
 
@@ -1139,7 +1140,7 @@  nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
 	nv50_crtc_set_dither(nv_crtc, false);
 	nv50_crtc_set_scale(nv_crtc, false);
 	nv50_crtc_set_color_vibrance(nv_crtc, false);
-	nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, false);
+	nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, false);
 	return 0;
 }
 
@@ -1151,7 +1152,7 @@  nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	int ret;
 
-	if (!crtc->fb) {
+	if (!crtc->primary->fb) {
 		NV_DEBUG(drm, "No FB bound\n");
 		return 0;
 	}
@@ -1161,8 +1162,8 @@  nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 		return ret;
 
 	nv50_display_flip_stop(crtc);
-	nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, true);
-	nv50_display_flip_next(crtc, crtc->fb, NULL, 1);
+	nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, true);
+	nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 24b6112..5be0b87 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -527,7 +527,7 @@  static int qxl_crtc_mode_set(struct drm_crtc *crtc,
 	bool recreate_primary = false;
 	int ret;
 	int surf_id;
-	if (!crtc->fb) {
+	if (!crtc->primary->fb) {
 		DRM_DEBUG_KMS("No FB bound\n");
 		return 0;
 	}
@@ -536,7 +536,7 @@  static int qxl_crtc_mode_set(struct drm_crtc *crtc,
 		qfb = to_qxl_framebuffer(old_fb);
 		old_bo = gem_to_qxl_bo(qfb->obj);
 	}
-	qfb = to_qxl_framebuffer(crtc->fb);
+	qfb = to_qxl_framebuffer(crtc->primary->fb);
 	bo = gem_to_qxl_bo(qfb->obj);
 	if (!m)
 		/* and do we care? */
@@ -609,14 +609,15 @@  static void qxl_crtc_disable(struct drm_crtc *crtc)
 	struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct qxl_device *qdev = dev->dev_private;
-	if (crtc->fb) {
-		struct qxl_framebuffer *qfb = to_qxl_framebuffer(crtc->fb);
+	if (crtc->primary->fb) {
+		struct qxl_framebuffer *qfb =
+			to_qxl_framebuffer(crtc->primary->fb);
 		struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
 		int ret;
 		ret = qxl_bo_reserve(bo, false);
 		qxl_bo_unpin(bo);
 		qxl_bo_unreserve(bo);
-		crtc->fb = NULL;
+		crtc->primary->fb = NULL;
 	}
 
 	qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0);
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index daa4dd3..fb187c7 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1106,7 +1106,7 @@  static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
 	int r;
 
 	/* no fb bound */
-	if (!atomic && !crtc->fb) {
+	if (!atomic && !crtc->primary->fb) {
 		DRM_DEBUG_KMS("No FB bound\n");
 		return 0;
 	}
@@ -1116,8 +1116,8 @@  static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
 		target_fb = fb;
 	}
 	else {
-		radeon_fb = to_radeon_framebuffer(crtc->fb);
-		target_fb = crtc->fb;
+		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
+		target_fb = crtc->primary->fb;
 	}
 
 	/* If atomic, assume fb object is pinned & idle & fenced and
@@ -1316,7 +1316,7 @@  static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
 	/* set pageflip to happen anywhere in vblank interval */
 	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
 
-	if (!atomic && fb && fb != crtc->fb) {
+	if (!atomic && fb && fb != crtc->primary->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
 		rbo = gem_to_radeon_bo(radeon_fb->obj);
 		r = radeon_bo_reserve(rbo, false);
@@ -1350,7 +1350,7 @@  static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
 	int r;
 
 	/* no fb bound */
-	if (!atomic && !crtc->fb) {
+	if (!atomic && !crtc->primary->fb) {
 		DRM_DEBUG_KMS("No FB bound\n");
 		return 0;
 	}
@@ -1360,8 +1360,8 @@  static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
 		target_fb = fb;
 	}
 	else {
-		radeon_fb = to_radeon_framebuffer(crtc->fb);
-		target_fb = crtc->fb;
+		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
+		target_fb = crtc->primary->fb;
 	}
 
 	obj = radeon_fb->obj;
@@ -1485,7 +1485,7 @@  static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
 	/* set pageflip to happen anywhere in vblank interval */
 	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
 
-	if (!atomic && fb && fb != crtc->fb) {
+	if (!atomic && fb && fb != crtc->primary->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
 		rbo = gem_to_radeon_bo(radeon_fb->obj);
 		r = radeon_bo_reserve(rbo, false);
@@ -1972,12 +1972,12 @@  static void atombios_crtc_disable(struct drm_crtc *crtc)
 	int i;
 
 	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-	if (crtc->fb) {
+	if (crtc->primary->fb) {
 		int r;
 		struct radeon_framebuffer *radeon_fb;
 		struct radeon_bo *rbo;
 
-		radeon_fb = to_radeon_framebuffer(crtc->fb);
+		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
 		rbo = gem_to_radeon_bo(radeon_fb->obj);
 		r = radeon_bo_reserve(rbo, false);
 		if (unlikely(r))
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 030f8e4..b6c3264 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -3220,12 +3220,12 @@  void r100_bandwidth_update(struct radeon_device *rdev)
 
 	if (rdev->mode_info.crtcs[0]->base.enabled) {
 		mode1 = &rdev->mode_info.crtcs[0]->base.mode;
-		pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8;
+		pixel_bytes1 = rdev->mode_info.crtcs[0]->base.primary->fb->bits_per_pixel / 8;
 	}
 	if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
 		if (rdev->mode_info.crtcs[1]->base.enabled) {
 			mode2 = &rdev->mode_info.crtcs[1]->base.mode;
-			pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8;
+			pixel_bytes2 = rdev->mode_info.crtcs[1]->base.primary->fb->bits_per_pixel / 8;
 		}
 	}
 
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 82d4f86..33b482b 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -89,7 +89,7 @@  static void radeon_property_change_mode(struct drm_encoder *encoder)
 
 	if (crtc && crtc->enabled) {
 		drm_crtc_helper_set_mode(crtc, &crtc->mode,
-					 crtc->x, crtc->y, crtc->fb);
+					 crtc->x, crtc->y, crtc->primary->fb);
 	}
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 2e72dcd..c524aba 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1424,7 +1424,8 @@  int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
 
 	/* unpin the front buffers */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
+		struct radeon_framebuffer *rfb =
+			to_radeon_framebuffer(crtc->primary->fb);
 		struct radeon_bo *robj;
 
 		if (rfb == NULL || rfb->obj == NULL) {
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index a29d217..4e90049 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -369,7 +369,7 @@  static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 	work->event = event;
 	work->rdev = rdev;
 	work->crtc_id = radeon_crtc->crtc_id;
-	old_radeon_fb = to_radeon_framebuffer(crtc->fb);
+	old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
 	new_radeon_fb = to_radeon_framebuffer(fb);
 	/* schedule unpin of the old buffer */
 	obj = old_radeon_fb->obj;
@@ -460,7 +460,7 @@  static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 
 	/* update crtc fb */
-	crtc->fb = fb;
+	crtc->primary->fb = fb;
 
 	r = drm_vblank_get(dev, radeon_crtc->crtc_id);
 	if (r) {
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index 0b158f9..cafb1cc 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -385,7 +385,7 @@  int radeon_crtc_do_set_base(struct drm_crtc *crtc,
 
 	DRM_DEBUG_KMS("\n");
 	/* no fb bound */
-	if (!atomic && !crtc->fb) {
+	if (!atomic && !crtc->primary->fb) {
 		DRM_DEBUG_KMS("No FB bound\n");
 		return 0;
 	}
@@ -395,8 +395,8 @@  int radeon_crtc_do_set_base(struct drm_crtc *crtc,
 		target_fb = fb;
 	}
 	else {
-		radeon_fb = to_radeon_framebuffer(crtc->fb);
-		target_fb = crtc->fb;
+		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
+		target_fb = crtc->primary->fb;
 	}
 
 	switch (target_fb->bits_per_pixel) {
@@ -444,7 +444,7 @@  retry:
 		 * We don't shutdown the display controller because new buffer
 		 * will end up in same spot.
 		 */
-		if (!atomic && fb && fb != crtc->fb) {
+		if (!atomic && fb && fb != crtc->primary->fb) {
 			struct radeon_bo *old_rbo;
 			unsigned long nsize, osize;
 
@@ -555,7 +555,7 @@  retry:
 	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset);
 	WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
 
-	if (!atomic && fb && fb != crtc->fb) {
+	if (!atomic && fb && fb != crtc->primary->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
 		rbo = gem_to_radeon_bo(radeon_fb->obj);
 		r = radeon_bo_reserve(rbo, false);
@@ -599,7 +599,7 @@  static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
 		}
 	}
 
-	switch (crtc->fb->bits_per_pixel) {
+	switch (crtc->primary->fb->bits_per_pixel) {
 	case 8:
 		format = 2;
 		break;
@@ -1087,12 +1087,12 @@  static void radeon_crtc_commit(struct drm_crtc *crtc)
 static void radeon_crtc_disable(struct drm_crtc *crtc)
 {
 	radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-	if (crtc->fb) {
+	if (crtc->primary->fb) {
 		int r;
 		struct radeon_framebuffer *radeon_fb;
 		struct radeon_bo *rbo;
 
-		radeon_fb = to_radeon_framebuffer(crtc->fb);
+		radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
 		rbo = gem_to_radeon_bo(radeon_fb->obj);
 		r = radeon_bo_reserve(rbo, false);
 		if (unlikely(r))
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index 1255944..c63b5e7 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -310,7 +310,7 @@  static int udl_crtc_mode_set(struct drm_crtc *crtc,
 
 {
 	struct drm_device *dev = crtc->dev;
-	struct udl_framebuffer *ufb = to_udl_fb(crtc->fb);
+	struct udl_framebuffer *ufb = to_udl_fb(crtc->primary->fb);
 	struct udl_device *udl = dev->dev_private;
 	char *buf;
 	char *wrptr;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 8a65041..1d59ed3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -468,7 +468,7 @@  static int do_surface_dirty_sou(struct vmw_private *dev_priv,
 	num_units = 0;
 	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list,
 			    head) {
-		if (crtc->fb != &framebuffer->base)
+		if (crtc->primary->fb != &framebuffer->base)
 			continue;
 		units[num_units++] = vmw_crtc_to_du(crtc);
 	}
@@ -883,7 +883,7 @@  static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
 
 	num_units = 0;
 	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
-		if (crtc->fb != &framebuffer->base)
+		if (crtc->primary->fb != &framebuffer->base)
 			continue;
 		units[num_units++] = vmw_crtc_to_du(crtc);
 	}
@@ -1245,7 +1245,7 @@  int vmw_kms_present(struct vmw_private *dev_priv,
 
 	num_units = 0;
 	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
-		if (crtc->fb != &vfb->base)
+		if (crtc->primary->fb != &vfb->base)
 			continue;
 		units[num_units++] = vmw_crtc_to_du(crtc);
 	}
@@ -1382,7 +1382,7 @@  int vmw_kms_readback(struct vmw_private *dev_priv,
 
 	num_units = 0;
 	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
-		if (crtc->fb != &vfb->base)
+		if (crtc->primary->fb != &vfb->base)
 			continue;
 		units[num_units++] = vmw_crtc_to_du(crtc);
 	}
@@ -1725,7 +1725,7 @@  int vmw_du_page_flip(struct drm_crtc *crtc,
 		     uint32_t page_flip_flags)
 {
 	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
-	struct drm_framebuffer *old_fb = crtc->fb;
+	struct drm_framebuffer *old_fb = crtc->primary->fb;
 	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
 	struct drm_file *file_priv ;
 	struct vmw_fence_obj *fence = NULL;
@@ -1743,7 +1743,7 @@  int vmw_du_page_flip(struct drm_crtc *crtc,
 	if (!vmw_kms_screen_object_flippable(dev_priv, crtc))
 		return -EINVAL;
 
-	crtc->fb = fb;
+	crtc->primary->fb = fb;
 
 	/* do a full screen dirty update */
 	clips.x1 = clips.y1 = 0;
@@ -1783,7 +1783,7 @@  int vmw_du_page_flip(struct drm_crtc *crtc,
 	return ret;
 
 out_no_fence:
-	crtc->fb = old_fb;
+	crtc->primary->fb = old_fb;
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 001ec81..08fdd7f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -93,7 +93,7 @@  static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
 
 		if (crtc == NULL)
 			return 0;
-		fb = entry->base.crtc.fb;
+		fb = entry->base.crtc.primary->fb;
 
 		return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0],
 					  fb->bits_per_pixel, fb->depth);
@@ -101,7 +101,7 @@  static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
 
 	if (!list_empty(&lds->active)) {
 		entry = list_entry(lds->active.next, typeof(*entry), active);
-		fb = entry->base.crtc.fb;
+		fb = entry->base.crtc.primary->fb;
 
 		vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0],
 				   fb->bits_per_pixel, fb->depth);
@@ -259,7 +259,7 @@  static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
 
 		connector->encoder = NULL;
 		encoder->crtc = NULL;
-		crtc->fb = NULL;
+		crtc->primary->fb = NULL;
 		crtc->enabled = false;
 
 		vmw_ldu_del_active(dev_priv, ldu);
@@ -280,7 +280,7 @@  static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
 
 	vmw_fb_off(dev_priv);
 
-	crtc->fb = fb;
+	crtc->primary->fb = fb;
 	encoder->crtc = crtc;
 	connector->encoder = encoder;
 	crtc->x = set->x;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 585da43..46ea096 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -307,7 +307,7 @@  static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
 
 		connector->encoder = NULL;
 		encoder->crtc = NULL;
-		crtc->fb = NULL;
+		crtc->primary->fb = NULL;
 		crtc->x = 0;
 		crtc->y = 0;
 		crtc->enabled = false;
@@ -368,7 +368,7 @@  static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
 
 		connector->encoder = NULL;
 		encoder->crtc = NULL;
-		crtc->fb = NULL;
+		crtc->primary->fb = NULL;
 		crtc->x = 0;
 		crtc->y = 0;
 		crtc->enabled = false;
@@ -381,7 +381,7 @@  static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
 	connector->encoder = encoder;
 	encoder->crtc = crtc;
 	crtc->mode = *mode;
-	crtc->fb = fb;
+	crtc->primary->fb = fb;
 	crtc->x = set->x;
 	crtc->y = set->y;
 	crtc->enabled = true;
@@ -574,5 +574,5 @@  void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv,
 	BUG_ON(!sou->base.is_implicit);
 
 	dev_priv->sou_priv->implicit_fb =
-		vmw_framebuffer_to_vfb(sou->base.crtc.fb);
+		vmw_framebuffer_to_vfb(sou->base.crtc.primary->fb);
 }
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 4dc84f8..9f7824d 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -309,9 +309,6 @@  struct drm_crtc {
 	/* primary plane for CRTC */
 	struct drm_plane *primary;
 
-	/* framebuffer the connector is currently bound to */
-	struct drm_framebuffer *fb;
-
 	/* 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;