Cc: Intel Graphics Development <intel-gfx at lists.freedesktop.org>
Signed-off-by: Matt Roper <matthew.d.roper at intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 90 +++++++++++++++++++++++++++++++++++-
 1 file changed, 89 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index f661469..36bee38 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10781,11 +10781,98 @@ static struct drm_plane 
*intel_primary_plane_create(struct drm_device *dev,
        return &primary->base;
 }

+static int
+intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
+                         struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+                         unsigned int crtc_w, unsigned int crtc_h,
+                         uint32_t src_x, uint32_t src_y,
+                         uint32_t src_w, uint32_t src_h)
+{
+       int ret;
+
+       /* setplane API takes shifted source rectangle values; unshift them */
+       src_x >>= 16;
+       src_y >>= 16;
+       src_w >>= 16;
+       src_h >>= 16;
+
+       /* Cursor planes are locked to their owning CRTC */
+       if (plane->possible_crtcs != drm_crtc_mask(crtc)) {
+               DRM_DEBUG_KMS("Cannot change cursor plane CRTC\n");
+               return -EINVAL;
+       }
+
+       /* Current hardware can't scale the cursor plane. */
+       if (crtc_w != src_w || crtc_h != src_h) {
+               DRM_DEBUG_KMS("Can't scale cursor plane\n");
+               return -EINVAL;
+       }
+
+       ret = cursor_set_common(crtc, crtc->cursor, fb);
+       if (ret)
+               return ret;
+
+       intel_crtc_cursor_move(crtc, crtc_x, crtc_y);
+       intel_crtc_update_cursor(crtc, fb);
+
+       return 0;
+}
+
+static int
+intel_cursor_plane_disable(struct drm_plane *plane)
+{
+       if (!plane->fb)
+               return 0;
+
+       BUG_ON(!plane->crtc);
+
+       return cursor_set_common(plane->crtc, plane, NULL);
+}
+
+static void intel_cursor_plane_destroy(struct drm_plane *plane)
+{
+       struct intel_plane *intel_plane = to_intel_plane(plane);
+       intel_cursor_plane_disable(plane);
+       drm_plane_cleanup(plane);
+       kfree(intel_plane);
+}
+
+static const struct drm_plane_funcs intel_cursor_plane_funcs = {
+       .update_plane = intel_cursor_plane_update,
+       .disable_plane = intel_cursor_plane_disable,
+       .destroy = intel_cursor_plane_destroy,
+};
+
+static const uint32_t cursor_formats[] = {
+       DRM_FORMAT_ARGB8888,
+};
+
+static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
+                                                  int pipe)
+{
+       struct intel_plane *cursor;
+
+       cursor = kzalloc(sizeof(*cursor), GFP_KERNEL);
+       if (cursor == NULL)
+               return NULL;
+
+       cursor->can_scale = false;
+       cursor->pipe = pipe;
+       cursor->plane = pipe;
+
+       drm_plane_init(dev, &cursor->base, 0,
+                      &intel_cursor_plane_funcs, cursor_formats,
+                      ARRAY_SIZE(cursor_formats),
+                      DRM_PLANE_TYPE_CURSOR);
+       return &cursor->base;
+}
+
 static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc;
        struct drm_plane *primary;
+       struct drm_plane *cursor;
        int i, ret;

        intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL);
@@ -10793,7 +10880,8 @@ static void intel_crtc_init(struct drm_device *dev, int 
pipe)
                return;

        primary = intel_primary_plane_create(dev, pipe);
-       ret = drm_crtc_init(dev, &intel_crtc->base, primary, NULL,
+       cursor = intel_cursor_plane_create(dev, pipe);
+       ret = drm_crtc_init(dev, &intel_crtc->base, primary, cursor,
                            &intel_crtc_funcs);
        if (ret) {
                drm_crtc_cleanup(&intel_crtc->base);
-- 
1.8.5.1

Reply via email to