Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e8fe4f4b authored by Chris Wilson's avatar Chris Wilson Committed by Jani Nikula
Browse files

drm/i915: Track pinned vma in intel_plane_state

With atomic plane states we are able to track an allocation right from
preparation, during use and through to the final free after being
swapped out for a new plane. We can couple the VMA we pin for the
framebuffer (and its rotation) to this lifetime and avoid all the clumsy
lookups in between.

v2: Remove residual vma on plane cleanup (Chris)
v3: Add a description for the vma destruction in
    intel_plane_destroy_state (Maarten)

References: https://bugs.freedesktop.org/show_bug.cgi?id=98829


Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170116152131.18089-1-chris@chris-wilson.co.uk


Acked-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
(cherry picked from commit be1e3415)
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1485854491-27389-3-git-send-email-maarten.lankhorst@linux.intel.com
parent eeee74a4
Loading
Loading
Loading
Loading
+4 −12
Original line number Original line Diff line number Diff line
@@ -1012,6 +1012,8 @@ struct intel_fbc {
	struct work_struct underrun_work;
	struct work_struct underrun_work;


	struct intel_fbc_state_cache {
	struct intel_fbc_state_cache {
		struct i915_vma *vma;

		struct {
		struct {
			unsigned int mode_flags;
			unsigned int mode_flags;
			uint32_t hsw_bdw_pixel_rate;
			uint32_t hsw_bdw_pixel_rate;
@@ -1025,15 +1027,14 @@ struct intel_fbc {
		} plane;
		} plane;


		struct {
		struct {
			u64 ilk_ggtt_offset;
			uint32_t pixel_format;
			uint32_t pixel_format;
			unsigned int stride;
			unsigned int stride;
			int fence_reg;
			unsigned int tiling_mode;
		} fb;
		} fb;
	} state_cache;
	} state_cache;


	struct intel_fbc_reg_params {
	struct intel_fbc_reg_params {
		struct i915_vma *vma;

		struct {
		struct {
			enum pipe pipe;
			enum pipe pipe;
			enum plane plane;
			enum plane plane;
@@ -1041,10 +1042,8 @@ struct intel_fbc {
		} crtc;
		} crtc;


		struct {
		struct {
			u64 ggtt_offset;
			uint32_t pixel_format;
			uint32_t pixel_format;
			unsigned int stride;
			unsigned int stride;
			int fence_reg;
		} fb;
		} fb;


		int cfb_size;
		int cfb_size;
@@ -3168,13 +3167,6 @@ i915_gem_object_to_ggtt(struct drm_i915_gem_object *obj,
	return i915_gem_obj_to_vma(obj, &to_i915(obj->base.dev)->ggtt.base, view);
	return i915_gem_obj_to_vma(obj, &to_i915(obj->base.dev)->ggtt.base, view);
}
}


static inline unsigned long
i915_gem_object_ggtt_offset(struct drm_i915_gem_object *o,
			    const struct i915_ggtt_view *view)
{
	return i915_ggtt_offset(i915_gem_object_to_ggtt(o, view));
}

/* i915_gem_fence_reg.c */
/* i915_gem_fence_reg.c */
int __must_check i915_vma_get_fence(struct i915_vma *vma);
int __must_check i915_vma_get_fence(struct i915_vma *vma);
int __must_check i915_vma_put_fence(struct i915_vma *vma);
int __must_check i915_vma_put_fence(struct i915_vma *vma);
+20 −0
Original line number Original line Diff line number Diff line
@@ -85,6 +85,8 @@ intel_plane_duplicate_state(struct drm_plane *plane)


	__drm_atomic_helper_plane_duplicate_state(plane, state);
	__drm_atomic_helper_plane_duplicate_state(plane, state);


	intel_state->vma = NULL;

	return state;
	return state;
}
}


@@ -100,6 +102,24 @@ void
intel_plane_destroy_state(struct drm_plane *plane,
intel_plane_destroy_state(struct drm_plane *plane,
			  struct drm_plane_state *state)
			  struct drm_plane_state *state)
{
{
	struct i915_vma *vma;

	vma = fetch_and_zero(&to_intel_plane_state(state)->vma);

	/*
	 * FIXME: Normally intel_cleanup_plane_fb handles destruction of vma.
	 * We currently don't clear all planes during driver unload, so we have
	 * to be able to unpin vma here for now.
	 *
	 * Normally this can only happen during unload when kmscon is disabled
	 * and userspace doesn't attempt to set a framebuffer at all.
	 */
	if (vma) {
		mutex_lock(&plane->dev->struct_mutex);
		intel_unpin_fb_vma(vma);
		mutex_unlock(&plane->dev->struct_mutex);
	}

	drm_atomic_helper_plane_destroy_state(plane, state);
	drm_atomic_helper_plane_destroy_state(plane, state);
}
}


+42 −83
Original line number Original line Diff line number Diff line
@@ -2235,27 +2235,22 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
			i915_vma_pin_fence(vma);
			i915_vma_pin_fence(vma);
	}
	}


	i915_vma_get(vma);
