Commit be1e3415 authored by Chris Wilson's avatar Chris Wilson

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=98829Signed-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.ukAcked-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
parent 5464cd65
...@@ -1069,6 +1069,8 @@ struct intel_fbc { ...@@ -1069,6 +1069,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;
...@@ -1082,15 +1084,14 @@ struct intel_fbc { ...@@ -1082,15 +1084,14 @@ struct intel_fbc {
} plane; } plane;
struct { struct {
u64 ilk_ggtt_offset;
const struct drm_format_info *format; const struct drm_format_info *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;
...@@ -1098,10 +1099,8 @@ struct intel_fbc { ...@@ -1098,10 +1099,8 @@ struct intel_fbc {
} crtc; } crtc;
struct { struct {
u64 ggtt_offset;
const struct drm_format_info *format; const struct drm_format_info *format;
unsigned int stride; unsigned int stride;
int fence_reg;
} fb; } fb;
int cfb_size; int cfb_size;
...@@ -3398,13 +3397,6 @@ i915_gem_object_to_ggtt(struct drm_i915_gem_object *obj, ...@@ -3398,13 +3397,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);
......
...@@ -85,6 +85,8 @@ intel_plane_duplicate_state(struct drm_plane *plane) ...@@ -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 ...@@ -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);
} }
......
...@@ -2234,24 +2234,19 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation) ...@@ -2234,24 +2234,19 @@ 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->i915->drm.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);
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,
...@@ -2744,7 +2739,6 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, ...@@ -2744,7 +2739,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;
...@@ -2769,20 +2763,20 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, ...@@ -2769,20 +2763,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;
} }
...@@ -2803,6 +2797,19 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, ...@@ -2803,6 +2797,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;
...@@ -3098,13 +3105,13 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, ...@@ -3098,13 +3105,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);
...@@ -3201,7 +3208,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, ...@@ -3201,7 +3208,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);
...@@ -3224,23 +3231,6 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv, ...@@ -3224,23 +3231,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;
...@@ -3436,7 +3426,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane, ...@@ -3436,7 +3426,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
} }
I915_WRITE(PLANE_SURF(pipe, plane_id), I915_WRITE(PLANE_SURF(pipe, plane_id),
intel_fb_gtt_offset(fb, rotation) + surf_addr); intel_plane_ggtt_offset(plane_state) + surf_addr);
POSTING_READ(PLANE_SURF(pipe, plane_id)); POSTING_READ(PLANE_SURF(pipe, plane_id));
} }
...@@ -11565,7 +11555,7 @@ static void intel_unpin_work_fn(struct work_struct *__work) ...@@ -11565,7 +11555,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);
...@@ -12275,8 +12265,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, ...@@ -12275,8 +12265,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;
/* /*
...@@ -12331,7 +12323,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, ...@@ -12331,7 +12323,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:
...@@ -14832,6 +14825,8 @@ intel_prepare_plane_fb(struct drm_plane *plane, ...@@ -14832,6 +14825,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;
...@@ -14850,19 +14845,12 @@ void ...@@ -14850,19 +14845,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
...@@ -15014,6 +15002,7 @@ intel_legacy_cursor_update(struct drm_plane *plane, ...@@ -15014,6 +15002,7 @@ intel_legacy_cursor_update(struct drm_plane *plane,
struct intel_plane *intel_plane = to_intel_plane(plane); struct intel_plane *intel_plane = to_intel_plane(plane);
struct drm_framebuffer *old_fb; struct drm_framebuffer *old_fb;
struct drm_crtc_state *crtc_state = crtc->state; struct drm_crtc_state *crtc_state = crtc->state;
struct i915_vma *old_vma;
/* /*
* When crtc is inactive or there is a modeset pending, * When crtc is inactive or there is a modeset pending,
...@@ -15085,9 +15074,12 @@ intel_legacy_cursor_update(struct drm_plane *plane, ...@@ -15085,9 +15074,12 @@ intel_legacy_cursor_update(struct drm_plane *plane,
ret = PTR_ERR(vma); ret = PTR_ERR(vma);
goto out_unlock; goto out_unlock;
} }
to_intel_plane_state(new_plane_state)->vma = vma;
} }
old_fb = old_plane_state->fb; old_fb = old_plane_state->fb;
old_vma = to_intel_plane_state(old_plane_state)->vma;
i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(fb), i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(fb),
intel_plane->frontbuffer_bit); intel_plane->frontbuffer_bit);
...@@ -15097,6 +15089,7 @@ intel_legacy_cursor_update(struct drm_plane *plane, ...@@ -15097,6 +15089,7 @@ intel_legacy_cursor_update(struct drm_plane *plane,
*to_intel_plane_state(old_plane_state) = *to_intel_plane_state(new_plane_state); *to_intel_plane_state(old_plane_state) = *to_intel_plane_state(new_plane_state);
new_plane_state->fence = NULL; new_plane_state->fence = NULL;
new_plane_state->fb = old_fb; new_plane_state->fb = old_fb;
to_intel_plane_state(new_plane_state)->vma = old_vma;
intel_plane->update_plane(plane, intel_plane->update_plane(plane,
to_intel_crtc_state(crtc->state), to_intel_crtc_state(crtc->state),
...@@ -15335,7 +15328,7 @@ intel_update_cursor_plane(struct drm_plane *plane, ...@@ -15335,7 +15328,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;
...@@ -17224,41 +17217,12 @@ void intel_display_resume(struct drm_device *dev) ...@@ -17224,41 +17217,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)
......
...@@ -376,6 +376,7 @@ struct intel_atomic_state { ...@@ -376,6 +376,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;
...@@ -1067,6 +1068,7 @@ struct intel_flip_work { ...@@ -1067,6 +1068,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;
...@@ -1302,7 +1304,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, ...@@ -1302,7 +1304,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,
...@@ -1391,7 +1393,10 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode, ...@@ -1391,7 +1393,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);
......
...@@ -173,7 +173,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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.format = fb->format; cache->fb.format = fb->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) ...@@ -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) ...@@ -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, ...@@ -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.format = cache->fb.format; params->fb.format = cache->fb.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,
......
...@@ -284,7 +284,7 @@ static int intelfb_create(struct drm_fb_helper *helper, ...@@ -284,7 +284,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
out_destroy_fbi: out_destroy_fbi:
drm_fb_helper_release_fbi(helper); drm_fb_helper_release_fbi(helper);
out_unpin: out_unpin:
intel_unpin_fb_obj(&ifbdev->fb->base, DRM_ROTATE_0); intel_unpin_fb_vma(vma);
out_unlock: out_unlock:
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return ret; return ret;
...@@ -549,7 +549,7 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev) ...@@ -549,7 +549,7 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
if (ifbdev->fb) { if (ifbdev->fb) {
mutex_lock(&ifbdev->helper.dev->struct_mutex); mutex_lock(&ifbdev->helper.dev->struct_mutex);
intel_unpin_fb_obj(&ifbdev->fb->base, DRM_ROTATE_0); intel_unpin_fb_vma(ifbdev->vma);
mutex_unlock(&ifbdev->helper.dev->struct_mutex); mutex_unlock(&ifbdev->helper.dev->struct_mutex);
drm_framebuffer_remove(&ifbdev->fb->base); drm_framebuffer_remove(&ifbdev->fb->base);
......
...@@ -273,7 +273,7 @@ skl_update_plane(struct drm_plane *drm_plane, ...@@ -273,7 +273,7 @@ skl_update_plane(struct drm_plane *drm_plane,
I915_WRITE(PLANE_CTL(pipe, plane_id), plane_ctl); I915_WRITE(PLANE_CTL(pipe, plane_id), plane_ctl);
I915_WRITE(PLANE_SURF(pipe, plane_id), I915_WRITE(PLANE_SURF(pipe, plane_id),
intel_fb_gtt_offset(fb, rotation) + surf_addr); intel_plane_ggtt_offset(plane_state) + surf_addr);
POSTING_READ(PLANE_SURF(pipe, plane_id)); POSTING_READ(PLANE_SURF(pipe, plane_id));
} }
...@@ -458,7 +458,7 @@ vlv_update_plane(struct drm_plane *dplane, ...@@ -458,7 +458,7 @@ vlv_update_plane(struct drm_plane *dplane,
I915_WRITE(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w); I915_WRITE(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
I915_WRITE(SPCNTR(pipe, plane_id), sprctl); I915_WRITE(SPCNTR(pipe, plane_id), sprctl);
I915_WRITE(SPSURF(pipe, plane_id), I915_WRITE(SPSURF(pipe, plane_id),
intel_fb_gtt_offset(fb, rotation) + sprsurf_offset); intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
POSTING_READ(SPSURF(pipe, plane_id)); POSTING_READ(SPSURF(pipe, plane_id));
} }
...@@ -594,7 +594,7 @@ ivb_update_plane(struct drm_plane *plane, ...@@ -594,7 +594,7 @@ ivb_update_plane(struct drm_plane *plane,
I915_WRITE(SPRSCALE(pipe), sprscale); I915_WRITE(SPRSCALE(pipe), sprscale);
I915_WRITE(SPRCTL(pipe), sprctl); I915_WRITE(SPRCTL(pipe), sprctl);
I915_WRITE(SPRSURF(pipe), I915_WRITE(SPRSURF(pipe),
intel_fb_gtt_offset(fb, rotation) + sprsurf_offset); intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
POSTING_READ(SPRSURF(pipe)); POSTING_READ(SPRSURF(pipe));
} }
...@@ -721,7 +721,7 @@ ilk_update_plane(struct drm_plane *plane, ...@@ -721,7 +721,7 @@ ilk_update_plane(struct drm_plane *plane,
I915_WRITE(DVSSCALE(pipe), dvsscale); I915_WRITE(DVSSCALE(pipe), dvsscale);
I915_WRITE(DVSCNTR(pipe), dvscntr); I915_WRITE(DVSCNTR(pipe), dvscntr);
I915_WRITE(DVSSURF(pipe), I915_WRITE(DVSSURF(pipe),
intel_fb_gtt_offset(fb, rotation) + dvssurf_offset); intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
POSTING_READ(DVSSURF(pipe)); POSTING_READ(DVSSURF(pipe));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment