1 /*
2 * Copyright © 2011 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Jesse Barnes <jbarnes@virtuousgeek.org>
25 *
26 * New plane/sprite handling.
27 *
28 * The older chips had a separate interface for programming plane related
29 * registers; newer ones are much simpler and we can use the new DRM plane
30 * support.
31 */
32
33 #include <linux/string_helpers.h>
34
35 #include <drm/drm_atomic_helper.h>
36 #include <drm/drm_blend.h>
37 #include <drm/drm_color_mgmt.h>
38 #include <drm/drm_fourcc.h>
39 #include <drm/drm_rect.h>
40
41 #include "i915_drv.h"
42 #include "i9xx_plane.h"
43 #include "intel_atomic_plane.h"
44 #include "intel_de.h"
45 #include "intel_display_types.h"
46 #include "intel_fb.h"
47 #include "intel_frontbuffer.h"
48 #include "intel_sprite.h"
49 #include "intel_sprite_regs.h"
50
sprite_name(struct intel_display * display,enum pipe pipe,int sprite)51 static char sprite_name(struct intel_display *display, enum pipe pipe, int sprite)
52 {
53 return pipe * DISPLAY_RUNTIME_INFO(display)->num_sprites[pipe] + sprite + 'A';
54 }
55
i9xx_plane_linear_gamma(u16 gamma[8])56 static void i9xx_plane_linear_gamma(u16 gamma[8])
57 {
58 /* The points are not evenly spaced. */
59 static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
60 int i;
61
62 for (i = 0; i < 8; i++)
63 gamma[i] = (in[i] << 8) / 32;
64 }
65
66 static void
chv_sprite_update_csc(const struct intel_plane_state * plane_state)67 chv_sprite_update_csc(const struct intel_plane_state *plane_state)
68 {
69 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
70 struct intel_display *display = to_intel_display(plane->base.dev);
71 const struct drm_framebuffer *fb = plane_state->hw.fb;
72 enum plane_id plane_id = plane->id;
73 /*
74 * |r| | c0 c1 c2 | |cr|
75 * |g| = | c3 c4 c5 | x |y |
76 * |b| | c6 c7 c8 | |cb|
77 *
78 * Coefficients are s3.12.
79 *
80 * Cb and Cr apparently come in as signed already, and
81 * we always get full range data in on account of CLRC0/1.
82 */
83 static const s16 csc_matrix[][9] = {
84 /* BT.601 full range YCbCr -> full range RGB */
85 [DRM_COLOR_YCBCR_BT601] = {
86 5743, 4096, 0,
87 -2925, 4096, -1410,
88 0, 4096, 7258,
89 },
90 /* BT.709 full range YCbCr -> full range RGB */
91 [DRM_COLOR_YCBCR_BT709] = {
92 6450, 4096, 0,
93 -1917, 4096, -767,
94 0, 4096, 7601,
95 },
96 };
97 const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
98
99 /* Seems RGB data bypasses the CSC always */
100 if (!fb->format->is_yuv)
101 return;
102
103 intel_de_write_fw(display, SPCSCYGOFF(plane_id),
104 SPCSC_OOFF(0) | SPCSC_IOFF(0));
105 intel_de_write_fw(display, SPCSCCBOFF(plane_id),
106 SPCSC_OOFF(0) | SPCSC_IOFF(0));
107 intel_de_write_fw(display, SPCSCCROFF(plane_id),
108 SPCSC_OOFF(0) | SPCSC_IOFF(0));
109
110 intel_de_write_fw(display, SPCSCC01(plane_id),
111 SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
112 intel_de_write_fw(display, SPCSCC23(plane_id),
113 SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
114 intel_de_write_fw(display, SPCSCC45(plane_id),
115 SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
116 intel_de_write_fw(display, SPCSCC67(plane_id),
117 SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
118 intel_de_write_fw(display, SPCSCC8(plane_id), SPCSC_C0(csc[8]));
119
120 intel_de_write_fw(display, SPCSCYGICLAMP(plane_id),
121 SPCSC_IMAX(1023) | SPCSC_IMIN(0));
122 intel_de_write_fw(display, SPCSCCBICLAMP(plane_id),
123 SPCSC_IMAX(512) | SPCSC_IMIN(-512));
124 intel_de_write_fw(display, SPCSCCRICLAMP(plane_id),
125 SPCSC_IMAX(512) | SPCSC_IMIN(-512));
126
127 intel_de_write_fw(display, SPCSCYGOCLAMP(plane_id),
128 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
129 intel_de_write_fw(display, SPCSCCBOCLAMP(plane_id),
130 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
131 intel_de_write_fw(display, SPCSCCROCLAMP(plane_id),
132 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
133 }
134
135 #define SIN_0 0
136 #define COS_0 1
137
138 static void
vlv_sprite_update_clrc(const struct intel_plane_state * plane_state)139 vlv_sprite_update_clrc(const struct intel_plane_state *plane_state)
140 {
141 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
142 struct intel_display *display = to_intel_display(plane->base.dev);
143 const struct drm_framebuffer *fb = plane_state->hw.fb;
144 enum pipe pipe = plane->pipe;
145 enum plane_id plane_id = plane->id;
146 int contrast, brightness, sh_scale, sh_sin, sh_cos;
147
148 if (fb->format->is_yuv &&
149 plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
150 /*
151 * Expand limited range to full range:
152 * Contrast is applied first and is used to expand Y range.
153 * Brightness is applied second and is used to remove the
154 * offset from Y. Saturation/hue is used to expand CbCr range.
155 */
156 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
157 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
158 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
159 sh_sin = SIN_0 * sh_scale;
160 sh_cos = COS_0 * sh_scale;
161 } else {
162 /* Pass-through everything. */
163 contrast = 1 << 6;
164 brightness = 0;
165 sh_scale = 1 << 7;
166 sh_sin = SIN_0 * sh_scale;
167 sh_cos = COS_0 * sh_scale;
168 }
169
170 /* FIXME these register are single buffered :( */
171 intel_de_write_fw(display, SPCLRC0(pipe, plane_id),
172 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
173 intel_de_write_fw(display, SPCLRC1(pipe, plane_id),
174 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
175 }
176
177 static void
vlv_plane_ratio(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state,unsigned int * num,unsigned int * den)178 vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
179 const struct intel_plane_state *plane_state,
180 unsigned int *num, unsigned int *den)
181 {
182 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
183 const struct drm_framebuffer *fb = plane_state->hw.fb;
184 unsigned int cpp = fb->format->cpp[0];
185
186 /*
187 * VLV bspec only considers cases where all three planes are
188 * enabled, and cases where the primary and one sprite is enabled.
189 * Let's assume the case with just two sprites enabled also
190 * maps to the latter case.
191 */
192 if (hweight8(active_planes) == 3) {
193 switch (cpp) {
194 case 8:
195 *num = 11;
196 *den = 8;
197 break;
198 case 4:
199 *num = 18;
200 *den = 16;
201 break;
202 default:
203 *num = 1;
204 *den = 1;
205 break;
206 }
207 } else if (hweight8(active_planes) == 2) {
208 switch (cpp) {
209 case 8:
210 *num = 10;
211 *den = 8;
212 break;
213 case 4:
214 *num = 17;
215 *den = 16;
216 break;
217 default:
218 *num = 1;
219 *den = 1;
220 break;
221 }
222 } else {
223 switch (cpp) {
224 case 8:
225 *num = 10;
226 *den = 8;
227 break;
228 default:
229 *num = 1;
230 *den = 1;
231 break;
232 }
233 }
234 }
235
vlv_plane_min_cdclk(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)236 int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
237 const struct intel_plane_state *plane_state)
238 {
239 unsigned int pixel_rate;
240 unsigned int num, den;
241
242 /*
243 * Note that crtc_state->pixel_rate accounts for both
244 * horizontal and vertical panel fitter downscaling factors.
245 * Pre-HSW bspec tells us to only consider the horizontal
246 * downscaling factor here. We ignore that and just consider
247 * both for simplicity.
248 */
249 pixel_rate = crtc_state->pixel_rate;
250
251 vlv_plane_ratio(crtc_state, plane_state, &num, &den);
252
253 return DIV_ROUND_UP(pixel_rate * num, den);
254 }
255
vlv_sprite_min_alignment(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane)256 static unsigned int vlv_sprite_min_alignment(struct intel_plane *plane,
257 const struct drm_framebuffer *fb,
258 int color_plane)
259 {
260 switch (fb->modifier) {
261 case I915_FORMAT_MOD_X_TILED:
262 return 4 * 1024;
263 case DRM_FORMAT_MOD_LINEAR:
264 return 128 * 1024;
265 default:
266 MISSING_CASE(fb->modifier);
267 return 0;
268 }
269 }
270
vlv_sprite_ctl_crtc(const struct intel_crtc_state * crtc_state)271 static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
272 {
273 u32 sprctl = 0;
274
275 if (crtc_state->gamma_enable)
276 sprctl |= SP_PIPE_GAMMA_ENABLE;
277
278 return sprctl;
279 }
280
vlv_sprite_ctl(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)281 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
282 const struct intel_plane_state *plane_state)
283 {
284 const struct drm_framebuffer *fb = plane_state->hw.fb;
285 unsigned int rotation = plane_state->hw.rotation;
286 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
287 u32 sprctl;
288
289 sprctl = SP_ENABLE;
290
291 switch (fb->format->format) {
292 case DRM_FORMAT_YUYV:
293 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
294 break;
295 case DRM_FORMAT_YVYU:
296 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
297 break;
298 case DRM_FORMAT_UYVY:
299 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
300 break;
301 case DRM_FORMAT_VYUY:
302 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
303 break;
304 case DRM_FORMAT_C8:
305 sprctl |= SP_FORMAT_8BPP;
306 break;
307 case DRM_FORMAT_RGB565:
308 sprctl |= SP_FORMAT_BGR565;
309 break;
310 case DRM_FORMAT_XRGB8888:
311 sprctl |= SP_FORMAT_BGRX8888;
312 break;
313 case DRM_FORMAT_ARGB8888:
314 sprctl |= SP_FORMAT_BGRA8888;
315 break;
316 case DRM_FORMAT_XBGR2101010:
317 sprctl |= SP_FORMAT_RGBX1010102;
318 break;
319 case DRM_FORMAT_ABGR2101010:
320 sprctl |= SP_FORMAT_RGBA1010102;
321 break;
322 case DRM_FORMAT_XRGB2101010:
323 sprctl |= SP_FORMAT_BGRX1010102;
324 break;
325 case DRM_FORMAT_ARGB2101010:
326 sprctl |= SP_FORMAT_BGRA1010102;
327 break;
328 case DRM_FORMAT_XBGR8888:
329 sprctl |= SP_FORMAT_RGBX8888;
330 break;
331 case DRM_FORMAT_ABGR8888:
332 sprctl |= SP_FORMAT_RGBA8888;
333 break;
334 default:
335 MISSING_CASE(fb->format->format);
336 return 0;
337 }
338
339 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
340 sprctl |= SP_YUV_FORMAT_BT709;
341
342 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
343 sprctl |= SP_TILED;
344
345 if (rotation & DRM_MODE_ROTATE_180)
346 sprctl |= SP_ROTATE_180;
347
348 if (rotation & DRM_MODE_REFLECT_X)
349 sprctl |= SP_MIRROR;
350
351 if (key->flags & I915_SET_COLORKEY_SOURCE)
352 sprctl |= SP_SOURCE_KEY;
353
354 return sprctl;
355 }
356
vlv_sprite_update_gamma(const struct intel_plane_state * plane_state)357 static void vlv_sprite_update_gamma(const struct intel_plane_state *plane_state)
358 {
359 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
360 struct intel_display *display = to_intel_display(plane->base.dev);
361 const struct drm_framebuffer *fb = plane_state->hw.fb;
362 enum pipe pipe = plane->pipe;
363 enum plane_id plane_id = plane->id;
364 u16 gamma[8];
365 int i;
366
367 /* Seems RGB data bypasses the gamma always */
368 if (!fb->format->is_yuv)
369 return;
370
371 i9xx_plane_linear_gamma(gamma);
372
373 /* FIXME these register are single buffered :( */
374 /* The two end points are implicit (0.0 and 1.0) */
375 for (i = 1; i < 8 - 1; i++)
376 intel_de_write_fw(display, SPGAMC(pipe, plane_id, i - 1),
377 gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
378 }
379
380 static void
vlv_sprite_update_noarm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)381 vlv_sprite_update_noarm(struct intel_plane *plane,
382 const struct intel_crtc_state *crtc_state,
383 const struct intel_plane_state *plane_state)
384 {
385 struct intel_display *display = to_intel_display(plane->base.dev);
386 enum pipe pipe = plane->pipe;
387 enum plane_id plane_id = plane->id;
388 int crtc_x = plane_state->uapi.dst.x1;
389 int crtc_y = plane_state->uapi.dst.y1;
390 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
391 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
392
393 intel_de_write_fw(display, SPSTRIDE(pipe, plane_id),
394 plane_state->view.color_plane[0].mapping_stride);
395 intel_de_write_fw(display, SPPOS(pipe, plane_id),
396 SP_POS_Y(crtc_y) | SP_POS_X(crtc_x));
397 intel_de_write_fw(display, SPSIZE(pipe, plane_id),
398 SP_HEIGHT(crtc_h - 1) | SP_WIDTH(crtc_w - 1));
399 }
400
401 static void
vlv_sprite_update_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)402 vlv_sprite_update_arm(struct intel_plane *plane,
403 const struct intel_crtc_state *crtc_state,
404 const struct intel_plane_state *plane_state)
405 {
406 struct intel_display *display = to_intel_display(plane->base.dev);
407 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
408 enum pipe pipe = plane->pipe;
409 enum plane_id plane_id = plane->id;
410 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
411 u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
412 u32 x = plane_state->view.color_plane[0].x;
413 u32 y = plane_state->view.color_plane[0].y;
414 u32 sprctl, linear_offset;
415
416 sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
417
418 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
419
420 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
421 chv_sprite_update_csc(plane_state);
422
423 if (key->flags) {
424 intel_de_write_fw(display, SPKEYMINVAL(pipe, plane_id),
425 key->min_value);
426 intel_de_write_fw(display, SPKEYMSK(pipe, plane_id),
427 key->channel_mask);
428 intel_de_write_fw(display, SPKEYMAXVAL(pipe, plane_id),
429 key->max_value);
430 }
431
432 intel_de_write_fw(display, SPCONSTALPHA(pipe, plane_id), 0);
433
434 intel_de_write_fw(display, SPLINOFF(pipe, plane_id), linear_offset);
435 intel_de_write_fw(display, SPTILEOFF(pipe, plane_id),
436 SP_OFFSET_Y(y) | SP_OFFSET_X(x));
437
438 /*
439 * The control register self-arms if the plane was previously
440 * disabled. Try to make the plane enable atomic by writing
441 * the control register just before the surface register.
442 */
443 intel_de_write_fw(display, SPCNTR(pipe, plane_id), sprctl);
444 intel_de_write_fw(display, SPSURF(pipe, plane_id),
445 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
446
447 vlv_sprite_update_clrc(plane_state);
448 vlv_sprite_update_gamma(plane_state);
449 }
450
451 static void
vlv_sprite_disable_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state)452 vlv_sprite_disable_arm(struct intel_plane *plane,
453 const struct intel_crtc_state *crtc_state)
454 {
455 struct intel_display *display = to_intel_display(plane->base.dev);
456 enum pipe pipe = plane->pipe;
457 enum plane_id plane_id = plane->id;
458
459 intel_de_write_fw(display, SPCNTR(pipe, plane_id), 0);
460 intel_de_write_fw(display, SPSURF(pipe, plane_id), 0);
461 }
462
463 static bool
vlv_sprite_get_hw_state(struct intel_plane * plane,enum pipe * pipe)464 vlv_sprite_get_hw_state(struct intel_plane *plane,
465 enum pipe *pipe)
466 {
467 struct intel_display *display = to_intel_display(plane->base.dev);
468 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
469 enum intel_display_power_domain power_domain;
470 enum plane_id plane_id = plane->id;
471 intel_wakeref_t wakeref;
472 bool ret;
473
474 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
475 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
476 if (!wakeref)
477 return false;
478
479 ret = intel_de_read(display, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
480
481 *pipe = plane->pipe;
482
483 intel_display_power_put(dev_priv, power_domain, wakeref);
484
485 return ret;
486 }
487
ivb_plane_ratio(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state,unsigned int * num,unsigned int * den)488 static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
489 const struct intel_plane_state *plane_state,
490 unsigned int *num, unsigned int *den)
491 {
492 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
493 const struct drm_framebuffer *fb = plane_state->hw.fb;
494 unsigned int cpp = fb->format->cpp[0];
495
496 if (hweight8(active_planes) == 2) {
497 switch (cpp) {
498 case 8:
499 *num = 10;
500 *den = 8;
501 break;
502 case 4:
503 *num = 17;
504 *den = 16;
505 break;
506 default:
507 *num = 1;
508 *den = 1;
509 break;
510 }
511 } else {
512 switch (cpp) {
513 case 8:
514 *num = 9;
515 *den = 8;
516 break;
517 default:
518 *num = 1;
519 *den = 1;
520 break;
521 }
522 }
523 }
524
ivb_plane_ratio_scaling(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state,unsigned int * num,unsigned int * den)525 static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
526 const struct intel_plane_state *plane_state,
527 unsigned int *num, unsigned int *den)
528 {
529 const struct drm_framebuffer *fb = plane_state->hw.fb;
530 unsigned int cpp = fb->format->cpp[0];
531
532 switch (cpp) {
533 case 8:
534 *num = 12;
535 *den = 8;
536 break;
537 case 4:
538 *num = 19;
539 *den = 16;
540 break;
541 case 2:
542 *num = 33;
543 *den = 32;
544 break;
545 default:
546 *num = 1;
547 *den = 1;
548 break;
549 }
550 }
551
ivb_plane_min_cdclk(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)552 int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
553 const struct intel_plane_state *plane_state)
554 {
555 unsigned int pixel_rate;
556 unsigned int num, den;
557
558 /*
559 * Note that crtc_state->pixel_rate accounts for both
560 * horizontal and vertical panel fitter downscaling factors.
561 * Pre-HSW bspec tells us to only consider the horizontal
562 * downscaling factor here. We ignore that and just consider
563 * both for simplicity.
564 */
565 pixel_rate = crtc_state->pixel_rate;
566
567 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
568
569 return DIV_ROUND_UP(pixel_rate * num, den);
570 }
571
ivb_sprite_min_cdclk(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)572 static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
573 const struct intel_plane_state *plane_state)
574 {
575 unsigned int src_w, dst_w, pixel_rate;
576 unsigned int num, den;
577
578 /*
579 * Note that crtc_state->pixel_rate accounts for both
580 * horizontal and vertical panel fitter downscaling factors.
581 * Pre-HSW bspec tells us to only consider the horizontal
582 * downscaling factor here. We ignore that and just consider
583 * both for simplicity.
584 */
585 pixel_rate = crtc_state->pixel_rate;
586
587 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
588 dst_w = drm_rect_width(&plane_state->uapi.dst);
589
590 if (src_w != dst_w)
591 ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
592 else
593 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
594
595 /* Horizontal downscaling limits the maximum pixel rate */
596 dst_w = min(src_w, dst_w);
597
598 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
599 den * dst_w);
600 }
601
hsw_plane_ratio(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state,unsigned int * num,unsigned int * den)602 static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
603 const struct intel_plane_state *plane_state,
604 unsigned int *num, unsigned int *den)
605 {
606 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
607 const struct drm_framebuffer *fb = plane_state->hw.fb;
608 unsigned int cpp = fb->format->cpp[0];
609
610 if (hweight8(active_planes) == 2) {
611 switch (cpp) {
612 case 8:
613 *num = 10;
614 *den = 8;
615 break;
616 default:
617 *num = 1;
618 *den = 1;
619 break;
620 }
621 } else {
622 switch (cpp) {
623 case 8:
624 *num = 9;
625 *den = 8;
626 break;
627 default:
628 *num = 1;
629 *den = 1;
630 break;
631 }
632 }
633 }
634
hsw_plane_min_cdclk(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)635 int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
636 const struct intel_plane_state *plane_state)
637 {
638 unsigned int pixel_rate = crtc_state->pixel_rate;
639 unsigned int num, den;
640
641 hsw_plane_ratio(crtc_state, plane_state, &num, &den);
642
643 return DIV_ROUND_UP(pixel_rate * num, den);
644 }
645
ivb_sprite_ctl_crtc(const struct intel_crtc_state * crtc_state)646 static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
647 {
648 u32 sprctl = 0;
649
650 if (crtc_state->gamma_enable)
651 sprctl |= SPRITE_PIPE_GAMMA_ENABLE;
652
653 if (crtc_state->csc_enable)
654 sprctl |= SPRITE_PIPE_CSC_ENABLE;
655
656 return sprctl;
657 }
658
ivb_need_sprite_gamma(const struct intel_plane_state * plane_state)659 static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
660 {
661 struct drm_i915_private *dev_priv =
662 to_i915(plane_state->uapi.plane->dev);
663 const struct drm_framebuffer *fb = plane_state->hw.fb;
664
665 return fb->format->cpp[0] == 8 &&
666 (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
667 }
668
ivb_sprite_ctl(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)669 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
670 const struct intel_plane_state *plane_state)
671 {
672 struct drm_i915_private *dev_priv =
673 to_i915(plane_state->uapi.plane->dev);
674 const struct drm_framebuffer *fb = plane_state->hw.fb;
675 unsigned int rotation = plane_state->hw.rotation;
676 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
677 u32 sprctl;
678
679 sprctl = SPRITE_ENABLE;
680
681 if (IS_IVYBRIDGE(dev_priv))
682 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
683
684 switch (fb->format->format) {
685 case DRM_FORMAT_XBGR8888:
686 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
687 break;
688 case DRM_FORMAT_XRGB8888:
689 sprctl |= SPRITE_FORMAT_RGBX888;
690 break;
691 case DRM_FORMAT_XBGR2101010:
692 sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
693 break;
694 case DRM_FORMAT_XRGB2101010:
695 sprctl |= SPRITE_FORMAT_RGBX101010;
696 break;
697 case DRM_FORMAT_XBGR16161616F:
698 sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
699 break;
700 case DRM_FORMAT_XRGB16161616F:
701 sprctl |= SPRITE_FORMAT_RGBX161616;
702 break;
703 case DRM_FORMAT_YUYV:
704 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
705 break;
706 case DRM_FORMAT_YVYU:
707 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
708 break;
709 case DRM_FORMAT_UYVY:
710 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
711 break;
712 case DRM_FORMAT_VYUY:
713 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
714 break;
715 default:
716 MISSING_CASE(fb->format->format);
717 return 0;
718 }
719
720 if (!ivb_need_sprite_gamma(plane_state))
721 sprctl |= SPRITE_PLANE_GAMMA_DISABLE;
722
723 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
724 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
725
726 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
727 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
728
729 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
730 sprctl |= SPRITE_TILED;
731
732 if (rotation & DRM_MODE_ROTATE_180)
733 sprctl |= SPRITE_ROTATE_180;
734
735 if (key->flags & I915_SET_COLORKEY_DESTINATION)
736 sprctl |= SPRITE_DEST_KEY;
737 else if (key->flags & I915_SET_COLORKEY_SOURCE)
738 sprctl |= SPRITE_SOURCE_KEY;
739
740 return sprctl;
741 }
742
ivb_sprite_linear_gamma(const struct intel_plane_state * plane_state,u16 gamma[18])743 static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
744 u16 gamma[18])
745 {
746 int scale, i;
747
748 /*
749 * WaFP16GammaEnabling:ivb,hsw
750 * "Workaround : When using the 64-bit format, the sprite output
751 * on each color channel has one quarter amplitude. It can be
752 * brought up to full amplitude by using sprite internal gamma
753 * correction, pipe gamma correction, or pipe color space
754 * conversion to multiply the sprite output by four."
755 */
756 scale = 4;
757
758 for (i = 0; i < 16; i++)
759 gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
760
761 gamma[i] = min((scale * i << 10) / 16, 1 << 10);
762 i++;
763
764 gamma[i] = 3 << 10;
765 i++;
766 }
767
ivb_sprite_update_gamma(const struct intel_plane_state * plane_state)768 static void ivb_sprite_update_gamma(const struct intel_plane_state *plane_state)
769 {
770 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
771 struct intel_display *display = to_intel_display(plane->base.dev);
772 enum pipe pipe = plane->pipe;
773 u16 gamma[18];
774 int i;
775
776 if (!ivb_need_sprite_gamma(plane_state))
777 return;
778
779 ivb_sprite_linear_gamma(plane_state, gamma);
780
781 /* FIXME these register are single buffered :( */
782 for (i = 0; i < 16; i++)
783 intel_de_write_fw(display, SPRGAMC(pipe, i),
784 gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
785
786 intel_de_write_fw(display, SPRGAMC16(pipe, 0), gamma[i]);
787 intel_de_write_fw(display, SPRGAMC16(pipe, 1), gamma[i]);
788 intel_de_write_fw(display, SPRGAMC16(pipe, 2), gamma[i]);
789 i++;
790
791 intel_de_write_fw(display, SPRGAMC17(pipe, 0), gamma[i]);
792 intel_de_write_fw(display, SPRGAMC17(pipe, 1), gamma[i]);
793 intel_de_write_fw(display, SPRGAMC17(pipe, 2), gamma[i]);
794 i++;
795 }
796
797 static void
ivb_sprite_update_noarm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)798 ivb_sprite_update_noarm(struct intel_plane *plane,
799 const struct intel_crtc_state *crtc_state,
800 const struct intel_plane_state *plane_state)
801 {
802 struct intel_display *display = to_intel_display(plane->base.dev);
803 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
804 enum pipe pipe = plane->pipe;
805 int crtc_x = plane_state->uapi.dst.x1;
806 int crtc_y = plane_state->uapi.dst.y1;
807 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
808 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
809 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
810 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
811 u32 sprscale = 0;
812
813 if (crtc_w != src_w || crtc_h != src_h)
814 sprscale = SPRITE_SCALE_ENABLE |
815 SPRITE_SRC_WIDTH(src_w - 1) |
816 SPRITE_SRC_HEIGHT(src_h - 1);
817
818 intel_de_write_fw(display, SPRSTRIDE(pipe),
819 plane_state->view.color_plane[0].mapping_stride);
820 intel_de_write_fw(display, SPRPOS(pipe),
821 SPRITE_POS_Y(crtc_y) | SPRITE_POS_X(crtc_x));
822 intel_de_write_fw(display, SPRSIZE(pipe),
823 SPRITE_HEIGHT(crtc_h - 1) | SPRITE_WIDTH(crtc_w - 1));
824 if (IS_IVYBRIDGE(dev_priv))
825 intel_de_write_fw(display, SPRSCALE(pipe), sprscale);
826 }
827
828 static void
ivb_sprite_update_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)829 ivb_sprite_update_arm(struct intel_plane *plane,
830 const struct intel_crtc_state *crtc_state,
831 const struct intel_plane_state *plane_state)
832 {
833 struct intel_display *display = to_intel_display(plane->base.dev);
834 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
835 enum pipe pipe = plane->pipe;
836 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
837 u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
838 u32 x = plane_state->view.color_plane[0].x;
839 u32 y = plane_state->view.color_plane[0].y;
840 u32 sprctl, linear_offset;
841
842 sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
843
844 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
845
846 if (key->flags) {
847 intel_de_write_fw(display, SPRKEYVAL(pipe), key->min_value);
848 intel_de_write_fw(display, SPRKEYMSK(pipe),
849 key->channel_mask);
850 intel_de_write_fw(display, SPRKEYMAX(pipe), key->max_value);
851 }
852
853 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
854 * register */
855 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
856 intel_de_write_fw(display, SPROFFSET(pipe),
857 SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
858 } else {
859 intel_de_write_fw(display, SPRLINOFF(pipe), linear_offset);
860 intel_de_write_fw(display, SPRTILEOFF(pipe),
861 SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
862 }
863
864 /*
865 * The control register self-arms if the plane was previously
866 * disabled. Try to make the plane enable atomic by writing
867 * the control register just before the surface register.
868 */
869 intel_de_write_fw(display, SPRCTL(pipe), sprctl);
870 intel_de_write_fw(display, SPRSURF(pipe),
871 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
872
873 ivb_sprite_update_gamma(plane_state);
874 }
875
876 static void
ivb_sprite_disable_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state)877 ivb_sprite_disable_arm(struct intel_plane *plane,
878 const struct intel_crtc_state *crtc_state)
879 {
880 struct intel_display *display = to_intel_display(plane->base.dev);
881 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
882 enum pipe pipe = plane->pipe;
883
884 intel_de_write_fw(display, SPRCTL(pipe), 0);
885 /* Disable the scaler */
886 if (IS_IVYBRIDGE(dev_priv))
887 intel_de_write_fw(display, SPRSCALE(pipe), 0);
888 intel_de_write_fw(display, SPRSURF(pipe), 0);
889 }
890
891 static bool
ivb_sprite_get_hw_state(struct intel_plane * plane,enum pipe * pipe)892 ivb_sprite_get_hw_state(struct intel_plane *plane,
893 enum pipe *pipe)
894 {
895 struct intel_display *display = to_intel_display(plane->base.dev);
896 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
897 enum intel_display_power_domain power_domain;
898 intel_wakeref_t wakeref;
899 bool ret;
900
901 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
902 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
903 if (!wakeref)
904 return false;
905
906 ret = intel_de_read(display, SPRCTL(plane->pipe)) & SPRITE_ENABLE;
907
908 *pipe = plane->pipe;
909
910 intel_display_power_put(dev_priv, power_domain, wakeref);
911
912 return ret;
913 }
914
g4x_sprite_min_cdclk(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)915 static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
916 const struct intel_plane_state *plane_state)
917 {
918 const struct drm_framebuffer *fb = plane_state->hw.fb;
919 unsigned int hscale, pixel_rate;
920 unsigned int limit, decimate;
921
922 /*
923 * Note that crtc_state->pixel_rate accounts for both
924 * horizontal and vertical panel fitter downscaling factors.
925 * Pre-HSW bspec tells us to only consider the horizontal
926 * downscaling factor here. We ignore that and just consider
927 * both for simplicity.
928 */
929 pixel_rate = crtc_state->pixel_rate;
930
931 /* Horizontal downscaling limits the maximum pixel rate */
932 hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
933 &plane_state->uapi.dst,
934 0, INT_MAX);
935 hscale = max(hscale, 0x10000u);
936
937 /* Decimation steps at 2x,4x,8x,16x */
938 decimate = ilog2(hscale >> 16);
939 hscale >>= decimate;
940
941 /* Starting limit is 90% of cdclk */
942 limit = 9;
943
944 /* -10% per decimation step */
945 limit -= decimate;
946
947 /* -10% for RGB */
948 if (!fb->format->is_yuv)
949 limit--;
950
951 /*
952 * We should also do -10% if sprite scaling is enabled
953 * on the other pipe, but we can't really check for that,
954 * so we ignore it.
955 */
956
957 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
958 limit << 16);
959 }
960
961 static unsigned int
g4x_sprite_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)962 g4x_sprite_max_stride(struct intel_plane *plane,
963 u32 pixel_format, u64 modifier,
964 unsigned int rotation)
965 {
966 const struct drm_format_info *info = drm_format_info(pixel_format);
967 int cpp = info->cpp[0];
968
969 /* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
970 if (modifier == I915_FORMAT_MOD_X_TILED)
971 return min(4096 * cpp, 16 * 1024);
972 else
973 return 16 * 1024;
974 }
975
976 static unsigned int
hsw_sprite_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)977 hsw_sprite_max_stride(struct intel_plane *plane,
978 u32 pixel_format, u64 modifier,
979 unsigned int rotation)
980 {
981 const struct drm_format_info *info = drm_format_info(pixel_format);
982 int cpp = info->cpp[0];
983
984 /* Limit to 8k pixels to guarantee OFFSET.x doesn't get too big. */
985 return min(8192 * cpp, 16 * 1024);
986 }
987
g4x_sprite_min_alignment(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane)988 static unsigned int g4x_sprite_min_alignment(struct intel_plane *plane,
989 const struct drm_framebuffer *fb,
990 int color_plane)
991 {
992 return 4 * 1024;
993 }
994
g4x_sprite_ctl_crtc(const struct intel_crtc_state * crtc_state)995 static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
996 {
997 u32 dvscntr = 0;
998
999 if (crtc_state->gamma_enable)
1000 dvscntr |= DVS_PIPE_GAMMA_ENABLE;
1001
1002 if (crtc_state->csc_enable)
1003 dvscntr |= DVS_PIPE_CSC_ENABLE;
1004
1005 return dvscntr;
1006 }
1007
g4x_sprite_ctl(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)1008 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1009 const struct intel_plane_state *plane_state)
1010 {
1011 struct drm_i915_private *dev_priv =
1012 to_i915(plane_state->uapi.plane->dev);
1013 const struct drm_framebuffer *fb = plane_state->hw.fb;
1014 unsigned int rotation = plane_state->hw.rotation;
1015 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1016 u32 dvscntr;
1017
1018 dvscntr = DVS_ENABLE;
1019
1020 if (IS_SANDYBRIDGE(dev_priv))
1021 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1022
1023 switch (fb->format->format) {
1024 case DRM_FORMAT_XBGR8888:
1025 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1026 break;
1027 case DRM_FORMAT_XRGB8888:
1028 dvscntr |= DVS_FORMAT_RGBX888;
1029 break;
1030 case DRM_FORMAT_XBGR2101010:
1031 dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
1032 break;
1033 case DRM_FORMAT_XRGB2101010:
1034 dvscntr |= DVS_FORMAT_RGBX101010;
1035 break;
1036 case DRM_FORMAT_XBGR16161616F:
1037 dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1038 break;
1039 case DRM_FORMAT_XRGB16161616F:
1040 dvscntr |= DVS_FORMAT_RGBX161616;
1041 break;
1042 case DRM_FORMAT_YUYV:
1043 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1044 break;
1045 case DRM_FORMAT_YVYU:
1046 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1047 break;
1048 case DRM_FORMAT_UYVY:
1049 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1050 break;
1051 case DRM_FORMAT_VYUY:
1052 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1053 break;
1054 default:
1055 MISSING_CASE(fb->format->format);
1056 return 0;
1057 }
1058
1059 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1060 dvscntr |= DVS_YUV_FORMAT_BT709;
1061
1062 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1063 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1064
1065 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1066 dvscntr |= DVS_TILED;
1067
1068 if (rotation & DRM_MODE_ROTATE_180)
1069 dvscntr |= DVS_ROTATE_180;
1070
1071 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1072 dvscntr |= DVS_DEST_KEY;
1073 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1074 dvscntr |= DVS_SOURCE_KEY;
1075
1076 return dvscntr;
1077 }
1078
g4x_sprite_update_gamma(const struct intel_plane_state * plane_state)1079 static void g4x_sprite_update_gamma(const struct intel_plane_state *plane_state)
1080 {
1081 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1082 struct intel_display *display = to_intel_display(plane->base.dev);
1083 const struct drm_framebuffer *fb = plane_state->hw.fb;
1084 enum pipe pipe = plane->pipe;
1085 u16 gamma[8];
1086 int i;
1087
1088 /* Seems RGB data bypasses the gamma always */
1089 if (!fb->format->is_yuv)
1090 return;
1091
1092 i9xx_plane_linear_gamma(gamma);
1093
1094 /* FIXME these register are single buffered :( */
1095 /* The two end points are implicit (0.0 and 1.0) */
1096 for (i = 1; i < 8 - 1; i++)
1097 intel_de_write_fw(display, DVSGAMC_G4X(pipe, i - 1),
1098 gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
1099 }
1100
ilk_sprite_linear_gamma(u16 gamma[17])1101 static void ilk_sprite_linear_gamma(u16 gamma[17])
1102 {
1103 int i;
1104
1105 for (i = 0; i < 17; i++)
1106 gamma[i] = (i << 10) / 16;
1107 }
1108
ilk_sprite_update_gamma(const struct intel_plane_state * plane_state)1109 static void ilk_sprite_update_gamma(const struct intel_plane_state *plane_state)
1110 {
1111 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1112 struct intel_display *display = to_intel_display(plane->base.dev);
1113 const struct drm_framebuffer *fb = plane_state->hw.fb;
1114 enum pipe pipe = plane->pipe;
1115 u16 gamma[17];
1116 int i;
1117
1118 /* Seems RGB data bypasses the gamma always */
1119 if (!fb->format->is_yuv)
1120 return;
1121
1122 ilk_sprite_linear_gamma(gamma);
1123
1124 /* FIXME these register are single buffered :( */
1125 for (i = 0; i < 16; i++)
1126 intel_de_write_fw(display, DVSGAMC_ILK(pipe, i),
1127 gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
1128
1129 intel_de_write_fw(display, DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1130 intel_de_write_fw(display, DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1131 intel_de_write_fw(display, DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1132 i++;
1133 }
1134
1135 static void
g4x_sprite_update_noarm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)1136 g4x_sprite_update_noarm(struct intel_plane *plane,
1137 const struct intel_crtc_state *crtc_state,
1138 const struct intel_plane_state *plane_state)
1139 {
1140 struct intel_display *display = to_intel_display(plane->base.dev);
1141 enum pipe pipe = plane->pipe;
1142 int crtc_x = plane_state->uapi.dst.x1;
1143 int crtc_y = plane_state->uapi.dst.y1;
1144 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1145 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1146 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1147 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1148 u32 dvsscale = 0;
1149
1150 if (crtc_w != src_w || crtc_h != src_h)
1151 dvsscale = DVS_SCALE_ENABLE |
1152 DVS_SRC_WIDTH(src_w - 1) |
1153 DVS_SRC_HEIGHT(src_h - 1);
1154
1155 intel_de_write_fw(display, DVSSTRIDE(pipe),
1156 plane_state->view.color_plane[0].mapping_stride);
1157 intel_de_write_fw(display, DVSPOS(pipe),
1158 DVS_POS_Y(crtc_y) | DVS_POS_X(crtc_x));
1159 intel_de_write_fw(display, DVSSIZE(pipe),
1160 DVS_HEIGHT(crtc_h - 1) | DVS_WIDTH(crtc_w - 1));
1161 intel_de_write_fw(display, DVSSCALE(pipe), dvsscale);
1162 }
1163
1164 static void
g4x_sprite_update_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)1165 g4x_sprite_update_arm(struct intel_plane *plane,
1166 const struct intel_crtc_state *crtc_state,
1167 const struct intel_plane_state *plane_state)
1168 {
1169 struct intel_display *display = to_intel_display(plane->base.dev);
1170 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1171 enum pipe pipe = plane->pipe;
1172 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1173 u32 dvssurf_offset = plane_state->view.color_plane[0].offset;
1174 u32 x = plane_state->view.color_plane[0].x;
1175 u32 y = plane_state->view.color_plane[0].y;
1176 u32 dvscntr, linear_offset;
1177
1178 dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1179
1180 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1181
1182 if (key->flags) {
1183 intel_de_write_fw(display, DVSKEYVAL(pipe), key->min_value);
1184 intel_de_write_fw(display, DVSKEYMSK(pipe),
1185 key->channel_mask);
1186 intel_de_write_fw(display, DVSKEYMAX(pipe), key->max_value);
1187 }
1188
1189 intel_de_write_fw(display, DVSLINOFF(pipe), linear_offset);
1190 intel_de_write_fw(display, DVSTILEOFF(pipe),
1191 DVS_OFFSET_Y(y) | DVS_OFFSET_X(x));
1192
1193 /*
1194 * The control register self-arms if the plane was previously
1195 * disabled. Try to make the plane enable atomic by writing
1196 * the control register just before the surface register.
1197 */
1198 intel_de_write_fw(display, DVSCNTR(pipe), dvscntr);
1199 intel_de_write_fw(display, DVSSURF(pipe),
1200 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1201
1202 if (IS_G4X(dev_priv))
1203 g4x_sprite_update_gamma(plane_state);
1204 else
1205 ilk_sprite_update_gamma(plane_state);
1206 }
1207
1208 static void
g4x_sprite_disable_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state)1209 g4x_sprite_disable_arm(struct intel_plane *plane,
1210 const struct intel_crtc_state *crtc_state)
1211 {
1212 struct intel_display *display = to_intel_display(plane->base.dev);
1213 enum pipe pipe = plane->pipe;
1214
1215 intel_de_write_fw(display, DVSCNTR(pipe), 0);
1216 /* Disable the scaler */
1217 intel_de_write_fw(display, DVSSCALE(pipe), 0);
1218 intel_de_write_fw(display, DVSSURF(pipe), 0);
1219 }
1220
1221 static bool
g4x_sprite_get_hw_state(struct intel_plane * plane,enum pipe * pipe)1222 g4x_sprite_get_hw_state(struct intel_plane *plane,
1223 enum pipe *pipe)
1224 {
1225 struct intel_display *display = to_intel_display(plane->base.dev);
1226 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1227 enum intel_display_power_domain power_domain;
1228 intel_wakeref_t wakeref;
1229 bool ret;
1230
1231 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1232 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1233 if (!wakeref)
1234 return false;
1235
1236 ret = intel_de_read(display, DVSCNTR(plane->pipe)) & DVS_ENABLE;
1237
1238 *pipe = plane->pipe;
1239
1240 intel_display_power_put(dev_priv, power_domain, wakeref);
1241
1242 return ret;
1243 }
1244
g4x_fb_scalable(const struct drm_framebuffer * fb)1245 static bool g4x_fb_scalable(const struct drm_framebuffer *fb)
1246 {
1247 if (!fb)
1248 return false;
1249
1250 switch (fb->format->format) {
1251 case DRM_FORMAT_C8:
1252 case DRM_FORMAT_XRGB16161616F:
1253 case DRM_FORMAT_ARGB16161616F:
1254 case DRM_FORMAT_XBGR16161616F:
1255 case DRM_FORMAT_ABGR16161616F:
1256 return false;
1257 default:
1258 return true;
1259 }
1260 }
1261
1262 static int
g4x_sprite_check_scaling(struct intel_crtc_state * crtc_state,struct intel_plane_state * plane_state)1263 g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1264 struct intel_plane_state *plane_state)
1265 {
1266 struct intel_display *display = to_intel_display(crtc_state);
1267 const struct drm_framebuffer *fb = plane_state->hw.fb;
1268 const struct drm_rect *src = &plane_state->uapi.src;
1269 const struct drm_rect *dst = &plane_state->uapi.dst;
1270 int src_x, src_w, src_h, crtc_w, crtc_h;
1271 const struct drm_display_mode *adjusted_mode =
1272 &crtc_state->hw.adjusted_mode;
1273 unsigned int stride = plane_state->view.color_plane[0].mapping_stride;
1274 unsigned int cpp = fb->format->cpp[0];
1275 unsigned int width_bytes;
1276 int min_width, min_height;
1277
1278 crtc_w = drm_rect_width(dst);
1279 crtc_h = drm_rect_height(dst);
1280
1281 src_x = src->x1 >> 16;
1282 src_w = drm_rect_width(src) >> 16;
1283 src_h = drm_rect_height(src) >> 16;
1284
1285 if (src_w == crtc_w && src_h == crtc_h)
1286 return 0;
1287
1288 min_width = 3;
1289
1290 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1291 if (src_h & 1) {
1292 drm_dbg_kms(display->drm,
1293 "Source height must be even with interlaced modes\n");
1294 return -EINVAL;
1295 }
1296 min_height = 6;
1297 } else {
1298 min_height = 3;
1299 }
1300
1301 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1302
1303 if (src_w < min_width || src_h < min_height ||
1304 src_w > 2048 || src_h > 2048) {
1305 drm_dbg_kms(display->drm,
1306 "Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1307 src_w, src_h, min_width, min_height, 2048, 2048);
1308 return -EINVAL;
1309 }
1310
1311 if (width_bytes > 4096) {
1312 drm_dbg_kms(display->drm,
1313 "Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1314 width_bytes, 4096);
1315 return -EINVAL;
1316 }
1317
1318 if (stride > 4096) {
1319 drm_dbg_kms(display->drm,
1320 "Stride (%u) exceeds hardware max with scaling (%u)\n",
1321 stride, 4096);
1322 return -EINVAL;
1323 }
1324
1325 return 0;
1326 }
1327
1328 static int
g4x_sprite_check(struct intel_crtc_state * crtc_state,struct intel_plane_state * plane_state)1329 g4x_sprite_check(struct intel_crtc_state *crtc_state,
1330 struct intel_plane_state *plane_state)
1331 {
1332 struct intel_display *display = to_intel_display(crtc_state);
1333 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1334 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1335 int min_scale = DRM_PLANE_NO_SCALING;
1336 int max_scale = DRM_PLANE_NO_SCALING;
1337 int ret;
1338
1339 if (g4x_fb_scalable(plane_state->hw.fb)) {
1340 if (DISPLAY_VER(display) < 7) {
1341 min_scale = 1;
1342 max_scale = 16 << 16;
1343 } else if (IS_IVYBRIDGE(dev_priv)) {
1344 min_scale = 1;
1345 max_scale = 2 << 16;
1346 }
1347 }
1348
1349 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1350 min_scale, max_scale, true);
1351 if (ret)
1352 return ret;
1353
1354 ret = i9xx_check_plane_surface(plane_state);
1355 if (ret)
1356 return ret;
1357
1358 if (!plane_state->uapi.visible)
1359 return 0;
1360
1361 ret = intel_plane_check_src_coordinates(plane_state);
1362 if (ret)
1363 return ret;
1364
1365 ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1366 if (ret)
1367 return ret;
1368
1369 if (DISPLAY_VER(display) >= 7)
1370 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1371 else
1372 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1373
1374 return 0;
1375 }
1376
chv_plane_check_rotation(const struct intel_plane_state * plane_state)1377 int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1378 {
1379 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1380 struct intel_display *display = to_intel_display(plane->base.dev);
1381 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1382 unsigned int rotation = plane_state->hw.rotation;
1383
1384 /* CHV ignores the mirror bit when the rotate bit is set :( */
1385 if (IS_CHERRYVIEW(dev_priv) &&
1386 rotation & DRM_MODE_ROTATE_180 &&
1387 rotation & DRM_MODE_REFLECT_X) {
1388 drm_dbg_kms(display->drm,
1389 "Cannot rotate and reflect at the same time\n");
1390 return -EINVAL;
1391 }
1392
1393 return 0;
1394 }
1395
1396 static int
vlv_sprite_check(struct intel_crtc_state * crtc_state,struct intel_plane_state * plane_state)1397 vlv_sprite_check(struct intel_crtc_state *crtc_state,
1398 struct intel_plane_state *plane_state)
1399 {
1400 int ret;
1401
1402 ret = chv_plane_check_rotation(plane_state);
1403 if (ret)
1404 return ret;
1405
1406 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1407 DRM_PLANE_NO_SCALING,
1408 DRM_PLANE_NO_SCALING,
1409 true);
1410 if (ret)
1411 return ret;
1412
1413 ret = i9xx_check_plane_surface(plane_state);
1414 if (ret)
1415 return ret;
1416
1417 if (!plane_state->uapi.visible)
1418 return 0;
1419
1420 ret = intel_plane_check_src_coordinates(plane_state);
1421 if (ret)
1422 return ret;
1423
1424 plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1425
1426 return 0;
1427 }
1428
1429 static const u32 g4x_sprite_formats[] = {
1430 DRM_FORMAT_XRGB8888,
1431 DRM_FORMAT_YUYV,
1432 DRM_FORMAT_YVYU,
1433 DRM_FORMAT_UYVY,
1434 DRM_FORMAT_VYUY,
1435 };
1436
1437 static const u32 snb_sprite_formats[] = {
1438 DRM_FORMAT_XRGB8888,
1439 DRM_FORMAT_XBGR8888,
1440 DRM_FORMAT_XRGB2101010,
1441 DRM_FORMAT_XBGR2101010,
1442 DRM_FORMAT_XRGB16161616F,
1443 DRM_FORMAT_XBGR16161616F,
1444 DRM_FORMAT_YUYV,
1445 DRM_FORMAT_YVYU,
1446 DRM_FORMAT_UYVY,
1447 DRM_FORMAT_VYUY,
1448 };
1449
1450 static const u32 vlv_sprite_formats[] = {
1451 DRM_FORMAT_C8,
1452 DRM_FORMAT_RGB565,
1453 DRM_FORMAT_XRGB8888,
1454 DRM_FORMAT_XBGR8888,
1455 DRM_FORMAT_ARGB8888,
1456 DRM_FORMAT_ABGR8888,
1457 DRM_FORMAT_XBGR2101010,
1458 DRM_FORMAT_ABGR2101010,
1459 DRM_FORMAT_YUYV,
1460 DRM_FORMAT_YVYU,
1461 DRM_FORMAT_UYVY,
1462 DRM_FORMAT_VYUY,
1463 };
1464
1465 static const u32 chv_pipe_b_sprite_formats[] = {
1466 DRM_FORMAT_C8,
1467 DRM_FORMAT_RGB565,
1468 DRM_FORMAT_XRGB8888,
1469 DRM_FORMAT_XBGR8888,
1470 DRM_FORMAT_ARGB8888,
1471 DRM_FORMAT_ABGR8888,
1472 DRM_FORMAT_XRGB2101010,
1473 DRM_FORMAT_XBGR2101010,
1474 DRM_FORMAT_ARGB2101010,
1475 DRM_FORMAT_ABGR2101010,
1476 DRM_FORMAT_YUYV,
1477 DRM_FORMAT_YVYU,
1478 DRM_FORMAT_UYVY,
1479 DRM_FORMAT_VYUY,
1480 };
1481
g4x_sprite_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)1482 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1483 u32 format, u64 modifier)
1484 {
1485 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1486 return false;
1487
1488 switch (format) {
1489 case DRM_FORMAT_XRGB8888:
1490 case DRM_FORMAT_YUYV:
1491 case DRM_FORMAT_YVYU:
1492 case DRM_FORMAT_UYVY:
1493 case DRM_FORMAT_VYUY:
1494 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1495 modifier == I915_FORMAT_MOD_X_TILED)
1496 return true;
1497 fallthrough;
1498 default:
1499 return false;
1500 }
1501 }
1502
snb_sprite_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)1503 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1504 u32 format, u64 modifier)
1505 {
1506 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1507 return false;
1508
1509 switch (format) {
1510 case DRM_FORMAT_XRGB8888:
1511 case DRM_FORMAT_XBGR8888:
1512 case DRM_FORMAT_XRGB2101010:
1513 case DRM_FORMAT_XBGR2101010:
1514 case DRM_FORMAT_XRGB16161616F:
1515 case DRM_FORMAT_XBGR16161616F:
1516 case DRM_FORMAT_YUYV:
1517 case DRM_FORMAT_YVYU:
1518 case DRM_FORMAT_UYVY:
1519 case DRM_FORMAT_VYUY:
1520 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1521 modifier == I915_FORMAT_MOD_X_TILED)
1522 return true;
1523 fallthrough;
1524 default:
1525 return false;
1526 }
1527 }
1528
vlv_sprite_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)1529 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1530 u32 format, u64 modifier)
1531 {
1532 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1533 return false;
1534
1535 switch (format) {
1536 case DRM_FORMAT_C8:
1537 case DRM_FORMAT_RGB565:
1538 case DRM_FORMAT_ABGR8888:
1539 case DRM_FORMAT_ARGB8888:
1540 case DRM_FORMAT_XBGR8888:
1541 case DRM_FORMAT_XRGB8888:
1542 case DRM_FORMAT_XBGR2101010:
1543 case DRM_FORMAT_ABGR2101010:
1544 case DRM_FORMAT_XRGB2101010:
1545 case DRM_FORMAT_ARGB2101010:
1546 case DRM_FORMAT_YUYV:
1547 case DRM_FORMAT_YVYU:
1548 case DRM_FORMAT_UYVY:
1549 case DRM_FORMAT_VYUY:
1550 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1551 modifier == I915_FORMAT_MOD_X_TILED)
1552 return true;
1553 fallthrough;
1554 default:
1555 return false;
1556 }
1557 }
1558
1559 static const struct drm_plane_funcs g4x_sprite_funcs = {
1560 .update_plane = drm_atomic_helper_update_plane,
1561 .disable_plane = drm_atomic_helper_disable_plane,
1562 .destroy = intel_plane_destroy,
1563 .atomic_duplicate_state = intel_plane_duplicate_state,
1564 .atomic_destroy_state = intel_plane_destroy_state,
1565 .format_mod_supported = g4x_sprite_format_mod_supported,
1566 };
1567
1568 static const struct drm_plane_funcs snb_sprite_funcs = {
1569 .update_plane = drm_atomic_helper_update_plane,
1570 .disable_plane = drm_atomic_helper_disable_plane,
1571 .destroy = intel_plane_destroy,
1572 .atomic_duplicate_state = intel_plane_duplicate_state,
1573 .atomic_destroy_state = intel_plane_destroy_state,
1574 .format_mod_supported = snb_sprite_format_mod_supported,
1575 };
1576
1577 static const struct drm_plane_funcs vlv_sprite_funcs = {
1578 .update_plane = drm_atomic_helper_update_plane,
1579 .disable_plane = drm_atomic_helper_disable_plane,
1580 .destroy = intel_plane_destroy,
1581 .atomic_duplicate_state = intel_plane_duplicate_state,
1582 .atomic_destroy_state = intel_plane_destroy_state,
1583 .format_mod_supported = vlv_sprite_format_mod_supported,
1584 };
1585
1586 struct intel_plane *
intel_sprite_plane_create(struct drm_i915_private * dev_priv,enum pipe pipe,int sprite)1587 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1588 enum pipe pipe, int sprite)
1589 {
1590 struct intel_display *display = &dev_priv->display;
1591 struct intel_plane *plane;
1592 const struct drm_plane_funcs *plane_funcs;
1593 unsigned int supported_rotations;
1594 const u64 *modifiers;
1595 const u32 *formats;
1596 int num_formats;
1597 int ret, zpos;
1598
1599 plane = intel_plane_alloc();
1600 if (IS_ERR(plane))
1601 return plane;
1602
1603 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1604 plane->update_noarm = vlv_sprite_update_noarm;
1605 plane->update_arm = vlv_sprite_update_arm;
1606 plane->disable_arm = vlv_sprite_disable_arm;
1607 plane->get_hw_state = vlv_sprite_get_hw_state;
1608 plane->check_plane = vlv_sprite_check;
1609 plane->max_stride = i965_plane_max_stride;
1610 plane->min_alignment = vlv_sprite_min_alignment;
1611 plane->min_cdclk = vlv_plane_min_cdclk;
1612
1613 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1614 formats = chv_pipe_b_sprite_formats;
1615 num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
1616 } else {
1617 formats = vlv_sprite_formats;
1618 num_formats = ARRAY_SIZE(vlv_sprite_formats);
1619 }
1620
1621 plane_funcs = &vlv_sprite_funcs;
1622 } else if (DISPLAY_VER(display) >= 7) {
1623 plane->update_noarm = ivb_sprite_update_noarm;
1624 plane->update_arm = ivb_sprite_update_arm;
1625 plane->disable_arm = ivb_sprite_disable_arm;
1626 plane->get_hw_state = ivb_sprite_get_hw_state;
1627 plane->check_plane = g4x_sprite_check;
1628
1629 if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
1630 plane->max_stride = hsw_sprite_max_stride;
1631 plane->min_cdclk = hsw_plane_min_cdclk;
1632 } else {
1633 plane->max_stride = g4x_sprite_max_stride;
1634 plane->min_cdclk = ivb_sprite_min_cdclk;
1635 }
1636
1637 plane->min_alignment = g4x_sprite_min_alignment;
1638
1639 formats = snb_sprite_formats;
1640 num_formats = ARRAY_SIZE(snb_sprite_formats);
1641
1642 plane_funcs = &snb_sprite_funcs;
1643 } else {
1644 plane->update_noarm = g4x_sprite_update_noarm;
1645 plane->update_arm = g4x_sprite_update_arm;
1646 plane->disable_arm = g4x_sprite_disable_arm;
1647 plane->get_hw_state = g4x_sprite_get_hw_state;
1648 plane->check_plane = g4x_sprite_check;
1649 plane->max_stride = g4x_sprite_max_stride;
1650 plane->min_alignment = g4x_sprite_min_alignment;
1651 plane->min_cdclk = g4x_sprite_min_cdclk;
1652
1653 if (IS_SANDYBRIDGE(dev_priv)) {
1654 formats = snb_sprite_formats;
1655 num_formats = ARRAY_SIZE(snb_sprite_formats);
1656
1657 plane_funcs = &snb_sprite_funcs;
1658 } else {
1659 formats = g4x_sprite_formats;
1660 num_formats = ARRAY_SIZE(g4x_sprite_formats);
1661
1662 plane_funcs = &g4x_sprite_funcs;
1663 }
1664 }
1665
1666 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1667 supported_rotations =
1668 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1669 DRM_MODE_REFLECT_X;
1670 } else {
1671 supported_rotations =
1672 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1673 }
1674
1675 plane->pipe = pipe;
1676 plane->id = PLANE_SPRITE0 + sprite;
1677 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
1678
1679 modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X);
1680
1681 ret = drm_universal_plane_init(display->drm, &plane->base,
1682 0, plane_funcs,
1683 formats, num_formats, modifiers,
1684 DRM_PLANE_TYPE_OVERLAY,
1685 "sprite %c", sprite_name(display, pipe, sprite));
1686 kfree(modifiers);
1687
1688 if (ret)
1689 goto fail;
1690
1691 drm_plane_create_rotation_property(&plane->base,
1692 DRM_MODE_ROTATE_0,
1693 supported_rotations);
1694
1695 drm_plane_create_color_properties(&plane->base,
1696 BIT(DRM_COLOR_YCBCR_BT601) |
1697 BIT(DRM_COLOR_YCBCR_BT709),
1698 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1699 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1700 DRM_COLOR_YCBCR_BT709,
1701 DRM_COLOR_YCBCR_LIMITED_RANGE);
1702
1703 zpos = sprite + 1;
1704 drm_plane_create_zpos_immutable_property(&plane->base, zpos);
1705
1706 intel_plane_helper_add(plane);
1707
1708 return plane;
1709
1710 fail:
1711 intel_plane_free(plane);
1712
1713 return ERR_PTR(ret);
1714 }
1715