err:
err:
	intel_runtime_pm_put(dev_priv);
	intel_runtime_pm_put(dev_priv);
	return vma;
	return vma;
}
}


void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
void intel_unpin_fb_vma(struct i915_vma *vma)
{
{
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
	lockdep_assert_held(&vma->vm->dev->struct_mutex);
	struct i915_ggtt_view view;
	struct i915_vma *vma;

	WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));

	intel_fill_fb_ggtt_view(&view, fb, rotation);
	vma = i915_gem_object_to_ggtt(obj, &view);


	if (WARN_ON_ONCE(!vma))
	if (WARN_ON_ONCE(!vma))
		return;
		return;


	i915_vma_unpin_fence(vma);
	i915_vma_unpin_fence(vma);
	i915_gem_object_unpin_from_display_plane(vma);
	i915_gem_object_unpin_from_display_plane(vma);
	i915_vma_put(vma);
}
}


static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane,
static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane,
@@ -2750,7 +2745,6 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
	struct drm_device *dev = intel_crtc->base.dev;
	struct drm_device *dev = intel_crtc->base.dev;
	struct drm_i915_private *dev_priv = to_i915(dev);
	struct drm_i915_private *dev_priv = to_i915(dev);
	struct drm_crtc *c;
	struct drm_crtc *c;
	struct intel_crtc *i;
	struct drm_i915_gem_object *obj;
	struct drm_i915_gem_object *obj;
	struct drm_plane *primary = intel_crtc->base.primary;
	struct drm_plane *primary = intel_crtc->base.primary;
	struct drm_plane_state *plane_state = primary->state;
	struct drm_plane_state *plane_state = primary->state;
@@ -2775,20 +2769,20 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
	 * an fb with another CRTC instead
	 * an fb with another CRTC instead
	 */
	 */
	for_each_crtc(dev, c) {
	for_each_crtc(dev, c) {
		i = to_intel_crtc(c);
		struct intel_plane_state *state;


		if (c == &intel_crtc->base)
		if (c == &intel_crtc->base)
			continue;
			continue;


		if (!i->active)
		if (!to_intel_crtc(c)->active)
			continue;
			continue;


		fb = c->primary->fb;
		state = to_intel_plane_state(c->primary->state);
		if (!fb)
		if (!state->vma)
			continue;
			continue;


		obj = intel_fb_obj(fb);
		if (intel_plane_ggtt_offset(state) == plane_config->base) {
		if (i915_gem_object_ggtt_offset(obj, NULL) == plane_config->base) {
			fb = c->primary->fb;
			drm_framebuffer_reference(fb);
			drm_framebuffer_reference(fb);
			goto valid_fb;
			goto valid_fb;
		}
		}
@@ -2809,6 +2803,19 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
	return;
	return;


valid_fb:
valid_fb:
	mutex_lock(&dev->struct_mutex);
	intel_state->vma =
		intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
	mutex_unlock(&dev->struct_mutex);
	if (IS_ERR(intel_state->vma)) {
		DRM_ERROR("failed to pin boot fb on pipe %d: %li\n",
			  intel_crtc->pipe, PTR_ERR(intel_state->vma));

		intel_state->vma = NULL;
		drm_framebuffer_unreference(fb);
		return;
	}

	plane_state->src_x = 0;
	plane_state->src_x = 0;
	plane_state->src_y = 0;
	plane_state->src_y = 0;
	plane_state->src_w = fb->width << 16;
	plane_state->src_w = fb->width << 16;
@@ -3104,13 +3111,13 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
	if (INTEL_GEN(dev_priv) >= 4) {
	if (INTEL_GEN(dev_priv) >= 4) {
		I915_WRITE(DSPSURF(plane),
		I915_WRITE(DSPSURF(plane),
			   intel_fb_gtt_offset(fb, rotation) +
			   intel_plane_ggtt_offset(plane_state) +
			   intel_crtc->dspaddr_offset);
			   intel_crtc->dspaddr_offset);
		I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
		I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
		I915_WRITE(DSPLINOFF(plane), linear_offset);
		I915_WRITE(DSPLINOFF(plane), linear_offset);
	} else {
	} else {
		I915_WRITE(DSPADDR(plane),
		I915_WRITE(DSPADDR(plane),
			   intel_fb_gtt_offset(fb, rotation) +
			   intel_plane_ggtt_offset(plane_state) +
			   intel_crtc->dspaddr_offset);
			   intel_crtc->dspaddr_offset);
	}
	}
	POSTING_READ(reg);
	POSTING_READ(reg);
@@ -3207,7 +3214,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,


	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
	I915_WRITE(DSPSURF(plane),
	I915_WRITE(DSPSURF(plane),
		   intel_fb_gtt_offset(fb, rotation) +
		   intel_plane_ggtt_offset(plane_state) +
		   intel_crtc->dspaddr_offset);
		   intel_crtc->dspaddr_offset);
	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
		I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
		I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
@@ -3230,23 +3237,6 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
	}
	}
}
}


