diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index de6768f384665..262e8904769e5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11689,6 +11689,65 @@ intel_primary_plane_disable(struct drm_plane *plane) return 0; } +/** + * intel_prepare_plane_fb - Prepare fb for usage on plane + * @plane: drm plane to prepare for + * @fb: framebuffer to prepare for presentation + * + * Prepares a framebuffer for usage on a display plane. Generally this + * involves pinning the underlying object and updating the frontbuffer tracking + * bits. Some older platforms need special physical address handling for + * cursor planes. + * + * Returns 0 on success, negative error code on failure. + */ +int +intel_prepare_plane_fb(struct drm_plane *plane, + struct drm_framebuffer *fb) +{ + struct drm_device *dev = plane->dev; + struct intel_plane *intel_plane = to_intel_plane(plane); + enum pipe pipe = intel_plane->pipe; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); + unsigned frontbuffer_bits = 0; + int ret = 0; + + if (WARN_ON(fb == plane->fb || !obj)) + return 0; + + switch (plane->type) { + case DRM_PLANE_TYPE_PRIMARY: + frontbuffer_bits = INTEL_FRONTBUFFER_PRIMARY(pipe); + break; + case DRM_PLANE_TYPE_CURSOR: + frontbuffer_bits = INTEL_FRONTBUFFER_CURSOR(pipe); + break; + case DRM_PLANE_TYPE_OVERLAY: + frontbuffer_bits = INTEL_FRONTBUFFER_SPRITE(pipe); + break; + } + + mutex_lock(&dev->struct_mutex); + + if (plane->type == DRM_PLANE_TYPE_CURSOR && + INTEL_INFO(dev)->cursor_needs_physical) { + int align = IS_I830(dev) ? 16 * 1024 : 256; + ret = i915_gem_object_attach_phys(obj, align); + if (ret) + DRM_DEBUG_KMS("failed to attach phys object\n"); + } else { + ret = intel_pin_and_fence_fb_obj(plane, fb, NULL); + } + + if (ret == 0) + i915_gem_track_fb(old_obj, obj, frontbuffer_bits); + + mutex_unlock(&dev->struct_mutex); + + return ret; +} + static int intel_check_primary_plane(struct drm_plane *plane, struct intel_plane_state *state) @@ -11706,42 +11765,6 @@ intel_check_primary_plane(struct drm_plane *plane, false, true, &state->visible); } -static int -intel_prepare_primary_plane(struct drm_plane *plane, - struct intel_plane_state *state) -{ - struct drm_crtc *crtc = state->base.crtc; - struct drm_framebuffer *fb = state->base.fb; - struct drm_device *dev = crtc->dev; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); - int ret; - - intel_crtc_wait_for_pending_flips(crtc); - - if (intel_crtc_has_pending_flip(crtc)) { - DRM_ERROR("pipe is still busy with an old pageflip\n"); - return -EBUSY; - } - - if (old_obj != obj) { - mutex_lock(&dev->struct_mutex); - ret = intel_pin_and_fence_fb_obj(plane, fb, NULL); - if (ret == 0) - i915_gem_track_fb(old_obj, obj, - INTEL_FRONTBUFFER_PRIMARY(pipe)); - mutex_unlock(&dev->struct_mutex); - if (ret != 0) { - DRM_DEBUG_KMS("pin & fence failed\n"); - return ret; - } - } - - return 0; -} - static void intel_commit_primary_plane(struct drm_plane *plane, struct intel_plane_state *state) @@ -11843,6 +11866,7 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { + struct drm_framebuffer *old_fb = plane->fb; struct intel_plane_state state; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int ret; @@ -11874,9 +11898,18 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, if (ret) return ret; - ret = intel_prepare_primary_plane(plane, &state); - if (ret) - return ret; + intel_crtc_wait_for_pending_flips(crtc); + + if (intel_crtc_has_pending_flip(crtc)) { + DRM_ERROR("pipe is still busy with an old pageflip\n"); + return -EBUSY; + } + + if (fb != old_fb && fb) { + ret = intel_prepare_plane_fb(plane, fb); + if (ret) + return ret; + } intel_commit_primary_plane(plane, &state); @@ -12013,42 +12046,6 @@ intel_check_cursor_plane(struct drm_plane *plane, return ret; } -static int -intel_prepare_cursor_plane(struct drm_plane *plane, - struct intel_plane_state *state) -{ - struct drm_device *dev = plane->dev; - struct drm_framebuffer *fb = state->base.fb; - struct intel_crtc *intel_crtc = to_intel_crtc(state->base.crtc); - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); - enum pipe pipe = intel_crtc->pipe; - int ret = 0; - - if (old_obj != obj) { - /* we only need to pin inside GTT if cursor is non-phy */ - mutex_lock(&dev->struct_mutex); - if (!INTEL_INFO(dev)->cursor_needs_physical) { - if (obj) - ret = intel_pin_and_fence_fb_obj(plane, fb, NULL); - } else { - int align = IS_I830(dev) ? 16 * 1024 : 256; - if (obj) - ret = i915_gem_object_attach_phys(obj, align); - if (ret) - DRM_DEBUG_KMS("failed to attach phys object\n"); - } - - if (ret == 0) - i915_gem_track_fb(intel_crtc->cursor_bo, obj, - INTEL_FRONTBUFFER_CURSOR(pipe)); - - mutex_unlock(&dev->struct_mutex); - } - - return ret; -} - static void intel_commit_cursor_plane(struct drm_plane *plane, struct intel_plane_state *state) @@ -12058,6 +12055,7 @@ intel_commit_cursor_plane(struct drm_plane *plane, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane = to_intel_plane(plane); struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); + struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); enum pipe pipe = intel_crtc->pipe; unsigned old_width; uint32_t addr; @@ -12079,6 +12077,17 @@ intel_commit_cursor_plane(struct drm_plane *plane, if (intel_crtc->cursor_bo == obj) goto update; + /* + * 'prepare' is only called when fb != NULL; we still need to update + * frontbuffer tracking for the 'disable' case here. + */ + if (!obj) { + mutex_lock(&dev->struct_mutex); + i915_gem_track_fb(old_obj, NULL, + INTEL_FRONTBUFFER_CURSOR(pipe)); + mutex_unlock(&dev->struct_mutex); + } + if (!obj) addr = 0; else if (!INTEL_INFO(dev)->cursor_needs_physical) @@ -12118,6 +12127,7 @@ intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { + struct drm_framebuffer *old_fb = plane->fb; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane_state state; int ret; @@ -12149,9 +12159,11 @@ intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, if (ret) return ret; - ret = intel_prepare_cursor_plane(plane, &state); - if (ret) - return ret; + if (fb != old_fb && fb) { + ret = intel_prepare_plane_fb(plane, fb); + if (ret) + return ret; + } intel_commit_cursor_plane(plane, &state); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b4d181fd94125..a36f696e23519 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -922,6 +922,8 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane); void intel_finish_page_flip(struct drm_device *dev, int pipe); void intel_finish_page_flip_plane(struct drm_device *dev, int plane); void intel_check_page_flip(struct drm_device *dev, int pipe); +int intel_prepare_plane_fb(struct drm_plane *plane, + struct drm_framebuffer *fb); /* shared dpll functions */ struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index fc96d1326310e..5d8c2e07f986e 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1257,41 +1257,6 @@ intel_check_sprite_plane(struct drm_plane *plane, return 0; } -static int -intel_prepare_sprite_plane(struct drm_plane *plane, - struct intel_plane_state *state) -{ - struct drm_device *dev = plane->dev; - struct drm_crtc *crtc = state->base.crtc; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_plane *intel_plane = to_intel_plane(plane); - enum pipe pipe = intel_crtc->pipe; - struct drm_framebuffer *fb = state->base.fb; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct drm_i915_gem_object *old_obj = intel_plane->obj; - int ret; - - if (old_obj != obj) { - mutex_lock(&dev->struct_mutex); - - /* Note that this will apply the VT-d workaround for scanouts, - * which is more restrictive than required for sprites. (The - * primary plane requires 256KiB alignment with 64 PTE padding, - * the sprite planes only require 128KiB alignment and 32 PTE - * padding. - */ - ret = intel_pin_and_fence_fb_obj(plane, fb, NULL); - if (ret == 0) - i915_gem_track_fb(old_obj, obj, - INTEL_FRONTBUFFER_SPRITE(pipe)); - mutex_unlock(&dev->struct_mutex); - if (ret) - return ret; - } - - return 0; -} - static void intel_commit_sprite_plane(struct drm_plane *plane, struct intel_plane_state *state) @@ -1387,6 +1352,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { + struct drm_framebuffer *old_fb = plane->fb; struct intel_plane_state state; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int ret; @@ -1417,9 +1383,11 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, if (ret) return ret; - ret = intel_prepare_sprite_plane(plane, &state); - if (ret) - return ret; + if (fb != old_fb && fb) { + ret = intel_prepare_plane_fb(plane, fb); + if (ret) + return ret; + } intel_commit_sprite_plane(plane, &state); return 0;