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