u32 intel_fb_gtt_offset(struct drm_framebuffer *fb,
			unsigned int rotation)
{
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
	struct i915_ggtt_view view;
	struct i915_vma *vma;

	intel_fill_fb_ggtt_view(&view, fb, rotation);

	vma = i915_gem_object_to_ggtt(obj, &view);
	if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
		 view.type))
		return -1;

	return i915_ggtt_offset(vma);
}

static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
{
{
	struct drm_device *dev = intel_crtc->base.dev;
	struct drm_device *dev = intel_crtc->base.dev;
@@ -3441,7 +3431,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
	}
	}


	I915_WRITE(PLANE_SURF(pipe, 0),
	I915_WRITE(PLANE_SURF(pipe, 0),
		   intel_fb_gtt_offset(fb, rotation) + surf_addr);
		   intel_plane_ggtt_offset(plane_state) + surf_addr);


	POSTING_READ(PLANE_SURF(pipe, 0));
	POSTING_READ(PLANE_SURF(pipe, 0));
}
}
@@ -11536,7 +11526,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)
		flush_work(&work->mmio_work);
		flush_work(&work->mmio_work);


	mutex_lock(&dev->struct_mutex);
	mutex_lock(&dev->struct_mutex);
	intel_unpin_fb_obj(work->old_fb, primary->state->rotation);
	intel_unpin_fb_vma(work->old_vma);
	i915_gem_object_put(work->pending_flip_obj);
	i915_gem_object_put(work->pending_flip_obj);
	mutex_unlock(&dev->struct_mutex);
	mutex_unlock(&dev->struct_mutex);


