1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <drm/drm_atomic.h>
34#include <drm/drm_atomic_helper.h>
35#include <drm/drm_color_mgmt.h>
36#include <drm/drm_crtc.h>
37#include <drm/drm_fourcc.h>
38#include <drm/drm_plane_helper.h>
39#include <drm/drm_rect.h>
40#include <drm/i915_drm.h>
41
42#include "i915_drv.h"
43#include "i915_trace.h"
44#include "intel_atomic_plane.h"
45#include "intel_display_types.h"
46#include "intel_frontbuffer.h"
47#include "intel_pm.h"
48#include "intel_psr.h"
49#include "intel_sprite.h"
50
51bool is_planar_yuv_format(u32 pixelformat)
52{
53 switch (pixelformat) {
54 case DRM_FORMAT_NV12:
55 case DRM_FORMAT_P010:
56 case DRM_FORMAT_P012:
57 case DRM_FORMAT_P016:
58 return true;
59 default:
60 return false;
61 }
62}
63
64int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
65 int usecs)
66{
67
68 if (!adjusted_mode->crtc_htotal)
69 return 1;
70
71 return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
72 1000 * adjusted_mode->crtc_htotal);
73}
74
75
76
77#if IS_ENABLED(CONFIG_PROVE_LOCKING)
78#define VBLANK_EVASION_TIME_US 250
79#else
80#define VBLANK_EVASION_TIME_US 100
81#endif
82
83
84
85
86
87
88
89
90
91
92
93
94
95void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
96{
97 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
98 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
99 const struct drm_display_mode *adjusted_mode = &new_crtc_state->base.adjusted_mode;
100 long timeout = msecs_to_jiffies_timeout(1);
101 int scanline, min, max, vblank_start;
102 wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
103 bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
104 intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
105 DEFINE_WAIT(wait);
106 u32 psr_status;
107
108 vblank_start = adjusted_mode->crtc_vblank_start;
109 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
110 vblank_start = DIV_ROUND_UP(vblank_start, 2);
111
112
113 min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
114 VBLANK_EVASION_TIME_US);
115 max = vblank_start - 1;
116
117 if (min <= 0 || max <= 0)
118 goto irq_disable;
119
120 if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
121 goto irq_disable;
122
123
124
125
126
127
128 if (intel_psr_wait_for_idle(new_crtc_state, &psr_status))
129 DRM_ERROR("PSR idle timed out 0x%x, atomic update may fail\n",
130 psr_status);
131
132 local_irq_disable();
133
134 crtc->debug.min_vbl = min;
135 crtc->debug.max_vbl = max;
136 trace_i915_pipe_update_start(crtc);
137
138 for (;;) {
139
140
141
142
143
144 prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
145
146 scanline = intel_get_crtc_scanline(crtc);
147 if (scanline < min || scanline > max)
148 break;
149
150 if (!timeout) {
151 DRM_ERROR("Potential atomic update failure on pipe %c\n",
152 pipe_name(crtc->pipe));
153 break;
154 }
155
156 local_irq_enable();
157
158 timeout = schedule_timeout(timeout);
159
160 local_irq_disable();
161 }
162
163 finish_wait(wq, &wait);
164
165 drm_crtc_vblank_put(&crtc->base);
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182 while (need_vlv_dsi_wa && scanline == vblank_start)
183 scanline = intel_get_crtc_scanline(crtc);
184
185 crtc->debug.scanline_start = scanline;
186 crtc->debug.start_vbl_time = ktime_get();
187 crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
188
189 trace_i915_pipe_update_vblank_evaded(crtc);
190 return;
191
192irq_disable:
193 local_irq_disable();
194}
195
196
197
198
199
200
201
202
203
204void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
205{
206 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
207 enum pipe pipe = crtc->pipe;
208 int scanline_end = intel_get_crtc_scanline(crtc);
209 u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
210 ktime_t end_vbl_time = ktime_get();
211 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
212
213 trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
214
215
216
217
218
219 if (new_crtc_state->base.event) {
220 WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);
221
222 spin_lock(&crtc->base.dev->event_lock);
223 drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event);
224 spin_unlock(&crtc->base.dev->event_lock);
225
226 new_crtc_state->base.event = NULL;
227 }
228
229 local_irq_enable();
230
231 if (intel_vgpu_active(dev_priv))
232 return;
233
234 if (crtc->debug.start_vbl_count &&
235 crtc->debug.start_vbl_count != end_vbl_count) {
236 DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n",
237 pipe_name(pipe), crtc->debug.start_vbl_count,
238 end_vbl_count,
239 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
240 crtc->debug.min_vbl, crtc->debug.max_vbl,
241 crtc->debug.scanline_start, scanline_end);
242 }
243#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
244 else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
245 VBLANK_EVASION_TIME_US)
246 DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
247 pipe_name(pipe),
248 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
249 VBLANK_EVASION_TIME_US);
250#endif
251}
252
253int intel_plane_check_stride(const struct intel_plane_state *plane_state)
254{
255 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
256 const struct drm_framebuffer *fb = plane_state->base.fb;
257 unsigned int rotation = plane_state->base.rotation;
258 u32 stride, max_stride;
259
260
261
262
263
264
265
266 if (intel_plane_can_remap(plane_state) &&
267 !plane_state->base.visible)
268 return 0;
269
270
271 stride = plane_state->color_plane[0].stride;
272 max_stride = plane->max_stride(plane, fb->format->format,
273 fb->modifier, rotation);
274
275 if (stride > max_stride) {
276 DRM_DEBUG_KMS("[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n",
277 fb->base.id, stride,
278 plane->base.base.id, plane->base.name, max_stride);
279 return -EINVAL;
280 }
281
282 return 0;
283}
284
285int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
286{
287 const struct drm_framebuffer *fb = plane_state->base.fb;
288 struct drm_rect *src = &plane_state->base.src;
289 u32 src_x, src_y, src_w, src_h, hsub, vsub;
290 bool rotated = drm_rotation_90_or_270(plane_state->base.rotation);
291
292
293
294
295
296
297
298 src_x = src->x1 >> 16;
299 src_w = drm_rect_width(src) >> 16;
300 src_y = src->y1 >> 16;
301 src_h = drm_rect_height(src) >> 16;
302
303 src->x1 = src_x << 16;
304 src->x2 = (src_x + src_w) << 16;
305 src->y1 = src_y << 16;
306 src->y2 = (src_y + src_h) << 16;
307
308 if (!fb->format->is_yuv)
309 return 0;
310
311
312 if (!rotated) {
313 hsub = fb->format->hsub;
314 vsub = fb->format->vsub;
315 } else {
316 hsub = vsub = max(fb->format->hsub, fb->format->vsub);
317 }
318
319 if (src_x % hsub || src_w % hsub) {
320 DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u for %sYUV planes\n",
321 src_x, src_w, hsub, rotated ? "rotated " : "");
322 return -EINVAL;
323 }
324
325 if (src_y % vsub || src_h % vsub) {
326 DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u for %sYUV planes\n",
327 src_y, src_h, vsub, rotated ? "rotated " : "");
328 return -EINVAL;
329 }
330
331 return 0;
332}
333
334bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
335{
336 return INTEL_GEN(dev_priv) >= 11 &&
337 icl_hdr_plane_mask() & BIT(plane_id);
338}
339
340static unsigned int
341skl_plane_max_stride(struct intel_plane *plane,
342 u32 pixel_format, u64 modifier,
343 unsigned int rotation)
344{
345 const struct drm_format_info *info = drm_format_info(pixel_format);
346 int cpp = info->cpp[0];
347
348
349
350
351
352 if (drm_rotation_90_or_270(rotation))
353 return min(8192, 32768 / cpp);
354 else
355 return min(8192 * cpp, 32768);
356}
357
358static void
359skl_program_scaler(struct intel_plane *plane,
360 const struct intel_crtc_state *crtc_state,
361 const struct intel_plane_state *plane_state)
362{
363 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
364 enum pipe pipe = plane->pipe;
365 int scaler_id = plane_state->scaler_id;
366 const struct intel_scaler *scaler =
367 &crtc_state->scaler_state.scalers[scaler_id];
368 int crtc_x = plane_state->base.dst.x1;
369 int crtc_y = plane_state->base.dst.y1;
370 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
371 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
372 u16 y_hphase, uv_rgb_hphase;
373 u16 y_vphase, uv_rgb_vphase;
374 int hscale, vscale;
375
376 hscale = drm_rect_calc_hscale(&plane_state->base.src,
377 &plane_state->base.dst,
378 0, INT_MAX);
379 vscale = drm_rect_calc_vscale(&plane_state->base.src,
380 &plane_state->base.dst,
381 0, INT_MAX);
382
383
384 if (is_planar_yuv_format(plane_state->base.fb->format->format) &&
385 !icl_is_hdr_plane(dev_priv, plane->id)) {
386 y_hphase = skl_scaler_calc_phase(1, hscale, false);
387 y_vphase = skl_scaler_calc_phase(1, vscale, false);
388
389
390 uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
391 uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
392 } else {
393
394 y_hphase = 0;
395 y_vphase = 0;
396
397 uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
398 uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
399 }
400
401 I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
402 PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode);
403 I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
404 PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
405 I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
406 PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
407 I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
408 I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h);
409}
410
411
412#define PREOFF_YUV_TO_RGB_HI 0x1800
413#define PREOFF_YUV_TO_RGB_ME 0x1F00
414#define PREOFF_YUV_TO_RGB_LO 0x1800
415
416#define ROFF(x) (((x) & 0xffff) << 16)
417#define GOFF(x) (((x) & 0xffff) << 0)
418#define BOFF(x) (((x) & 0xffff) << 16)
419
420static void
421icl_program_input_csc(struct intel_plane *plane,
422 const struct intel_crtc_state *crtc_state,
423 const struct intel_plane_state *plane_state)
424{
425 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
426 enum pipe pipe = plane->pipe;
427 enum plane_id plane_id = plane->id;
428
429 static const u16 input_csc_matrix[][9] = {
430
431
432
433
434
435
436
437 [DRM_COLOR_YCBCR_BT601] = {
438 0x7AF8, 0x7800, 0x0,
439 0x8B28, 0x7800, 0x9AC0,
440 0x0, 0x7800, 0x7DD8,
441 },
442
443
444
445
446
447
448
449 [DRM_COLOR_YCBCR_BT709] = {
450 0x7C98, 0x7800, 0x0,
451 0x9EF8, 0x7800, 0xAC00,
452 0x0, 0x7800, 0x7ED8,
453 },
454
455
456
457
458
459
460
461 [DRM_COLOR_YCBCR_BT2020] = {
462 0x7BC8, 0x7800, 0x0,
463 0x8928, 0x7800, 0xAA88,
464 0x0, 0x7800, 0x7F10,
465 },
466 };
467
468
469 static const u16 input_csc_matrix_lr[][9] = {
470
471
472
473
474
475
476
477 [DRM_COLOR_YCBCR_BT601] = {
478 0x7CC8, 0x7950, 0x0,
479 0x8D00, 0x7950, 0x9C88,
480 0x0, 0x7950, 0x6810,
481 },
482
483
484
485
486
487
488
489 [DRM_COLOR_YCBCR_BT709] = {
490 0x7E58, 0x7950, 0x0,
491 0x8888, 0x7950, 0xADA8,
492 0x0, 0x7950, 0x6870,
493 },
494
495
496
497
498
499
500
501 [DRM_COLOR_YCBCR_BT2020] = {
502 0x7D70, 0x7950, 0x0,
503 0x8A68, 0x7950, 0xAC00,
504 0x0, 0x7950, 0x6890,
505 },
506 };
507 const u16 *csc;
508
509 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
510 csc = input_csc_matrix[plane_state->base.color_encoding];
511 else
512 csc = input_csc_matrix_lr[plane_state->base.color_encoding];
513
514 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0), ROFF(csc[0]) |
515 GOFF(csc[1]));
516 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1), BOFF(csc[2]));
517 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2), ROFF(csc[3]) |
518 GOFF(csc[4]));
519 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3), BOFF(csc[5]));
520 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4), ROFF(csc[6]) |
521 GOFF(csc[7]));
522 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5), BOFF(csc[8]));
523
524 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
525 PREOFF_YUV_TO_RGB_HI);
526 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
527 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1), 0);
528 else
529 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
530 PREOFF_YUV_TO_RGB_ME);
531 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
532 PREOFF_YUV_TO_RGB_LO);
533 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
534 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
535 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
536}
537
538static void
539skl_program_plane(struct intel_plane *plane,
540 const struct intel_crtc_state *crtc_state,
541 const struct intel_plane_state *plane_state,
542 int color_plane, bool slave, u32 plane_ctl)
543{
544 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
545 enum plane_id plane_id = plane->id;
546 enum pipe pipe = plane->pipe;
547 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
548 u32 surf_addr = plane_state->color_plane[color_plane].offset;
549 u32 stride = skl_plane_stride(plane_state, color_plane);
550 u32 aux_stride = skl_plane_stride(plane_state, 1);
551 int crtc_x = plane_state->base.dst.x1;
552 int crtc_y = plane_state->base.dst.y1;
553 u32 x = plane_state->color_plane[color_plane].x;
554 u32 y = plane_state->color_plane[color_plane].y;
555 u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
556 u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
557 struct intel_plane *linked = plane_state->linked_plane;
558 const struct drm_framebuffer *fb = plane_state->base.fb;
559 u8 alpha = plane_state->base.alpha >> 8;
560 u32 plane_color_ctl = 0;
561 unsigned long irqflags;
562 u32 keymsk, keymax;
563
564 plane_ctl |= skl_plane_ctl_crtc(crtc_state);
565
566 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
567 plane_color_ctl = plane_state->color_ctl |
568 glk_plane_color_ctl_crtc(crtc_state);
569
570
571 src_w--;
572 src_h--;
573
574 keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
575
576 keymsk = key->channel_mask & 0x7ffffff;
577 if (alpha < 0xff)
578 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
579
580
581 if (plane_state->scaler_id >= 0) {
582 crtc_x = 0;
583 crtc_y = 0;
584 }
585
586 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
587
588 I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
589 I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
590 I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
591 I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
592 (plane_state->color_plane[1].offset - surf_addr) | aux_stride);
593
594 if (icl_is_hdr_plane(dev_priv, plane_id)) {
595 u32 cus_ctl = 0;
596
597 if (linked) {
598
599 cus_ctl = PLANE_CUS_ENABLE |
600 PLANE_CUS_HPHASE_0 |
601 PLANE_CUS_VPHASE_SIGN_NEGATIVE |
602 PLANE_CUS_VPHASE_0_25;
603
604 if (linked->id == PLANE_SPRITE5)
605 cus_ctl |= PLANE_CUS_PLANE_7;
606 else if (linked->id == PLANE_SPRITE4)
607 cus_ctl |= PLANE_CUS_PLANE_6;
608 else
609 MISSING_CASE(linked->id);
610 }
611
612 I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), cus_ctl);
613 }
614
615 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
616 I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
617
618 if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
619 icl_program_input_csc(plane, crtc_state, plane_state);
620
621 skl_write_plane_wm(plane, crtc_state);
622
623 I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
624 I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), keymsk);
625 I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), keymax);
626
627 I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
628
629 if (INTEL_GEN(dev_priv) < 11)
630 I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
631 (plane_state->color_plane[1].y << 16) |
632 plane_state->color_plane[1].x);
633
634
635
636
637
638
639 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
640 I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
641 intel_plane_ggtt_offset(plane_state) + surf_addr);
642
643 if (!slave && plane_state->scaler_id >= 0)
644 skl_program_scaler(plane, crtc_state, plane_state);
645
646 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
647}
648
649static void
650skl_update_plane(struct intel_plane *plane,
651 const struct intel_crtc_state *crtc_state,
652 const struct intel_plane_state *plane_state)
653{
654 int color_plane = 0;
655
656 if (plane_state->linked_plane) {
657
658 color_plane = 1;
659 }
660
661 skl_program_plane(plane, crtc_state, plane_state,
662 color_plane, false, plane_state->ctl);
663}
664
665static void
666icl_update_slave(struct intel_plane *plane,
667 const struct intel_crtc_state *crtc_state,
668 const struct intel_plane_state *plane_state)
669{
670 skl_program_plane(plane, crtc_state, plane_state, 0, true,
671 plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE);
672}
673
674static void
675skl_disable_plane(struct intel_plane *plane,
676 const struct intel_crtc_state *crtc_state)
677{
678 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
679 enum plane_id plane_id = plane->id;
680 enum pipe pipe = plane->pipe;
681 unsigned long irqflags;
682
683 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
684
685 if (icl_is_hdr_plane(dev_priv, plane_id))
686 I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), 0);
687
688 skl_write_plane_wm(plane, crtc_state);
689
690 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
691 I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
692
693 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
694}
695
696static bool
697skl_plane_get_hw_state(struct intel_plane *plane,
698 enum pipe *pipe)
699{
700 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
701 enum intel_display_power_domain power_domain;
702 enum plane_id plane_id = plane->id;
703 intel_wakeref_t wakeref;
704 bool ret;
705
706 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
707 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
708 if (!wakeref)
709 return false;
710
711 ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
712
713 *pipe = plane->pipe;
714
715 intel_display_power_put(dev_priv, power_domain, wakeref);
716
717 return ret;
718}
719
720static void i9xx_plane_linear_gamma(u16 gamma[8])
721{
722
723 static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
724 int i;
725
726 for (i = 0; i < 8; i++)
727 gamma[i] = (in[i] << 8) / 32;
728}
729
730static void
731chv_update_csc(const struct intel_plane_state *plane_state)
732{
733 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
734 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
735 const struct drm_framebuffer *fb = plane_state->base.fb;
736 enum plane_id plane_id = plane->id;
737
738
739
740
741
742
743
744
745
746
747 static const s16 csc_matrix[][9] = {
748
749 [DRM_COLOR_YCBCR_BT601] = {
750 5743, 4096, 0,
751 -2925, 4096, -1410,
752 0, 4096, 7258,
753 },
754
755 [DRM_COLOR_YCBCR_BT709] = {
756 6450, 4096, 0,
757 -1917, 4096, -767,
758 0, 4096, 7601,
759 },
760 };
761 const s16 *csc = csc_matrix[plane_state->base.color_encoding];
762
763
764 if (!fb->format->is_yuv)
765 return;
766
767 I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
768 I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
769 I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
770
771 I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
772 I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
773 I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
774 I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
775 I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8]));
776
777 I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
778 I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
779 I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
780
781 I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
782 I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
783 I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
784}
785
786#define SIN_0 0
787#define COS_0 1
788
789static void
790vlv_update_clrc(const struct intel_plane_state *plane_state)
791{
792 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
793 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
794 const struct drm_framebuffer *fb = plane_state->base.fb;
795 enum pipe pipe = plane->pipe;
796 enum plane_id plane_id = plane->id;
797 int contrast, brightness, sh_scale, sh_sin, sh_cos;
798
799 if (fb->format->is_yuv &&
800 plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
801
802
803
804
805
806
807 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
808 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
809 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
810 sh_sin = SIN_0 * sh_scale;
811 sh_cos = COS_0 * sh_scale;
812 } else {
813
814 contrast = 1 << 6;
815 brightness = 0;
816 sh_scale = 1 << 7;
817 sh_sin = SIN_0 * sh_scale;
818 sh_cos = COS_0 * sh_scale;
819 }
820
821
822 I915_WRITE_FW(SPCLRC0(pipe, plane_id),
823 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
824 I915_WRITE_FW(SPCLRC1(pipe, plane_id),
825 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
826}
827
828static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
829{
830 u32 sprctl = 0;
831
832 if (crtc_state->gamma_enable)
833 sprctl |= SP_GAMMA_ENABLE;
834
835 return sprctl;
836}
837
838static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
839 const struct intel_plane_state *plane_state)
840{
841 const struct drm_framebuffer *fb = plane_state->base.fb;
842 unsigned int rotation = plane_state->base.rotation;
843 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
844 u32 sprctl;
845
846 sprctl = SP_ENABLE;
847
848 switch (fb->format->format) {
849 case DRM_FORMAT_YUYV:
850 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
851 break;
852 case DRM_FORMAT_YVYU:
853 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
854 break;
855 case DRM_FORMAT_UYVY:
856 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
857 break;
858 case DRM_FORMAT_VYUY:
859 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
860 break;
861 case DRM_FORMAT_RGB565:
862 sprctl |= SP_FORMAT_BGR565;
863 break;
864 case DRM_FORMAT_XRGB8888:
865 sprctl |= SP_FORMAT_BGRX8888;
866 break;
867 case DRM_FORMAT_ARGB8888:
868 sprctl |= SP_FORMAT_BGRA8888;
869 break;
870 case DRM_FORMAT_XBGR2101010:
871 sprctl |= SP_FORMAT_RGBX1010102;
872 break;
873 case DRM_FORMAT_ABGR2101010:
874 sprctl |= SP_FORMAT_RGBA1010102;
875 break;
876 case DRM_FORMAT_XBGR8888:
877 sprctl |= SP_FORMAT_RGBX8888;
878 break;
879 case DRM_FORMAT_ABGR8888:
880 sprctl |= SP_FORMAT_RGBA8888;
881 break;
882 default:
883 MISSING_CASE(fb->format->format);
884 return 0;
885 }
886
887 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
888 sprctl |= SP_YUV_FORMAT_BT709;
889
890 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
891 sprctl |= SP_TILED;
892
893 if (rotation & DRM_MODE_ROTATE_180)
894 sprctl |= SP_ROTATE_180;
895
896 if (rotation & DRM_MODE_REFLECT_X)
897 sprctl |= SP_MIRROR;
898
899 if (key->flags & I915_SET_COLORKEY_SOURCE)
900 sprctl |= SP_SOURCE_KEY;
901
902 return sprctl;
903}
904
905static void vlv_update_gamma(const struct intel_plane_state *plane_state)
906{
907 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
908 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
909 const struct drm_framebuffer *fb = plane_state->base.fb;
910 enum pipe pipe = plane->pipe;
911 enum plane_id plane_id = plane->id;
912 u16 gamma[8];
913 int i;
914
915
916 if (!fb->format->is_yuv)
917 return;
918
919 i9xx_plane_linear_gamma(gamma);
920
921
922
923 for (i = 1; i < 8 - 1; i++)
924 I915_WRITE_FW(SPGAMC(pipe, plane_id, i - 1),
925 gamma[i] << 16 |
926 gamma[i] << 8 |
927 gamma[i]);
928}
929
930static void
931vlv_update_plane(struct intel_plane *plane,
932 const struct intel_crtc_state *crtc_state,
933 const struct intel_plane_state *plane_state)
934{
935 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
936 enum pipe pipe = plane->pipe;
937 enum plane_id plane_id = plane->id;
938 u32 sprsurf_offset = plane_state->color_plane[0].offset;
939 u32 linear_offset;
940 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
941 int crtc_x = plane_state->base.dst.x1;
942 int crtc_y = plane_state->base.dst.y1;
943 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
944 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
945 u32 x = plane_state->color_plane[0].x;
946 u32 y = plane_state->color_plane[0].y;
947 unsigned long irqflags;
948 u32 sprctl;
949
950 sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
951
952
953 crtc_w--;
954 crtc_h--;
955
956 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
957
958 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
959
960 I915_WRITE_FW(SPSTRIDE(pipe, plane_id),
961 plane_state->color_plane[0].stride);
962 I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
963 I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
964 I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
965
966 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
967 chv_update_csc(plane_state);
968
969 if (key->flags) {
970 I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
971 I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
972 I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
973 }
974
975 I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
976 I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
977
978
979
980
981
982
983 I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
984 I915_WRITE_FW(SPSURF(pipe, plane_id),
985 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
986
987 vlv_update_clrc(plane_state);
988 vlv_update_gamma(plane_state);
989
990 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
991}
992
993static void
994vlv_disable_plane(struct intel_plane *plane,
995 const struct intel_crtc_state *crtc_state)
996{
997 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
998 enum pipe pipe = plane->pipe;
999 enum plane_id plane_id = plane->id;
1000 unsigned long irqflags;
1001
1002 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1003
1004 I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
1005 I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
1006
1007 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1008}
1009
1010static bool
1011vlv_plane_get_hw_state(struct intel_plane *plane,
1012 enum pipe *pipe)
1013{
1014 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1015 enum intel_display_power_domain power_domain;
1016 enum plane_id plane_id = plane->id;
1017 intel_wakeref_t wakeref;
1018 bool ret;
1019
1020 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1021 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1022 if (!wakeref)
1023 return false;
1024
1025 ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
1026
1027 *pipe = plane->pipe;
1028
1029 intel_display_power_put(dev_priv, power_domain, wakeref);
1030
1031 return ret;
1032}
1033
1034static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1035{
1036 u32 sprctl = 0;
1037
1038 if (crtc_state->gamma_enable)
1039 sprctl |= SPRITE_GAMMA_ENABLE;
1040
1041 if (crtc_state->csc_enable)
1042 sprctl |= SPRITE_PIPE_CSC_ENABLE;
1043
1044 return sprctl;
1045}
1046
1047static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
1048 const struct intel_plane_state *plane_state)
1049{
1050 struct drm_i915_private *dev_priv =
1051 to_i915(plane_state->base.plane->dev);
1052 const struct drm_framebuffer *fb = plane_state->base.fb;
1053 unsigned int rotation = plane_state->base.rotation;
1054 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1055 u32 sprctl;
1056
1057 sprctl = SPRITE_ENABLE;
1058
1059 if (IS_IVYBRIDGE(dev_priv))
1060 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
1061
1062 switch (fb->format->format) {
1063 case DRM_FORMAT_XBGR8888:
1064 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
1065 break;
1066 case DRM_FORMAT_XRGB8888:
1067 sprctl |= SPRITE_FORMAT_RGBX888;
1068 break;
1069 case DRM_FORMAT_YUYV:
1070 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
1071 break;
1072 case DRM_FORMAT_YVYU:
1073 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
1074 break;
1075 case DRM_FORMAT_UYVY:
1076 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
1077 break;
1078 case DRM_FORMAT_VYUY:
1079 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
1080 break;
1081 default:
1082 MISSING_CASE(fb->format->format);
1083 return 0;
1084 }
1085
1086 sprctl |= SPRITE_INT_GAMMA_DISABLE;
1087
1088 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
1089 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
1090
1091 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1092 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
1093
1094 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1095 sprctl |= SPRITE_TILED;
1096
1097 if (rotation & DRM_MODE_ROTATE_180)
1098 sprctl |= SPRITE_ROTATE_180;
1099
1100 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1101 sprctl |= SPRITE_DEST_KEY;
1102 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1103 sprctl |= SPRITE_SOURCE_KEY;
1104
1105 return sprctl;
1106}
1107
1108static void ivb_sprite_linear_gamma(u16 gamma[18])
1109{
1110 int i;
1111
1112 for (i = 0; i < 17; i++)
1113 gamma[i] = (i << 10) / 16;
1114
1115 gamma[i] = 3 << 10;
1116 i++;
1117}
1118
1119static void ivb_update_gamma(const struct intel_plane_state *plane_state)
1120{
1121 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1122 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1123 enum pipe pipe = plane->pipe;
1124 u16 gamma[18];
1125 int i;
1126
1127 ivb_sprite_linear_gamma(gamma);
1128
1129
1130 for (i = 0; i < 16; i++)
1131 I915_WRITE_FW(SPRGAMC(pipe, i),
1132 gamma[i] << 20 |
1133 gamma[i] << 10 |
1134 gamma[i]);
1135
1136 I915_WRITE_FW(SPRGAMC16(pipe, 0), gamma[i]);
1137 I915_WRITE_FW(SPRGAMC16(pipe, 1), gamma[i]);
1138 I915_WRITE_FW(SPRGAMC16(pipe, 2), gamma[i]);
1139 i++;
1140
1141 I915_WRITE_FW(SPRGAMC17(pipe, 0), gamma[i]);
1142 I915_WRITE_FW(SPRGAMC17(pipe, 1), gamma[i]);
1143 I915_WRITE_FW(SPRGAMC17(pipe, 2), gamma[i]);
1144 i++;
1145}
1146
1147static void
1148ivb_update_plane(struct intel_plane *plane,
1149 const struct intel_crtc_state *crtc_state,
1150 const struct intel_plane_state *plane_state)
1151{
1152 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1153 enum pipe pipe = plane->pipe;
1154 u32 sprsurf_offset = plane_state->color_plane[0].offset;
1155 u32 linear_offset;
1156 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1157 int crtc_x = plane_state->base.dst.x1;
1158 int crtc_y = plane_state->base.dst.y1;
1159 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
1160 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
1161 u32 x = plane_state->color_plane[0].x;
1162 u32 y = plane_state->color_plane[0].y;
1163 u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
1164 u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
1165 u32 sprctl, sprscale = 0;
1166 unsigned long irqflags;
1167
1168 sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
1169
1170
1171 src_w--;
1172 src_h--;
1173 crtc_w--;
1174 crtc_h--;
1175
1176 if (crtc_w != src_w || crtc_h != src_h)
1177 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
1178
1179 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1180
1181 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1182
1183 I915_WRITE_FW(SPRSTRIDE(pipe), plane_state->color_plane[0].stride);
1184 I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
1185 I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
1186 if (IS_IVYBRIDGE(dev_priv))
1187 I915_WRITE_FW(SPRSCALE(pipe), sprscale);
1188
1189 if (key->flags) {
1190 I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
1191 I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
1192 I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
1193 }
1194
1195
1196
1197 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1198 I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
1199 } else {
1200 I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
1201 I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
1202 }
1203
1204
1205
1206
1207
1208
1209 I915_WRITE_FW(SPRCTL(pipe), sprctl);
1210 I915_WRITE_FW(SPRSURF(pipe),
1211 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1212
1213 ivb_update_gamma(plane_state);
1214
1215 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1216}
1217
1218static void
1219ivb_disable_plane(struct intel_plane *plane,
1220 const struct intel_crtc_state *crtc_state)
1221{
1222 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1223 enum pipe pipe = plane->pipe;
1224 unsigned long irqflags;
1225
1226 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1227
1228 I915_WRITE_FW(SPRCTL(pipe), 0);
1229
1230 if (IS_IVYBRIDGE(dev_priv))
1231 I915_WRITE_FW(SPRSCALE(pipe), 0);
1232 I915_WRITE_FW(SPRSURF(pipe), 0);
1233
1234 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1235}
1236
1237static bool
1238ivb_plane_get_hw_state(struct intel_plane *plane,
1239 enum pipe *pipe)
1240{
1241 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1242 enum intel_display_power_domain power_domain;
1243 intel_wakeref_t wakeref;
1244 bool ret;
1245
1246 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1247 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1248 if (!wakeref)
1249 return false;
1250
1251 ret = I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
1252
1253 *pipe = plane->pipe;
1254
1255 intel_display_power_put(dev_priv, power_domain, wakeref);
1256
1257 return ret;
1258}
1259
1260static unsigned int
1261g4x_sprite_max_stride(struct intel_plane *plane,
1262 u32 pixel_format, u64 modifier,
1263 unsigned int rotation)
1264{
1265 return 16384;
1266}
1267
1268static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1269{
1270 u32 dvscntr = 0;
1271
1272 if (crtc_state->gamma_enable)
1273 dvscntr |= DVS_GAMMA_ENABLE;
1274
1275 if (crtc_state->csc_enable)
1276 dvscntr |= DVS_PIPE_CSC_ENABLE;
1277
1278 return dvscntr;
1279}
1280
1281static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1282 const struct intel_plane_state *plane_state)
1283{
1284 struct drm_i915_private *dev_priv =
1285 to_i915(plane_state->base.plane->dev);
1286 const struct drm_framebuffer *fb = plane_state->base.fb;
1287 unsigned int rotation = plane_state->base.rotation;
1288 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1289 u32 dvscntr;
1290
1291 dvscntr = DVS_ENABLE;
1292
1293 if (IS_GEN(dev_priv, 6))
1294 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1295
1296 switch (fb->format->format) {
1297 case DRM_FORMAT_XBGR8888:
1298 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1299 break;
1300 case DRM_FORMAT_XRGB8888:
1301 dvscntr |= DVS_FORMAT_RGBX888;
1302 break;
1303 case DRM_FORMAT_YUYV:
1304 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1305 break;
1306 case DRM_FORMAT_YVYU:
1307 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1308 break;
1309 case DRM_FORMAT_UYVY:
1310 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1311 break;
1312 case DRM_FORMAT_VYUY:
1313 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1314 break;
1315 default:
1316 MISSING_CASE(fb->format->format);
1317 return 0;
1318 }
1319
1320 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
1321 dvscntr |= DVS_YUV_FORMAT_BT709;
1322
1323 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1324 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1325
1326 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1327 dvscntr |= DVS_TILED;
1328
1329 if (rotation & DRM_MODE_ROTATE_180)
1330 dvscntr |= DVS_ROTATE_180;
1331
1332 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1333 dvscntr |= DVS_DEST_KEY;
1334 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1335 dvscntr |= DVS_SOURCE_KEY;
1336
1337 return dvscntr;
1338}
1339
1340static void g4x_update_gamma(const struct intel_plane_state *plane_state)
1341{
1342 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1343 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1344 const struct drm_framebuffer *fb = plane_state->base.fb;
1345 enum pipe pipe = plane->pipe;
1346 u16 gamma[8];
1347 int i;
1348
1349
1350 if (!fb->format->is_yuv)
1351 return;
1352
1353 i9xx_plane_linear_gamma(gamma);
1354
1355
1356
1357 for (i = 1; i < 8 - 1; i++)
1358 I915_WRITE_FW(DVSGAMC_G4X(pipe, i - 1),
1359 gamma[i] << 16 |
1360 gamma[i] << 8 |
1361 gamma[i]);
1362}
1363
1364static void ilk_sprite_linear_gamma(u16 gamma[17])
1365{
1366 int i;
1367
1368 for (i = 0; i < 17; i++)
1369 gamma[i] = (i << 10) / 16;
1370}
1371
1372static void ilk_update_gamma(const struct intel_plane_state *plane_state)
1373{
1374 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1375 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1376 const struct drm_framebuffer *fb = plane_state->base.fb;
1377 enum pipe pipe = plane->pipe;
1378 u16 gamma[17];
1379 int i;
1380
1381
1382 if (!fb->format->is_yuv)
1383 return;
1384
1385 ilk_sprite_linear_gamma(gamma);
1386
1387
1388 for (i = 0; i < 16; i++)
1389 I915_WRITE_FW(DVSGAMC_ILK(pipe, i),
1390 gamma[i] << 20 |
1391 gamma[i] << 10 |
1392 gamma[i]);
1393
1394 I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1395 I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1396 I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1397 i++;
1398}
1399
1400static void
1401g4x_update_plane(struct intel_plane *plane,
1402 const struct intel_crtc_state *crtc_state,
1403 const struct intel_plane_state *plane_state)
1404{
1405 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1406 enum pipe pipe = plane->pipe;
1407 u32 dvssurf_offset = plane_state->color_plane[0].offset;
1408 u32 linear_offset;
1409 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1410 int crtc_x = plane_state->base.dst.x1;
1411 int crtc_y = plane_state->base.dst.y1;
1412 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
1413 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
1414 u32 x = plane_state->color_plane[0].x;
1415 u32 y = plane_state->color_plane[0].y;
1416 u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
1417 u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
1418 u32 dvscntr, dvsscale = 0;
1419 unsigned long irqflags;
1420
1421 dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1422
1423
1424 src_w--;
1425 src_h--;
1426 crtc_w--;
1427 crtc_h--;
1428
1429 if (crtc_w != src_w || crtc_h != src_h)
1430 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
1431
1432 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1433
1434 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1435
1436 I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride);
1437 I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
1438 I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
1439 I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
1440
1441 if (key->flags) {
1442 I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
1443 I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
1444 I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
1445 }
1446
1447 I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
1448 I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
1449
1450
1451
1452
1453
1454
1455 I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
1456 I915_WRITE_FW(DVSSURF(pipe),
1457 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1458
1459 if (IS_G4X(dev_priv))
1460 g4x_update_gamma(plane_state);
1461 else
1462 ilk_update_gamma(plane_state);
1463
1464 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1465}
1466
1467static void
1468g4x_disable_plane(struct intel_plane *plane,
1469 const struct intel_crtc_state *crtc_state)
1470{
1471 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1472 enum pipe pipe = plane->pipe;
1473 unsigned long irqflags;
1474
1475 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1476
1477 I915_WRITE_FW(DVSCNTR(pipe), 0);
1478
1479 I915_WRITE_FW(DVSSCALE(pipe), 0);
1480 I915_WRITE_FW(DVSSURF(pipe), 0);
1481
1482 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1483}
1484
1485static bool
1486g4x_plane_get_hw_state(struct intel_plane *plane,
1487 enum pipe *pipe)
1488{
1489 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1490 enum intel_display_power_domain power_domain;
1491 intel_wakeref_t wakeref;
1492 bool ret;
1493
1494 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1495 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1496 if (!wakeref)
1497 return false;
1498
1499 ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
1500
1501 *pipe = plane->pipe;
1502
1503 intel_display_power_put(dev_priv, power_domain, wakeref);
1504
1505 return ret;
1506}
1507
1508static bool intel_fb_scalable(const struct drm_framebuffer *fb)
1509{
1510 if (!fb)
1511 return false;
1512
1513 switch (fb->format->format) {
1514 case DRM_FORMAT_C8:
1515 return false;
1516 default:
1517 return true;
1518 }
1519}
1520
1521static int
1522g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1523 struct intel_plane_state *plane_state)
1524{
1525 const struct drm_framebuffer *fb = plane_state->base.fb;
1526 const struct drm_rect *src = &plane_state->base.src;
1527 const struct drm_rect *dst = &plane_state->base.dst;
1528 int src_x, src_w, src_h, crtc_w, crtc_h;
1529 const struct drm_display_mode *adjusted_mode =
1530 &crtc_state->base.adjusted_mode;
1531 unsigned int stride = plane_state->color_plane[0].stride;
1532 unsigned int cpp = fb->format->cpp[0];
1533 unsigned int width_bytes;
1534 int min_width, min_height;
1535
1536 crtc_w = drm_rect_width(dst);
1537 crtc_h = drm_rect_height(dst);
1538
1539 src_x = src->x1 >> 16;
1540 src_w = drm_rect_width(src) >> 16;
1541 src_h = drm_rect_height(src) >> 16;
1542
1543 if (src_w == crtc_w && src_h == crtc_h)
1544 return 0;
1545
1546 min_width = 3;
1547
1548 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1549 if (src_h & 1) {
1550 DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
1551 return -EINVAL;
1552 }
1553 min_height = 6;
1554 } else {
1555 min_height = 3;
1556 }
1557
1558 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1559
1560 if (src_w < min_width || src_h < min_height ||
1561 src_w > 2048 || src_h > 2048) {
1562 DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1563 src_w, src_h, min_width, min_height, 2048, 2048);
1564 return -EINVAL;
1565 }
1566
1567 if (width_bytes > 4096) {
1568 DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1569 width_bytes, 4096);
1570 return -EINVAL;
1571 }
1572
1573 if (stride > 4096) {
1574 DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
1575 stride, 4096);
1576 return -EINVAL;
1577 }
1578
1579 return 0;
1580}
1581
1582static int
1583g4x_sprite_check(struct intel_crtc_state *crtc_state,
1584 struct intel_plane_state *plane_state)
1585{
1586 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1587 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1588 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1589 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1590 int ret;
1591
1592 if (intel_fb_scalable(plane_state->base.fb)) {
1593 if (INTEL_GEN(dev_priv) < 7) {
1594 min_scale = 1;
1595 max_scale = 16 << 16;
1596 } else if (IS_IVYBRIDGE(dev_priv)) {
1597 min_scale = 1;
1598 max_scale = 2 << 16;
1599 }
1600 }
1601
1602 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1603 &crtc_state->base,
1604 min_scale, max_scale,
1605 true, true);
1606 if (ret)
1607 return ret;
1608
1609 ret = i9xx_check_plane_surface(plane_state);
1610 if (ret)
1611 return ret;
1612
1613 if (!plane_state->base.visible)
1614 return 0;
1615
1616 ret = intel_plane_check_src_coordinates(plane_state);
1617 if (ret)
1618 return ret;
1619
1620 ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1621 if (ret)
1622 return ret;
1623
1624 if (INTEL_GEN(dev_priv) >= 7)
1625 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1626 else
1627 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1628
1629 return 0;
1630}
1631
1632int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1633{
1634 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1635 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1636 unsigned int rotation = plane_state->base.rotation;
1637
1638
1639 if (IS_CHERRYVIEW(dev_priv) &&
1640 rotation & DRM_MODE_ROTATE_180 &&
1641 rotation & DRM_MODE_REFLECT_X) {
1642 DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n");
1643 return -EINVAL;
1644 }
1645
1646 return 0;
1647}
1648
1649static int
1650vlv_sprite_check(struct intel_crtc_state *crtc_state,
1651 struct intel_plane_state *plane_state)
1652{
1653 int ret;
1654
1655 ret = chv_plane_check_rotation(plane_state);
1656 if (ret)
1657 return ret;
1658
1659 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1660 &crtc_state->base,
1661 DRM_PLANE_HELPER_NO_SCALING,
1662 DRM_PLANE_HELPER_NO_SCALING,
1663 true, true);
1664 if (ret)
1665 return ret;
1666
1667 ret = i9xx_check_plane_surface(plane_state);
1668 if (ret)
1669 return ret;
1670
1671 if (!plane_state->base.visible)
1672 return 0;
1673
1674 ret = intel_plane_check_src_coordinates(plane_state);
1675 if (ret)
1676 return ret;
1677
1678 plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1679
1680 return 0;
1681}
1682
1683static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1684 const struct intel_plane_state *plane_state)
1685{
1686 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1687 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1688 const struct drm_framebuffer *fb = plane_state->base.fb;
1689 unsigned int rotation = plane_state->base.rotation;
1690 struct drm_format_name_buf format_name;
1691
1692 if (!fb)
1693 return 0;
1694
1695 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1696 is_ccs_modifier(fb->modifier)) {
1697 DRM_DEBUG_KMS("RC support only with 0/180 degree rotation (%x)\n",
1698 rotation);
1699 return -EINVAL;
1700 }
1701
1702 if (rotation & DRM_MODE_REFLECT_X &&
1703 fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1704 DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n");
1705 return -EINVAL;
1706 }
1707
1708 if (drm_rotation_90_or_270(rotation)) {
1709 if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
1710 fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
1711 DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
1712 return -EINVAL;
1713 }
1714
1715
1716
1717
1718
1719 switch (fb->format->format) {
1720 case DRM_FORMAT_RGB565:
1721 if (INTEL_GEN(dev_priv) >= 11)
1722 break;
1723
1724 case DRM_FORMAT_C8:
1725 case DRM_FORMAT_XRGB16161616F:
1726 case DRM_FORMAT_XBGR16161616F:
1727 case DRM_FORMAT_ARGB16161616F:
1728 case DRM_FORMAT_ABGR16161616F:
1729 case DRM_FORMAT_Y210:
1730 case DRM_FORMAT_Y212:
1731 case DRM_FORMAT_Y216:
1732 case DRM_FORMAT_XVYU12_16161616:
1733 case DRM_FORMAT_XVYU16161616:
1734 DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
1735 drm_get_format_name(fb->format->format,
1736 &format_name));
1737 return -EINVAL;
1738 default:
1739 break;
1740 }
1741 }
1742
1743
1744 if (crtc_state->base.enable &&
1745 crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1746 (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
1747 fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
1748 fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
1749 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) {
1750 DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n");
1751 return -EINVAL;
1752 }
1753
1754 return 0;
1755}
1756
1757static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1758 const struct intel_plane_state *plane_state)
1759{
1760 struct drm_i915_private *dev_priv =
1761 to_i915(plane_state->base.plane->dev);
1762 int crtc_x = plane_state->base.dst.x1;
1763 int crtc_w = drm_rect_width(&plane_state->base.dst);
1764 int pipe_src_w = crtc_state->pipe_src_w;
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775 if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
1776 (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1777 DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n",
1778 crtc_x + crtc_w < 4 ? "end" : "start",
1779 crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1780 4, pipe_src_w - 4);
1781 return -ERANGE;
1782 }
1783
1784 return 0;
1785}
1786
1787static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1788{
1789 const struct drm_framebuffer *fb = plane_state->base.fb;
1790 unsigned int rotation = plane_state->base.rotation;
1791 int src_w = drm_rect_width(&plane_state->base.src) >> 16;
1792
1793
1794 if (is_planar_yuv_format(fb->format->format) && src_w & 3 &&
1795 (rotation == DRM_MODE_ROTATE_270 ||
1796 rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1797 DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
1798 return -EINVAL;
1799 }
1800
1801 return 0;
1802}
1803
1804static int skl_plane_check(struct intel_crtc_state *crtc_state,
1805 struct intel_plane_state *plane_state)
1806{
1807 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1808 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1809 const struct drm_framebuffer *fb = plane_state->base.fb;
1810 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1811 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1812 int ret;
1813
1814 ret = skl_plane_check_fb(crtc_state, plane_state);
1815 if (ret)
1816 return ret;
1817
1818
1819 if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
1820 min_scale = 1;
1821 max_scale = skl_max_scale(crtc_state, fb->format->format);
1822 }
1823
1824 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1825 &crtc_state->base,
1826 min_scale, max_scale,
1827 true, true);
1828 if (ret)
1829 return ret;
1830
1831 ret = skl_check_plane_surface(plane_state);
1832 if (ret)
1833 return ret;
1834
1835 if (!plane_state->base.visible)
1836 return 0;
1837
1838 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
1839 if (ret)
1840 return ret;
1841
1842 ret = intel_plane_check_src_coordinates(plane_state);
1843 if (ret)
1844 return ret;
1845
1846 ret = skl_plane_check_nv12_rotation(plane_state);
1847 if (ret)
1848 return ret;
1849
1850
1851 if (!(plane_state->base.alpha >> 8))
1852 plane_state->base.visible = false;
1853
1854 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
1855
1856 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1857 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
1858 plane_state);
1859
1860 return 0;
1861}
1862
1863static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1864{
1865 return INTEL_GEN(dev_priv) >= 9;
1866}
1867
1868static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1869 const struct drm_intel_sprite_colorkey *set)
1870{
1871 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1872 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1873 struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1874
1875 *key = *set;
1876
1877
1878
1879
1880
1881 if (plane->id == PLANE_PRIMARY &&
1882 set->flags & I915_SET_COLORKEY_SOURCE)
1883 key->flags = 0;
1884
1885
1886
1887
1888
1889 if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1890 set->flags & I915_SET_COLORKEY_DESTINATION)
1891 key->flags = 0;
1892}
1893
1894int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1895 struct drm_file *file_priv)
1896{
1897 struct drm_i915_private *dev_priv = to_i915(dev);
1898 struct drm_intel_sprite_colorkey *set = data;
1899 struct drm_plane *plane;
1900 struct drm_plane_state *plane_state;
1901 struct drm_atomic_state *state;
1902 struct drm_modeset_acquire_ctx ctx;
1903 int ret = 0;
1904
1905
1906 set->flags &= ~I915_SET_COLORKEY_NONE;
1907
1908 if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1909 return -EINVAL;
1910
1911
1912 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1913 return -EINVAL;
1914
1915 if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1916 set->flags & I915_SET_COLORKEY_DESTINATION)
1917 return -EINVAL;
1918
1919 plane = drm_plane_find(dev, file_priv, set->plane_id);
1920 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1921 return -ENOENT;
1922
1923
1924
1925
1926
1927
1928 if (INTEL_GEN(dev_priv) >= 9 &&
1929 to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1930 set->flags & I915_SET_COLORKEY_DESTINATION)
1931 return -EINVAL;
1932
1933 drm_modeset_acquire_init(&ctx, 0);
1934
1935 state = drm_atomic_state_alloc(plane->dev);
1936 if (!state) {
1937 ret = -ENOMEM;
1938 goto out;
1939 }
1940 state->acquire_ctx = &ctx;
1941
1942 while (1) {
1943 plane_state = drm_atomic_get_plane_state(state, plane);
1944 ret = PTR_ERR_OR_ZERO(plane_state);
1945 if (!ret)
1946 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1947
1948
1949
1950
1951
1952 if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1953 struct intel_crtc *crtc =
1954 intel_get_crtc_for_pipe(dev_priv,
1955 to_intel_plane(plane)->pipe);
1956
1957 plane_state = drm_atomic_get_plane_state(state,
1958 crtc->base.primary);
1959 ret = PTR_ERR_OR_ZERO(plane_state);
1960 if (!ret)
1961 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1962 }
1963
1964 if (!ret)
1965 ret = drm_atomic_commit(state);
1966
1967 if (ret != -EDEADLK)
1968 break;
1969
1970 drm_atomic_state_clear(state);
1971 drm_modeset_backoff(&ctx);
1972 }
1973
1974 drm_atomic_state_put(state);
1975out:
1976 drm_modeset_drop_locks(&ctx);
1977 drm_modeset_acquire_fini(&ctx);
1978 return ret;
1979}
1980
1981static const u32 g4x_plane_formats[] = {
1982 DRM_FORMAT_XRGB8888,
1983 DRM_FORMAT_YUYV,
1984 DRM_FORMAT_YVYU,
1985 DRM_FORMAT_UYVY,
1986 DRM_FORMAT_VYUY,
1987};
1988
1989static const u64 i9xx_plane_format_modifiers[] = {
1990 I915_FORMAT_MOD_X_TILED,
1991 DRM_FORMAT_MOD_LINEAR,
1992 DRM_FORMAT_MOD_INVALID
1993};
1994
1995static const u32 snb_plane_formats[] = {
1996 DRM_FORMAT_XBGR8888,
1997 DRM_FORMAT_XRGB8888,
1998 DRM_FORMAT_YUYV,
1999 DRM_FORMAT_YVYU,
2000 DRM_FORMAT_UYVY,
2001 DRM_FORMAT_VYUY,
2002};
2003
2004static const u32 vlv_plane_formats[] = {
2005 DRM_FORMAT_RGB565,
2006 DRM_FORMAT_ABGR8888,
2007 DRM_FORMAT_ARGB8888,
2008 DRM_FORMAT_XBGR8888,
2009 DRM_FORMAT_XRGB8888,
2010 DRM_FORMAT_XBGR2101010,
2011 DRM_FORMAT_ABGR2101010,
2012 DRM_FORMAT_YUYV,
2013 DRM_FORMAT_YVYU,
2014 DRM_FORMAT_UYVY,
2015 DRM_FORMAT_VYUY,
2016};
2017
2018static const u32 skl_plane_formats[] = {
2019 DRM_FORMAT_C8,
2020 DRM_FORMAT_RGB565,
2021 DRM_FORMAT_XRGB8888,
2022 DRM_FORMAT_XBGR8888,
2023 DRM_FORMAT_ARGB8888,
2024 DRM_FORMAT_ABGR8888,
2025 DRM_FORMAT_XRGB2101010,
2026 DRM_FORMAT_XBGR2101010,
2027 DRM_FORMAT_YUYV,
2028 DRM_FORMAT_YVYU,
2029 DRM_FORMAT_UYVY,
2030 DRM_FORMAT_VYUY,
2031};
2032
2033static const u32 skl_planar_formats[] = {
2034 DRM_FORMAT_C8,
2035 DRM_FORMAT_RGB565,
2036 DRM_FORMAT_XRGB8888,
2037 DRM_FORMAT_XBGR8888,
2038 DRM_FORMAT_ARGB8888,
2039 DRM_FORMAT_ABGR8888,
2040 DRM_FORMAT_XRGB2101010,
2041 DRM_FORMAT_XBGR2101010,
2042 DRM_FORMAT_YUYV,
2043 DRM_FORMAT_YVYU,
2044 DRM_FORMAT_UYVY,
2045 DRM_FORMAT_VYUY,
2046 DRM_FORMAT_NV12,
2047};
2048
2049static const u32 glk_planar_formats[] = {
2050 DRM_FORMAT_C8,
2051 DRM_FORMAT_RGB565,
2052 DRM_FORMAT_XRGB8888,
2053 DRM_FORMAT_XBGR8888,
2054 DRM_FORMAT_ARGB8888,
2055 DRM_FORMAT_ABGR8888,
2056 DRM_FORMAT_XRGB2101010,
2057 DRM_FORMAT_XBGR2101010,
2058 DRM_FORMAT_YUYV,
2059 DRM_FORMAT_YVYU,
2060 DRM_FORMAT_UYVY,
2061 DRM_FORMAT_VYUY,
2062 DRM_FORMAT_NV12,
2063 DRM_FORMAT_P010,
2064 DRM_FORMAT_P012,
2065 DRM_FORMAT_P016,
2066};
2067
2068static const u32 icl_sdr_y_plane_formats[] = {
2069 DRM_FORMAT_C8,
2070 DRM_FORMAT_RGB565,
2071 DRM_FORMAT_XRGB8888,
2072 DRM_FORMAT_XBGR8888,
2073 DRM_FORMAT_ARGB8888,
2074 DRM_FORMAT_ABGR8888,
2075 DRM_FORMAT_XRGB2101010,
2076 DRM_FORMAT_XBGR2101010,
2077 DRM_FORMAT_YUYV,
2078 DRM_FORMAT_YVYU,
2079 DRM_FORMAT_UYVY,
2080 DRM_FORMAT_VYUY,
2081 DRM_FORMAT_Y210,
2082 DRM_FORMAT_Y212,
2083 DRM_FORMAT_Y216,
2084 DRM_FORMAT_XVYU2101010,
2085 DRM_FORMAT_XVYU12_16161616,
2086 DRM_FORMAT_XVYU16161616,
2087};
2088
2089static const u32 icl_sdr_uv_plane_formats[] = {
2090 DRM_FORMAT_C8,
2091 DRM_FORMAT_RGB565,
2092 DRM_FORMAT_XRGB8888,
2093 DRM_FORMAT_XBGR8888,
2094 DRM_FORMAT_ARGB8888,
2095 DRM_FORMAT_ABGR8888,
2096 DRM_FORMAT_XRGB2101010,
2097 DRM_FORMAT_XBGR2101010,
2098 DRM_FORMAT_YUYV,
2099 DRM_FORMAT_YVYU,
2100 DRM_FORMAT_UYVY,
2101 DRM_FORMAT_VYUY,
2102 DRM_FORMAT_NV12,
2103 DRM_FORMAT_P010,
2104 DRM_FORMAT_P012,
2105 DRM_FORMAT_P016,
2106 DRM_FORMAT_Y210,
2107 DRM_FORMAT_Y212,
2108 DRM_FORMAT_Y216,
2109 DRM_FORMAT_XVYU2101010,
2110 DRM_FORMAT_XVYU12_16161616,
2111 DRM_FORMAT_XVYU16161616,
2112};
2113
2114static const u32 icl_hdr_plane_formats[] = {
2115 DRM_FORMAT_C8,
2116 DRM_FORMAT_RGB565,
2117 DRM_FORMAT_XRGB8888,
2118 DRM_FORMAT_XBGR8888,
2119 DRM_FORMAT_ARGB8888,
2120 DRM_FORMAT_ABGR8888,
2121 DRM_FORMAT_XRGB2101010,
2122 DRM_FORMAT_XBGR2101010,
2123 DRM_FORMAT_XRGB16161616F,
2124 DRM_FORMAT_XBGR16161616F,
2125 DRM_FORMAT_ARGB16161616F,
2126 DRM_FORMAT_ABGR16161616F,
2127 DRM_FORMAT_YUYV,
2128 DRM_FORMAT_YVYU,
2129 DRM_FORMAT_UYVY,
2130 DRM_FORMAT_VYUY,
2131 DRM_FORMAT_NV12,
2132 DRM_FORMAT_P010,
2133 DRM_FORMAT_P012,
2134 DRM_FORMAT_P016,
2135 DRM_FORMAT_Y210,
2136 DRM_FORMAT_Y212,
2137 DRM_FORMAT_Y216,
2138 DRM_FORMAT_XVYU2101010,
2139 DRM_FORMAT_XVYU12_16161616,
2140 DRM_FORMAT_XVYU16161616,
2141};
2142
2143static const u64 skl_plane_format_modifiers_noccs[] = {
2144 I915_FORMAT_MOD_Yf_TILED,
2145 I915_FORMAT_MOD_Y_TILED,
2146 I915_FORMAT_MOD_X_TILED,
2147 DRM_FORMAT_MOD_LINEAR,
2148 DRM_FORMAT_MOD_INVALID
2149};
2150
2151static const u64 skl_plane_format_modifiers_ccs[] = {
2152 I915_FORMAT_MOD_Yf_TILED_CCS,
2153 I915_FORMAT_MOD_Y_TILED_CCS,
2154 I915_FORMAT_MOD_Yf_TILED,
2155 I915_FORMAT_MOD_Y_TILED,
2156 I915_FORMAT_MOD_X_TILED,
2157 DRM_FORMAT_MOD_LINEAR,
2158 DRM_FORMAT_MOD_INVALID
2159};
2160
2161static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
2162 u32 format, u64 modifier)
2163{
2164 switch (modifier) {
2165 case DRM_FORMAT_MOD_LINEAR:
2166 case I915_FORMAT_MOD_X_TILED:
2167 break;
2168 default:
2169 return false;
2170 }
2171
2172 switch (format) {
2173 case DRM_FORMAT_XRGB8888:
2174 case DRM_FORMAT_YUYV:
2175 case DRM_FORMAT_YVYU:
2176 case DRM_FORMAT_UYVY:
2177 case DRM_FORMAT_VYUY:
2178 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2179 modifier == I915_FORMAT_MOD_X_TILED)
2180 return true;
2181
2182 default:
2183 return false;
2184 }
2185}
2186
2187static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
2188 u32 format, u64 modifier)
2189{
2190 switch (modifier) {
2191 case DRM_FORMAT_MOD_LINEAR:
2192 case I915_FORMAT_MOD_X_TILED:
2193 break;
2194 default:
2195 return false;
2196 }
2197
2198 switch (format) {
2199 case DRM_FORMAT_XRGB8888:
2200 case DRM_FORMAT_XBGR8888:
2201 case DRM_FORMAT_YUYV:
2202 case DRM_FORMAT_YVYU:
2203 case DRM_FORMAT_UYVY:
2204 case DRM_FORMAT_VYUY:
2205 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2206 modifier == I915_FORMAT_MOD_X_TILED)
2207 return true;
2208
2209 default:
2210 return false;
2211 }
2212}
2213
2214static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
2215 u32 format, u64 modifier)
2216{
2217 switch (modifier) {
2218 case DRM_FORMAT_MOD_LINEAR:
2219 case I915_FORMAT_MOD_X_TILED:
2220 break;
2221 default:
2222 return false;
2223 }
2224
2225 switch (format) {
2226 case DRM_FORMAT_RGB565:
2227 case DRM_FORMAT_ABGR8888:
2228 case DRM_FORMAT_ARGB8888:
2229 case DRM_FORMAT_XBGR8888:
2230 case DRM_FORMAT_XRGB8888:
2231 case DRM_FORMAT_XBGR2101010:
2232 case DRM_FORMAT_ABGR2101010:
2233 case DRM_FORMAT_YUYV:
2234 case DRM_FORMAT_YVYU:
2235 case DRM_FORMAT_UYVY:
2236 case DRM_FORMAT_VYUY:
2237 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2238 modifier == I915_FORMAT_MOD_X_TILED)
2239 return true;
2240
2241 default:
2242 return false;
2243 }
2244}
2245
2246static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2247 u32 format, u64 modifier)
2248{
2249 struct intel_plane *plane = to_intel_plane(_plane);
2250
2251 switch (modifier) {
2252 case DRM_FORMAT_MOD_LINEAR:
2253 case I915_FORMAT_MOD_X_TILED:
2254 case I915_FORMAT_MOD_Y_TILED:
2255 case I915_FORMAT_MOD_Yf_TILED:
2256 break;
2257 case I915_FORMAT_MOD_Y_TILED_CCS:
2258 case I915_FORMAT_MOD_Yf_TILED_CCS:
2259 if (!plane->has_ccs)
2260 return false;
2261 break;
2262 default:
2263 return false;
2264 }
2265
2266 switch (format) {
2267 case DRM_FORMAT_XRGB8888:
2268 case DRM_FORMAT_XBGR8888:
2269 case DRM_FORMAT_ARGB8888:
2270 case DRM_FORMAT_ABGR8888:
2271 if (is_ccs_modifier(modifier))
2272 return true;
2273
2274 case DRM_FORMAT_RGB565:
2275 case DRM_FORMAT_XRGB2101010:
2276 case DRM_FORMAT_XBGR2101010:
2277 case DRM_FORMAT_YUYV:
2278 case DRM_FORMAT_YVYU:
2279 case DRM_FORMAT_UYVY:
2280 case DRM_FORMAT_VYUY:
2281 case DRM_FORMAT_NV12:
2282 case DRM_FORMAT_P010:
2283 case DRM_FORMAT_P012:
2284 case DRM_FORMAT_P016:
2285 case DRM_FORMAT_XVYU2101010:
2286 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2287 return true;
2288
2289 case DRM_FORMAT_C8:
2290 case DRM_FORMAT_XBGR16161616F:
2291 case DRM_FORMAT_ABGR16161616F:
2292 case DRM_FORMAT_XRGB16161616F:
2293 case DRM_FORMAT_ARGB16161616F:
2294 case DRM_FORMAT_Y210:
2295 case DRM_FORMAT_Y212:
2296 case DRM_FORMAT_Y216:
2297 case DRM_FORMAT_XVYU12_16161616:
2298 case DRM_FORMAT_XVYU16161616:
2299 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2300 modifier == I915_FORMAT_MOD_X_TILED ||
2301 modifier == I915_FORMAT_MOD_Y_TILED)
2302 return true;
2303
2304 default:
2305 return false;
2306 }
2307}
2308
2309static const struct drm_plane_funcs g4x_sprite_funcs = {
2310 .update_plane = drm_atomic_helper_update_plane,
2311 .disable_plane = drm_atomic_helper_disable_plane,
2312 .destroy = intel_plane_destroy,
2313 .atomic_duplicate_state = intel_plane_duplicate_state,
2314 .atomic_destroy_state = intel_plane_destroy_state,
2315 .format_mod_supported = g4x_sprite_format_mod_supported,
2316};
2317
2318static const struct drm_plane_funcs snb_sprite_funcs = {
2319 .update_plane = drm_atomic_helper_update_plane,
2320 .disable_plane = drm_atomic_helper_disable_plane,
2321 .destroy = intel_plane_destroy,
2322 .atomic_duplicate_state = intel_plane_duplicate_state,
2323 .atomic_destroy_state = intel_plane_destroy_state,
2324 .format_mod_supported = snb_sprite_format_mod_supported,
2325};
2326
2327static const struct drm_plane_funcs vlv_sprite_funcs = {
2328 .update_plane = drm_atomic_helper_update_plane,
2329 .disable_plane = drm_atomic_helper_disable_plane,
2330 .destroy = intel_plane_destroy,
2331 .atomic_duplicate_state = intel_plane_duplicate_state,
2332 .atomic_destroy_state = intel_plane_destroy_state,
2333 .format_mod_supported = vlv_sprite_format_mod_supported,
2334};
2335
2336static const struct drm_plane_funcs skl_plane_funcs = {
2337 .update_plane = drm_atomic_helper_update_plane,
2338 .disable_plane = drm_atomic_helper_disable_plane,
2339 .destroy = intel_plane_destroy,
2340 .atomic_duplicate_state = intel_plane_duplicate_state,
2341 .atomic_destroy_state = intel_plane_destroy_state,
2342 .format_mod_supported = skl_plane_format_mod_supported,
2343};
2344
2345static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
2346 enum pipe pipe, enum plane_id plane_id)
2347{
2348 if (!HAS_FBC(dev_priv))
2349 return false;
2350
2351 return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
2352}
2353
2354static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
2355 enum pipe pipe, enum plane_id plane_id)
2356{
2357
2358 if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
2359 return false;
2360
2361 if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
2362 return false;
2363
2364 if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
2365 return false;
2366
2367 return true;
2368}
2369
2370static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
2371 enum pipe pipe, enum plane_id plane_id,
2372 int *num_formats)
2373{
2374 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2375 *num_formats = ARRAY_SIZE(skl_planar_formats);
2376 return skl_planar_formats;
2377 } else {
2378 *num_formats = ARRAY_SIZE(skl_plane_formats);
2379 return skl_plane_formats;
2380 }
2381}
2382
2383static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
2384 enum pipe pipe, enum plane_id plane_id,
2385 int *num_formats)
2386{
2387 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2388 *num_formats = ARRAY_SIZE(glk_planar_formats);
2389 return glk_planar_formats;
2390 } else {
2391 *num_formats = ARRAY_SIZE(skl_plane_formats);
2392 return skl_plane_formats;
2393 }
2394}
2395
2396static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
2397 enum pipe pipe, enum plane_id plane_id,
2398 int *num_formats)
2399{
2400 if (icl_is_hdr_plane(dev_priv, plane_id)) {
2401 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
2402 return icl_hdr_plane_formats;
2403 } else if (icl_is_nv12_y_plane(plane_id)) {
2404 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
2405 return icl_sdr_y_plane_formats;
2406 } else {
2407 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
2408 return icl_sdr_uv_plane_formats;
2409 }
2410}
2411
2412static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
2413 enum pipe pipe, enum plane_id plane_id)
2414{
2415 if (plane_id == PLANE_CURSOR)
2416 return false;
2417
2418 if (INTEL_GEN(dev_priv) >= 10)
2419 return true;
2420
2421 if (IS_GEMINILAKE(dev_priv))
2422 return pipe != PIPE_C;
2423
2424 return pipe != PIPE_C &&
2425 (plane_id == PLANE_PRIMARY ||
2426 plane_id == PLANE_SPRITE0);
2427}
2428
2429struct intel_plane *
2430skl_universal_plane_create(struct drm_i915_private *dev_priv,
2431 enum pipe pipe, enum plane_id plane_id)
2432{
2433 struct intel_plane *plane;
2434 enum drm_plane_type plane_type;
2435 unsigned int supported_rotations;
2436 unsigned int possible_crtcs;
2437 const u64 *modifiers;
2438 const u32 *formats;
2439 int num_formats;
2440 int ret;
2441
2442 plane = intel_plane_alloc();
2443 if (IS_ERR(plane))
2444 return plane;
2445
2446 plane->pipe = pipe;
2447 plane->id = plane_id;
2448 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2449
2450 plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
2451 if (plane->has_fbc) {
2452 struct intel_fbc *fbc = &dev_priv->fbc;
2453
2454 fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
2455 }
2456
2457 plane->max_stride = skl_plane_max_stride;
2458 plane->update_plane = skl_update_plane;
2459 plane->disable_plane = skl_disable_plane;
2460 plane->get_hw_state = skl_plane_get_hw_state;
2461 plane->check_plane = skl_plane_check;
2462 if (icl_is_nv12_y_plane(plane_id))
2463 plane->update_slave = icl_update_slave;
2464
2465 if (INTEL_GEN(dev_priv) >= 11)
2466 formats = icl_get_plane_formats(dev_priv, pipe,
2467 plane_id, &num_formats);
2468 else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
2469 formats = glk_get_plane_formats(dev_priv, pipe,
2470 plane_id, &num_formats);
2471 else
2472 formats = skl_get_plane_formats(dev_priv, pipe,
2473 plane_id, &num_formats);
2474
2475 plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
2476 if (plane->has_ccs)
2477 modifiers = skl_plane_format_modifiers_ccs;
2478 else
2479 modifiers = skl_plane_format_modifiers_noccs;
2480
2481 if (plane_id == PLANE_PRIMARY)
2482 plane_type = DRM_PLANE_TYPE_PRIMARY;
2483 else
2484 plane_type = DRM_PLANE_TYPE_OVERLAY;
2485
2486 possible_crtcs = BIT(pipe);
2487
2488 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2489 possible_crtcs, &skl_plane_funcs,
2490 formats, num_formats, modifiers,
2491 plane_type,
2492 "plane %d%c", plane_id + 1,
2493 pipe_name(pipe));
2494 if (ret)
2495 goto fail;
2496
2497 supported_rotations =
2498 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2499 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2500
2501 if (INTEL_GEN(dev_priv) >= 10)
2502 supported_rotations |= DRM_MODE_REFLECT_X;
2503
2504 drm_plane_create_rotation_property(&plane->base,
2505 DRM_MODE_ROTATE_0,
2506 supported_rotations);
2507
2508 drm_plane_create_color_properties(&plane->base,
2509 BIT(DRM_COLOR_YCBCR_BT601) |
2510 BIT(DRM_COLOR_YCBCR_BT709),
2511 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2512 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2513 DRM_COLOR_YCBCR_BT709,
2514 DRM_COLOR_YCBCR_LIMITED_RANGE);
2515
2516 drm_plane_create_alpha_property(&plane->base);
2517 drm_plane_create_blend_mode_property(&plane->base,
2518 BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2519 BIT(DRM_MODE_BLEND_PREMULTI) |
2520 BIT(DRM_MODE_BLEND_COVERAGE));
2521
2522 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
2523
2524 return plane;
2525
2526fail:
2527 intel_plane_free(plane);
2528
2529 return ERR_PTR(ret);
2530}
2531
2532struct intel_plane *
2533intel_sprite_plane_create(struct drm_i915_private *dev_priv,
2534 enum pipe pipe, int sprite)
2535{
2536 struct intel_plane *plane;
2537 const struct drm_plane_funcs *plane_funcs;
2538 unsigned long possible_crtcs;
2539 unsigned int supported_rotations;
2540 const u64 *modifiers;
2541 const u32 *formats;
2542 int num_formats;
2543 int ret;
2544
2545 if (INTEL_GEN(dev_priv) >= 9)
2546 return skl_universal_plane_create(dev_priv, pipe,
2547 PLANE_SPRITE0 + sprite);
2548
2549 plane = intel_plane_alloc();
2550 if (IS_ERR(plane))
2551 return plane;
2552
2553 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
2554 plane->max_stride = i9xx_plane_max_stride;
2555 plane->update_plane = vlv_update_plane;
2556 plane->disable_plane = vlv_disable_plane;
2557 plane->get_hw_state = vlv_plane_get_hw_state;
2558 plane->check_plane = vlv_sprite_check;
2559
2560 formats = vlv_plane_formats;
2561 num_formats = ARRAY_SIZE(vlv_plane_formats);
2562 modifiers = i9xx_plane_format_modifiers;
2563
2564 plane_funcs = &vlv_sprite_funcs;
2565 } else if (INTEL_GEN(dev_priv) >= 7) {
2566 plane->max_stride = g4x_sprite_max_stride;
2567 plane->update_plane = ivb_update_plane;
2568 plane->disable_plane = ivb_disable_plane;
2569 plane->get_hw_state = ivb_plane_get_hw_state;
2570 plane->check_plane = g4x_sprite_check;
2571
2572 formats = snb_plane_formats;
2573 num_formats = ARRAY_SIZE(snb_plane_formats);
2574 modifiers = i9xx_plane_format_modifiers;
2575
2576 plane_funcs = &snb_sprite_funcs;
2577 } else {
2578 plane->max_stride = g4x_sprite_max_stride;
2579 plane->update_plane = g4x_update_plane;
2580 plane->disable_plane = g4x_disable_plane;
2581 plane->get_hw_state = g4x_plane_get_hw_state;
2582 plane->check_plane = g4x_sprite_check;
2583
2584 modifiers = i9xx_plane_format_modifiers;
2585 if (IS_GEN(dev_priv, 6)) {
2586 formats = snb_plane_formats;
2587 num_formats = ARRAY_SIZE(snb_plane_formats);
2588
2589 plane_funcs = &snb_sprite_funcs;
2590 } else {
2591 formats = g4x_plane_formats;
2592 num_formats = ARRAY_SIZE(g4x_plane_formats);
2593
2594 plane_funcs = &g4x_sprite_funcs;
2595 }
2596 }
2597
2598 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
2599 supported_rotations =
2600 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
2601 DRM_MODE_REFLECT_X;
2602 } else {
2603 supported_rotations =
2604 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
2605 }
2606
2607 plane->pipe = pipe;
2608 plane->id = PLANE_SPRITE0 + sprite;
2609 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
2610
2611 possible_crtcs = BIT(pipe);
2612
2613 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2614 possible_crtcs, plane_funcs,
2615 formats, num_formats, modifiers,
2616 DRM_PLANE_TYPE_OVERLAY,
2617 "sprite %c", sprite_name(pipe, sprite));
2618 if (ret)
2619 goto fail;
2620
2621 drm_plane_create_rotation_property(&plane->base,
2622 DRM_MODE_ROTATE_0,
2623 supported_rotations);
2624
2625 drm_plane_create_color_properties(&plane->base,
2626 BIT(DRM_COLOR_YCBCR_BT601) |
2627 BIT(DRM_COLOR_YCBCR_BT709),
2628 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2629 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2630 DRM_COLOR_YCBCR_BT709,
2631 DRM_COLOR_YCBCR_LIMITED_RANGE);
2632
2633 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
2634
2635 return plane;
2636
2637fail:
2638 intel_plane_free(plane);
2639
2640 return ERR_PTR(ret);
2641}
2642