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