@@ -12246,8 +12236,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
		goto cleanup_pending;
		goto cleanup_pending;
	}
	}


	work->gtt_offset = intel_fb_gtt_offset(fb, primary->state->rotation);
	work->old_vma = to_intel_plane_state(primary->state)->vma;
	work->gtt_offset += intel_crtc->dspaddr_offset;
	to_intel_plane_state(primary->state)->vma = vma;

	work->gtt_offset = i915_ggtt_offset(vma) + intel_crtc->dspaddr_offset;
	work->rotation = crtc->primary->state->rotation;
	work->rotation = crtc->primary->state->rotation;


	/*
	/*
@@ -12301,7 +12293,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
cleanup_request:
cleanup_request:
	i915_add_request_no_flush(request);
	i915_add_request_no_flush(request);
cleanup_unpin:
cleanup_unpin:
	intel_unpin_fb_obj(fb, crtc->primary->state->rotation);
	to_intel_plane_state(primary->state)->vma = work->old_vma;
	intel_unpin_fb_vma(vma);
cleanup_pending:
cleanup_pending:
	atomic_dec(&intel_crtc->unpin_work_count);
	atomic_dec(&intel_crtc->unpin_work_count);
unlock:
unlock:
@@ -14794,6 +14787,8 @@ intel_prepare_plane_fb(struct drm_plane *plane,
			DRM_DEBUG_KMS("failed to pin object\n");
			DRM_DEBUG_KMS("failed to pin object\n");
			return PTR_ERR(vma);
			return PTR_ERR(vma);
		}
		}

		to_intel_plane_state(new_state)->vma = vma;
	}
	}


	return 0;
	return 0;
@@ -14812,19 +14807,12 @@ void
intel_cleanup_plane_fb(struct drm_plane *plane,
intel_cleanup_plane_fb(struct drm_plane *plane,
		       struct drm_plane_state *old_state)
		       struct drm_plane_state *old_state)
{
{
	struct drm_i915_private *dev_priv = to_i915(plane->dev);
	struct i915_vma *vma;
	struct intel_plane_state *old_intel_state;
	struct drm_i915_gem_object *old_obj = intel_fb_obj(old_state->fb);
	struct drm_i915_gem_object *obj = intel_fb_obj(plane->state->fb);

	old_intel_state = to_intel_plane_state(old_state);

	if (!obj && !old_obj)
		return;


	if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
	/* Should only be called after a successful intel_prepare_plane_fb()! */
	    !INTEL_INFO(dev_priv)->cursor_needs_physical))
	vma = fetch_and_zero(&to_intel_plane_state(old_state)->vma);
		intel_unpin_fb_obj(old_state->fb, old_state->rotation);
	if (vma)
		intel_unpin_fb_vma(vma);
}
}


