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