From: Ander Conselvan de Oliveira <conselv...@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(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index c59985d..20539c4 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5587,10 +5587,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;
@@ -5602,10 +5604,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 */
@@ -5661,17 +5662,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;
@@ -5680,15 +5710,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)
-- 
1.7.8.6

Reply via email to