int
int
@@ -15166,7 +15154,7 @@ intel_update_cursor_plane(struct drm_plane *plane,
	if (!obj)
	if (!obj)
		addr = 0;
		addr = 0;
	else if (!INTEL_INFO(dev_priv)->cursor_needs_physical)
	else if (!INTEL_INFO(dev_priv)->cursor_needs_physical)
		addr = i915_gem_object_ggtt_offset(obj, NULL);
		addr = intel_plane_ggtt_offset(state);
	else
	else
		addr = obj->phys_handle->busaddr;
		addr = obj->phys_handle->busaddr;


@@ -17066,41 +17054,12 @@ void intel_display_resume(struct drm_device *dev)
void intel_modeset_gem_init(struct drm_device *dev)
void intel_modeset_gem_init(struct drm_device *dev)
{
{
	struct drm_i915_private *dev_priv = to_i915(dev);
	struct drm_i915_private *dev_priv = to_i915(dev);
	struct drm_crtc *c;
	struct drm_i915_gem_object *obj;


	intel_init_gt_powersave(dev_priv);
	intel_init_gt_powersave(dev_priv);


	intel_modeset_init_hw(dev);
	intel_modeset_init_hw(dev);


	intel_setup_overlay(dev_priv);
	intel_setup_overlay(dev_priv);

	/*
	 * Make sure any fbs we allocated at startup are properly
	 * pinned & fenced.  When we do the allocation it's too early
	 * for this.
	 */
	for_each_crtc(dev, c) {
		struct i915_vma *vma;

		obj = intel_fb_obj(c->primary->fb);
		if (obj == NULL)
			continue;

		mutex_lock(&dev->struct_mutex);
		vma = intel_pin_and_fence_fb_obj(c->primary->fb,
						 c->primary->state->rotation);
		mutex_unlock(&dev->struct_mutex);
		if (IS_ERR(vma)) {
			DRM_ERROR("failed to pin boot fb on pipe %d\n",
				  to_intel_crtc(c)->pipe);
			drm_framebuffer_unreference(c->primary->fb);
			c->primary->fb = NULL;
			c->primary->crtc = c->primary->state->crtc = NULL;
			update_state_fb(c->primary);
			c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
		}
	}
}
}


int intel_connector_register(struct drm_connector *connector)
int intel_connector_register(struct drm_connector *connector)
+7 −2
Original line number Original line Diff line number Diff line
@@ -377,6 +377,7 @@ struct intel_atomic_state {
struct intel_plane_state {
struct intel_plane_state {
	struct drm_plane_state base;
	struct drm_plane_state base;
	struct drm_rect clip;
	struct drm_rect clip;
	struct i915_vma *vma;


	struct {
	struct {
		u32 offset;
		u32 offset;
@@ -1046,6 +1047,7 @@ struct intel_flip_work {
	struct work_struct mmio_work;
	struct work_struct mmio_work;


	struct drm_crtc *crtc;
	struct drm_crtc *crtc;
	struct i915_vma *old_vma;
	struct drm_framebuffer *old_fb;
	struct drm_framebuffer *old_fb;
	struct drm_i915_gem_object *pending_flip_obj;
	struct drm_i915_gem_object *pending_flip_obj;
	struct drm_pending_vblank_event *event;
	struct drm_pending_vblank_event *event;
@@ -1273,7 +1275,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
				    struct drm_modeset_acquire_ctx *ctx);
				    struct drm_modeset_acquire_ctx *ctx);
struct i915_vma *
struct i915_vma *
intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
void intel_unpin_fb_vma(struct i915_vma *vma);
struct drm_framebuffer *
struct drm_framebuffer *
__intel_framebuffer_create(struct drm_device *dev,
__intel_framebuffer_create(struct drm_device *dev,
			   struct drm_mode_fb_cmd2 *mode_cmd,
			   struct drm_mode_fb_cmd2 *mode_cmd,
@@ -1362,7 +1364,10 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);


u32 intel_fb_gtt_offset(struct drm_framebuffer *fb, unsigned int rotation);
static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
{
	return i915_ggtt_offset(state->vma);
}


u32 skl_plane_ctl_format(uint32_t pixel_format);
u32 skl_plane_ctl_format(uint32_t pixel_format);
u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
+20 −32
Original line number Original line Diff line number Diff line
@@ -173,7 +173,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
	if (IS_I945GM(dev_priv))
	if (IS_I945GM(dev_priv))
		fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
		fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
	fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
	fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
	fbc_ctl |= params->fb.fence_reg;
	fbc_ctl |= params->vma->fence->id;
	I915_WRITE(FBC_CONTROL, fbc_ctl);
	I915_WRITE(FBC_CONTROL, fbc_ctl);
}
}


@@ -193,8 +193,8 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv)
	else
	else
		dpfc_ctl |= DPFC_CTL_LIMIT_1X;
		dpfc_ctl |= DPFC_CTL_LIMIT_1X;


	if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
	if (params->vma->fence) {
		dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fb.fence_reg;
		dpfc_ctl |= DPFC_CTL_FENCE_EN | params->vma->fence->id;
		I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
		I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
	} else {
	} else {
		I915_WRITE(DPFC_FENCE_YOFF, 0);
		I915_WRITE(DPFC_FENCE_YOFF, 0);
@@ -251,13 +251,14 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
		break;
		break;
	}
	}


	if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
	if (params->vma->fence) {
		dpfc_ctl |= DPFC_CTL_FENCE_EN;
		dpfc_ctl |= DPFC_CTL_FENCE_EN;
		if (IS_GEN5(dev_priv))
		if (IS_GEN5(dev_priv))
			dpfc_ctl |= params->fb.fence_reg;
			dpfc_ctl |= params->vma->fence->id;
		if (IS_GEN6(dev_priv)) {
		if (IS_GEN6(dev_priv)) {
			I915_WRITE(SNB_DPFC_CTL_SA,
			I915_WRITE(SNB_DPFC_CTL_SA,
				   SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
				   SNB_CPU_FENCE_ENABLE |
				   params->vma->fence->id);
			I915_WRITE(DPFC_CPU_FENCE_OFFSET,
			I915_WRITE(DPFC_CPU_FENCE_OFFSET,
				   params->crtc.fence_y_offset);
				   params->crtc.fence_y_offset);
		}
		}
@@ -269,7 +270,8 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
	}
	}


	I915_WRITE(ILK_DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
	I915_WRITE(ILK_DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
	I915_WRITE(ILK_FBC_RT_BASE, params->fb.ggtt_offset | ILK_FBC_RT_VALID);
	I915_WRITE(ILK_FBC_RT_BASE,
		   i915_ggtt_offset(params->vma) | ILK_FBC_RT_VALID);
	/* enable it... */
	/* enable it... */
	I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
	I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);


@@ -319,10 +321,11 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
		break;
		break;
	}
	}


	if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
	if (params->vma->fence) {
		dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
		dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
		I915_WRITE(SNB_DPFC_CTL_SA,
		I915_WRITE(SNB_DPFC_CTL_SA,
			   SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
			   SNB_CPU_FENCE_ENABLE |
			   params->vma->fence->id);
		I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset);
		I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset);
	} else {
	} else {
		I915_WRITE(SNB_DPFC_CTL_SA,0);
		I915_WRITE(SNB_DPFC_CTL_SA,0);
@@ -727,14 +730,6 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
	return effective_w <= max_w && effective_h <= max_h;
	return effective_w <= max_w && effective_h <= max_h;
}
}


