15ca02815Sjsg // SPDX-License-Identifier: MIT
25ca02815Sjsg /*
35ca02815Sjsg * Copyright © 2020 Intel Corporation
45ca02815Sjsg */
55ca02815Sjsg #include <linux/kernel.h>
65ca02815Sjsg
75ca02815Sjsg #include <drm/drm_atomic_helper.h>
85ca02815Sjsg #include <drm/drm_atomic_uapi.h>
91bb76ff1Sjsg #include <drm/drm_blend.h>
105ca02815Sjsg #include <drm/drm_damage_helper.h>
115ca02815Sjsg #include <drm/drm_fourcc.h>
125ca02815Sjsg
13f005ef32Sjsg #include "i915_reg.h"
145ca02815Sjsg #include "intel_atomic.h"
155ca02815Sjsg #include "intel_atomic_plane.h"
165ca02815Sjsg #include "intel_cursor.h"
175ca02815Sjsg #include "intel_de.h"
185ca02815Sjsg #include "intel_display.h"
19f005ef32Sjsg #include "intel_display_types.h"
205ca02815Sjsg #include "intel_fb.h"
211bb76ff1Sjsg #include "intel_fb_pin.h"
225ca02815Sjsg #include "intel_frontbuffer.h"
235ca02815Sjsg #include "intel_psr.h"
241bb76ff1Sjsg #include "skl_watermark.h"
255ca02815Sjsg
265416343cSjsg #include "gem/i915_gem_object.h"
275416343cSjsg
285ca02815Sjsg /* Cursor formats */
295ca02815Sjsg static const u32 intel_cursor_formats[] = {
305ca02815Sjsg DRM_FORMAT_ARGB8888,
315ca02815Sjsg };
325ca02815Sjsg
intel_cursor_base(const struct intel_plane_state * plane_state)335ca02815Sjsg static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
345ca02815Sjsg {
355ca02815Sjsg struct drm_i915_private *dev_priv =
365ca02815Sjsg to_i915(plane_state->uapi.plane->dev);
375ca02815Sjsg u32 base;
385ca02815Sjsg
39f005ef32Sjsg if (DISPLAY_INFO(dev_priv)->cursor_needs_physical)
40*d156f4f9Sjsg base = plane_state->phys_dma_addr;
415ca02815Sjsg else
425ca02815Sjsg base = intel_plane_ggtt_offset(plane_state);
435ca02815Sjsg
445ca02815Sjsg return base + plane_state->view.color_plane[0].offset;
455ca02815Sjsg }
465ca02815Sjsg
intel_cursor_position(const struct intel_plane_state * plane_state)475ca02815Sjsg static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
485ca02815Sjsg {
495ca02815Sjsg int x = plane_state->uapi.dst.x1;
505ca02815Sjsg int y = plane_state->uapi.dst.y1;
515ca02815Sjsg u32 pos = 0;
525ca02815Sjsg
535ca02815Sjsg if (x < 0) {
541bb76ff1Sjsg pos |= CURSOR_POS_X_SIGN;
555ca02815Sjsg x = -x;
565ca02815Sjsg }
571bb76ff1Sjsg pos |= CURSOR_POS_X(x);
585ca02815Sjsg
595ca02815Sjsg if (y < 0) {
601bb76ff1Sjsg pos |= CURSOR_POS_Y_SIGN;
615ca02815Sjsg y = -y;
625ca02815Sjsg }
631bb76ff1Sjsg pos |= CURSOR_POS_Y(y);
645ca02815Sjsg
655ca02815Sjsg return pos;
665ca02815Sjsg }
675ca02815Sjsg
intel_cursor_size_ok(const struct intel_plane_state * plane_state)685ca02815Sjsg static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
695ca02815Sjsg {
705ca02815Sjsg const struct drm_mode_config *config =
715ca02815Sjsg &plane_state->uapi.plane->dev->mode_config;
725ca02815Sjsg int width = drm_rect_width(&plane_state->uapi.dst);
735ca02815Sjsg int height = drm_rect_height(&plane_state->uapi.dst);
745ca02815Sjsg
755ca02815Sjsg return width > 0 && width <= config->cursor_width &&
765ca02815Sjsg height > 0 && height <= config->cursor_height;
775ca02815Sjsg }
785ca02815Sjsg
intel_cursor_check_surface(struct intel_plane_state * plane_state)795ca02815Sjsg static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
805ca02815Sjsg {
815ca02815Sjsg struct drm_i915_private *dev_priv =
825ca02815Sjsg to_i915(plane_state->uapi.plane->dev);
835ca02815Sjsg unsigned int rotation = plane_state->hw.rotation;
845ca02815Sjsg int src_x, src_y;
855ca02815Sjsg u32 offset;
865ca02815Sjsg int ret;
875ca02815Sjsg
885ca02815Sjsg ret = intel_plane_compute_gtt(plane_state);
895ca02815Sjsg if (ret)
905ca02815Sjsg return ret;
915ca02815Sjsg
925ca02815Sjsg if (!plane_state->uapi.visible)
935ca02815Sjsg return 0;
945ca02815Sjsg
955ca02815Sjsg src_x = plane_state->uapi.src.x1 >> 16;
965ca02815Sjsg src_y = plane_state->uapi.src.y1 >> 16;
975ca02815Sjsg
985ca02815Sjsg intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
995ca02815Sjsg offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
1005ca02815Sjsg plane_state, 0);
1015ca02815Sjsg
1025ca02815Sjsg if (src_x != 0 || src_y != 0) {
1035ca02815Sjsg drm_dbg_kms(&dev_priv->drm,
1045ca02815Sjsg "Arbitrary cursor panning not supported\n");
1055ca02815Sjsg return -EINVAL;
1065ca02815Sjsg }
1075ca02815Sjsg
1085ca02815Sjsg /*
1095ca02815Sjsg * Put the final coordinates back so that the src
1105ca02815Sjsg * coordinate checks will see the right values.
1115ca02815Sjsg */
1125ca02815Sjsg drm_rect_translate_to(&plane_state->uapi.src,
1135ca02815Sjsg src_x << 16, src_y << 16);
1145ca02815Sjsg
1155ca02815Sjsg /* ILK+ do this automagically in hardware */
1165ca02815Sjsg if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) {
1175ca02815Sjsg const struct drm_framebuffer *fb = plane_state->hw.fb;
1185ca02815Sjsg int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1195ca02815Sjsg int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1205ca02815Sjsg
1215ca02815Sjsg offset += (src_h * src_w - 1) * fb->format->cpp[0];
1225ca02815Sjsg }
1235ca02815Sjsg
1245ca02815Sjsg plane_state->view.color_plane[0].offset = offset;
1255ca02815Sjsg plane_state->view.color_plane[0].x = src_x;
1265ca02815Sjsg plane_state->view.color_plane[0].y = src_y;
1275ca02815Sjsg
1285ca02815Sjsg return 0;
1295ca02815Sjsg }
1305ca02815Sjsg
intel_check_cursor(struct intel_crtc_state * crtc_state,struct intel_plane_state * plane_state)1315ca02815Sjsg static int intel_check_cursor(struct intel_crtc_state *crtc_state,
1325ca02815Sjsg struct intel_plane_state *plane_state)
1335ca02815Sjsg {
1345ca02815Sjsg const struct drm_framebuffer *fb = plane_state->hw.fb;
1355ca02815Sjsg struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1365ca02815Sjsg const struct drm_rect src = plane_state->uapi.src;
1375ca02815Sjsg const struct drm_rect dst = plane_state->uapi.dst;
1385ca02815Sjsg int ret;
1395ca02815Sjsg
1405ca02815Sjsg if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
1415ca02815Sjsg drm_dbg_kms(&i915->drm, "cursor cannot be tiled\n");
1425ca02815Sjsg return -EINVAL;
1435ca02815Sjsg }
1445ca02815Sjsg
1455ca02815Sjsg ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1461bb76ff1Sjsg DRM_PLANE_NO_SCALING,
1471bb76ff1Sjsg DRM_PLANE_NO_SCALING,
1485ca02815Sjsg true);
1495ca02815Sjsg if (ret)
1505ca02815Sjsg return ret;
1515ca02815Sjsg
1525ca02815Sjsg /* Use the unclipped src/dst rectangles, which we program to hw */
1535ca02815Sjsg plane_state->uapi.src = src;
1545ca02815Sjsg plane_state->uapi.dst = dst;
1555ca02815Sjsg
1561bb76ff1Sjsg /* final plane coordinates will be relative to the plane's pipe */
1571bb76ff1Sjsg drm_rect_translate(&plane_state->uapi.dst,
1581bb76ff1Sjsg -crtc_state->pipe_src.x1,
1591bb76ff1Sjsg -crtc_state->pipe_src.y1);
1601bb76ff1Sjsg
1615ca02815Sjsg ret = intel_cursor_check_surface(plane_state);
1625ca02815Sjsg if (ret)
1635ca02815Sjsg return ret;
1645ca02815Sjsg
1655ca02815Sjsg if (!plane_state->uapi.visible)
1665ca02815Sjsg return 0;
1675ca02815Sjsg
1685ca02815Sjsg ret = intel_plane_check_src_coordinates(plane_state);
1695ca02815Sjsg if (ret)
1705ca02815Sjsg return ret;
1715ca02815Sjsg
1725ca02815Sjsg return 0;
1735ca02815Sjsg }
1745ca02815Sjsg
1755ca02815Sjsg static unsigned int
i845_cursor_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)1765ca02815Sjsg i845_cursor_max_stride(struct intel_plane *plane,
1775ca02815Sjsg u32 pixel_format, u64 modifier,
1785ca02815Sjsg unsigned int rotation)
1795ca02815Sjsg {
1805ca02815Sjsg return 2048;
1815ca02815Sjsg }
1825ca02815Sjsg
i845_cursor_ctl_crtc(const struct intel_crtc_state * crtc_state)1835ca02815Sjsg static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
1845ca02815Sjsg {
1855ca02815Sjsg u32 cntl = 0;
1865ca02815Sjsg
1875ca02815Sjsg if (crtc_state->gamma_enable)
1881bb76ff1Sjsg cntl |= CURSOR_PIPE_GAMMA_ENABLE;
1895ca02815Sjsg
1905ca02815Sjsg return cntl;
1915ca02815Sjsg }
1925ca02815Sjsg
i845_cursor_ctl(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)1935ca02815Sjsg static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
1945ca02815Sjsg const struct intel_plane_state *plane_state)
1955ca02815Sjsg {
1965ca02815Sjsg return CURSOR_ENABLE |
1975ca02815Sjsg CURSOR_FORMAT_ARGB |
1981bb76ff1Sjsg CURSOR_STRIDE(plane_state->view.color_plane[0].mapping_stride);
1995ca02815Sjsg }
2005ca02815Sjsg
i845_cursor_size_ok(const struct intel_plane_state * plane_state)2015ca02815Sjsg static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
2025ca02815Sjsg {
2035ca02815Sjsg int width = drm_rect_width(&plane_state->uapi.dst);
2045ca02815Sjsg
2055ca02815Sjsg /*
2065ca02815Sjsg * 845g/865g are only limited by the width of their cursors,
2075ca02815Sjsg * the height is arbitrary up to the precision of the register.
2085ca02815Sjsg */
2095ca02815Sjsg return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64);
2105ca02815Sjsg }
2115ca02815Sjsg
i845_check_cursor(struct intel_crtc_state * crtc_state,struct intel_plane_state * plane_state)2125ca02815Sjsg static int i845_check_cursor(struct intel_crtc_state *crtc_state,
2135ca02815Sjsg struct intel_plane_state *plane_state)
2145ca02815Sjsg {
2155ca02815Sjsg const struct drm_framebuffer *fb = plane_state->hw.fb;
2165ca02815Sjsg struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
2175ca02815Sjsg int ret;
2185ca02815Sjsg
2195ca02815Sjsg ret = intel_check_cursor(crtc_state, plane_state);
2205ca02815Sjsg if (ret)
2215ca02815Sjsg return ret;
2225ca02815Sjsg
2235ca02815Sjsg /* if we want to turn off the cursor ignore width and height */
2245ca02815Sjsg if (!fb)
2255ca02815Sjsg return 0;
2265ca02815Sjsg
2275ca02815Sjsg /* Check for which cursor types we support */
2285ca02815Sjsg if (!i845_cursor_size_ok(plane_state)) {
2295ca02815Sjsg drm_dbg_kms(&i915->drm,
2305ca02815Sjsg "Cursor dimension %dx%d not supported\n",
2315ca02815Sjsg drm_rect_width(&plane_state->uapi.dst),
2325ca02815Sjsg drm_rect_height(&plane_state->uapi.dst));
2335ca02815Sjsg return -EINVAL;
2345ca02815Sjsg }
2355ca02815Sjsg
2365ca02815Sjsg drm_WARN_ON(&i915->drm, plane_state->uapi.visible &&
2371bb76ff1Sjsg plane_state->view.color_plane[0].mapping_stride != fb->pitches[0]);
2385ca02815Sjsg
2395ca02815Sjsg switch (fb->pitches[0]) {
2405ca02815Sjsg case 256:
2415ca02815Sjsg case 512:
2425ca02815Sjsg case 1024:
2435ca02815Sjsg case 2048:
2445ca02815Sjsg break;
2455ca02815Sjsg default:
2465ca02815Sjsg drm_dbg_kms(&i915->drm, "Invalid cursor stride (%u)\n",
2475ca02815Sjsg fb->pitches[0]);
2485ca02815Sjsg return -EINVAL;
2495ca02815Sjsg }
2505ca02815Sjsg
2515ca02815Sjsg plane_state->ctl = i845_cursor_ctl(crtc_state, plane_state);
2525ca02815Sjsg
2535ca02815Sjsg return 0;
2545ca02815Sjsg }
2555ca02815Sjsg
2561bb76ff1Sjsg /* TODO: split into noarm+arm pair */
i845_cursor_update_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)2571bb76ff1Sjsg static void i845_cursor_update_arm(struct intel_plane *plane,
2585ca02815Sjsg const struct intel_crtc_state *crtc_state,
2595ca02815Sjsg const struct intel_plane_state *plane_state)
2605ca02815Sjsg {
2615ca02815Sjsg struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2625ca02815Sjsg u32 cntl = 0, base = 0, pos = 0, size = 0;
2635ca02815Sjsg
2645ca02815Sjsg if (plane_state && plane_state->uapi.visible) {
2655ca02815Sjsg unsigned int width = drm_rect_width(&plane_state->uapi.dst);
2665ca02815Sjsg unsigned int height = drm_rect_height(&plane_state->uapi.dst);
2675ca02815Sjsg
2685ca02815Sjsg cntl = plane_state->ctl |
2695ca02815Sjsg i845_cursor_ctl_crtc(crtc_state);
2705ca02815Sjsg
2711bb76ff1Sjsg size = CURSOR_HEIGHT(height) | CURSOR_WIDTH(width);
2725ca02815Sjsg
2735ca02815Sjsg base = intel_cursor_base(plane_state);
2745ca02815Sjsg pos = intel_cursor_position(plane_state);
2755ca02815Sjsg }
2765ca02815Sjsg
2775ca02815Sjsg /* On these chipsets we can only modify the base/size/stride
2785ca02815Sjsg * whilst the cursor is disabled.
2795ca02815Sjsg */
2805ca02815Sjsg if (plane->cursor.base != base ||
2815ca02815Sjsg plane->cursor.size != size ||
2825ca02815Sjsg plane->cursor.cntl != cntl) {
2835ca02815Sjsg intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), 0);
2845ca02815Sjsg intel_de_write_fw(dev_priv, CURBASE(PIPE_A), base);
2851bb76ff1Sjsg intel_de_write_fw(dev_priv, CURSIZE(PIPE_A), size);
2865ca02815Sjsg intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
2875ca02815Sjsg intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), cntl);
2885ca02815Sjsg
2895ca02815Sjsg plane->cursor.base = base;
2905ca02815Sjsg plane->cursor.size = size;
2915ca02815Sjsg plane->cursor.cntl = cntl;
2925ca02815Sjsg } else {
2935ca02815Sjsg intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
2945ca02815Sjsg }
2955ca02815Sjsg }
2965ca02815Sjsg
i845_cursor_disable_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state)2971bb76ff1Sjsg static void i845_cursor_disable_arm(struct intel_plane *plane,
2985ca02815Sjsg const struct intel_crtc_state *crtc_state)
2995ca02815Sjsg {
3001bb76ff1Sjsg i845_cursor_update_arm(plane, crtc_state, NULL);
3015ca02815Sjsg }
3025ca02815Sjsg
i845_cursor_get_hw_state(struct intel_plane * plane,enum pipe * pipe)3035ca02815Sjsg static bool i845_cursor_get_hw_state(struct intel_plane *plane,
3045ca02815Sjsg enum pipe *pipe)
3055ca02815Sjsg {
3065ca02815Sjsg struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
3075ca02815Sjsg enum intel_display_power_domain power_domain;
3085ca02815Sjsg intel_wakeref_t wakeref;
3095ca02815Sjsg bool ret;
3105ca02815Sjsg
3115ca02815Sjsg power_domain = POWER_DOMAIN_PIPE(PIPE_A);
3125ca02815Sjsg wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
3135ca02815Sjsg if (!wakeref)
3145ca02815Sjsg return false;
3155ca02815Sjsg
3165ca02815Sjsg ret = intel_de_read(dev_priv, CURCNTR(PIPE_A)) & CURSOR_ENABLE;
3175ca02815Sjsg
3185ca02815Sjsg *pipe = PIPE_A;
3195ca02815Sjsg
3205ca02815Sjsg intel_display_power_put(dev_priv, power_domain, wakeref);
3215ca02815Sjsg
3225ca02815Sjsg return ret;
3235ca02815Sjsg }
3245ca02815Sjsg
3255ca02815Sjsg static unsigned int
i9xx_cursor_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)3265ca02815Sjsg i9xx_cursor_max_stride(struct intel_plane *plane,
3275ca02815Sjsg u32 pixel_format, u64 modifier,
3285ca02815Sjsg unsigned int rotation)
3295ca02815Sjsg {
3305ca02815Sjsg return plane->base.dev->mode_config.cursor_width * 4;
3315ca02815Sjsg }
3325ca02815Sjsg
i9xx_cursor_ctl_crtc(const struct intel_crtc_state * crtc_state)3335ca02815Sjsg static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
3345ca02815Sjsg {
3355ca02815Sjsg struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
3365ca02815Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
3375ca02815Sjsg u32 cntl = 0;
3385ca02815Sjsg
3395ca02815Sjsg if (DISPLAY_VER(dev_priv) >= 11)
3405ca02815Sjsg return cntl;
3415ca02815Sjsg
3425ca02815Sjsg if (crtc_state->gamma_enable)
3431bb76ff1Sjsg cntl = MCURSOR_PIPE_GAMMA_ENABLE;
3445ca02815Sjsg
3455ca02815Sjsg if (crtc_state->csc_enable)
3465ca02815Sjsg cntl |= MCURSOR_PIPE_CSC_ENABLE;
3475ca02815Sjsg
3485ca02815Sjsg if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv))
3491bb76ff1Sjsg cntl |= MCURSOR_PIPE_SEL(crtc->pipe);
3505ca02815Sjsg
3515ca02815Sjsg return cntl;
3525ca02815Sjsg }
3535ca02815Sjsg
i9xx_cursor_ctl(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)3545ca02815Sjsg static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
3555ca02815Sjsg const struct intel_plane_state *plane_state)
3565ca02815Sjsg {
3575ca02815Sjsg struct drm_i915_private *dev_priv =
3585ca02815Sjsg to_i915(plane_state->uapi.plane->dev);
3595ca02815Sjsg u32 cntl = 0;
3605ca02815Sjsg
3615ca02815Sjsg if (IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv))
3625ca02815Sjsg cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
3635ca02815Sjsg
3645ca02815Sjsg switch (drm_rect_width(&plane_state->uapi.dst)) {
3655ca02815Sjsg case 64:
3665ca02815Sjsg cntl |= MCURSOR_MODE_64_ARGB_AX;
3675ca02815Sjsg break;
3685ca02815Sjsg case 128:
3695ca02815Sjsg cntl |= MCURSOR_MODE_128_ARGB_AX;
3705ca02815Sjsg break;
3715ca02815Sjsg case 256:
3725ca02815Sjsg cntl |= MCURSOR_MODE_256_ARGB_AX;
3735ca02815Sjsg break;
3745ca02815Sjsg default:
3755ca02815Sjsg MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));
3765ca02815Sjsg return 0;
3775ca02815Sjsg }
3785ca02815Sjsg
3795ca02815Sjsg if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
3805ca02815Sjsg cntl |= MCURSOR_ROTATE_180;
3815ca02815Sjsg
3825ca02815Sjsg /* Wa_22012358565:adl-p */
3835ca02815Sjsg if (DISPLAY_VER(dev_priv) == 13)
3845ca02815Sjsg cntl |= MCURSOR_ARB_SLOTS(1);
3855ca02815Sjsg
3865ca02815Sjsg return cntl;
3875ca02815Sjsg }
3885ca02815Sjsg
i9xx_cursor_size_ok(const struct intel_plane_state * plane_state)3895ca02815Sjsg static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
3905ca02815Sjsg {
3915ca02815Sjsg struct drm_i915_private *dev_priv =
3925ca02815Sjsg to_i915(plane_state->uapi.plane->dev);
3935ca02815Sjsg int width = drm_rect_width(&plane_state->uapi.dst);
3945ca02815Sjsg int height = drm_rect_height(&plane_state->uapi.dst);
3955ca02815Sjsg
3965ca02815Sjsg if (!intel_cursor_size_ok(plane_state))
3975ca02815Sjsg return false;
3985ca02815Sjsg
3995ca02815Sjsg /* Cursor width is limited to a few power-of-two sizes */
4005ca02815Sjsg switch (width) {
4015ca02815Sjsg case 256:
4025ca02815Sjsg case 128:
4035ca02815Sjsg case 64:
4045ca02815Sjsg break;
4055ca02815Sjsg default:
4065ca02815Sjsg return false;
4075ca02815Sjsg }
4085ca02815Sjsg
4095ca02815Sjsg /*
4105ca02815Sjsg * IVB+ have CUR_FBC_CTL which allows an arbitrary cursor
4115ca02815Sjsg * height from 8 lines up to the cursor width, when the
4125ca02815Sjsg * cursor is not rotated. Everything else requires square
4135ca02815Sjsg * cursors.
4145ca02815Sjsg */
4155ca02815Sjsg if (HAS_CUR_FBC(dev_priv) &&
4165ca02815Sjsg plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
4175ca02815Sjsg if (height < 8 || height > width)
4185ca02815Sjsg return false;
4195ca02815Sjsg } else {
4205ca02815Sjsg if (height != width)
4215ca02815Sjsg return false;
4225ca02815Sjsg }
4235ca02815Sjsg
4245ca02815Sjsg return true;
4255ca02815Sjsg }
4265ca02815Sjsg
i9xx_check_cursor(struct intel_crtc_state * crtc_state,struct intel_plane_state * plane_state)4275ca02815Sjsg static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
4285ca02815Sjsg struct intel_plane_state *plane_state)
4295ca02815Sjsg {
4305ca02815Sjsg struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
4315ca02815Sjsg struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
4325ca02815Sjsg const struct drm_framebuffer *fb = plane_state->hw.fb;
4335ca02815Sjsg enum pipe pipe = plane->pipe;
4345ca02815Sjsg int ret;
4355ca02815Sjsg
4365ca02815Sjsg ret = intel_check_cursor(crtc_state, plane_state);
4375ca02815Sjsg if (ret)
4385ca02815Sjsg return ret;
4395ca02815Sjsg
4405ca02815Sjsg /* if we want to turn off the cursor ignore width and height */
4415ca02815Sjsg if (!fb)
4425ca02815Sjsg return 0;
4435ca02815Sjsg
4445ca02815Sjsg /* Check for which cursor types we support */
4455ca02815Sjsg if (!i9xx_cursor_size_ok(plane_state)) {
4465ca02815Sjsg drm_dbg(&dev_priv->drm,
4475ca02815Sjsg "Cursor dimension %dx%d not supported\n",
4485ca02815Sjsg drm_rect_width(&plane_state->uapi.dst),
4495ca02815Sjsg drm_rect_height(&plane_state->uapi.dst));
4505ca02815Sjsg return -EINVAL;
4515ca02815Sjsg }
4525ca02815Sjsg
4535ca02815Sjsg drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible &&
4541bb76ff1Sjsg plane_state->view.color_plane[0].mapping_stride != fb->pitches[0]);
4555ca02815Sjsg
4565ca02815Sjsg if (fb->pitches[0] !=
4575ca02815Sjsg drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
4585ca02815Sjsg drm_dbg_kms(&dev_priv->drm,
4595ca02815Sjsg "Invalid cursor stride (%u) (cursor width %d)\n",
4605ca02815Sjsg fb->pitches[0],
4615ca02815Sjsg drm_rect_width(&plane_state->uapi.dst));
4625ca02815Sjsg return -EINVAL;
4635ca02815Sjsg }
4645ca02815Sjsg
4655ca02815Sjsg /*
4665ca02815Sjsg * There's something wrong with the cursor on CHV pipe C.
4675ca02815Sjsg * If it straddles the left edge of the screen then
4685ca02815Sjsg * moving it away from the edge or disabling it often
4695ca02815Sjsg * results in a pipe underrun, and often that can lead to
4705ca02815Sjsg * dead pipe (constant underrun reported, and it scans
4715ca02815Sjsg * out just a solid color). To recover from that, the
4725ca02815Sjsg * display power well must be turned off and on again.
4735ca02815Sjsg * Refuse the put the cursor into that compromised position.
4745ca02815Sjsg */
4755ca02815Sjsg if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
4765ca02815Sjsg plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
4775ca02815Sjsg drm_dbg_kms(&dev_priv->drm,
4785ca02815Sjsg "CHV cursor C not allowed to straddle the left screen edge\n");
4795ca02815Sjsg return -EINVAL;
4805ca02815Sjsg }
4815ca02815Sjsg
4825ca02815Sjsg plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state);
4835ca02815Sjsg
4845ca02815Sjsg return 0;
4855ca02815Sjsg }
4865ca02815Sjsg
4871bb76ff1Sjsg /* TODO: split into noarm+arm pair */
i9xx_cursor_update_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)4881bb76ff1Sjsg static void i9xx_cursor_update_arm(struct intel_plane *plane,
4895ca02815Sjsg const struct intel_crtc_state *crtc_state,
4905ca02815Sjsg const struct intel_plane_state *plane_state)
4915ca02815Sjsg {
4925ca02815Sjsg struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
4935ca02815Sjsg enum pipe pipe = plane->pipe;
4945ca02815Sjsg u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
4955ca02815Sjsg
4965ca02815Sjsg if (plane_state && plane_state->uapi.visible) {
4975ca02815Sjsg int width = drm_rect_width(&plane_state->uapi.dst);
4985ca02815Sjsg int height = drm_rect_height(&plane_state->uapi.dst);
4995ca02815Sjsg
5005ca02815Sjsg cntl = plane_state->ctl |
5015ca02815Sjsg i9xx_cursor_ctl_crtc(crtc_state);
5025ca02815Sjsg
5035ca02815Sjsg if (width != height)
5041bb76ff1Sjsg fbc_ctl = CUR_FBC_EN | CUR_FBC_HEIGHT(height - 1);
5055ca02815Sjsg
5065ca02815Sjsg base = intel_cursor_base(plane_state);
5075ca02815Sjsg pos = intel_cursor_position(plane_state);
5085ca02815Sjsg }
5095ca02815Sjsg
5105ca02815Sjsg /*
5115ca02815Sjsg * On some platforms writing CURCNTR first will also
5125ca02815Sjsg * cause CURPOS to be armed by the CURBASE write.
5135ca02815Sjsg * Without the CURCNTR write the CURPOS write would
5145ca02815Sjsg * arm itself. Thus we always update CURCNTR before
5155ca02815Sjsg * CURPOS.
5165ca02815Sjsg *
5175ca02815Sjsg * On other platforms CURPOS always requires the
5185ca02815Sjsg * CURBASE write to arm the update. Additonally
5195ca02815Sjsg * a write to any of the cursor register will cancel
5205ca02815Sjsg * an already armed cursor update. Thus leaving out
5215ca02815Sjsg * the CURBASE write after CURPOS could lead to a
5225ca02815Sjsg * cursor that doesn't appear to move, or even change
5235ca02815Sjsg * shape. Thus we always write CURBASE.
5245ca02815Sjsg *
5255ca02815Sjsg * The other registers are armed by the CURBASE write
5265ca02815Sjsg * except when the plane is getting enabled at which time
5275ca02815Sjsg * the CURCNTR write arms the update.
5285ca02815Sjsg */
5295ca02815Sjsg
5305ca02815Sjsg if (DISPLAY_VER(dev_priv) >= 9)
5315ca02815Sjsg skl_write_cursor_wm(plane, crtc_state);
5325ca02815Sjsg
5331bb76ff1Sjsg if (plane_state)
534f005ef32Sjsg intel_psr2_program_plane_sel_fetch_arm(plane, crtc_state,
535f005ef32Sjsg plane_state);
5361bb76ff1Sjsg else
537f005ef32Sjsg intel_psr2_disable_plane_sel_fetch_arm(plane, crtc_state);
5385ca02815Sjsg
5395ca02815Sjsg if (plane->cursor.base != base ||
5405ca02815Sjsg plane->cursor.size != fbc_ctl ||
5415ca02815Sjsg plane->cursor.cntl != cntl) {
5425ca02815Sjsg if (HAS_CUR_FBC(dev_priv))
5435ca02815Sjsg intel_de_write_fw(dev_priv, CUR_FBC_CTL(pipe),
5445ca02815Sjsg fbc_ctl);
5455ca02815Sjsg intel_de_write_fw(dev_priv, CURCNTR(pipe), cntl);
5465ca02815Sjsg intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
5475ca02815Sjsg intel_de_write_fw(dev_priv, CURBASE(pipe), base);
5485ca02815Sjsg
5495ca02815Sjsg plane->cursor.base = base;
5505ca02815Sjsg plane->cursor.size = fbc_ctl;
5515ca02815Sjsg plane->cursor.cntl = cntl;
5525ca02815Sjsg } else {
5535ca02815Sjsg intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
5545ca02815Sjsg intel_de_write_fw(dev_priv, CURBASE(pipe), base);
5555ca02815Sjsg }
5565ca02815Sjsg }
5575ca02815Sjsg
i9xx_cursor_disable_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state)5581bb76ff1Sjsg static void i9xx_cursor_disable_arm(struct intel_plane *plane,
5595ca02815Sjsg const struct intel_crtc_state *crtc_state)
5605ca02815Sjsg {
5611bb76ff1Sjsg i9xx_cursor_update_arm(plane, crtc_state, NULL);
5625ca02815Sjsg }
5635ca02815Sjsg
i9xx_cursor_get_hw_state(struct intel_plane * plane,enum pipe * pipe)5645ca02815Sjsg static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
5655ca02815Sjsg enum pipe *pipe)
5665ca02815Sjsg {
5675ca02815Sjsg struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
5685ca02815Sjsg enum intel_display_power_domain power_domain;
5695ca02815Sjsg intel_wakeref_t wakeref;
5705ca02815Sjsg bool ret;
5715ca02815Sjsg u32 val;
5725ca02815Sjsg
5735ca02815Sjsg /*
5745ca02815Sjsg * Not 100% correct for planes that can move between pipes,
5755ca02815Sjsg * but that's only the case for gen2-3 which don't have any
5765ca02815Sjsg * display power wells.
5775ca02815Sjsg */
5785ca02815Sjsg power_domain = POWER_DOMAIN_PIPE(plane->pipe);
5795ca02815Sjsg wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
5805ca02815Sjsg if (!wakeref)
5815ca02815Sjsg return false;
5825ca02815Sjsg
5835ca02815Sjsg val = intel_de_read(dev_priv, CURCNTR(plane->pipe));
5845ca02815Sjsg
5851bb76ff1Sjsg ret = val & MCURSOR_MODE_MASK;
5865ca02815Sjsg
5875ca02815Sjsg if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
5885ca02815Sjsg *pipe = plane->pipe;
5895ca02815Sjsg else
5901bb76ff1Sjsg *pipe = REG_FIELD_GET(MCURSOR_PIPE_SEL_MASK, val);
5915ca02815Sjsg
5925ca02815Sjsg intel_display_power_put(dev_priv, power_domain, wakeref);
5935ca02815Sjsg
5945ca02815Sjsg return ret;
5955ca02815Sjsg }
5965ca02815Sjsg
intel_cursor_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)5975ca02815Sjsg static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
5985ca02815Sjsg u32 format, u64 modifier)
5995ca02815Sjsg {
6001bb76ff1Sjsg if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
6011bb76ff1Sjsg return false;
6021bb76ff1Sjsg
6031bb76ff1Sjsg return format == DRM_FORMAT_ARGB8888;
6045ca02815Sjsg }
6055ca02815Sjsg
6065ca02815Sjsg static int
intel_legacy_cursor_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,u32 src_x,u32 src_y,u32 src_w,u32 src_h,struct drm_modeset_acquire_ctx * ctx)6075ca02815Sjsg intel_legacy_cursor_update(struct drm_plane *_plane,
6085ca02815Sjsg struct drm_crtc *_crtc,
6095ca02815Sjsg struct drm_framebuffer *fb,
6105ca02815Sjsg int crtc_x, int crtc_y,
6115ca02815Sjsg unsigned int crtc_w, unsigned int crtc_h,
6125ca02815Sjsg u32 src_x, u32 src_y,
6135ca02815Sjsg u32 src_w, u32 src_h,
6145ca02815Sjsg struct drm_modeset_acquire_ctx *ctx)
6155ca02815Sjsg {
6165ca02815Sjsg struct intel_plane *plane = to_intel_plane(_plane);
6175ca02815Sjsg struct intel_crtc *crtc = to_intel_crtc(_crtc);
6185ca02815Sjsg struct intel_plane_state *old_plane_state =
6195ca02815Sjsg to_intel_plane_state(plane->base.state);
6205ca02815Sjsg struct intel_plane_state *new_plane_state;
6215ca02815Sjsg struct intel_crtc_state *crtc_state =
6225ca02815Sjsg to_intel_crtc_state(crtc->base.state);
6235ca02815Sjsg struct intel_crtc_state *new_crtc_state;
6245ca02815Sjsg int ret;
6255ca02815Sjsg
6265ca02815Sjsg /*
6275ca02815Sjsg * When crtc is inactive or there is a modeset pending,
6285ca02815Sjsg * wait for it to complete in the slowpath.
6295ca02815Sjsg * PSR2 selective fetch also requires the slow path as
6305ca02815Sjsg * PSR2 plane and transcoder registers can only be updated during
6315ca02815Sjsg * vblank.
6325ca02815Sjsg *
6335ca02815Sjsg * FIXME bigjoiner fastpath would be good
6345ca02815Sjsg */
635f005ef32Sjsg if (!crtc_state->hw.active ||
636f005ef32Sjsg intel_crtc_needs_modeset(crtc_state) ||
637f005ef32Sjsg intel_crtc_needs_fastset(crtc_state) ||
638f005ef32Sjsg crtc_state->bigjoiner_pipes)
6395ca02815Sjsg goto slow;
6405ca02815Sjsg
6415ca02815Sjsg /*
6425ca02815Sjsg * Don't do an async update if there is an outstanding commit modifying
6435ca02815Sjsg * the plane. This prevents our async update's changes from getting
6445ca02815Sjsg * overridden by a previous synchronous update's state.
6455ca02815Sjsg */
6465ca02815Sjsg if (old_plane_state->uapi.commit &&
6475ca02815Sjsg !try_wait_for_completion(&old_plane_state->uapi.commit->hw_done))
6485ca02815Sjsg goto slow;
6495ca02815Sjsg
6505ca02815Sjsg /*
6515ca02815Sjsg * If any parameters change that may affect watermarks,
6525ca02815Sjsg * take the slowpath. Only changing fb or position should be
6535ca02815Sjsg * in the fastpath.
6545ca02815Sjsg */
6555ca02815Sjsg if (old_plane_state->uapi.crtc != &crtc->base ||
6565ca02815Sjsg old_plane_state->uapi.src_w != src_w ||
6575ca02815Sjsg old_plane_state->uapi.src_h != src_h ||
6585ca02815Sjsg old_plane_state->uapi.crtc_w != crtc_w ||
6595ca02815Sjsg old_plane_state->uapi.crtc_h != crtc_h ||
6605ca02815Sjsg !old_plane_state->uapi.fb != !fb)
6615ca02815Sjsg goto slow;
6625ca02815Sjsg
6635ca02815Sjsg new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base));
6645ca02815Sjsg if (!new_plane_state)
6655ca02815Sjsg return -ENOMEM;
6665ca02815Sjsg
6675ca02815Sjsg new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(&crtc->base));
6685ca02815Sjsg if (!new_crtc_state) {
6695ca02815Sjsg ret = -ENOMEM;
6705ca02815Sjsg goto out_free;
6715ca02815Sjsg }
6725ca02815Sjsg
6735ca02815Sjsg drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb);
6745ca02815Sjsg
6755ca02815Sjsg new_plane_state->uapi.src_x = src_x;
6765ca02815Sjsg new_plane_state->uapi.src_y = src_y;
6775ca02815Sjsg new_plane_state->uapi.src_w = src_w;
6785ca02815Sjsg new_plane_state->uapi.src_h = src_h;
6795ca02815Sjsg new_plane_state->uapi.crtc_x = crtc_x;
6805ca02815Sjsg new_plane_state->uapi.crtc_y = crtc_y;
6815ca02815Sjsg new_plane_state->uapi.crtc_w = crtc_w;
6825ca02815Sjsg new_plane_state->uapi.crtc_h = crtc_h;
6835ca02815Sjsg
6845ca02815Sjsg intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state, crtc);
6855ca02815Sjsg
6865ca02815Sjsg ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,
6875ca02815Sjsg old_plane_state, new_plane_state);
6885ca02815Sjsg if (ret)
6895ca02815Sjsg goto out_free;
6905ca02815Sjsg
6915ca02815Sjsg ret = intel_plane_pin_fb(new_plane_state);
6925ca02815Sjsg if (ret)
6935ca02815Sjsg goto out_free;
6945ca02815Sjsg
6955ca02815Sjsg intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb),
6961bb76ff1Sjsg ORIGIN_CURSOR_UPDATE);
6975ca02815Sjsg intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb),
6985ca02815Sjsg to_intel_frontbuffer(new_plane_state->hw.fb),
6995ca02815Sjsg plane->frontbuffer_bit);
7005ca02815Sjsg
7015ca02815Sjsg /* Swap plane state */
7025ca02815Sjsg plane->base.state = &new_plane_state->uapi;
7035ca02815Sjsg
7045ca02815Sjsg /*
7055ca02815Sjsg * We cannot swap crtc_state as it may be in use by an atomic commit or
7065ca02815Sjsg * page flip that's running simultaneously. If we swap crtc_state and
7075ca02815Sjsg * destroy the old state, we will cause a use-after-free there.
7085ca02815Sjsg *
7095ca02815Sjsg * Only update active_planes, which is needed for our internal
7105ca02815Sjsg * bookkeeping. Either value will do the right thing when updating
7115ca02815Sjsg * planes atomically. If the cursor was part of the atomic update then
7125ca02815Sjsg * we would have taken the slowpath.
7135ca02815Sjsg */
7145ca02815Sjsg crtc_state->active_planes = new_crtc_state->active_planes;
7155ca02815Sjsg
7161bb76ff1Sjsg /*
7171bb76ff1Sjsg * Technically we should do a vblank evasion here to make
7181bb76ff1Sjsg * sure all the cursor registers update on the same frame.
7191bb76ff1Sjsg * For now just make sure the register writes happen as
7201bb76ff1Sjsg * quickly as possible to minimize the race window.
7211bb76ff1Sjsg */
7221bb76ff1Sjsg local_irq_disable();
7231bb76ff1Sjsg
7241bb76ff1Sjsg if (new_plane_state->uapi.visible) {
7251bb76ff1Sjsg intel_plane_update_noarm(plane, crtc_state, new_plane_state);
7261bb76ff1Sjsg intel_plane_update_arm(plane, crtc_state, new_plane_state);
7271bb76ff1Sjsg } else {
7281bb76ff1Sjsg intel_plane_disable_arm(plane, crtc_state);
7291bb76ff1Sjsg }
7301bb76ff1Sjsg
7311bb76ff1Sjsg local_irq_enable();
7325ca02815Sjsg
7335ca02815Sjsg intel_plane_unpin_fb(old_plane_state);
7345ca02815Sjsg
7355ca02815Sjsg out_free:
7365ca02815Sjsg if (new_crtc_state)
7375ca02815Sjsg intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi);
7385ca02815Sjsg if (ret)
7395ca02815Sjsg intel_plane_destroy_state(&plane->base, &new_plane_state->uapi);
7405ca02815Sjsg else
7415ca02815Sjsg intel_plane_destroy_state(&plane->base, &old_plane_state->uapi);
7425ca02815Sjsg return ret;
7435ca02815Sjsg
7445ca02815Sjsg slow:
7455ca02815Sjsg return drm_atomic_helper_update_plane(&plane->base, &crtc->base, fb,
7465ca02815Sjsg crtc_x, crtc_y, crtc_w, crtc_h,
7475ca02815Sjsg src_x, src_y, src_w, src_h, ctx);
7485ca02815Sjsg }
7495ca02815Sjsg
7505ca02815Sjsg static const struct drm_plane_funcs intel_cursor_plane_funcs = {
7515ca02815Sjsg .update_plane = intel_legacy_cursor_update,
7525ca02815Sjsg .disable_plane = drm_atomic_helper_disable_plane,
7535ca02815Sjsg .destroy = intel_plane_destroy,
7545ca02815Sjsg .atomic_duplicate_state = intel_plane_duplicate_state,
7555ca02815Sjsg .atomic_destroy_state = intel_plane_destroy_state,
7565ca02815Sjsg .format_mod_supported = intel_cursor_format_mod_supported,
7575ca02815Sjsg };
7585ca02815Sjsg
7595ca02815Sjsg struct intel_plane *
intel_cursor_plane_create(struct drm_i915_private * dev_priv,enum pipe pipe)7605ca02815Sjsg intel_cursor_plane_create(struct drm_i915_private *dev_priv,
7615ca02815Sjsg enum pipe pipe)
7625ca02815Sjsg {
7635ca02815Sjsg struct intel_plane *cursor;
7645ca02815Sjsg int ret, zpos;
7651bb76ff1Sjsg u64 *modifiers;
7665ca02815Sjsg
7675ca02815Sjsg cursor = intel_plane_alloc();
7685ca02815Sjsg if (IS_ERR(cursor))
7695ca02815Sjsg return cursor;
7705ca02815Sjsg
7715ca02815Sjsg cursor->pipe = pipe;
7725ca02815Sjsg cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
7735ca02815Sjsg cursor->id = PLANE_CURSOR;
7745ca02815Sjsg cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
7755ca02815Sjsg
7765ca02815Sjsg if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
7775ca02815Sjsg cursor->max_stride = i845_cursor_max_stride;
7781bb76ff1Sjsg cursor->update_arm = i845_cursor_update_arm;
7791bb76ff1Sjsg cursor->disable_arm = i845_cursor_disable_arm;
7805ca02815Sjsg cursor->get_hw_state = i845_cursor_get_hw_state;
7815ca02815Sjsg cursor->check_plane = i845_check_cursor;
7825ca02815Sjsg } else {
7835ca02815Sjsg cursor->max_stride = i9xx_cursor_max_stride;
7841bb76ff1Sjsg cursor->update_arm = i9xx_cursor_update_arm;
7851bb76ff1Sjsg cursor->disable_arm = i9xx_cursor_disable_arm;
7865ca02815Sjsg cursor->get_hw_state = i9xx_cursor_get_hw_state;
7875ca02815Sjsg cursor->check_plane = i9xx_check_cursor;
7885ca02815Sjsg }
7895ca02815Sjsg
7905ca02815Sjsg cursor->cursor.base = ~0;
7915ca02815Sjsg cursor->cursor.cntl = ~0;
7925ca02815Sjsg
7935ca02815Sjsg if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
7945ca02815Sjsg cursor->cursor.size = ~0;
7955ca02815Sjsg
7961bb76ff1Sjsg modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_NONE);
7971bb76ff1Sjsg
7985ca02815Sjsg ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
7995ca02815Sjsg 0, &intel_cursor_plane_funcs,
8005ca02815Sjsg intel_cursor_formats,
8015ca02815Sjsg ARRAY_SIZE(intel_cursor_formats),
8021bb76ff1Sjsg modifiers,
8035ca02815Sjsg DRM_PLANE_TYPE_CURSOR,
8045ca02815Sjsg "cursor %c", pipe_name(pipe));
8051bb76ff1Sjsg
8061bb76ff1Sjsg kfree(modifiers);
8071bb76ff1Sjsg
8085ca02815Sjsg if (ret)
8095ca02815Sjsg goto fail;
8105ca02815Sjsg
8115ca02815Sjsg if (DISPLAY_VER(dev_priv) >= 4)
8125ca02815Sjsg drm_plane_create_rotation_property(&cursor->base,
8135ca02815Sjsg DRM_MODE_ROTATE_0,
8145ca02815Sjsg DRM_MODE_ROTATE_0 |
8155ca02815Sjsg DRM_MODE_ROTATE_180);
8165ca02815Sjsg
817f005ef32Sjsg zpos = DISPLAY_RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
8185ca02815Sjsg drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
8195ca02815Sjsg
8205ca02815Sjsg if (DISPLAY_VER(dev_priv) >= 12)
8215ca02815Sjsg drm_plane_enable_fb_damage_clips(&cursor->base);
8225ca02815Sjsg
8235ca02815Sjsg intel_plane_helper_add(cursor);
8245ca02815Sjsg
8255ca02815Sjsg return cursor;
8265ca02815Sjsg
8275ca02815Sjsg fail:
8285ca02815Sjsg intel_plane_free(cursor);
8295ca02815Sjsg
8305ca02815Sjsg return ERR_PTR(ret);
8315ca02815Sjsg }
832