@@ -6173,10 +6173,12 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
}
}
-static int intel_crtc_cursor_set(struct drm_crtc *crtc,
+static int intel_crtc_cursor_prepare(struct drm_crtc *crtc,
struct drm_file *file,
uint32_t handle,
- uint32_t width, uint32_t height)
+ uint32_t width, uint32_t height,
+ struct drm_i915_gem_object **obj_ret,
+ uint32_t *addr_ret)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -6188,10 +6190,9 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
/* if we want to turn off the cursor ignore width and height */
if (!handle) {
DRM_DEBUG_KMS("cursor off\n");
- addr = 0;
- obj = NULL;
- mutex_lock(&dev->struct_mutex);
- goto finish;
+ *addr_ret = 0;
+ *obj_ret = NULL;
+ return 0;
}
/* Currently we only support 64x64 cursors */
@@ -6247,17 +6248,46 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
if (IS_GEN2(dev))
I915_WRITE(CURSIZE, (height << 12) | width);
- finish:
- if (intel_crtc->cursor_bo) {
- if (dev_priv->info->cursor_needs_physical) {
- if (intel_crtc->cursor_bo != obj)
- i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
- } else
- i915_gem_object_unpin(intel_crtc->cursor_bo);
- drm_gem_object_unreference(&intel_crtc->cursor_bo->base);
- }
+ mutex_unlock(&dev->struct_mutex);
+
+ *obj_ret = obj;
+ *addr_ret = addr;
+
+ return 0;
+fail_unpin:
+ i915_gem_object_unpin(obj);
+fail_locked:
+ mutex_unlock(&dev->struct_mutex);
+fail:
+ drm_gem_object_unreference_unlocked(&obj->base);
+ return ret;
+}
+
+static void intel_crtc_cursor_bo_unref(struct drm_crtc *crtc,
+ struct drm_i915_gem_object *obj)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+ mutex_lock(&dev->struct_mutex);
+
+ if (dev_priv->info->cursor_needs_physical) {
+ if (obj != intel_crtc->cursor_bo)
+ i915_gem_detach_phys_object(dev, obj);
+ } else
+ i915_gem_object_unpin(obj);
+ drm_gem_object_unreference(&obj->base);
mutex_unlock(&dev->struct_mutex);
+}
+
+static void intel_crtc_cursor_commit(struct drm_crtc *crtc, uint32_t handle,
+ uint32_t width, uint32_t height,
+ struct drm_i915_gem_object *obj,
+ uint32_t addr)
+{
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
intel_crtc->cursor_addr = addr;
intel_crtc->cursor_handle = handle;
@@ -6266,15 +6296,31 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
intel_crtc->cursor_height = height;
intel_crtc_update_cursor(crtc, true);
+}
+
+static int intel_crtc_cursor_set(struct drm_crtc *crtc,
+ struct drm_file *file,
+ uint32_t handle,
+ uint32_t width, uint32_t height)
+{
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ int ret;
+ struct drm_i915_gem_object *obj, *old_obj;
+ uint32_t addr;
+
+ ret = intel_crtc_cursor_prepare(crtc, file, handle, width, height,
+ &obj, &addr);
+ if (ret)
+ return ret;
+
+ old_obj = intel_crtc->cursor_bo;
+
+ intel_crtc_cursor_commit(crtc, handle, width, height, obj, addr);
+
+ if (old_obj)
+ intel_crtc_cursor_bo_unref(crtc, old_obj);
return 0;
-fail_unpin:
- i915_gem_object_unpin(obj);
-fail_locked:
- mutex_unlock(&dev->struct_mutex);
-fail:
- drm_gem_object_unreference_unlocked(&obj->base);
- return ret;
}
static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
From: Ander Conselvan de Oliveira <conselvan2@gmail.com> The atomic mode setting API will need to pin the cursor bo without making changes to the current setup. Only on a later stage the cursor registers can be written and the previous bo released. This patch splits intel_crtc_cursor_set() into three parts: prepare, commit and unref. intel_crtc_cursor_prepare() will pin the cursor bo and return a gem object and the address to be written to the cursor registers. intel_crtc_cursor_commit() takes that object and address and actually changes the cursor. intel_crtc_cursor_unref() is used to release the previous cursor bo. --- drivers/gpu/drm/i915/intel_display.c | 90 +++++++++++++++++++++++++-------- 1 files changed, 68 insertions(+), 22 deletions(-)