/* XXX replace me when we have VMA tracking for intel_plane_state */
static int get_fence_id(struct drm_framebuffer *fb)
{
	struct i915_vma *vma = i915_gem_object_to_ggtt(intel_fb_obj(fb), NULL);

	return vma && vma->fence ? vma->fence->id : I915_FENCE_REG_NONE;
}

static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
					 struct intel_crtc_state *crtc_state,
					 struct intel_crtc_state *crtc_state,
					 struct intel_plane_state *plane_state)
					 struct intel_plane_state *plane_state)
@@ -743,7 +738,8 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
	struct intel_fbc *fbc = &dev_priv->fbc;
	struct intel_fbc *fbc = &dev_priv->fbc;
	struct intel_fbc_state_cache *cache = &fbc->state_cache;
	struct intel_fbc_state_cache *cache = &fbc->state_cache;
	struct drm_framebuffer *fb = plane_state->base.fb;
	struct drm_framebuffer *fb = plane_state->base.fb;
	struct drm_i915_gem_object *obj;

	cache->vma = NULL;


	cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags;
	cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags;
	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
@@ -758,16 +754,10 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
	if (!cache->plane.visible)
	if (!cache->plane.visible)
		return;
		return;


	obj = intel_fb_obj(fb);

	/* FIXME: We lack the proper locking here, so only run this on the
	 * platforms that need. */
	if (IS_GEN(dev_priv, 5, 6))
		cache->fb.ilk_ggtt_offset = i915_gem_object_ggtt_offset(obj, NULL);
	cache->fb.pixel_format = fb->pixel_format;
	cache->fb.pixel_format = fb->pixel_format;
	cache->fb.stride = fb->pitches[0];
	cache->fb.stride = fb->pitches[0];
	cache->fb.fence_reg = get_fence_id(fb);

	cache->fb.tiling_mode = i915_gem_object_get_tiling(obj);
	cache->vma = plane_state->vma;
}
}


static bool intel_fbc_can_activate(struct intel_crtc *crtc)
static bool intel_fbc_can_activate(struct intel_crtc *crtc)
@@ -784,7 +774,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
		return false;
		return false;
	}
	}


	if (!cache->plane.visible) {
	if (!cache->vma) {
		fbc->no_fbc_reason = "primary plane not visible";
		fbc->no_fbc_reason = "primary plane not visible";
		return false;
		return false;
	}
	}
@@ -807,8 +797,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
	 * so have no fence associated with it) due to aperture constaints
	 * so have no fence associated with it) due to aperture constaints
	 * at the time of pinning.
	 * at the time of pinning.
	 */
	 */
	if (cache->fb.tiling_mode != I915_TILING_X ||
	if (!cache->vma->fence) {
	    cache->fb.fence_reg == I915_FENCE_REG_NONE) {
		fbc->no_fbc_reason = "framebuffer not tiled or fenced";
		fbc->no_fbc_reason = "framebuffer not tiled or fenced";
		return false;
		return false;
	}
	}
@@ -888,17 +877,16 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
	 * zero. */
	 * zero. */
	memset(params, 0, sizeof(*params));
	memset(params, 0, sizeof(*params));


	params->vma = cache->vma;

	params->crtc.pipe = crtc->pipe;
	params->crtc.pipe = crtc->pipe;
	params->crtc.plane = crtc->plane;
	params->crtc.plane = crtc->plane;
	params->crtc.fence_y_offset = get_crtc_fence_y_offset(crtc);
	params->crtc.fence_y_offset = get_crtc_fence_y_offset(crtc);


	params->fb.pixel_format = cache->fb.pixel_format;
	params->fb.pixel_format = cache->fb.pixel_format;
	params->fb.stride = cache->fb.stride;
	params->fb.stride = cache->fb.stride;
	params->fb.fence_reg = cache->fb.fence_reg;


	params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache);
	params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache);

	params->fb.ggtt_offset = cache->fb.ilk_ggtt_offset;
}
}


static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1,
static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1,
Loading