0001
0002
0003
0004
0005 #include <linux/kernel.h>
0006
0007 #include <drm/drm_atomic_helper.h>
0008 #include <drm/drm_atomic_uapi.h>
0009 #include <drm/drm_blend.h>
0010 #include <drm/drm_damage_helper.h>
0011 #include <drm/drm_plane_helper.h>
0012 #include <drm/drm_fourcc.h>
0013
0014 #include "intel_atomic.h"
0015 #include "intel_atomic_plane.h"
0016 #include "intel_cursor.h"
0017 #include "intel_de.h"
0018 #include "intel_display_types.h"
0019 #include "intel_display.h"
0020 #include "intel_fb.h"
0021 #include "intel_fb_pin.h"
0022 #include "intel_frontbuffer.h"
0023 #include "intel_pm.h"
0024 #include "intel_psr.h"
0025 #include "intel_sprite.h"
0026
0027
0028 static const u32 intel_cursor_formats[] = {
0029 DRM_FORMAT_ARGB8888,
0030 };
0031
0032 static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
0033 {
0034 struct drm_i915_private *dev_priv =
0035 to_i915(plane_state->uapi.plane->dev);
0036 const struct drm_framebuffer *fb = plane_state->hw.fb;
0037 const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
0038 u32 base;
0039
0040 if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
0041 base = sg_dma_address(obj->mm.pages->sgl);
0042 else
0043 base = intel_plane_ggtt_offset(plane_state);
0044
0045 return base + plane_state->view.color_plane[0].offset;
0046 }
0047
0048 static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
0049 {
0050 int x = plane_state->uapi.dst.x1;
0051 int y = plane_state->uapi.dst.y1;
0052 u32 pos = 0;
0053
0054 if (x < 0) {
0055 pos |= CURSOR_POS_X_SIGN;
0056 x = -x;
0057 }
0058 pos |= CURSOR_POS_X(x);
0059
0060 if (y < 0) {
0061 pos |= CURSOR_POS_Y_SIGN;
0062 y = -y;
0063 }
0064 pos |= CURSOR_POS_Y(y);
0065
0066 return pos;
0067 }
0068
0069 static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
0070 {
0071 const struct drm_mode_config *config =
0072 &plane_state->uapi.plane->dev->mode_config;
0073 int width = drm_rect_width(&plane_state->uapi.dst);
0074 int height = drm_rect_height(&plane_state->uapi.dst);
0075
0076 return width > 0 && width <= config->cursor_width &&
0077 height > 0 && height <= config->cursor_height;
0078 }
0079
0080 static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
0081 {
0082 struct drm_i915_private *dev_priv =
0083 to_i915(plane_state->uapi.plane->dev);
0084 unsigned int rotation = plane_state->hw.rotation;
0085 int src_x, src_y;
0086 u32 offset;
0087 int ret;
0088
0089 ret = intel_plane_compute_gtt(plane_state);
0090 if (ret)
0091 return ret;
0092
0093 if (!plane_state->uapi.visible)
0094 return 0;
0095
0096 src_x = plane_state->uapi.src.x1 >> 16;
0097 src_y = plane_state->uapi.src.y1 >> 16;
0098
0099 intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
0100 offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
0101 plane_state, 0);
0102
0103 if (src_x != 0 || src_y != 0) {
0104 drm_dbg_kms(&dev_priv->drm,
0105 "Arbitrary cursor panning not supported\n");
0106 return -EINVAL;
0107 }
0108
0109
0110
0111
0112
0113 drm_rect_translate_to(&plane_state->uapi.src,
0114 src_x << 16, src_y << 16);
0115
0116
0117 if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) {
0118 const struct drm_framebuffer *fb = plane_state->hw.fb;
0119 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
0120 int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
0121
0122 offset += (src_h * src_w - 1) * fb->format->cpp[0];
0123 }
0124
0125 plane_state->view.color_plane[0].offset = offset;
0126 plane_state->view.color_plane[0].x = src_x;
0127 plane_state->view.color_plane[0].y = src_y;
0128
0129 return 0;
0130 }
0131
0132 static int intel_check_cursor(struct intel_crtc_state *crtc_state,
0133 struct intel_plane_state *plane_state)
0134 {
0135 const struct drm_framebuffer *fb = plane_state->hw.fb;
0136 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
0137 const struct drm_rect src = plane_state->uapi.src;
0138 const struct drm_rect dst = plane_state->uapi.dst;
0139 int ret;
0140
0141 if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
0142 drm_dbg_kms(&i915->drm, "cursor cannot be tiled\n");
0143 return -EINVAL;
0144 }
0145
0146 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
0147 DRM_PLANE_HELPER_NO_SCALING,
0148 DRM_PLANE_HELPER_NO_SCALING,
0149 true);
0150 if (ret)
0151 return ret;
0152
0153
0154 plane_state->uapi.src = src;
0155 plane_state->uapi.dst = dst;
0156
0157
0158 drm_rect_translate(&plane_state->uapi.dst,
0159 -crtc_state->pipe_src.x1,
0160 -crtc_state->pipe_src.y1);
0161
0162 ret = intel_cursor_check_surface(plane_state);
0163 if (ret)
0164 return ret;
0165
0166 if (!plane_state->uapi.visible)
0167 return 0;
0168
0169 ret = intel_plane_check_src_coordinates(plane_state);
0170 if (ret)
0171 return ret;
0172
0173 return 0;
0174 }
0175
0176 static unsigned int
0177 i845_cursor_max_stride(struct intel_plane *plane,
0178 u32 pixel_format, u64 modifier,
0179 unsigned int rotation)
0180 {
0181 return 2048;
0182 }
0183
0184 static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
0185 {
0186 u32 cntl = 0;
0187
0188 if (crtc_state->gamma_enable)
0189 cntl |= CURSOR_PIPE_GAMMA_ENABLE;
0190
0191 return cntl;
0192 }
0193
0194 static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
0195 const struct intel_plane_state *plane_state)
0196 {
0197 return CURSOR_ENABLE |
0198 CURSOR_FORMAT_ARGB |
0199 CURSOR_STRIDE(plane_state->view.color_plane[0].mapping_stride);
0200 }
0201
0202 static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
0203 {
0204 int width = drm_rect_width(&plane_state->uapi.dst);
0205
0206
0207
0208
0209
0210 return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64);
0211 }
0212
0213 static int i845_check_cursor(struct intel_crtc_state *crtc_state,
0214 struct intel_plane_state *plane_state)
0215 {
0216 const struct drm_framebuffer *fb = plane_state->hw.fb;
0217 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
0218 int ret;
0219
0220 ret = intel_check_cursor(crtc_state, plane_state);
0221 if (ret)
0222 return ret;
0223
0224
0225 if (!fb)
0226 return 0;
0227
0228
0229 if (!i845_cursor_size_ok(plane_state)) {
0230 drm_dbg_kms(&i915->drm,
0231 "Cursor dimension %dx%d not supported\n",
0232 drm_rect_width(&plane_state->uapi.dst),
0233 drm_rect_height(&plane_state->uapi.dst));
0234 return -EINVAL;
0235 }
0236
0237 drm_WARN_ON(&i915->drm, plane_state->uapi.visible &&
0238 plane_state->view.color_plane[0].mapping_stride != fb->pitches[0]);
0239
0240 switch (fb->pitches[0]) {
0241 case 256:
0242 case 512:
0243 case 1024:
0244 case 2048:
0245 break;
0246 default:
0247 drm_dbg_kms(&i915->drm, "Invalid cursor stride (%u)\n",
0248 fb->pitches[0]);
0249 return -EINVAL;
0250 }
0251
0252 plane_state->ctl = i845_cursor_ctl(crtc_state, plane_state);
0253
0254 return 0;
0255 }
0256
0257
0258 static void i845_cursor_update_arm(struct intel_plane *plane,
0259 const struct intel_crtc_state *crtc_state,
0260 const struct intel_plane_state *plane_state)
0261 {
0262 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0263 u32 cntl = 0, base = 0, pos = 0, size = 0;
0264
0265 if (plane_state && plane_state->uapi.visible) {
0266 unsigned int width = drm_rect_width(&plane_state->uapi.dst);
0267 unsigned int height = drm_rect_height(&plane_state->uapi.dst);
0268
0269 cntl = plane_state->ctl |
0270 i845_cursor_ctl_crtc(crtc_state);
0271
0272 size = CURSOR_HEIGHT(height) | CURSOR_WIDTH(width);
0273
0274 base = intel_cursor_base(plane_state);
0275 pos = intel_cursor_position(plane_state);
0276 }
0277
0278
0279
0280
0281 if (plane->cursor.base != base ||
0282 plane->cursor.size != size ||
0283 plane->cursor.cntl != cntl) {
0284 intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), 0);
0285 intel_de_write_fw(dev_priv, CURBASE(PIPE_A), base);
0286 intel_de_write_fw(dev_priv, CURSIZE(PIPE_A), size);
0287 intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
0288 intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), cntl);
0289
0290 plane->cursor.base = base;
0291 plane->cursor.size = size;
0292 plane->cursor.cntl = cntl;
0293 } else {
0294 intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
0295 }
0296 }
0297
0298 static void i845_cursor_disable_arm(struct intel_plane *plane,
0299 const struct intel_crtc_state *crtc_state)
0300 {
0301 i845_cursor_update_arm(plane, crtc_state, NULL);
0302 }
0303
0304 static bool i845_cursor_get_hw_state(struct intel_plane *plane,
0305 enum pipe *pipe)
0306 {
0307 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0308 enum intel_display_power_domain power_domain;
0309 intel_wakeref_t wakeref;
0310 bool ret;
0311
0312 power_domain = POWER_DOMAIN_PIPE(PIPE_A);
0313 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
0314 if (!wakeref)
0315 return false;
0316
0317 ret = intel_de_read(dev_priv, CURCNTR(PIPE_A)) & CURSOR_ENABLE;
0318
0319 *pipe = PIPE_A;
0320
0321 intel_display_power_put(dev_priv, power_domain, wakeref);
0322
0323 return ret;
0324 }
0325
0326 static unsigned int
0327 i9xx_cursor_max_stride(struct intel_plane *plane,
0328 u32 pixel_format, u64 modifier,
0329 unsigned int rotation)
0330 {
0331 return plane->base.dev->mode_config.cursor_width * 4;
0332 }
0333
0334 static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
0335 {
0336 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
0337 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
0338 u32 cntl = 0;
0339
0340 if (DISPLAY_VER(dev_priv) >= 11)
0341 return cntl;
0342
0343 if (crtc_state->gamma_enable)
0344 cntl = MCURSOR_PIPE_GAMMA_ENABLE;
0345
0346 if (crtc_state->csc_enable)
0347 cntl |= MCURSOR_PIPE_CSC_ENABLE;
0348
0349 if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv))
0350 cntl |= MCURSOR_PIPE_SEL(crtc->pipe);
0351
0352 return cntl;
0353 }
0354
0355 static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
0356 const struct intel_plane_state *plane_state)
0357 {
0358 struct drm_i915_private *dev_priv =
0359 to_i915(plane_state->uapi.plane->dev);
0360 u32 cntl = 0;
0361
0362 if (IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv))
0363 cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
0364
0365 switch (drm_rect_width(&plane_state->uapi.dst)) {
0366 case 64:
0367 cntl |= MCURSOR_MODE_64_ARGB_AX;
0368 break;
0369 case 128:
0370 cntl |= MCURSOR_MODE_128_ARGB_AX;
0371 break;
0372 case 256:
0373 cntl |= MCURSOR_MODE_256_ARGB_AX;
0374 break;
0375 default:
0376 MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));
0377 return 0;
0378 }
0379
0380 if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
0381 cntl |= MCURSOR_ROTATE_180;
0382
0383
0384 if (DISPLAY_VER(dev_priv) == 13)
0385 cntl |= MCURSOR_ARB_SLOTS(1);
0386
0387 return cntl;
0388 }
0389
0390 static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
0391 {
0392 struct drm_i915_private *dev_priv =
0393 to_i915(plane_state->uapi.plane->dev);
0394 int width = drm_rect_width(&plane_state->uapi.dst);
0395 int height = drm_rect_height(&plane_state->uapi.dst);
0396
0397 if (!intel_cursor_size_ok(plane_state))
0398 return false;
0399
0400
0401 switch (width) {
0402 case 256:
0403 case 128:
0404 case 64:
0405 break;
0406 default:
0407 return false;
0408 }
0409
0410
0411
0412
0413
0414
0415
0416 if (HAS_CUR_FBC(dev_priv) &&
0417 plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
0418 if (height < 8 || height > width)
0419 return false;
0420 } else {
0421 if (height != width)
0422 return false;
0423 }
0424
0425 return true;
0426 }
0427
0428 static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
0429 struct intel_plane_state *plane_state)
0430 {
0431 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
0432 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0433 const struct drm_framebuffer *fb = plane_state->hw.fb;
0434 enum pipe pipe = plane->pipe;
0435 int ret;
0436
0437 ret = intel_check_cursor(crtc_state, plane_state);
0438 if (ret)
0439 return ret;
0440
0441
0442 if (!fb)
0443 return 0;
0444
0445
0446 if (!i9xx_cursor_size_ok(plane_state)) {
0447 drm_dbg(&dev_priv->drm,
0448 "Cursor dimension %dx%d not supported\n",
0449 drm_rect_width(&plane_state->uapi.dst),
0450 drm_rect_height(&plane_state->uapi.dst));
0451 return -EINVAL;
0452 }
0453
0454 drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible &&
0455 plane_state->view.color_plane[0].mapping_stride != fb->pitches[0]);
0456
0457 if (fb->pitches[0] !=
0458 drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
0459 drm_dbg_kms(&dev_priv->drm,
0460 "Invalid cursor stride (%u) (cursor width %d)\n",
0461 fb->pitches[0],
0462 drm_rect_width(&plane_state->uapi.dst));
0463 return -EINVAL;
0464 }
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
0477 plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
0478 drm_dbg_kms(&dev_priv->drm,
0479 "CHV cursor C not allowed to straddle the left screen edge\n");
0480 return -EINVAL;
0481 }
0482
0483 plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state);
0484
0485 return 0;
0486 }
0487
0488
0489 static void i9xx_cursor_update_arm(struct intel_plane *plane,
0490 const struct intel_crtc_state *crtc_state,
0491 const struct intel_plane_state *plane_state)
0492 {
0493 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0494 enum pipe pipe = plane->pipe;
0495 u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
0496
0497 if (plane_state && plane_state->uapi.visible) {
0498 int width = drm_rect_width(&plane_state->uapi.dst);
0499 int height = drm_rect_height(&plane_state->uapi.dst);
0500
0501 cntl = plane_state->ctl |
0502 i9xx_cursor_ctl_crtc(crtc_state);
0503
0504 if (width != height)
0505 fbc_ctl = CUR_FBC_EN | CUR_FBC_HEIGHT(height - 1);
0506
0507 base = intel_cursor_base(plane_state);
0508 pos = intel_cursor_position(plane_state);
0509 }
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531 if (DISPLAY_VER(dev_priv) >= 9)
0532 skl_write_cursor_wm(plane, crtc_state);
0533
0534 if (plane_state)
0535 intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, 0);
0536 else
0537 intel_psr2_disable_plane_sel_fetch(plane, crtc_state);
0538
0539 if (plane->cursor.base != base ||
0540 plane->cursor.size != fbc_ctl ||
0541 plane->cursor.cntl != cntl) {
0542 if (HAS_CUR_FBC(dev_priv))
0543 intel_de_write_fw(dev_priv, CUR_FBC_CTL(pipe),
0544 fbc_ctl);
0545 intel_de_write_fw(dev_priv, CURCNTR(pipe), cntl);
0546 intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
0547 intel_de_write_fw(dev_priv, CURBASE(pipe), base);
0548
0549 plane->cursor.base = base;
0550 plane->cursor.size = fbc_ctl;
0551 plane->cursor.cntl = cntl;
0552 } else {
0553 intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
0554 intel_de_write_fw(dev_priv, CURBASE(pipe), base);
0555 }
0556 }
0557
0558 static void i9xx_cursor_disable_arm(struct intel_plane *plane,
0559 const struct intel_crtc_state *crtc_state)
0560 {
0561 i9xx_cursor_update_arm(plane, crtc_state, NULL);
0562 }
0563
0564 static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
0565 enum pipe *pipe)
0566 {
0567 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0568 enum intel_display_power_domain power_domain;
0569 intel_wakeref_t wakeref;
0570 bool ret;
0571 u32 val;
0572
0573
0574
0575
0576
0577
0578 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
0579 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
0580 if (!wakeref)
0581 return false;
0582
0583 val = intel_de_read(dev_priv, CURCNTR(plane->pipe));
0584
0585 ret = val & MCURSOR_MODE_MASK;
0586
0587 if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
0588 *pipe = plane->pipe;
0589 else
0590 *pipe = REG_FIELD_GET(MCURSOR_PIPE_SEL_MASK, val);
0591
0592 intel_display_power_put(dev_priv, power_domain, wakeref);
0593
0594 return ret;
0595 }
0596
0597 static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
0598 u32 format, u64 modifier)
0599 {
0600 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
0601 return false;
0602
0603 return format == DRM_FORMAT_ARGB8888;
0604 }
0605
0606 static int
0607 intel_legacy_cursor_update(struct drm_plane *_plane,
0608 struct drm_crtc *_crtc,
0609 struct drm_framebuffer *fb,
0610 int crtc_x, int crtc_y,
0611 unsigned int crtc_w, unsigned int crtc_h,
0612 u32 src_x, u32 src_y,
0613 u32 src_w, u32 src_h,
0614 struct drm_modeset_acquire_ctx *ctx)
0615 {
0616 struct intel_plane *plane = to_intel_plane(_plane);
0617 struct intel_crtc *crtc = to_intel_crtc(_crtc);
0618 struct intel_plane_state *old_plane_state =
0619 to_intel_plane_state(plane->base.state);
0620 struct intel_plane_state *new_plane_state;
0621 struct intel_crtc_state *crtc_state =
0622 to_intel_crtc_state(crtc->base.state);
0623 struct intel_crtc_state *new_crtc_state;
0624 int ret;
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635 if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
0636 crtc_state->update_pipe || crtc_state->bigjoiner_pipes)
0637 goto slow;
0638
0639
0640
0641
0642
0643
0644 if (old_plane_state->uapi.commit &&
0645 !try_wait_for_completion(&old_plane_state->uapi.commit->hw_done))
0646 goto slow;
0647
0648
0649
0650
0651
0652
0653 if (old_plane_state->uapi.crtc != &crtc->base ||
0654 old_plane_state->uapi.src_w != src_w ||
0655 old_plane_state->uapi.src_h != src_h ||
0656 old_plane_state->uapi.crtc_w != crtc_w ||
0657 old_plane_state->uapi.crtc_h != crtc_h ||
0658 !old_plane_state->uapi.fb != !fb)
0659 goto slow;
0660
0661 new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base));
0662 if (!new_plane_state)
0663 return -ENOMEM;
0664
0665 new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(&crtc->base));
0666 if (!new_crtc_state) {
0667 ret = -ENOMEM;
0668 goto out_free;
0669 }
0670
0671 drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb);
0672
0673 new_plane_state->uapi.src_x = src_x;
0674 new_plane_state->uapi.src_y = src_y;
0675 new_plane_state->uapi.src_w = src_w;
0676 new_plane_state->uapi.src_h = src_h;
0677 new_plane_state->uapi.crtc_x = crtc_x;
0678 new_plane_state->uapi.crtc_y = crtc_y;
0679 new_plane_state->uapi.crtc_w = crtc_w;
0680 new_plane_state->uapi.crtc_h = crtc_h;
0681
0682 intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state, crtc);
0683
0684 ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,
0685 old_plane_state, new_plane_state);
0686 if (ret)
0687 goto out_free;
0688
0689 ret = intel_plane_pin_fb(new_plane_state);
0690 if (ret)
0691 goto out_free;
0692
0693 intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb),
0694 ORIGIN_CURSOR_UPDATE);
0695 intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb),
0696 to_intel_frontbuffer(new_plane_state->hw.fb),
0697 plane->frontbuffer_bit);
0698
0699
0700 plane->base.state = &new_plane_state->uapi;
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712 crtc_state->active_planes = new_crtc_state->active_planes;
0713
0714
0715
0716
0717
0718
0719
0720 local_irq_disable();
0721
0722 if (new_plane_state->uapi.visible) {
0723 intel_plane_update_noarm(plane, crtc_state, new_plane_state);
0724 intel_plane_update_arm(plane, crtc_state, new_plane_state);
0725 } else {
0726 intel_plane_disable_arm(plane, crtc_state);
0727 }
0728
0729 local_irq_enable();
0730
0731 intel_plane_unpin_fb(old_plane_state);
0732
0733 out_free:
0734 if (new_crtc_state)
0735 intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi);
0736 if (ret)
0737 intel_plane_destroy_state(&plane->base, &new_plane_state->uapi);
0738 else
0739 intel_plane_destroy_state(&plane->base, &old_plane_state->uapi);
0740 return ret;
0741
0742 slow:
0743 return drm_atomic_helper_update_plane(&plane->base, &crtc->base, fb,
0744 crtc_x, crtc_y, crtc_w, crtc_h,
0745 src_x, src_y, src_w, src_h, ctx);
0746 }
0747
0748 static const struct drm_plane_funcs intel_cursor_plane_funcs = {
0749 .update_plane = intel_legacy_cursor_update,
0750 .disable_plane = drm_atomic_helper_disable_plane,
0751 .destroy = intel_plane_destroy,
0752 .atomic_duplicate_state = intel_plane_duplicate_state,
0753 .atomic_destroy_state = intel_plane_destroy_state,
0754 .format_mod_supported = intel_cursor_format_mod_supported,
0755 };
0756
0757 struct intel_plane *
0758 intel_cursor_plane_create(struct drm_i915_private *dev_priv,
0759 enum pipe pipe)
0760 {
0761 struct intel_plane *cursor;
0762 int ret, zpos;
0763 u64 *modifiers;
0764
0765 cursor = intel_plane_alloc();
0766 if (IS_ERR(cursor))
0767 return cursor;
0768
0769 cursor->pipe = pipe;
0770 cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
0771 cursor->id = PLANE_CURSOR;
0772 cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
0773
0774 if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
0775 cursor->max_stride = i845_cursor_max_stride;
0776 cursor->update_arm = i845_cursor_update_arm;
0777 cursor->disable_arm = i845_cursor_disable_arm;
0778 cursor->get_hw_state = i845_cursor_get_hw_state;
0779 cursor->check_plane = i845_check_cursor;
0780 } else {
0781 cursor->max_stride = i9xx_cursor_max_stride;
0782 cursor->update_arm = i9xx_cursor_update_arm;
0783 cursor->disable_arm = i9xx_cursor_disable_arm;
0784 cursor->get_hw_state = i9xx_cursor_get_hw_state;
0785 cursor->check_plane = i9xx_check_cursor;
0786 }
0787
0788 cursor->cursor.base = ~0;
0789 cursor->cursor.cntl = ~0;
0790
0791 if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
0792 cursor->cursor.size = ~0;
0793
0794 modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_NONE);
0795
0796 ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
0797 0, &intel_cursor_plane_funcs,
0798 intel_cursor_formats,
0799 ARRAY_SIZE(intel_cursor_formats),
0800 modifiers,
0801 DRM_PLANE_TYPE_CURSOR,
0802 "cursor %c", pipe_name(pipe));
0803
0804 kfree(modifiers);
0805
0806 if (ret)
0807 goto fail;
0808
0809 if (DISPLAY_VER(dev_priv) >= 4)
0810 drm_plane_create_rotation_property(&cursor->base,
0811 DRM_MODE_ROTATE_0,
0812 DRM_MODE_ROTATE_0 |
0813 DRM_MODE_ROTATE_180);
0814
0815 zpos = RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
0816 drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
0817
0818 if (DISPLAY_VER(dev_priv) >= 12)
0819 drm_plane_enable_fb_damage_clips(&cursor->base);
0820
0821 intel_plane_helper_add(cursor);
0822
0823 return cursor;
0824
0825 fail:
0826 intel_plane_free(cursor);
0827
0828 return ERR_PTR(ret);
0829 }