1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2020 Intel Corporation
4 */
5#include <linux/kernel.h>
6
7#include <drm/drm_atomic_helper.h>
8#include <drm/drm_atomic_uapi.h>
9#include <drm/drm_blend.h>
10#include <drm/drm_damage_helper.h>
11#include <drm/drm_fourcc.h>
12#include <drm/drm_print.h>
13#include <drm/drm_vblank.h>
14
15#include "i915_utils.h"
16#include "intel_atomic.h"
17#include "intel_cursor.h"
18#include "intel_cursor_regs.h"
19#include "intel_de.h"
20#include "intel_display.h"
21#include "intel_display_types.h"
22#include "intel_fb.h"
23#include "intel_fb_pin.h"
24#include "intel_frontbuffer.h"
25#include "intel_plane.h"
26#include "intel_psr.h"
27#include "intel_psr_regs.h"
28#include "intel_vblank.h"
29#include "skl_watermark.h"
30
31/* Cursor formats */
32static const u32 intel_cursor_formats[] = {
33 DRM_FORMAT_ARGB8888,
34};
35
36static u32 intel_cursor_surf_offset(const struct intel_plane_state *plane_state)
37{
38 return plane_state->view.color_plane[0].offset;
39}
40
41static u32 intel_cursor_position(const struct intel_crtc_state *crtc_state,
42 const struct intel_plane_state *plane_state,
43 bool early_tpt)
44{
45 int x = plane_state->uapi.dst.x1;
46 int y = plane_state->uapi.dst.y1;
47 u32 pos = 0;
48
49 /*
50 * Formula from Bspec:
51 * MAX(-1 * <Cursor vertical size from CUR_CTL base on cursor mode
52 * select setting> + 1, CUR_POS Y Position - Update region Y position
53 */
54 if (early_tpt)
55 y = max(-1 * drm_rect_height(&plane_state->uapi.dst) + 1,
56 y - crtc_state->psr2_su_area.y1);
57
58 if (x < 0) {
59 pos |= CURSOR_POS_X_SIGN;
60 x = -x;
61 }
62 pos |= CURSOR_POS_X(x);
63
64 if (y < 0) {
65 pos |= CURSOR_POS_Y_SIGN;
66 y = -y;
67 }
68 pos |= CURSOR_POS_Y(y);
69
70 return pos;
71}
72
73static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
74{
75 const struct drm_mode_config *config =
76 &plane_state->uapi.plane->dev->mode_config;
77 int width = drm_rect_width(r: &plane_state->uapi.dst);
78 int height = drm_rect_height(r: &plane_state->uapi.dst);
79
80 return width > 0 && width <= config->cursor_width &&
81 height > 0 && height <= config->cursor_height;
82}
83
84static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
85{
86 struct intel_display *display = to_intel_display(plane_state);
87 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
88 unsigned int rotation = plane_state->hw.rotation;
89 int src_x, src_y;
90 u32 offset;
91 int ret;
92
93 ret = intel_plane_compute_gtt(plane_state);
94 if (ret)
95 return ret;
96
97 if (!plane_state->uapi.visible)
98 return 0;
99
100 src_x = plane_state->uapi.src.x1 >> 16;
101 src_y = plane_state->uapi.src.y1 >> 16;
102
103 intel_add_fb_offsets(x: &src_x, y: &src_y, plane_state, color_plane: 0);
104 offset = intel_plane_compute_aligned_offset(x: &src_x, y: &src_y,
105 plane_state, color_plane: 0);
106
107 if (src_x != 0 || src_y != 0) {
108 drm_dbg_kms(display->drm,
109 "[PLANE:%d:%s] arbitrary cursor panning not supported\n",
110 plane->base.base.id, plane->base.name);
111 return -EINVAL;
112 }
113
114 /*
115 * Put the final coordinates back so that the src
116 * coordinate checks will see the right values.
117 */
118 drm_rect_translate_to(r: &plane_state->uapi.src,
119 x: src_x << 16, y: src_y << 16);
120
121 /* ILK+ do this automagically in hardware */
122 if (HAS_GMCH(display) && rotation & DRM_MODE_ROTATE_180) {
123 const struct drm_framebuffer *fb = plane_state->hw.fb;
124 int src_w = drm_rect_width(r: &plane_state->uapi.src) >> 16;
125 int src_h = drm_rect_height(r: &plane_state->uapi.src) >> 16;
126
127 offset += (src_h * src_w - 1) * fb->format->cpp[0];
128 }
129
130 plane_state->view.color_plane[0].offset = offset;
131 plane_state->view.color_plane[0].x = src_x;
132 plane_state->view.color_plane[0].y = src_y;
133
134 return 0;
135}
136
137static int intel_check_cursor(struct intel_crtc_state *crtc_state,
138 struct intel_plane_state *plane_state)
139{
140 struct intel_display *display = to_intel_display(plane_state);
141 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
142 const struct drm_framebuffer *fb = plane_state->hw.fb;
143 const struct drm_rect src = plane_state->uapi.src;
144 const struct drm_rect dst = plane_state->uapi.dst;
145 int ret;
146
147 if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
148 drm_dbg_kms(display->drm, "[PLANE:%d:%s] cursor cannot be tiled\n",
149 plane->base.base.id, plane->base.name);
150 return -EINVAL;
151 }
152
153 ret = intel_plane_check_clipping(plane_state, crtc_state,
154 DRM_PLANE_NO_SCALING,
155 DRM_PLANE_NO_SCALING,
156 can_position: true);
157 if (ret)
158 return ret;
159
160 /* Use the unclipped src/dst rectangles, which we program to hw */
161 plane_state->uapi.src = src;
162 plane_state->uapi.dst = dst;
163
164 /* final plane coordinates will be relative to the plane's pipe */
165 drm_rect_translate(r: &plane_state->uapi.dst,
166 dx: -crtc_state->pipe_src.x1,
167 dy: -crtc_state->pipe_src.y1);
168
169 ret = intel_cursor_check_surface(plane_state);
170 if (ret)
171 return ret;
172
173 if (!plane_state->uapi.visible)
174 return 0;
175
176 ret = intel_plane_check_src_coordinates(plane_state);
177 if (ret)
178 return ret;
179
180 return 0;
181}
182
183static unsigned int
184i845_cursor_max_stride(struct intel_plane *plane,
185 u32 pixel_format, u64 modifier,
186 unsigned int rotation)
187{
188 return 2048;
189}
190
191static unsigned int i845_cursor_min_alignment(struct intel_plane *plane,
192 const struct drm_framebuffer *fb,
193 int color_plane)
194{
195 return 32;
196}
197
198static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
199{
200 u32 cntl = 0;
201
202 if (crtc_state->gamma_enable)
203 cntl |= CURSOR_PIPE_GAMMA_ENABLE;
204
205 return cntl;
206}
207
208static u32 i845_cursor_ctl(const struct intel_plane_state *plane_state)
209{
210 return CURSOR_ENABLE |
211 CURSOR_FORMAT_ARGB |
212 CURSOR_STRIDE(plane_state->view.color_plane[0].mapping_stride);
213}
214
215static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
216{
217 int width = drm_rect_width(r: &plane_state->uapi.dst);
218
219 /*
220 * 845g/865g are only limited by the width of their cursors,
221 * the height is arbitrary up to the precision of the register.
222 */
223 return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64);
224}
225
226static int i845_check_cursor(struct intel_crtc_state *crtc_state,
227 struct intel_plane_state *plane_state)
228{
229 struct intel_display *display = to_intel_display(plane_state);
230 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
231 const struct drm_framebuffer *fb = plane_state->hw.fb;
232 int ret;
233
234 ret = intel_check_cursor(crtc_state, plane_state);
235 if (ret)
236 return ret;
237
238 /* if we want to turn off the cursor ignore width and height */
239 if (!fb)
240 return 0;
241
242 /* Check for which cursor types we support */
243 if (!i845_cursor_size_ok(plane_state)) {
244 drm_dbg_kms(display->drm,
245 "[PLANE:%d:%s] cursor dimension %dx%d not supported\n",
246 plane->base.base.id, plane->base.name,
247 drm_rect_width(&plane_state->uapi.dst),
248 drm_rect_height(&plane_state->uapi.dst));
249 return -EINVAL;
250 }
251
252 drm_WARN_ON(display->drm, plane_state->uapi.visible &&
253 plane_state->view.color_plane[0].mapping_stride != fb->pitches[0]);
254
255 switch (fb->pitches[0]) {
256 case 256:
257 case 512:
258 case 1024:
259 case 2048:
260 break;
261 default:
262 drm_dbg_kms(display->drm, "[PLANE:%d:%s] invalid cursor stride (%u)\n",
263 plane->base.base.id, plane->base.name,
264 fb->pitches[0]);
265 return -EINVAL;
266 }
267
268 plane_state->ctl = i845_cursor_ctl(plane_state);
269
270 return 0;
271}
272
273/* TODO: split into noarm+arm pair */
274static void i845_cursor_update_arm(struct intel_dsb *dsb,
275 struct intel_plane *plane,
276 const struct intel_crtc_state *crtc_state,
277 const struct intel_plane_state *plane_state)
278{
279 struct intel_display *display = to_intel_display(plane);
280 u32 cntl = 0, base = 0, pos = 0, size = 0;
281
282 if (plane_state && plane_state->uapi.visible) {
283 unsigned int width = drm_rect_width(r: &plane_state->uapi.dst);
284 unsigned int height = drm_rect_height(r: &plane_state->uapi.dst);
285
286 cntl = plane_state->ctl |
287 i845_cursor_ctl_crtc(crtc_state);
288
289 size = CURSOR_HEIGHT(height) | CURSOR_WIDTH(width);
290
291 base = plane_state->surf;
292 pos = intel_cursor_position(crtc_state, plane_state, early_tpt: false);
293 }
294
295 /* On these chipsets we can only modify the base/size/stride
296 * whilst the cursor is disabled.
297 */
298 if (plane->cursor.base != base ||
299 plane->cursor.size != size ||
300 plane->cursor.cntl != cntl) {
301 intel_de_write_fw(display, CURCNTR(display, PIPE_A), val: 0);
302 intel_de_write_fw(display, CURBASE(display, PIPE_A), val: base);
303 intel_de_write_fw(display, CURSIZE(display, PIPE_A), val: size);
304 intel_de_write_fw(display, CURPOS(display, PIPE_A), val: pos);
305 intel_de_write_fw(display, CURCNTR(display, PIPE_A), val: cntl);
306
307 plane->cursor.base = base;
308 plane->cursor.size = size;
309 plane->cursor.cntl = cntl;
310 } else {
311 intel_de_write_fw(display, CURPOS(display, PIPE_A), val: pos);
312 }
313}
314
315static void i845_cursor_disable_arm(struct intel_dsb *dsb,
316 struct intel_plane *plane,
317 const struct intel_crtc_state *crtc_state)
318{
319 i845_cursor_update_arm(dsb, plane, crtc_state, NULL);
320}
321
322static bool i845_cursor_get_hw_state(struct intel_plane *plane,
323 enum pipe *pipe)
324{
325 struct intel_display *display = to_intel_display(plane);
326 enum intel_display_power_domain power_domain;
327 intel_wakeref_t wakeref;
328 bool ret;
329
330 power_domain = POWER_DOMAIN_PIPE(PIPE_A);
331 wakeref = intel_display_power_get_if_enabled(display, domain: power_domain);
332 if (!wakeref)
333 return false;
334
335 ret = intel_de_read(display, CURCNTR(display, PIPE_A)) & CURSOR_ENABLE;
336
337 *pipe = PIPE_A;
338
339 intel_display_power_put(display, domain: power_domain, wakeref);
340
341 return ret;
342}
343
344static unsigned int
345i9xx_cursor_max_stride(struct intel_plane *plane,
346 u32 pixel_format, u64 modifier,
347 unsigned int rotation)
348{
349 return plane->base.dev->mode_config.cursor_width * 4;
350}
351
352static unsigned int i830_cursor_min_alignment(struct intel_plane *plane,
353 const struct drm_framebuffer *fb,
354 int color_plane)
355{
356 /* "AlmadorM Errata – Requires 32-bpp cursor data to be 16KB aligned." */
357 return 16 * 1024; /* physical */
358}
359
360static unsigned int i85x_cursor_min_alignment(struct intel_plane *plane,
361 const struct drm_framebuffer *fb,
362 int color_plane)
363{
364 return 256; /* physical */
365}
366
367static unsigned int i9xx_cursor_min_alignment(struct intel_plane *plane,
368 const struct drm_framebuffer *fb,
369 int color_plane)
370{
371 struct intel_display *display = to_intel_display(plane);
372
373 if (intel_scanout_needs_vtd_wa(display))
374 return 64 * 1024;
375
376 return 4 * 1024; /* physical for i915/i945 */
377}
378
379static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
380{
381 struct intel_display *display = to_intel_display(crtc_state);
382 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
383 u32 cntl = 0;
384
385 if (DISPLAY_VER(display) >= 11)
386 return cntl;
387
388 if (crtc_state->gamma_enable)
389 cntl = MCURSOR_PIPE_GAMMA_ENABLE;
390
391 if (crtc_state->csc_enable)
392 cntl |= MCURSOR_PIPE_CSC_ENABLE;
393
394 if (DISPLAY_VER(display) < 5 && !display->platform.g4x)
395 cntl |= MCURSOR_PIPE_SEL(crtc->pipe);
396
397 return cntl;
398}
399
400static u32 i9xx_cursor_ctl(const struct intel_plane_state *plane_state)
401{
402 struct intel_display *display = to_intel_display(plane_state);
403 u32 cntl = 0;
404
405 if (display->platform.sandybridge || display->platform.ivybridge)
406 cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
407
408 switch (drm_rect_width(r: &plane_state->uapi.dst)) {
409 case 64:
410 cntl |= MCURSOR_MODE_64_ARGB_AX;
411 break;
412 case 128:
413 cntl |= MCURSOR_MODE_128_ARGB_AX;
414 break;
415 case 256:
416 cntl |= MCURSOR_MODE_256_ARGB_AX;
417 break;
418 default:
419 MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));
420 return 0;
421 }
422
423 if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
424 cntl |= MCURSOR_ROTATE_180;
425
426 /* Wa_22012358565:adl-p */
427 if (DISPLAY_VER(display) == 13)
428 cntl |= MCURSOR_ARB_SLOTS(1);
429
430 return cntl;
431}
432
433static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
434{
435 struct intel_display *display = to_intel_display(plane_state);
436 int width = drm_rect_width(r: &plane_state->uapi.dst);
437 int height = drm_rect_height(r: &plane_state->uapi.dst);
438
439 if (!intel_cursor_size_ok(plane_state))
440 return false;
441
442 /* Cursor width is limited to a few power-of-two sizes */
443 switch (width) {
444 case 256:
445 case 128:
446 case 64:
447 break;
448 default:
449 return false;
450 }
451
452 /*
453 * IVB+ have CUR_FBC_CTL which allows an arbitrary cursor
454 * height from 8 lines up to the cursor width, when the
455 * cursor is not rotated. Everything else requires square
456 * cursors.
457 */
458 if (HAS_CUR_FBC(display) &&
459 plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
460 if (height < 8 || height > width)
461 return false;
462 } else {
463 if (height != width)
464 return false;
465 }
466
467 return true;
468}
469
470static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
471 struct intel_plane_state *plane_state)
472{
473 struct intel_display *display = to_intel_display(plane_state);
474 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
475 const struct drm_framebuffer *fb = plane_state->hw.fb;
476 enum pipe pipe = plane->pipe;
477 int ret;
478
479 ret = intel_check_cursor(crtc_state, plane_state);
480 if (ret)
481 return ret;
482
483 /* if we want to turn off the cursor ignore width and height */
484 if (!fb)
485 return 0;
486
487 /* Check for which cursor types we support */
488 if (!i9xx_cursor_size_ok(plane_state)) {
489 drm_dbg_kms(display->drm,
490 "[PLANE:%d:%s] cursor dimension %dx%d not supported\n",
491 plane->base.base.id, plane->base.name,
492 drm_rect_width(&plane_state->uapi.dst),
493 drm_rect_height(&plane_state->uapi.dst));
494 return -EINVAL;
495 }
496
497 drm_WARN_ON(display->drm, plane_state->uapi.visible &&
498 plane_state->view.color_plane[0].mapping_stride != fb->pitches[0]);
499
500 if (fb->pitches[0] !=
501 drm_rect_width(r: &plane_state->uapi.dst) * fb->format->cpp[0]) {
502 drm_dbg_kms(display->drm,
503 "[PLANE:%d:%s] invalid cursor stride (%u) (cursor width %d)\n",
504 plane->base.base.id, plane->base.name,
505 fb->pitches[0], drm_rect_width(&plane_state->uapi.dst));
506 return -EINVAL;
507 }
508
509 /*
510 * There's something wrong with the cursor on CHV pipe C.
511 * If it straddles the left edge of the screen then
512 * moving it away from the edge or disabling it often
513 * results in a pipe underrun, and often that can lead to
514 * dead pipe (constant underrun reported, and it scans
515 * out just a solid color). To recover from that, the
516 * display power well must be turned off and on again.
517 * Refuse the put the cursor into that compromised position.
518 */
519 if (display->platform.cherryview && pipe == PIPE_C &&
520 plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
521 drm_dbg_kms(display->drm,
522 "[PLANE:%d:%s] cursor not allowed to straddle the left screen edge\n",
523 plane->base.base.id, plane->base.name);
524 return -EINVAL;
525 }
526
527 plane_state->ctl = i9xx_cursor_ctl(plane_state);
528
529 return 0;
530}
531
532static void i9xx_cursor_disable_sel_fetch_arm(struct intel_dsb *dsb,
533 struct intel_plane *plane,
534 const struct intel_crtc_state *crtc_state)
535{
536 struct intel_display *display = to_intel_display(plane);
537 enum pipe pipe = plane->pipe;
538
539 if (!crtc_state->enable_psr2_sel_fetch)
540 return;
541
542 intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), val: 0);
543}
544
545static void wa_16021440873(struct intel_dsb *dsb,
546 struct intel_plane *plane,
547 const struct intel_crtc_state *crtc_state,
548 const struct intel_plane_state *plane_state)
549{
550 struct intel_display *display = to_intel_display(plane);
551 u32 ctl = plane_state->ctl;
552 int et_y_position = drm_rect_height(r: &crtc_state->pipe_src) + 1;
553 enum pipe pipe = plane->pipe;
554
555 ctl &= ~MCURSOR_MODE_MASK;
556 ctl |= MCURSOR_MODE_64_2B;
557
558 intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), val: ctl);
559
560 intel_de_write_dsb(display, dsb, CURPOS_ERLY_TPT(display, pipe),
561 CURSOR_POS_Y(et_y_position));
562}
563
564static void i9xx_cursor_update_sel_fetch_arm(struct intel_dsb *dsb,
565 struct intel_plane *plane,
566 const struct intel_crtc_state *crtc_state,
567 const struct intel_plane_state *plane_state)
568{
569 struct intel_display *display = to_intel_display(plane);
570 enum pipe pipe = plane->pipe;
571
572 if (!crtc_state->enable_psr2_sel_fetch)
573 return;
574
575 if (drm_rect_height(r: &plane_state->psr2_sel_fetch_area) > 0) {
576 if (crtc_state->enable_psr2_su_region_et) {
577 u32 val = intel_cursor_position(crtc_state, plane_state,
578 early_tpt: true);
579
580 intel_de_write_dsb(display, dsb, CURPOS_ERLY_TPT(display, pipe), val);
581 }
582
583 intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), val: plane_state->ctl);
584 } else {
585 /* Wa_16021440873 */
586 if (crtc_state->enable_psr2_su_region_et)
587 wa_16021440873(dsb, plane, crtc_state, plane_state);
588 else
589 i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state);
590 }
591}
592
593static u32 skl_cursor_ddb_reg_val(const struct skl_ddb_entry *entry)
594{
595 if (!entry->end)
596 return 0;
597
598 return CUR_BUF_END(entry->end - 1) |
599 CUR_BUF_START(entry->start);
600}
601
602static u32 skl_cursor_wm_reg_val(const struct skl_wm_level *level)
603{
604 u32 val = 0;
605
606 if (level->enable)
607 val |= CUR_WM_EN;
608 if (level->ignore_lines)
609 val |= CUR_WM_IGNORE_LINES;
610 val |= REG_FIELD_PREP(CUR_WM_BLOCKS_MASK, level->blocks);
611 val |= REG_FIELD_PREP(CUR_WM_LINES_MASK, level->lines);
612
613 return val;
614}
615
616static void skl_write_cursor_wm(struct intel_dsb *dsb,
617 struct intel_plane *plane,
618 const struct intel_crtc_state *crtc_state)
619{
620 struct intel_display *display = to_intel_display(plane->base.dev);
621 enum plane_id plane_id = plane->id;
622 enum pipe pipe = plane->pipe;
623 const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal;
624 const struct skl_ddb_entry *ddb =
625 &crtc_state->wm.skl.plane_ddb[plane_id];
626 int level;
627
628 for (level = 0; level < display->wm.num_levels; level++)
629 intel_de_write_dsb(display, dsb, CUR_WM(pipe, level),
630 val: skl_cursor_wm_reg_val(level: skl_plane_wm_level(pipe_wm, plane_id, level)));
631
632 intel_de_write_dsb(display, dsb, CUR_WM_TRANS(pipe),
633 val: skl_cursor_wm_reg_val(level: skl_plane_trans_wm(pipe_wm, plane_id)));
634
635 if (HAS_HW_SAGV_WM(display)) {
636 const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];
637
638 intel_de_write_dsb(display, dsb, CUR_WM_SAGV(pipe),
639 val: skl_cursor_wm_reg_val(level: &wm->sagv.wm0));
640 intel_de_write_dsb(display, dsb, CUR_WM_SAGV_TRANS(pipe),
641 val: skl_cursor_wm_reg_val(level: &wm->sagv.trans_wm));
642 }
643
644 intel_de_write_dsb(display, dsb, CUR_BUF_CFG(pipe),
645 val: skl_cursor_ddb_reg_val(entry: ddb));
646}
647
648/* TODO: split into noarm+arm pair */
649static void i9xx_cursor_update_arm(struct intel_dsb *dsb,
650 struct intel_plane *plane,
651 const struct intel_crtc_state *crtc_state,
652 const struct intel_plane_state *plane_state)
653{
654 struct intel_display *display = to_intel_display(plane);
655 enum pipe pipe = plane->pipe;
656 u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
657
658 if (plane_state && plane_state->uapi.visible) {
659 int width = drm_rect_width(r: &plane_state->uapi.dst);
660 int height = drm_rect_height(r: &plane_state->uapi.dst);
661
662 cntl = plane_state->ctl |
663 i9xx_cursor_ctl_crtc(crtc_state);
664
665 if (width != height)
666 fbc_ctl = CUR_FBC_EN | CUR_FBC_HEIGHT(height - 1);
667
668 base = plane_state->surf;
669 pos = intel_cursor_position(crtc_state, plane_state, early_tpt: false);
670 }
671
672 /*
673 * On some platforms writing CURCNTR first will also
674 * cause CURPOS to be armed by the CURBASE write.
675 * Without the CURCNTR write the CURPOS write would
676 * arm itself. Thus we always update CURCNTR before
677 * CURPOS.
678 *
679 * On other platforms CURPOS always requires the
680 * CURBASE write to arm the update. Additionally
681 * a write to any of the cursor register will cancel
682 * an already armed cursor update. Thus leaving out
683 * the CURBASE write after CURPOS could lead to a
684 * cursor that doesn't appear to move, or even change
685 * shape. Thus we always write CURBASE.
686 *
687 * The other registers are armed by the CURBASE write
688 * except when the plane is getting enabled at which time
689 * the CURCNTR write arms the update.
690 */
691
692 if (DISPLAY_VER(display) >= 9)
693 skl_write_cursor_wm(dsb, plane, crtc_state);
694
695 if (plane_state)
696 i9xx_cursor_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state);
697 else
698 i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state);
699
700 if (plane->cursor.base != base ||
701 plane->cursor.size != fbc_ctl ||
702 plane->cursor.cntl != cntl) {
703 if (HAS_CUR_FBC(display))
704 intel_de_write_dsb(display, dsb, CUR_FBC_CTL(display, pipe), val: fbc_ctl);
705 intel_de_write_dsb(display, dsb, CURCNTR(display, pipe), val: cntl);
706 intel_de_write_dsb(display, dsb, CURPOS(display, pipe), val: pos);
707 intel_de_write_dsb(display, dsb, CURBASE(display, pipe), val: base);
708
709 plane->cursor.base = base;
710 plane->cursor.size = fbc_ctl;
711 plane->cursor.cntl = cntl;
712 } else {
713 intel_de_write_dsb(display, dsb, CURPOS(display, pipe), val: pos);
714 intel_de_write_dsb(display, dsb, CURBASE(display, pipe), val: base);
715 }
716}
717
718static void i9xx_cursor_disable_arm(struct intel_dsb *dsb,
719 struct intel_plane *plane,
720 const struct intel_crtc_state *crtc_state)
721{
722 i9xx_cursor_update_arm(dsb, plane, crtc_state, NULL);
723}
724
725static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
726 enum pipe *pipe)
727{
728 struct intel_display *display = to_intel_display(plane);
729 enum intel_display_power_domain power_domain;
730 intel_wakeref_t wakeref;
731 bool ret;
732 u32 val;
733
734 /*
735 * Not 100% correct for planes that can move between pipes,
736 * but that's only the case for gen2-3 which don't have any
737 * display power wells.
738 */
739 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
740 wakeref = intel_display_power_get_if_enabled(display, domain: power_domain);
741 if (!wakeref)
742 return false;
743
744 val = intel_de_read(display, CURCNTR(display, plane->pipe));
745
746 ret = val & MCURSOR_MODE_MASK;
747
748 if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
749 *pipe = plane->pipe;
750 else
751 *pipe = REG_FIELD_GET(MCURSOR_PIPE_SEL_MASK, val);
752
753 intel_display_power_put(display, domain: power_domain, wakeref);
754
755 return ret;
756}
757
758static void g4x_cursor_capture_error(struct intel_crtc *crtc,
759 struct intel_plane *plane,
760 struct intel_plane_error *error)
761{
762 struct intel_display *display = to_intel_display(plane);
763
764 error->ctl = intel_de_read(display, CURCNTR(display, crtc->pipe));
765 error->surf = intel_de_read(display, CURBASE(display, crtc->pipe));
766 error->surflive = intel_de_read(display, CURSURFLIVE(display, crtc->pipe));
767}
768
769static void i9xx_cursor_capture_error(struct intel_crtc *crtc,
770 struct intel_plane *plane,
771 struct intel_plane_error *error)
772{
773 struct intel_display *display = to_intel_display(plane);
774
775 error->ctl = intel_de_read(display, CURCNTR(display, crtc->pipe));
776 error->surf = intel_de_read(display, CURBASE(display, crtc->pipe));
777}
778
779static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
780 u32 format, u64 modifier)
781{
782 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
783 return false;
784
785 return format == DRM_FORMAT_ARGB8888;
786}
787
788void intel_cursor_unpin_work(struct kthread_work *base)
789{
790 struct drm_vblank_work *work = to_drm_vblank_work(base);
791 struct intel_plane_state *plane_state =
792 container_of(work, typeof(*plane_state), unpin_work);
793 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
794
795 intel_plane_unpin_fb(old_plane_state: plane_state);
796 intel_plane_destroy_state(plane: &plane->base, state: &plane_state->uapi);
797}
798
799static int
800intel_legacy_cursor_update(struct drm_plane *_plane,
801 struct drm_crtc *_crtc,
802 struct drm_framebuffer *fb,
803 int crtc_x, int crtc_y,
804 unsigned int crtc_w, unsigned int crtc_h,
805 u32 src_x, u32 src_y,
806 u32 src_w, u32 src_h,
807 struct drm_modeset_acquire_ctx *ctx)
808{
809 struct intel_plane *plane = to_intel_plane(_plane);
810 struct intel_crtc *crtc = to_intel_crtc(_crtc);
811 struct intel_display *display = to_intel_display(plane);
812 struct intel_plane_state *old_plane_state =
813 to_intel_plane_state(plane->base.state);
814 struct intel_plane_state *new_plane_state;
815 struct intel_crtc_state *crtc_state =
816 to_intel_crtc_state(crtc->base.state);
817 struct intel_crtc_state *new_crtc_state;
818 struct intel_vblank_evade_ctx evade;
819 int ret;
820
821 /*
822 * When crtc is inactive or there is a modeset pending,
823 * wait for it to complete in the slowpath.
824 * PSR2 selective fetch also requires the slow path as
825 * PSR2 plane and transcoder registers can only be updated during
826 * vblank.
827 *
828 * FIXME joiner fastpath would be good
829 */
830 if (!crtc_state->hw.active ||
831 intel_crtc_needs_modeset(crtc_state) ||
832 intel_crtc_needs_fastset(crtc_state) ||
833 crtc_state->joiner_pipes)
834 goto slow;
835
836 /*
837 * Don't do an async update if there is an outstanding commit modifying
838 * the plane. This prevents our async update's changes from getting
839 * overridden by a previous synchronous update's state.
840 */
841 if (old_plane_state->uapi.commit &&
842 !try_wait_for_completion(x: &old_plane_state->uapi.commit->hw_done))
843 goto slow;
844
845 /*
846 * If any parameters change that may affect watermarks,
847 * take the slowpath. Only changing fb or position should be
848 * in the fastpath.
849 */
850 if (old_plane_state->uapi.crtc != &crtc->base ||
851 old_plane_state->uapi.src_w != src_w ||
852 old_plane_state->uapi.src_h != src_h ||
853 old_plane_state->uapi.crtc_w != crtc_w ||
854 old_plane_state->uapi.crtc_h != crtc_h ||
855 !old_plane_state->uapi.fb != !fb)
856 goto slow;
857
858 new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base));
859 if (!new_plane_state)
860 return -ENOMEM;
861
862 new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(&crtc->base));
863 if (!new_crtc_state) {
864 ret = -ENOMEM;
865 goto out_free;
866 }
867
868 drm_atomic_set_fb_for_plane(plane_state: &new_plane_state->uapi, fb);
869
870 new_plane_state->uapi.src_x = src_x;
871 new_plane_state->uapi.src_y = src_y;
872 new_plane_state->uapi.src_w = src_w;
873 new_plane_state->uapi.src_h = src_h;
874 new_plane_state->uapi.crtc_x = crtc_x;
875 new_plane_state->uapi.crtc_y = crtc_y;
876 new_plane_state->uapi.crtc_w = crtc_w;
877 new_plane_state->uapi.crtc_h = crtc_h;
878
879 intel_plane_copy_uapi_to_hw_state(plane_state: new_plane_state, from_plane_state: new_plane_state, crtc);
880
881 ret = intel_plane_atomic_check_with_state(old_crtc_state: crtc_state, crtc_state: new_crtc_state,
882 old_plane_state, intel_state: new_plane_state);
883 if (ret)
884 goto out_free;
885
886 ret = intel_plane_pin_fb(new_plane_state, old_plane_state);
887 if (ret)
888 goto out_free;
889
890 intel_frontbuffer_flush(front: to_intel_frontbuffer(fb: new_plane_state->hw.fb),
891 origin: ORIGIN_CURSOR_UPDATE);
892 intel_frontbuffer_track(old: to_intel_frontbuffer(fb: old_plane_state->hw.fb),
893 new: to_intel_frontbuffer(fb: new_plane_state->hw.fb),
894 frontbuffer_bits: plane->frontbuffer_bit);
895
896 /* Swap plane state */
897 plane->base.state = &new_plane_state->uapi;
898
899 /*
900 * We cannot swap crtc_state as it may be in use by an atomic commit or
901 * page flip that's running simultaneously. If we swap crtc_state and
902 * destroy the old state, we will cause a use-after-free there.
903 *
904 * Only update active_planes, which is needed for our internal
905 * bookkeeping. Either value will do the right thing when updating
906 * planes atomically. If the cursor was part of the atomic update then
907 * we would have taken the slowpath.
908 */
909 crtc_state->active_planes = new_crtc_state->active_planes;
910
911 intel_vblank_evade_init(old_crtc_state: crtc_state, new_crtc_state: crtc_state, evade: &evade);
912
913 intel_psr_lock(crtc_state);
914
915 if (!drm_WARN_ON(display->drm, drm_crtc_vblank_get(&crtc->base))) {
916 /*
917 * TODO: maybe check if we're still in PSR
918 * and skip the vblank evasion entirely?
919 */
920 intel_psr_wait_for_idle_locked(new_crtc_state: crtc_state);
921
922 local_irq_disable();
923
924 intel_vblank_evade(evade: &evade);
925
926 drm_crtc_vblank_put(crtc: &crtc->base);
927 } else {
928 local_irq_disable();
929 }
930
931 if (new_plane_state->uapi.visible) {
932 intel_plane_update_noarm(NULL, plane, crtc_state, plane_state: new_plane_state);
933 intel_plane_update_arm(NULL, plane, crtc_state, plane_state: new_plane_state);
934 } else {
935 intel_plane_disable_arm(NULL, plane, crtc_state);
936 }
937
938 local_irq_enable();
939
940 intel_psr_unlock(crtc_state);
941
942 if (old_plane_state->ggtt_vma != new_plane_state->ggtt_vma) {
943 drm_vblank_work_init(work: &old_plane_state->unpin_work, crtc: &crtc->base,
944 func: intel_cursor_unpin_work);
945
946 drm_vblank_work_schedule(work: &old_plane_state->unpin_work,
947 count: drm_crtc_accurate_vblank_count(crtc: &crtc->base) + 1,
948 nextonmiss: false);
949
950 old_plane_state = NULL;
951 } else {
952 intel_plane_unpin_fb(old_plane_state);
953 }
954
955out_free:
956 if (new_crtc_state)
957 intel_crtc_destroy_state(crtc: &crtc->base, state: &new_crtc_state->uapi);
958 if (ret)
959 intel_plane_destroy_state(plane: &plane->base, state: &new_plane_state->uapi);
960 else if (old_plane_state)
961 intel_plane_destroy_state(plane: &plane->base, state: &old_plane_state->uapi);
962 return ret;
963
964slow:
965 return drm_atomic_helper_update_plane(plane: &plane->base, crtc: &crtc->base, fb,
966 crtc_x, crtc_y, crtc_w, crtc_h,
967 src_x, src_y, src_w, src_h, ctx);
968}
969
970static const struct drm_plane_funcs intel_cursor_plane_funcs = {
971 .update_plane = intel_legacy_cursor_update,
972 .disable_plane = drm_atomic_helper_disable_plane,
973 .destroy = intel_plane_destroy,
974 .atomic_duplicate_state = intel_plane_duplicate_state,
975 .atomic_destroy_state = intel_plane_destroy_state,
976 .format_mod_supported = intel_cursor_format_mod_supported,
977};
978
979static void intel_cursor_add_size_hints_property(struct intel_plane *plane)
980{
981 struct intel_display *display = to_intel_display(plane);
982 const struct drm_mode_config *config = &display->drm->mode_config;
983 struct drm_plane_size_hint hints[4];
984 int size, max_size, num_hints = 0;
985
986 max_size = min(config->cursor_width, config->cursor_height);
987
988 /* for simplicity only enumerate the supported square+POT sizes */
989 for (size = 64; size <= max_size; size *= 2) {
990 if (drm_WARN_ON(display->drm, num_hints >= ARRAY_SIZE(hints)))
991 break;
992
993 hints[num_hints].width = size;
994 hints[num_hints].height = size;
995 num_hints++;
996 }
997
998 drm_plane_add_size_hints_property(plane: &plane->base, hints, num_hints);
999}
1000
1001struct intel_plane *
1002intel_cursor_plane_create(struct intel_display *display,
1003 enum pipe pipe)
1004{
1005 struct intel_plane *cursor;
1006 int ret, zpos;
1007 u64 *modifiers;
1008
1009 cursor = intel_plane_alloc();
1010 if (IS_ERR(ptr: cursor))
1011 return cursor;
1012
1013 cursor->pipe = pipe;
1014 cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
1015 cursor->id = PLANE_CURSOR;
1016 cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
1017
1018 if (display->platform.i845g || display->platform.i865g) {
1019 cursor->max_stride = i845_cursor_max_stride;
1020 cursor->min_alignment = i845_cursor_min_alignment;
1021 cursor->update_arm = i845_cursor_update_arm;
1022 cursor->disable_arm = i845_cursor_disable_arm;
1023 cursor->get_hw_state = i845_cursor_get_hw_state;
1024 cursor->check_plane = i845_check_cursor;
1025 } else {
1026 cursor->max_stride = i9xx_cursor_max_stride;
1027
1028 if (display->platform.i830)
1029 cursor->min_alignment = i830_cursor_min_alignment;
1030 else if (display->platform.i85x)
1031 cursor->min_alignment = i85x_cursor_min_alignment;
1032 else
1033 cursor->min_alignment = i9xx_cursor_min_alignment;
1034
1035 if (intel_scanout_needs_vtd_wa(display))
1036 cursor->vtd_guard = 2;
1037
1038 cursor->update_arm = i9xx_cursor_update_arm;
1039 cursor->disable_arm = i9xx_cursor_disable_arm;
1040 cursor->get_hw_state = i9xx_cursor_get_hw_state;
1041 cursor->check_plane = i9xx_check_cursor;
1042 }
1043
1044 cursor->surf_offset = intel_cursor_surf_offset;
1045
1046 if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
1047 cursor->capture_error = g4x_cursor_capture_error;
1048 else
1049 cursor->capture_error = i9xx_cursor_capture_error;
1050
1051 cursor->cursor.base = ~0;
1052 cursor->cursor.cntl = ~0;
1053
1054 if (display->platform.i845g || display->platform.i865g || HAS_CUR_FBC(display))
1055 cursor->cursor.size = ~0;
1056
1057 modifiers = intel_fb_plane_get_modifiers(display, INTEL_PLANE_CAP_NONE);
1058
1059 ret = drm_universal_plane_init(dev: display->drm, plane: &cursor->base,
1060 possible_crtcs: 0, funcs: &intel_cursor_plane_funcs,
1061 formats: intel_cursor_formats,
1062 ARRAY_SIZE(intel_cursor_formats),
1063 format_modifiers: modifiers,
1064 type: DRM_PLANE_TYPE_CURSOR,
1065 name: "cursor %c", pipe_name(pipe));
1066
1067 kfree(objp: modifiers);
1068
1069 if (ret)
1070 goto fail;
1071
1072 if (DISPLAY_VER(display) >= 4)
1073 drm_plane_create_rotation_property(plane: &cursor->base,
1074 DRM_MODE_ROTATE_0,
1075 DRM_MODE_ROTATE_0 |
1076 DRM_MODE_ROTATE_180);
1077
1078 intel_cursor_add_size_hints_property(plane: cursor);
1079
1080 zpos = DISPLAY_RUNTIME_INFO(display)->num_sprites[pipe] + 1;
1081 drm_plane_create_zpos_immutable_property(plane: &cursor->base, zpos);
1082
1083 if (DISPLAY_VER(display) >= 12)
1084 drm_plane_enable_fb_damage_clips(plane: &cursor->base);
1085
1086 intel_plane_helper_add(plane: cursor);
1087
1088 return cursor;
1089
1090fail:
1091 intel_plane_free(plane: cursor);
1092
1093 return ERR_PTR(error: ret);
1094}
1095