intel_sprite.c revision 1.4 1 /* $NetBSD: intel_sprite.c,v 1.4 2021/12/19 12:04:33 riastradh Exp $ */
2
3 /*
4 * Copyright 2011 Intel Corporation
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 * Jesse Barnes <jbarnes (at) virtuousgeek.org>
27 *
28 * New plane/sprite handling.
29 *
30 * The older chips had a separate interface for programming plane related
31 * registers; newer ones are much simpler and we can use the new DRM plane
32 * support.
33 */
34
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: intel_sprite.c,v 1.4 2021/12/19 12:04:33 riastradh Exp $");
37
38 #include <drm/drm_atomic.h>
39 #include <drm/drm_atomic_helper.h>
40 #include <drm/drm_color_mgmt.h>
41 #include <drm/drm_crtc.h>
42 #include <drm/drm_fourcc.h>
43 #include <drm/drm_plane_helper.h>
44 #include <drm/drm_rect.h>
45 #include <drm/i915_drm.h>
46
47 #include "i915_drv.h"
48 #include "i915_trace.h"
49 #include "intel_atomic_plane.h"
50 #include "intel_display_types.h"
51 #include "intel_frontbuffer.h"
52 #include "intel_pm.h"
53 #include "intel_psr.h"
54 #include "intel_sprite.h"
55
56 int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
57 int usecs)
58 {
59 /* paranoia */
60 if (!adjusted_mode->crtc_htotal)
61 return 1;
62
63 return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
64 1000 * adjusted_mode->crtc_htotal);
65 }
66
67 /* FIXME: We should instead only take spinlocks once for the entire update
68 * instead of once per mmio. */
69 #if IS_ENABLED(CONFIG_PROVE_LOCKING)
70 #define VBLANK_EVASION_TIME_US 250
71 #else
72 #define VBLANK_EVASION_TIME_US 100
73 #endif
74
75 /**
76 * intel_pipe_update_start() - start update of a set of display registers
77 * @new_crtc_state: the new crtc state
78 *
79 * Mark the start of an update to pipe registers that should be updated
80 * atomically regarding vblank. If the next vblank will happens within
81 * the next 100 us, this function waits until the vblank passes.
82 *
83 * After a successful call to this function, interrupts will be disabled
84 * until a subsequent call to intel_pipe_update_end(). That is done to
85 * avoid random delays.
86 */
87 void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
88 {
89 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
90 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
91 const struct drm_display_mode *adjusted_mode = &new_crtc_state->hw.adjusted_mode;
92 long timeout = msecs_to_jiffies_timeout(1);
93 int scanline, min, max, vblank_start;
94 drm_waitqueue_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
95 int ret;
96 bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
97 intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
98 u32 psr_status;
99
100 vblank_start = adjusted_mode->crtc_vblank_start;
101 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
102 vblank_start = DIV_ROUND_UP(vblank_start, 2);
103
104 /* FIXME needs to be calibrated sensibly */
105 min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
106 VBLANK_EVASION_TIME_US);
107 max = vblank_start - 1;
108
109 if (min <= 0 || max <= 0)
110 goto irq_disable;
111
112 if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
113 goto irq_disable;
114
115 /*
116 * Wait for psr to idle out after enabling the VBL interrupts
117 * VBL interrupts will start the PSR exit and prevent a PSR
118 * re-entry as well.
119 */
120 if (intel_psr_wait_for_idle(new_crtc_state, &psr_status))
121 DRM_ERROR("PSR idle timed out 0x%x, atomic update may fail\n",
122 psr_status);
123
124 spin_lock(&crtc->base.dev->event_lock);
125 spin_lock(&dev_priv->drm.vbl_lock);
126
127 crtc->debug.min_vbl = min;
128 crtc->debug.max_vbl = max;
129 trace_intel_pipe_update_start(crtc);
130
131 DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(ret, wq, &dev_priv->drm.vbl_lock,
132 timeout,
133 (scanline = intel_get_crtc_scanline(crtc),
134 scanline < min || scanline > max));
135 if (ret <= 0)
136 DRM_ERROR("Potential atomic update failure on pipe %c: %d\n",
137 pipe_name(crtc->pipe), ret ? ret : -EWOULDBLOCK);
138 drm_crtc_vblank_put_locked(&crtc->base);
139
140 /*
141 * On VLV/CHV DSI the scanline counter would appear to
142 * increment approx. 1/3 of a scanline before start of vblank.
143 * The registers still get latched at start of vblank however.
144 * This means we must not write any registers on the first
145 * line of vblank (since not the whole line is actually in
146 * vblank). And unfortunately we can't use the interrupt to
147 * wait here since it will fire too soon. We could use the
148 * frame start interrupt instead since it will fire after the
149 * critical scanline, but that would require more changes
150 * in the interrupt code. So for now we'll just do the nasty
151 * thing and poll for the bad scanline to pass us by.
152 *
153 * FIXME figure out if BXT+ DSI suffers from this as well
154 */
155 while (need_vlv_dsi_wa && scanline == vblank_start)
156 scanline = intel_get_crtc_scanline(crtc);
157
158 crtc->debug.scanline_start = scanline;
159 crtc->debug.start_vbl_time = ktime_get();
160 crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
161
162 trace_intel_pipe_update_vblank_evaded(crtc);
163 return;
164
165 irq_disable:
166 spin_lock(&crtc->base.dev->event_lock);
167 spin_lock(&dev_priv->drm.vbl_lock);
168 }
169
170 /**
171 * intel_pipe_update_end() - end update of a set of display registers
172 * @new_crtc_state: the new crtc state
173 *
174 * Mark the end of an update started with intel_pipe_update_start(). This
175 * re-enables interrupts and verifies the update was actually completed
176 * before a vblank.
177 */
178 void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
179 {
180 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
181 enum pipe pipe = crtc->pipe;
182 int scanline_end = intel_get_crtc_scanline(crtc);
183 u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
184 ktime_t end_vbl_time = ktime_get();
185 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
186
187 trace_intel_pipe_update_end(crtc, end_vbl_count, scanline_end);
188
189 /* We're still in the vblank-evade critical section, this can't race.
190 * Would be slightly nice to just grab the vblank count and arm the
191 * event outside of the critical section - the spinlock might spin for a
192 * while ... */
193 if (new_crtc_state->uapi.event) {
194 #ifndef __NetBSD__ /* XXX locking against self */
195 WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);
196 #endif
197
198 drm_crtc_arm_vblank_event(&crtc->base,
199 new_crtc_state->uapi.event);
200
201 new_crtc_state->uapi.event = NULL;
202 }
203
204 spin_unlock(&dev_priv->drm.vbl_lock);
205 spin_unlock(&crtc->base.dev->event_lock);
206
207 if (intel_vgpu_active(dev_priv))
208 return;
209
210 if (crtc->debug.start_vbl_count &&
211 crtc->debug.start_vbl_count != end_vbl_count) {
212 DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %"PRIdMAX" us, min %d, max %d, scanline start %d, end %d\n",
213 pipe_name(pipe), crtc->debug.start_vbl_count,
214 end_vbl_count,
215 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
216 crtc->debug.min_vbl, crtc->debug.max_vbl,
217 crtc->debug.scanline_start, scanline_end);
218 }
219 #ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
220 else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
221 VBLANK_EVASION_TIME_US)
222 DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
223 pipe_name(pipe),
224 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
225 VBLANK_EVASION_TIME_US);
226 #endif
227 }
228
229 int intel_plane_check_stride(const struct intel_plane_state *plane_state)
230 {
231 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
232 const struct drm_framebuffer *fb = plane_state->hw.fb;
233 unsigned int rotation = plane_state->hw.rotation;
234 u32 stride, max_stride;
235
236 /*
237 * We ignore stride for all invisible planes that
238 * can be remapped. Otherwise we could end up
239 * with a false positive when the remapping didn't
240 * kick in due the plane being invisible.
241 */
242 if (intel_plane_can_remap(plane_state) &&
243 !plane_state->uapi.visible)
244 return 0;
245
246 /* FIXME other color planes? */
247 stride = plane_state->color_plane[0].stride;
248 max_stride = plane->max_stride(plane, fb->format->format,
249 fb->modifier, rotation);
250
251 if (stride > max_stride) {
252 DRM_DEBUG_KMS("[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n",
253 fb->base.id, stride,
254 plane->base.base.id, plane->base.name, max_stride);
255 return -EINVAL;
256 }
257
258 return 0;
259 }
260
261 int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
262 {
263 const struct drm_framebuffer *fb = plane_state->hw.fb;
264 struct drm_rect *src = &plane_state->uapi.src;
265 u32 src_x, src_y, src_w, src_h, hsub, vsub;
266 bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
267
268 /*
269 * Hardware doesn't handle subpixel coordinates.
270 * Adjust to (macro)pixel boundary, but be careful not to
271 * increase the source viewport size, because that could
272 * push the downscaling factor out of bounds.
273 */
274 src_x = src->x1 >> 16;
275 src_w = drm_rect_width(src) >> 16;
276 src_y = src->y1 >> 16;
277 src_h = drm_rect_height(src) >> 16;
278
279 drm_rect_init(src, src_x << 16, src_y << 16,
280 src_w << 16, src_h << 16);
281
282 if (!fb->format->is_yuv)
283 return 0;
284
285 /* YUV specific checks */
286 if (!rotated) {
287 hsub = fb->format->hsub;
288 vsub = fb->format->vsub;
289 } else {
290 hsub = vsub = max(fb->format->hsub, fb->format->vsub);
291 }
292
293 if (src_x % hsub || src_w % hsub) {
294 DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u for %sYUV planes\n",
295 src_x, src_w, hsub, rotated ? "rotated " : "");
296 return -EINVAL;
297 }
298
299 if (src_y % vsub || src_h % vsub) {
300 DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u for %sYUV planes\n",
301 src_y, src_h, vsub, rotated ? "rotated " : "");
302 return -EINVAL;
303 }
304
305 return 0;
306 }
307
308 bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
309 {
310 return INTEL_GEN(dev_priv) >= 11 &&
311 icl_hdr_plane_mask() & BIT(plane_id);
312 }
313
314 static void
315 skl_plane_ratio(const struct intel_crtc_state *crtc_state,
316 const struct intel_plane_state *plane_state,
317 unsigned int *num, unsigned int *den)
318 {
319 struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
320 const struct drm_framebuffer *fb = plane_state->hw.fb;
321
322 if (fb->format->cpp[0] == 8) {
323 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
324 *num = 10;
325 *den = 8;
326 } else {
327 *num = 9;
328 *den = 8;
329 }
330 } else {
331 *num = 1;
332 *den = 1;
333 }
334 }
335
336 static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
337 const struct intel_plane_state *plane_state)
338 {
339 struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
340 unsigned int pixel_rate = crtc_state->pixel_rate;
341 unsigned int src_w, src_h, dst_w, dst_h;
342 unsigned int num, den;
343
344 skl_plane_ratio(crtc_state, plane_state, &num, &den);
345
346 /* two pixels per clock on glk+ */
347 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
348 den *= 2;
349
350 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
351 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
352 dst_w = drm_rect_width(&plane_state->uapi.dst);
353 dst_h = drm_rect_height(&plane_state->uapi.dst);
354
355 /* Downscaling limits the maximum pixel rate */
356 dst_w = min(src_w, dst_w);
357 dst_h = min(src_h, dst_h);
358
359 return DIV64_U64_ROUND_UP(mul_u32_u32(pixel_rate * num, src_w * src_h),
360 mul_u32_u32(den, dst_w * dst_h));
361 }
362
363 static unsigned int
364 skl_plane_max_stride(struct intel_plane *plane,
365 u32 pixel_format, u64 modifier,
366 unsigned int rotation)
367 {
368 const struct drm_format_info *info = drm_format_info(pixel_format);
369 int cpp = info->cpp[0];
370
371 /*
372 * "The stride in bytes must not exceed the
373 * of the size of 8K pixels and 32K bytes."
374 */
375 if (drm_rotation_90_or_270(rotation))
376 return min(8192, 32768 / cpp);
377 else
378 return min(8192 * cpp, 32768);
379 }
380
381 static void
382 skl_program_scaler(struct intel_plane *plane,
383 const struct intel_crtc_state *crtc_state,
384 const struct intel_plane_state *plane_state)
385 {
386 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
387 const struct drm_framebuffer *fb = plane_state->hw.fb;
388 enum pipe pipe = plane->pipe;
389 int scaler_id = plane_state->scaler_id;
390 const struct intel_scaler *scaler =
391 &crtc_state->scaler_state.scalers[scaler_id];
392 int crtc_x = plane_state->uapi.dst.x1;
393 int crtc_y = plane_state->uapi.dst.y1;
394 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
395 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
396 u16 y_hphase, uv_rgb_hphase;
397 u16 y_vphase, uv_rgb_vphase;
398 int hscale, vscale;
399
400 hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
401 &plane_state->uapi.dst,
402 0, INT_MAX);
403 vscale = drm_rect_calc_vscale(&plane_state->uapi.src,
404 &plane_state->uapi.dst,
405 0, INT_MAX);
406
407 /* TODO: handle sub-pixel coordinates */
408 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
409 !icl_is_hdr_plane(dev_priv, plane->id)) {
410 y_hphase = skl_scaler_calc_phase(1, hscale, false);
411 y_vphase = skl_scaler_calc_phase(1, vscale, false);
412
413 /* MPEG2 chroma siting convention */
414 uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
415 uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
416 } else {
417 /* not used */
418 y_hphase = 0;
419 y_vphase = 0;
420
421 uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
422 uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
423 }
424
425 I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
426 PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode);
427 I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
428 PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
429 I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
430 PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
431 I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
432 I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h);
433 }
434
435 /* Preoffset values for YUV to RGB Conversion */
436 #define PREOFF_YUV_TO_RGB_HI 0x1800
437 #define PREOFF_YUV_TO_RGB_ME 0x1F00
438 #define PREOFF_YUV_TO_RGB_LO 0x1800
439
440 #define ROFF(x) (((x) & 0xffff) << 16)
441 #define GOFF(x) (((x) & 0xffff) << 0)
442 #define BOFF(x) (((x) & 0xffff) << 16)
443
444 static void
445 icl_program_input_csc(struct intel_plane *plane,
446 const struct intel_crtc_state *crtc_state,
447 const struct intel_plane_state *plane_state)
448 {
449 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
450 enum pipe pipe = plane->pipe;
451 enum plane_id plane_id = plane->id;
452
453 static const u16 input_csc_matrix[][9] = {
454 /*
455 * BT.601 full range YCbCr -> full range RGB
456 * The matrix required is :
457 * [1.000, 0.000, 1.371,
458 * 1.000, -0.336, -0.698,
459 * 1.000, 1.732, 0.0000]
460 */
461 [DRM_COLOR_YCBCR_BT601] = {
462 0x7AF8, 0x7800, 0x0,
463 0x8B28, 0x7800, 0x9AC0,
464 0x0, 0x7800, 0x7DD8,
465 },
466 /*
467 * BT.709 full range YCbCr -> full range RGB
468 * The matrix required is :
469 * [1.000, 0.000, 1.574,
470 * 1.000, -0.187, -0.468,
471 * 1.000, 1.855, 0.0000]
472 */
473 [DRM_COLOR_YCBCR_BT709] = {
474 0x7C98, 0x7800, 0x0,
475 0x9EF8, 0x7800, 0xAC00,
476 0x0, 0x7800, 0x7ED8,
477 },
478 /*
479 * BT.2020 full range YCbCr -> full range RGB
480 * The matrix required is :
481 * [1.000, 0.000, 1.474,
482 * 1.000, -0.1645, -0.5713,
483 * 1.000, 1.8814, 0.0000]
484 */
485 [DRM_COLOR_YCBCR_BT2020] = {
486 0x7BC8, 0x7800, 0x0,
487 0x8928, 0x7800, 0xAA88,
488 0x0, 0x7800, 0x7F10,
489 },
490 };
491
492 /* Matrix for Limited Range to Full Range Conversion */
493 static const u16 input_csc_matrix_lr[][9] = {
494 /*
495 * BT.601 Limted range YCbCr -> full range RGB
496 * The matrix required is :
497 * [1.164384, 0.000, 1.596027,
498 * 1.164384, -0.39175, -0.812813,
499 * 1.164384, 2.017232, 0.0000]
500 */
501 [DRM_COLOR_YCBCR_BT601] = {
502 0x7CC8, 0x7950, 0x0,
503 0x8D00, 0x7950, 0x9C88,
504 0x0, 0x7950, 0x6810,
505 },
506 /*
507 * BT.709 Limited range YCbCr -> full range RGB
508 * The matrix required is :
509 * [1.164384, 0.000, 1.792741,
510 * 1.164384, -0.213249, -0.532909,
511 * 1.164384, 2.112402, 0.0000]
512 */
513 [DRM_COLOR_YCBCR_BT709] = {
514 0x7E58, 0x7950, 0x0,
515 0x8888, 0x7950, 0xADA8,
516 0x0, 0x7950, 0x6870,
517 },
518 /*
519 * BT.2020 Limited range YCbCr -> full range RGB
520 * The matrix required is :
521 * [1.164, 0.000, 1.678,
522 * 1.164, -0.1873, -0.6504,
523 * 1.164, 2.1417, 0.0000]
524 */
525 [DRM_COLOR_YCBCR_BT2020] = {
526 0x7D70, 0x7950, 0x0,
527 0x8A68, 0x7950, 0xAC00,
528 0x0, 0x7950, 0x6890,
529 },
530 };
531 const u16 *csc;
532
533 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
534 csc = input_csc_matrix[plane_state->hw.color_encoding];
535 else
536 csc = input_csc_matrix_lr[plane_state->hw.color_encoding];
537
538 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0), ROFF(csc[0]) |
539 GOFF(csc[1]));
540 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1), BOFF(csc[2]));
541 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2), ROFF(csc[3]) |
542 GOFF(csc[4]));
543 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3), BOFF(csc[5]));
544 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4), ROFF(csc[6]) |
545 GOFF(csc[7]));
546 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5), BOFF(csc[8]));
547
548 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
549 PREOFF_YUV_TO_RGB_HI);
550 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
551 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1), 0);
552 else
553 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
554 PREOFF_YUV_TO_RGB_ME);
555 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
556 PREOFF_YUV_TO_RGB_LO);
557 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
558 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
559 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
560 }
561
562 static void
563 skl_program_plane(struct intel_plane *plane,
564 const struct intel_crtc_state *crtc_state,
565 const struct intel_plane_state *plane_state,
566 int color_plane)
567 {
568 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
569 enum plane_id plane_id = plane->id;
570 enum pipe pipe = plane->pipe;
571 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
572 u32 surf_addr = plane_state->color_plane[color_plane].offset;
573 u32 stride = skl_plane_stride(plane_state, color_plane);
574 const struct drm_framebuffer *fb = plane_state->hw.fb;
575 int aux_plane = intel_main_to_aux_plane(fb, color_plane);
576 u32 aux_dist = plane_state->color_plane[aux_plane].offset - surf_addr;
577 u32 aux_stride = skl_plane_stride(plane_state, aux_plane);
578 int crtc_x = plane_state->uapi.dst.x1;
579 int crtc_y = plane_state->uapi.dst.y1;
580 u32 x = plane_state->color_plane[color_plane].x;
581 u32 y = plane_state->color_plane[color_plane].y;
582 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
583 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
584 u8 alpha = plane_state->hw.alpha >> 8;
585 u32 plane_color_ctl = 0;
586 unsigned long irqflags;
587 u32 keymsk, keymax;
588 u32 plane_ctl = plane_state->ctl;
589
590 plane_ctl |= skl_plane_ctl_crtc(crtc_state);
591
592 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
593 plane_color_ctl = plane_state->color_ctl |
594 glk_plane_color_ctl_crtc(crtc_state);
595
596 /* Sizes are 0 based */
597 src_w--;
598 src_h--;
599
600 keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
601
602 keymsk = key->channel_mask & 0x7ffffff;
603 if (alpha < 0xff)
604 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
605
606 /* The scaler will handle the output position */
607 if (plane_state->scaler_id >= 0) {
608 crtc_x = 0;
609 crtc_y = 0;
610 }
611
612 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
613
614 I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
615 I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
616 I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
617
618 if (INTEL_GEN(dev_priv) < 12)
619 aux_dist |= aux_stride;
620 I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), aux_dist);
621
622 if (icl_is_hdr_plane(dev_priv, plane_id))
623 I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), plane_state->cus_ctl);
624
625 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
626 I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
627
628 if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
629 icl_program_input_csc(plane, crtc_state, plane_state);
630
631 skl_write_plane_wm(plane, crtc_state);
632
633 I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
634 I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), keymsk);
635 I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), keymax);
636
637 I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
638
639 if (INTEL_GEN(dev_priv) < 11)
640 I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
641 (plane_state->color_plane[1].y << 16) |
642 plane_state->color_plane[1].x);
643
644 /*
645 * The control register self-arms if the plane was previously
646 * disabled. Try to make the plane enable atomic by writing
647 * the control register just before the surface register.
648 */
649 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
650 I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
651 intel_plane_ggtt_offset(plane_state) + surf_addr);
652
653 if (plane_state->scaler_id >= 0)
654 skl_program_scaler(plane, crtc_state, plane_state);
655
656 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
657 }
658
659 static void
660 skl_update_plane(struct intel_plane *plane,
661 const struct intel_crtc_state *crtc_state,
662 const struct intel_plane_state *plane_state)
663 {
664 int color_plane = 0;
665
666 if (plane_state->planar_linked_plane && !plane_state->planar_slave)
667 /* Program the UV plane on planar master */
668 color_plane = 1;
669
670 skl_program_plane(plane, crtc_state, plane_state, color_plane);
671 }
672 static void
673 skl_disable_plane(struct intel_plane *plane,
674 const struct intel_crtc_state *crtc_state)
675 {
676 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
677 enum plane_id plane_id = plane->id;
678 enum pipe pipe = plane->pipe;
679 unsigned long irqflags;
680
681 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
682
683 if (icl_is_hdr_plane(dev_priv, plane_id))
684 I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), 0);
685
686 skl_write_plane_wm(plane, crtc_state);
687
688 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
689 I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
690
691 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
692 }
693
694 static bool
695 skl_plane_get_hw_state(struct intel_plane *plane,
696 enum pipe *pipe)
697 {
698 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
699 enum intel_display_power_domain power_domain;
700 enum plane_id plane_id = plane->id;
701 intel_wakeref_t wakeref;
702 bool ret;
703
704 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
705 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
706 if (!wakeref)
707 return false;
708
709 ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
710
711 *pipe = plane->pipe;
712
713 intel_display_power_put(dev_priv, power_domain, wakeref);
714
715 return ret;
716 }
717
718 static void i9xx_plane_linear_gamma(u16 gamma[8])
719 {
720 /* The points are not evenly spaced. */
721 static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
722 int i;
723
724 for (i = 0; i < 8; i++)
725 gamma[i] = (in[i] << 8) / 32;
726 }
727
728 static void
729 chv_update_csc(const struct intel_plane_state *plane_state)
730 {
731 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
732 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
733 const struct drm_framebuffer *fb = plane_state->hw.fb;
734 enum plane_id plane_id = plane->id;
735 /*
736 * |r| | c0 c1 c2 | |cr|
737 * |g| = | c3 c4 c5 | x |y |
738 * |b| | c6 c7 c8 | |cb|
739 *
740 * Coefficients are s3.12.
741 *
742 * Cb and Cr apparently come in as signed already, and
743 * we always get full range data in on account of CLRC0/1.
744 */
745 static const s16 csc_matrix[][9] = {
746 /* BT.601 full range YCbCr -> full range RGB */
747 [DRM_COLOR_YCBCR_BT601] = {
748 5743, 4096, 0,
749 -2925, 4096, -1410,
750 0, 4096, 7258,
751 },
752 /* BT.709 full range YCbCr -> full range RGB */
753 [DRM_COLOR_YCBCR_BT709] = {
754 6450, 4096, 0,
755 -1917, 4096, -767,
756 0, 4096, 7601,
757 },
758 };
759 const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
760
761 /* Seems RGB data bypasses the CSC always */
762 if (!fb->format->is_yuv)
763 return;
764
765 I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
766 I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
767 I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
768
769 I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
770 I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
771 I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
772 I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
773 I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8]));
774
775 I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
776 I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
777 I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
778
779 I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
780 I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
781 I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
782 }
783
784 #define SIN_0 0
785 #define COS_0 1
786
787 static void
788 vlv_update_clrc(const struct intel_plane_state *plane_state)
789 {
790 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
791 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
792 const struct drm_framebuffer *fb = plane_state->hw.fb;
793 enum pipe pipe = plane->pipe;
794 enum plane_id plane_id = plane->id;
795 int contrast, brightness, sh_scale, sh_sin, sh_cos;
796
797 if (fb->format->is_yuv &&
798 plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
799 /*
800 * Expand limited range to full range:
801 * Contrast is applied first and is used to expand Y range.
802 * Brightness is applied second and is used to remove the
803 * offset from Y. Saturation/hue is used to expand CbCr range.
804 */
805 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
806 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
807 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
808 sh_sin = SIN_0 * sh_scale;
809 sh_cos = COS_0 * sh_scale;
810 } else {
811 /* Pass-through everything. */
812 contrast = 1 << 6;
813 brightness = 0;
814 sh_scale = 1 << 7;
815 sh_sin = SIN_0 * sh_scale;
816 sh_cos = COS_0 * sh_scale;
817 }
818
819 /* FIXME these register are single buffered :( */
820 I915_WRITE_FW(SPCLRC0(pipe, plane_id),
821 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
822 I915_WRITE_FW(SPCLRC1(pipe, plane_id),
823 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
824 }
825
826 static void
827 vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
828 const struct intel_plane_state *plane_state,
829 unsigned int *num, unsigned int *den)
830 {
831 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
832 const struct drm_framebuffer *fb = plane_state->hw.fb;
833 unsigned int cpp = fb->format->cpp[0];
834
835 /*
836 * VLV bspec only considers cases where all three planes are
837 * enabled, and cases where the primary and one sprite is enabled.
838 * Let's assume the case with just two sprites enabled also
839 * maps to the latter case.
840 */
841 if (hweight8(active_planes) == 3) {
842 switch (cpp) {
843 case 8:
844 *num = 11;
845 *den = 8;
846 break;
847 case 4:
848 *num = 18;
849 *den = 16;
850 break;
851 default:
852 *num = 1;
853 *den = 1;
854 break;
855 }
856 } else if (hweight8(active_planes) == 2) {
857 switch (cpp) {
858 case 8:
859 *num = 10;
860 *den = 8;
861 break;
862 case 4:
863 *num = 17;
864 *den = 16;
865 break;
866 default:
867 *num = 1;
868 *den = 1;
869 break;
870 }
871 } else {
872 switch (cpp) {
873 case 8:
874 *num = 10;
875 *den = 8;
876 break;
877 default:
878 *num = 1;
879 *den = 1;
880 break;
881 }
882 }
883 }
884
885 int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
886 const struct intel_plane_state *plane_state)
887 {
888 unsigned int pixel_rate;
889 unsigned int num, den;
890
891 /*
892 * Note that crtc_state->pixel_rate accounts for both
893 * horizontal and vertical panel fitter downscaling factors.
894 * Pre-HSW bspec tells us to only consider the horizontal
895 * downscaling factor here. We ignore that and just consider
896 * both for simplicity.
897 */
898 pixel_rate = crtc_state->pixel_rate;
899
900 vlv_plane_ratio(crtc_state, plane_state, &num, &den);
901
902 return DIV_ROUND_UP(pixel_rate * num, den);
903 }
904
905 static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
906 {
907 u32 sprctl = 0;
908
909 if (crtc_state->gamma_enable)
910 sprctl |= SP_GAMMA_ENABLE;
911
912 return sprctl;
913 }
914
915 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
916 const struct intel_plane_state *plane_state)
917 {
918 const struct drm_framebuffer *fb = plane_state->hw.fb;
919 unsigned int rotation = plane_state->hw.rotation;
920 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
921 u32 sprctl;
922
923 sprctl = SP_ENABLE;
924
925 switch (fb->format->format) {
926 case DRM_FORMAT_YUYV:
927 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
928 break;
929 case DRM_FORMAT_YVYU:
930 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
931 break;
932 case DRM_FORMAT_UYVY:
933 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
934 break;
935 case DRM_FORMAT_VYUY:
936 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
937 break;
938 case DRM_FORMAT_C8:
939 sprctl |= SP_FORMAT_8BPP;
940 break;
941 case DRM_FORMAT_RGB565:
942 sprctl |= SP_FORMAT_BGR565;
943 break;
944 case DRM_FORMAT_XRGB8888:
945 sprctl |= SP_FORMAT_BGRX8888;
946 break;
947 case DRM_FORMAT_ARGB8888:
948 sprctl |= SP_FORMAT_BGRA8888;
949 break;
950 case DRM_FORMAT_XBGR2101010:
951 sprctl |= SP_FORMAT_RGBX1010102;
952 break;
953 case DRM_FORMAT_ABGR2101010:
954 sprctl |= SP_FORMAT_RGBA1010102;
955 break;
956 case DRM_FORMAT_XRGB2101010:
957 sprctl |= SP_FORMAT_BGRX1010102;
958 break;
959 case DRM_FORMAT_ARGB2101010:
960 sprctl |= SP_FORMAT_BGRA1010102;
961 break;
962 case DRM_FORMAT_XBGR8888:
963 sprctl |= SP_FORMAT_RGBX8888;
964 break;
965 case DRM_FORMAT_ABGR8888:
966 sprctl |= SP_FORMAT_RGBA8888;
967 break;
968 default:
969 MISSING_CASE(fb->format->format);
970 return 0;
971 }
972
973 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
974 sprctl |= SP_YUV_FORMAT_BT709;
975
976 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
977 sprctl |= SP_TILED;
978
979 if (rotation & DRM_MODE_ROTATE_180)
980 sprctl |= SP_ROTATE_180;
981
982 if (rotation & DRM_MODE_REFLECT_X)
983 sprctl |= SP_MIRROR;
984
985 if (key->flags & I915_SET_COLORKEY_SOURCE)
986 sprctl |= SP_SOURCE_KEY;
987
988 return sprctl;
989 }
990
991 static void vlv_update_gamma(const struct intel_plane_state *plane_state)
992 {
993 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
994 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
995 const struct drm_framebuffer *fb = plane_state->hw.fb;
996 enum pipe pipe = plane->pipe;
997 enum plane_id plane_id = plane->id;
998 u16 gamma[8];
999 int i;
1000
1001 /* Seems RGB data bypasses the gamma always */
1002 if (!fb->format->is_yuv)
1003 return;
1004
1005 i9xx_plane_linear_gamma(gamma);
1006
1007 /* FIXME these register are single buffered :( */
1008 /* The two end points are implicit (0.0 and 1.0) */
1009 for (i = 1; i < 8 - 1; i++)
1010 I915_WRITE_FW(SPGAMC(pipe, plane_id, i - 1),
1011 gamma[i] << 16 |
1012 gamma[i] << 8 |
1013 gamma[i]);
1014 }
1015
1016 static void
1017 vlv_update_plane(struct intel_plane *plane,
1018 const struct intel_crtc_state *crtc_state,
1019 const struct intel_plane_state *plane_state)
1020 {
1021 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1022 enum pipe pipe = plane->pipe;
1023 enum plane_id plane_id = plane->id;
1024 u32 sprsurf_offset = plane_state->color_plane[0].offset;
1025 u32 linear_offset;
1026 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1027 int crtc_x = plane_state->uapi.dst.x1;
1028 int crtc_y = plane_state->uapi.dst.y1;
1029 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1030 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1031 u32 x = plane_state->color_plane[0].x;
1032 u32 y = plane_state->color_plane[0].y;
1033 unsigned long irqflags;
1034 u32 sprctl;
1035
1036 sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
1037
1038 /* Sizes are 0 based */
1039 crtc_w--;
1040 crtc_h--;
1041
1042 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1043
1044 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1045
1046 I915_WRITE_FW(SPSTRIDE(pipe, plane_id),
1047 plane_state->color_plane[0].stride);
1048 I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
1049 I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
1050 I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
1051
1052 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
1053 chv_update_csc(plane_state);
1054
1055 if (key->flags) {
1056 I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
1057 I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
1058 I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
1059 }
1060
1061 I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
1062 I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
1063
1064 /*
1065 * The control register self-arms if the plane was previously
1066 * disabled. Try to make the plane enable atomic by writing
1067 * the control register just before the surface register.
1068 */
1069 I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
1070 I915_WRITE_FW(SPSURF(pipe, plane_id),
1071 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1072
1073 vlv_update_clrc(plane_state);
1074 vlv_update_gamma(plane_state);
1075
1076 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1077 }
1078
1079 static void
1080 vlv_disable_plane(struct intel_plane *plane,
1081 const struct intel_crtc_state *crtc_state)
1082 {
1083 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1084 enum pipe pipe = plane->pipe;
1085 enum plane_id plane_id = plane->id;
1086 unsigned long irqflags;
1087
1088 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1089
1090 I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
1091 I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
1092
1093 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1094 }
1095
1096 static bool
1097 vlv_plane_get_hw_state(struct intel_plane *plane,
1098 enum pipe *pipe)
1099 {
1100 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1101 enum intel_display_power_domain power_domain;
1102 enum plane_id plane_id = plane->id;
1103 intel_wakeref_t wakeref;
1104 bool ret;
1105
1106 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1107 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1108 if (!wakeref)
1109 return false;
1110
1111 ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
1112
1113 *pipe = plane->pipe;
1114
1115 intel_display_power_put(dev_priv, power_domain, wakeref);
1116
1117 return ret;
1118 }
1119
1120 static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
1121 const struct intel_plane_state *plane_state,
1122 unsigned int *num, unsigned int *den)
1123 {
1124 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
1125 const struct drm_framebuffer *fb = plane_state->hw.fb;
1126 unsigned int cpp = fb->format->cpp[0];
1127
1128 if (hweight8(active_planes) == 2) {
1129 switch (cpp) {
1130 case 8:
1131 *num = 10;
1132 *den = 8;
1133 break;
1134 case 4:
1135 *num = 17;
1136 *den = 16;
1137 break;
1138 default:
1139 *num = 1;
1140 *den = 1;
1141 break;
1142 }
1143 } else {
1144 switch (cpp) {
1145 case 8:
1146 *num = 9;
1147 *den = 8;
1148 break;
1149 default:
1150 *num = 1;
1151 *den = 1;
1152 break;
1153 }
1154 }
1155 }
1156
1157 static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
1158 const struct intel_plane_state *plane_state,
1159 unsigned int *num, unsigned int *den)
1160 {
1161 const struct drm_framebuffer *fb = plane_state->hw.fb;
1162 unsigned int cpp = fb->format->cpp[0];
1163
1164 switch (cpp) {
1165 case 8:
1166 *num = 12;
1167 *den = 8;
1168 break;
1169 case 4:
1170 *num = 19;
1171 *den = 16;
1172 break;
1173 case 2:
1174 *num = 33;
1175 *den = 32;
1176 break;
1177 default:
1178 *num = 1;
1179 *den = 1;
1180 break;
1181 }
1182 }
1183
1184 int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
1185 const struct intel_plane_state *plane_state)
1186 {
1187 unsigned int pixel_rate;
1188 unsigned int num, den;
1189
1190 /*
1191 * Note that crtc_state->pixel_rate accounts for both
1192 * horizontal and vertical panel fitter downscaling factors.
1193 * Pre-HSW bspec tells us to only consider the horizontal
1194 * downscaling factor here. We ignore that and just consider
1195 * both for simplicity.
1196 */
1197 pixel_rate = crtc_state->pixel_rate;
1198
1199 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
1200
1201 return DIV_ROUND_UP(pixel_rate * num, den);
1202 }
1203
1204 static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
1205 const struct intel_plane_state *plane_state)
1206 {
1207 unsigned int src_w, dst_w, pixel_rate;
1208 unsigned int num, den;
1209
1210 /*
1211 * Note that crtc_state->pixel_rate accounts for both
1212 * horizontal and vertical panel fitter downscaling factors.
1213 * Pre-HSW bspec tells us to only consider the horizontal
1214 * downscaling factor here. We ignore that and just consider
1215 * both for simplicity.
1216 */
1217 pixel_rate = crtc_state->pixel_rate;
1218
1219 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1220 dst_w = drm_rect_width(&plane_state->uapi.dst);
1221
1222 if (src_w != dst_w)
1223 ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
1224 else
1225 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
1226
1227 /* Horizontal downscaling limits the maximum pixel rate */
1228 dst_w = min(src_w, dst_w);
1229
1230 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
1231 den * dst_w);
1232 }
1233
1234 static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
1235 const struct intel_plane_state *plane_state,
1236 unsigned int *num, unsigned int *den)
1237 {
1238 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
1239 const struct drm_framebuffer *fb = plane_state->hw.fb;
1240 unsigned int cpp = fb->format->cpp[0];
1241
1242 if (hweight8(active_planes) == 2) {
1243 switch (cpp) {
1244 case 8:
1245 *num = 10;
1246 *den = 8;
1247 break;
1248 default:
1249 *num = 1;
1250 *den = 1;
1251 break;
1252 }
1253 } else {
1254 switch (cpp) {
1255 case 8:
1256 *num = 9;
1257 *den = 8;
1258 break;
1259 default:
1260 *num = 1;
1261 *den = 1;
1262 break;
1263 }
1264 }
1265 }
1266
1267 int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
1268 const struct intel_plane_state *plane_state)
1269 {
1270 unsigned int pixel_rate = crtc_state->pixel_rate;
1271 unsigned int num, den;
1272
1273 hsw_plane_ratio(crtc_state, plane_state, &num, &den);
1274
1275 return DIV_ROUND_UP(pixel_rate * num, den);
1276 }
1277
1278 static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1279 {
1280 u32 sprctl = 0;
1281
1282 if (crtc_state->gamma_enable)
1283 sprctl |= SPRITE_GAMMA_ENABLE;
1284
1285 if (crtc_state->csc_enable)
1286 sprctl |= SPRITE_PIPE_CSC_ENABLE;
1287
1288 return sprctl;
1289 }
1290
1291 static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
1292 {
1293 struct drm_i915_private *dev_priv =
1294 to_i915(plane_state->uapi.plane->dev);
1295 const struct drm_framebuffer *fb = plane_state->hw.fb;
1296
1297 return fb->format->cpp[0] == 8 &&
1298 (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
1299 }
1300
1301 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
1302 const struct intel_plane_state *plane_state)
1303 {
1304 struct drm_i915_private *dev_priv =
1305 to_i915(plane_state->uapi.plane->dev);
1306 const struct drm_framebuffer *fb = plane_state->hw.fb;
1307 unsigned int rotation = plane_state->hw.rotation;
1308 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1309 u32 sprctl;
1310
1311 sprctl = SPRITE_ENABLE;
1312
1313 if (IS_IVYBRIDGE(dev_priv))
1314 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
1315
1316 switch (fb->format->format) {
1317 case DRM_FORMAT_XBGR8888:
1318 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
1319 break;
1320 case DRM_FORMAT_XRGB8888:
1321 sprctl |= SPRITE_FORMAT_RGBX888;
1322 break;
1323 case DRM_FORMAT_XBGR2101010:
1324 sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
1325 break;
1326 case DRM_FORMAT_XRGB2101010:
1327 sprctl |= SPRITE_FORMAT_RGBX101010;
1328 break;
1329 case DRM_FORMAT_XBGR16161616F:
1330 sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
1331 break;
1332 case DRM_FORMAT_XRGB16161616F:
1333 sprctl |= SPRITE_FORMAT_RGBX161616;
1334 break;
1335 case DRM_FORMAT_YUYV:
1336 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
1337 break;
1338 case DRM_FORMAT_YVYU:
1339 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
1340 break;
1341 case DRM_FORMAT_UYVY:
1342 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
1343 break;
1344 case DRM_FORMAT_VYUY:
1345 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
1346 break;
1347 default:
1348 MISSING_CASE(fb->format->format);
1349 return 0;
1350 }
1351
1352 if (!ivb_need_sprite_gamma(plane_state))
1353 sprctl |= SPRITE_INT_GAMMA_DISABLE;
1354
1355 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1356 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
1357
1358 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1359 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
1360
1361 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1362 sprctl |= SPRITE_TILED;
1363
1364 if (rotation & DRM_MODE_ROTATE_180)
1365 sprctl |= SPRITE_ROTATE_180;
1366
1367 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1368 sprctl |= SPRITE_DEST_KEY;
1369 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1370 sprctl |= SPRITE_SOURCE_KEY;
1371
1372 return sprctl;
1373 }
1374
1375 static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
1376 u16 gamma[18])
1377 {
1378 int scale, i;
1379
1380 /*
1381 * WaFP16GammaEnabling:ivb,hsw
1382 * "Workaround : When using the 64-bit format, the sprite output
1383 * on each color channel has one quarter amplitude. It can be
1384 * brought up to full amplitude by using sprite internal gamma
1385 * correction, pipe gamma correction, or pipe color space
1386 * conversion to multiply the sprite output by four."
1387 */
1388 scale = 4;
1389
1390 for (i = 0; i < 16; i++)
1391 gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
1392
1393 gamma[i] = min((scale * i << 10) / 16, 1 << 10);
1394 i++;
1395
1396 gamma[i] = 3 << 10;
1397 i++;
1398 }
1399
1400 static void ivb_update_gamma(const struct intel_plane_state *plane_state)
1401 {
1402 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1403 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1404 enum pipe pipe = plane->pipe;
1405 u16 gamma[18];
1406 int i;
1407
1408 if (!ivb_need_sprite_gamma(plane_state))
1409 return;
1410
1411 ivb_sprite_linear_gamma(plane_state, gamma);
1412
1413 /* FIXME these register are single buffered :( */
1414 for (i = 0; i < 16; i++)
1415 I915_WRITE_FW(SPRGAMC(pipe, i),
1416 gamma[i] << 20 |
1417 gamma[i] << 10 |
1418 gamma[i]);
1419
1420 I915_WRITE_FW(SPRGAMC16(pipe, 0), gamma[i]);
1421 I915_WRITE_FW(SPRGAMC16(pipe, 1), gamma[i]);
1422 I915_WRITE_FW(SPRGAMC16(pipe, 2), gamma[i]);
1423 i++;
1424
1425 I915_WRITE_FW(SPRGAMC17(pipe, 0), gamma[i]);
1426 I915_WRITE_FW(SPRGAMC17(pipe, 1), gamma[i]);
1427 I915_WRITE_FW(SPRGAMC17(pipe, 2), gamma[i]);
1428 i++;
1429 }
1430
1431 static void
1432 ivb_update_plane(struct intel_plane *plane,
1433 const struct intel_crtc_state *crtc_state,
1434 const struct intel_plane_state *plane_state)
1435 {
1436 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1437 enum pipe pipe = plane->pipe;
1438 u32 sprsurf_offset = plane_state->color_plane[0].offset;
1439 u32 linear_offset;
1440 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1441 int crtc_x = plane_state->uapi.dst.x1;
1442 int crtc_y = plane_state->uapi.dst.y1;
1443 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1444 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1445 u32 x = plane_state->color_plane[0].x;
1446 u32 y = plane_state->color_plane[0].y;
1447 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1448 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1449 u32 sprctl, sprscale = 0;
1450 unsigned long irqflags;
1451
1452 sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
1453
1454 /* Sizes are 0 based */
1455 src_w--;
1456 src_h--;
1457 crtc_w--;
1458 crtc_h--;
1459
1460 if (crtc_w != src_w || crtc_h != src_h)
1461 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
1462
1463 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1464
1465 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1466
1467 I915_WRITE_FW(SPRSTRIDE(pipe), plane_state->color_plane[0].stride);
1468 I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
1469 I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
1470 if (IS_IVYBRIDGE(dev_priv))
1471 I915_WRITE_FW(SPRSCALE(pipe), sprscale);
1472
1473 if (key->flags) {
1474 I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
1475 I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
1476 I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
1477 }
1478
1479 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
1480 * register */
1481 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1482 I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
1483 } else {
1484 I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
1485 I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
1486 }
1487
1488 /*
1489 * The control register self-arms if the plane was previously
1490 * disabled. Try to make the plane enable atomic by writing
1491 * the control register just before the surface register.
1492 */
1493 I915_WRITE_FW(SPRCTL(pipe), sprctl);
1494 I915_WRITE_FW(SPRSURF(pipe),
1495 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1496
1497 ivb_update_gamma(plane_state);
1498
1499 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1500 }
1501
1502 static void
1503 ivb_disable_plane(struct intel_plane *plane,
1504 const struct intel_crtc_state *crtc_state)
1505 {
1506 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1507 enum pipe pipe = plane->pipe;
1508 unsigned long irqflags;
1509
1510 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1511
1512 I915_WRITE_FW(SPRCTL(pipe), 0);
1513 /* Disable the scaler */
1514 if (IS_IVYBRIDGE(dev_priv))
1515 I915_WRITE_FW(SPRSCALE(pipe), 0);
1516 I915_WRITE_FW(SPRSURF(pipe), 0);
1517
1518 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1519 }
1520
1521 static bool
1522 ivb_plane_get_hw_state(struct intel_plane *plane,
1523 enum pipe *pipe)
1524 {
1525 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1526 enum intel_display_power_domain power_domain;
1527 intel_wakeref_t wakeref;
1528 bool ret;
1529
1530 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1531 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1532 if (!wakeref)
1533 return false;
1534
1535 ret = I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
1536
1537 *pipe = plane->pipe;
1538
1539 intel_display_power_put(dev_priv, power_domain, wakeref);
1540
1541 return ret;
1542 }
1543
1544 static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
1545 const struct intel_plane_state *plane_state)
1546 {
1547 const struct drm_framebuffer *fb = plane_state->hw.fb;
1548 unsigned int hscale, pixel_rate;
1549 unsigned int limit, decimate;
1550
1551 /*
1552 * Note that crtc_state->pixel_rate accounts for both
1553 * horizontal and vertical panel fitter downscaling factors.
1554 * Pre-HSW bspec tells us to only consider the horizontal
1555 * downscaling factor here. We ignore that and just consider
1556 * both for simplicity.
1557 */
1558 pixel_rate = crtc_state->pixel_rate;
1559
1560 /* Horizontal downscaling limits the maximum pixel rate */
1561 hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
1562 &plane_state->uapi.dst,
1563 0, INT_MAX);
1564 if (hscale < 0x10000)
1565 return pixel_rate;
1566
1567 /* Decimation steps at 2x,4x,8x,16x */
1568 decimate = ilog2(hscale >> 16);
1569 hscale >>= decimate;
1570
1571 /* Starting limit is 90% of cdclk */
1572 limit = 9;
1573
1574 /* -10% per decimation step */
1575 limit -= decimate;
1576
1577 /* -10% for RGB */
1578 if (fb->format->cpp[0] >= 4)
1579 limit--; /* -10% for RGB */
1580
1581 /*
1582 * We should also do -10% if sprite scaling is enabled
1583 * on the other pipe, but we can't really check for that,
1584 * so we ignore it.
1585 */
1586
1587 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
1588 limit << 16);
1589 }
1590
1591 static unsigned int
1592 g4x_sprite_max_stride(struct intel_plane *plane,
1593 u32 pixel_format, u64 modifier,
1594 unsigned int rotation)
1595 {
1596 return 16384;
1597 }
1598
1599 static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1600 {
1601 u32 dvscntr = 0;
1602
1603 if (crtc_state->gamma_enable)
1604 dvscntr |= DVS_GAMMA_ENABLE;
1605
1606 if (crtc_state->csc_enable)
1607 dvscntr |= DVS_PIPE_CSC_ENABLE;
1608
1609 return dvscntr;
1610 }
1611
1612 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1613 const struct intel_plane_state *plane_state)
1614 {
1615 struct drm_i915_private *dev_priv =
1616 to_i915(plane_state->uapi.plane->dev);
1617 const struct drm_framebuffer *fb = plane_state->hw.fb;
1618 unsigned int rotation = plane_state->hw.rotation;
1619 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1620 u32 dvscntr;
1621
1622 dvscntr = DVS_ENABLE;
1623
1624 if (IS_GEN(dev_priv, 6))
1625 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1626
1627 switch (fb->format->format) {
1628 case DRM_FORMAT_XBGR8888:
1629 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1630 break;
1631 case DRM_FORMAT_XRGB8888:
1632 dvscntr |= DVS_FORMAT_RGBX888;
1633 break;
1634 case DRM_FORMAT_XBGR2101010:
1635 dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
1636 break;
1637 case DRM_FORMAT_XRGB2101010:
1638 dvscntr |= DVS_FORMAT_RGBX101010;
1639 break;
1640 case DRM_FORMAT_XBGR16161616F:
1641 dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1642 break;
1643 case DRM_FORMAT_XRGB16161616F:
1644 dvscntr |= DVS_FORMAT_RGBX161616;
1645 break;
1646 case DRM_FORMAT_YUYV:
1647 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1648 break;
1649 case DRM_FORMAT_YVYU:
1650 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1651 break;
1652 case DRM_FORMAT_UYVY:
1653 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1654 break;
1655 case DRM_FORMAT_VYUY:
1656 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1657 break;
1658 default:
1659 MISSING_CASE(fb->format->format);
1660 return 0;
1661 }
1662
1663 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1664 dvscntr |= DVS_YUV_FORMAT_BT709;
1665
1666 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1667 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1668
1669 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1670 dvscntr |= DVS_TILED;
1671
1672 if (rotation & DRM_MODE_ROTATE_180)
1673 dvscntr |= DVS_ROTATE_180;
1674
1675 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1676 dvscntr |= DVS_DEST_KEY;
1677 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1678 dvscntr |= DVS_SOURCE_KEY;
1679
1680 return dvscntr;
1681 }
1682
1683 static void g4x_update_gamma(const struct intel_plane_state *plane_state)
1684 {
1685 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1686 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1687 const struct drm_framebuffer *fb = plane_state->hw.fb;
1688 enum pipe pipe = plane->pipe;
1689 u16 gamma[8];
1690 int i;
1691
1692 /* Seems RGB data bypasses the gamma always */
1693 if (!fb->format->is_yuv)
1694 return;
1695
1696 i9xx_plane_linear_gamma(gamma);
1697
1698 /* FIXME these register are single buffered :( */
1699 /* The two end points are implicit (0.0 and 1.0) */
1700 for (i = 1; i < 8 - 1; i++)
1701 I915_WRITE_FW(DVSGAMC_G4X(pipe, i - 1),
1702 gamma[i] << 16 |
1703 gamma[i] << 8 |
1704 gamma[i]);
1705 }
1706
1707 static void ilk_sprite_linear_gamma(u16 gamma[17])
1708 {
1709 int i;
1710
1711 for (i = 0; i < 17; i++)
1712 gamma[i] = (i << 10) / 16;
1713 }
1714
1715 static void ilk_update_gamma(const struct intel_plane_state *plane_state)
1716 {
1717 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1718 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1719 const struct drm_framebuffer *fb = plane_state->hw.fb;
1720 enum pipe pipe = plane->pipe;
1721 u16 gamma[17];
1722 int i;
1723
1724 /* Seems RGB data bypasses the gamma always */
1725 if (!fb->format->is_yuv)
1726 return;
1727
1728 ilk_sprite_linear_gamma(gamma);
1729
1730 /* FIXME these register are single buffered :( */
1731 for (i = 0; i < 16; i++)
1732 I915_WRITE_FW(DVSGAMC_ILK(pipe, i),
1733 gamma[i] << 20 |
1734 gamma[i] << 10 |
1735 gamma[i]);
1736
1737 I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1738 I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1739 I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1740 i++;
1741 }
1742
1743 static void
1744 g4x_update_plane(struct intel_plane *plane,
1745 const struct intel_crtc_state *crtc_state,
1746 const struct intel_plane_state *plane_state)
1747 {
1748 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1749 enum pipe pipe = plane->pipe;
1750 u32 dvssurf_offset = plane_state->color_plane[0].offset;
1751 u32 linear_offset;
1752 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1753 int crtc_x = plane_state->uapi.dst.x1;
1754 int crtc_y = plane_state->uapi.dst.y1;
1755 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1756 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1757 u32 x = plane_state->color_plane[0].x;
1758 u32 y = plane_state->color_plane[0].y;
1759 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1760 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1761 u32 dvscntr, dvsscale = 0;
1762 unsigned long irqflags;
1763
1764 dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1765
1766 /* Sizes are 0 based */
1767 src_w--;
1768 src_h--;
1769 crtc_w--;
1770 crtc_h--;
1771
1772 if (crtc_w != src_w || crtc_h != src_h)
1773 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
1774
1775 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1776
1777 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1778
1779 I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride);
1780 I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
1781 I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
1782 I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
1783
1784 if (key->flags) {
1785 I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
1786 I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
1787 I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
1788 }
1789
1790 I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
1791 I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
1792
1793 /*
1794 * The control register self-arms if the plane was previously
1795 * disabled. Try to make the plane enable atomic by writing
1796 * the control register just before the surface register.
1797 */
1798 I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
1799 I915_WRITE_FW(DVSSURF(pipe),
1800 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1801
1802 if (IS_G4X(dev_priv))
1803 g4x_update_gamma(plane_state);
1804 else
1805 ilk_update_gamma(plane_state);
1806
1807 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1808 }
1809
1810 static void
1811 g4x_disable_plane(struct intel_plane *plane,
1812 const struct intel_crtc_state *crtc_state)
1813 {
1814 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1815 enum pipe pipe = plane->pipe;
1816 unsigned long irqflags;
1817
1818 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1819
1820 I915_WRITE_FW(DVSCNTR(pipe), 0);
1821 /* Disable the scaler */
1822 I915_WRITE_FW(DVSSCALE(pipe), 0);
1823 I915_WRITE_FW(DVSSURF(pipe), 0);
1824
1825 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1826 }
1827
1828 static bool
1829 g4x_plane_get_hw_state(struct intel_plane *plane,
1830 enum pipe *pipe)
1831 {
1832 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1833 enum intel_display_power_domain power_domain;
1834 intel_wakeref_t wakeref;
1835 bool ret;
1836
1837 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1838 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1839 if (!wakeref)
1840 return false;
1841
1842 ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
1843
1844 *pipe = plane->pipe;
1845
1846 intel_display_power_put(dev_priv, power_domain, wakeref);
1847
1848 return ret;
1849 }
1850
1851 static bool intel_fb_scalable(const struct drm_framebuffer *fb)
1852 {
1853 if (!fb)
1854 return false;
1855
1856 switch (fb->format->format) {
1857 case DRM_FORMAT_C8:
1858 return false;
1859 case DRM_FORMAT_XRGB16161616F:
1860 case DRM_FORMAT_ARGB16161616F:
1861 case DRM_FORMAT_XBGR16161616F:
1862 case DRM_FORMAT_ABGR16161616F:
1863 return INTEL_GEN(to_i915(fb->dev)) >= 11;
1864 default:
1865 return true;
1866 }
1867 }
1868
1869 static int
1870 g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1871 struct intel_plane_state *plane_state)
1872 {
1873 const struct drm_framebuffer *fb = plane_state->hw.fb;
1874 const struct drm_rect *src = &plane_state->uapi.src;
1875 const struct drm_rect *dst = &plane_state->uapi.dst;
1876 int src_x, src_w, src_h, crtc_w, crtc_h;
1877 const struct drm_display_mode *adjusted_mode =
1878 &crtc_state->hw.adjusted_mode;
1879 unsigned int stride = plane_state->color_plane[0].stride;
1880 unsigned int cpp = fb->format->cpp[0];
1881 unsigned int width_bytes;
1882 int min_width, min_height;
1883
1884 crtc_w = drm_rect_width(dst);
1885 crtc_h = drm_rect_height(dst);
1886
1887 src_x = src->x1 >> 16;
1888 src_w = drm_rect_width(src) >> 16;
1889 src_h = drm_rect_height(src) >> 16;
1890
1891 if (src_w == crtc_w && src_h == crtc_h)
1892 return 0;
1893
1894 min_width = 3;
1895
1896 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1897 if (src_h & 1) {
1898 DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
1899 return -EINVAL;
1900 }
1901 min_height = 6;
1902 } else {
1903 min_height = 3;
1904 }
1905
1906 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1907
1908 if (src_w < min_width || src_h < min_height ||
1909 src_w > 2048 || src_h > 2048) {
1910 DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1911 src_w, src_h, min_width, min_height, 2048, 2048);
1912 return -EINVAL;
1913 }
1914
1915 if (width_bytes > 4096) {
1916 DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1917 width_bytes, 4096);
1918 return -EINVAL;
1919 }
1920
1921 if (stride > 4096) {
1922 DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
1923 stride, 4096);
1924 return -EINVAL;
1925 }
1926
1927 return 0;
1928 }
1929
1930 static int
1931 g4x_sprite_check(struct intel_crtc_state *crtc_state,
1932 struct intel_plane_state *plane_state)
1933 {
1934 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1935 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1936 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1937 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1938 int ret;
1939
1940 if (intel_fb_scalable(plane_state->hw.fb)) {
1941 if (INTEL_GEN(dev_priv) < 7) {
1942 min_scale = 1;
1943 max_scale = 16 << 16;
1944 } else if (IS_IVYBRIDGE(dev_priv)) {
1945 min_scale = 1;
1946 max_scale = 2 << 16;
1947 }
1948 }
1949
1950 ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
1951 &crtc_state->uapi,
1952 min_scale, max_scale,
1953 true, true);
1954 if (ret)
1955 return ret;
1956
1957 ret = i9xx_check_plane_surface(plane_state);
1958 if (ret)
1959 return ret;
1960
1961 if (!plane_state->uapi.visible)
1962 return 0;
1963
1964 ret = intel_plane_check_src_coordinates(plane_state);
1965 if (ret)
1966 return ret;
1967
1968 ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1969 if (ret)
1970 return ret;
1971
1972 if (INTEL_GEN(dev_priv) >= 7)
1973 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1974 else
1975 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1976
1977 return 0;
1978 }
1979
1980 int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1981 {
1982 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1983 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1984 unsigned int rotation = plane_state->hw.rotation;
1985
1986 /* CHV ignores the mirror bit when the rotate bit is set :( */
1987 if (IS_CHERRYVIEW(dev_priv) &&
1988 rotation & DRM_MODE_ROTATE_180 &&
1989 rotation & DRM_MODE_REFLECT_X) {
1990 DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n");
1991 return -EINVAL;
1992 }
1993
1994 return 0;
1995 }
1996
1997 static int
1998 vlv_sprite_check(struct intel_crtc_state *crtc_state,
1999 struct intel_plane_state *plane_state)
2000 {
2001 int ret;
2002
2003 ret = chv_plane_check_rotation(plane_state);
2004 if (ret)
2005 return ret;
2006
2007 ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
2008 &crtc_state->uapi,
2009 DRM_PLANE_HELPER_NO_SCALING,
2010 DRM_PLANE_HELPER_NO_SCALING,
2011 true, true);
2012 if (ret)
2013 return ret;
2014
2015 ret = i9xx_check_plane_surface(plane_state);
2016 if (ret)
2017 return ret;
2018
2019 if (!plane_state->uapi.visible)
2020 return 0;
2021
2022 ret = intel_plane_check_src_coordinates(plane_state);
2023 if (ret)
2024 return ret;
2025
2026 plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
2027
2028 return 0;
2029 }
2030
2031 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
2032 const struct intel_plane_state *plane_state)
2033 {
2034 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2035 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2036 const struct drm_framebuffer *fb = plane_state->hw.fb;
2037 unsigned int rotation = plane_state->hw.rotation;
2038 struct drm_format_name_buf format_name;
2039
2040 if (!fb)
2041 return 0;
2042
2043 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
2044 is_ccs_modifier(fb->modifier)) {
2045 DRM_DEBUG_KMS("RC support only with 0/180 degree rotation (%x)\n",
2046 rotation);
2047 return -EINVAL;
2048 }
2049
2050 if (rotation & DRM_MODE_REFLECT_X &&
2051 fb->modifier == DRM_FORMAT_MOD_LINEAR) {
2052 DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n");
2053 return -EINVAL;
2054 }
2055
2056 if (drm_rotation_90_or_270(rotation)) {
2057 if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
2058 fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
2059 DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
2060 return -EINVAL;
2061 }
2062
2063 /*
2064 * 90/270 is not allowed with RGB64 16:16:16:16 and
2065 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
2066 */
2067 switch (fb->format->format) {
2068 case DRM_FORMAT_RGB565:
2069 if (INTEL_GEN(dev_priv) >= 11)
2070 break;
2071 /* fall through */
2072 case DRM_FORMAT_C8:
2073 case DRM_FORMAT_XRGB16161616F:
2074 case DRM_FORMAT_XBGR16161616F:
2075 case DRM_FORMAT_ARGB16161616F:
2076 case DRM_FORMAT_ABGR16161616F:
2077 case DRM_FORMAT_Y210:
2078 case DRM_FORMAT_Y212:
2079 case DRM_FORMAT_Y216:
2080 case DRM_FORMAT_XVYU12_16161616:
2081 case DRM_FORMAT_XVYU16161616:
2082 DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
2083 drm_get_format_name(fb->format->format,
2084 &format_name));
2085 return -EINVAL;
2086 default:
2087 break;
2088 }
2089 }
2090
2091 /* Y-tiling is not supported in IF-ID Interlace mode */
2092 if (crtc_state->hw.enable &&
2093 crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
2094 (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
2095 fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
2096 fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
2097 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
2098 fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
2099 fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)) {
2100 DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n");
2101 return -EINVAL;
2102 }
2103
2104 return 0;
2105 }
2106
2107 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
2108 const struct intel_plane_state *plane_state)
2109 {
2110 struct drm_i915_private *dev_priv =
2111 to_i915(plane_state->uapi.plane->dev);
2112 int crtc_x = plane_state->uapi.dst.x1;
2113 int crtc_w = drm_rect_width(&plane_state->uapi.dst);
2114 int pipe_src_w = crtc_state->pipe_src_w;
2115
2116 /*
2117 * Display WA #1175: cnl,glk
2118 * Planes other than the cursor may cause FIFO underflow and display
2119 * corruption if starting less than 4 pixels from the right edge of
2120 * the screen.
2121 * Besides the above WA fix the similar problem, where planes other
2122 * than the cursor ending less than 4 pixels from the left edge of the
2123 * screen may cause FIFO underflow and display corruption.
2124 */
2125 if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
2126 (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
2127 DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n",
2128 crtc_x + crtc_w < 4 ? "end" : "start",
2129 crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
2130 4, pipe_src_w - 4);
2131 return -ERANGE;
2132 }
2133
2134 return 0;
2135 }
2136
2137 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
2138 {
2139 const struct drm_framebuffer *fb = plane_state->hw.fb;
2140 unsigned int rotation = plane_state->hw.rotation;
2141 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
2142
2143 /* Display WA #1106 */
2144 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
2145 src_w & 3 &&
2146 (rotation == DRM_MODE_ROTATE_270 ||
2147 rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
2148 DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
2149 return -EINVAL;
2150 }
2151
2152 return 0;
2153 }
2154
2155 static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
2156 const struct drm_framebuffer *fb)
2157 {
2158 /*
2159 * We don't yet know the final source width nor
2160 * whether we can use the HQ scaler mode. Assume
2161 * the best case.
2162 * FIXME need to properly check this later.
2163 */
2164 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
2165 !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
2166 return 0x30000 - 1;
2167 else
2168 return 0x20000 - 1;
2169 }
2170
2171 static int skl_plane_check(struct intel_crtc_state *crtc_state,
2172 struct intel_plane_state *plane_state)
2173 {
2174 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2175 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2176 const struct drm_framebuffer *fb = plane_state->hw.fb;
2177 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
2178 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
2179 int ret;
2180
2181 ret = skl_plane_check_fb(crtc_state, plane_state);
2182 if (ret)
2183 return ret;
2184
2185 /* use scaler when colorkey is not required */
2186 if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
2187 min_scale = 1;
2188 max_scale = skl_plane_max_scale(dev_priv, fb);
2189 }
2190
2191 ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
2192 &crtc_state->uapi,
2193 min_scale, max_scale,
2194 true, true);
2195 if (ret)
2196 return ret;
2197
2198 ret = skl_check_plane_surface(plane_state);
2199 if (ret)
2200 return ret;
2201
2202 if (!plane_state->uapi.visible)
2203 return 0;
2204
2205 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
2206 if (ret)
2207 return ret;
2208
2209 ret = intel_plane_check_src_coordinates(plane_state);
2210 if (ret)
2211 return ret;
2212
2213 ret = skl_plane_check_nv12_rotation(plane_state);
2214 if (ret)
2215 return ret;
2216
2217 /* HW only has 8 bits pixel precision, disable plane if invisible */
2218 if (!(plane_state->hw.alpha >> 8))
2219 plane_state->uapi.visible = false;
2220
2221 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
2222
2223 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
2224 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
2225 plane_state);
2226
2227 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
2228 icl_is_hdr_plane(dev_priv, plane->id))
2229 /* Enable and use MPEG-2 chroma siting */
2230 plane_state->cus_ctl = PLANE_CUS_ENABLE |
2231 PLANE_CUS_HPHASE_0 |
2232 PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
2233 else
2234 plane_state->cus_ctl = 0;
2235
2236 return 0;
2237 }
2238
2239 static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
2240 {
2241 return INTEL_GEN(dev_priv) >= 9;
2242 }
2243
2244 static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
2245 const struct drm_intel_sprite_colorkey *set)
2246 {
2247 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2248 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2249 struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
2250
2251 *key = *set;
2252
2253 /*
2254 * We want src key enabled on the
2255 * sprite and not on the primary.
2256 */
2257 if (plane->id == PLANE_PRIMARY &&
2258 set->flags & I915_SET_COLORKEY_SOURCE)
2259 key->flags = 0;
2260
2261 /*
2262 * On SKL+ we want dst key enabled on
2263 * the primary and not on the sprite.
2264 */
2265 if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
2266 set->flags & I915_SET_COLORKEY_DESTINATION)
2267 key->flags = 0;
2268 }
2269
2270 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
2271 struct drm_file *file_priv)
2272 {
2273 struct drm_i915_private *dev_priv = to_i915(dev);
2274 struct drm_intel_sprite_colorkey *set = data;
2275 struct drm_plane *plane;
2276 struct drm_plane_state *plane_state;
2277 struct drm_atomic_state *state;
2278 struct drm_modeset_acquire_ctx ctx;
2279 int ret = 0;
2280
2281 /* ignore the pointless "none" flag */
2282 set->flags &= ~I915_SET_COLORKEY_NONE;
2283
2284 if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
2285 return -EINVAL;
2286
2287 /* Make sure we don't try to enable both src & dest simultaneously */
2288 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
2289 return -EINVAL;
2290
2291 if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
2292 set->flags & I915_SET_COLORKEY_DESTINATION)
2293 return -EINVAL;
2294
2295 plane = drm_plane_find(dev, file_priv, set->plane_id);
2296 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
2297 return -ENOENT;
2298
2299 /*
2300 * SKL+ only plane 2 can do destination keying against plane 1.
2301 * Also multiple planes can't do destination keying on the same
2302 * pipe simultaneously.
2303 */
2304 if (INTEL_GEN(dev_priv) >= 9 &&
2305 to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
2306 set->flags & I915_SET_COLORKEY_DESTINATION)
2307 return -EINVAL;
2308
2309 drm_modeset_acquire_init(&ctx, 0);
2310
2311 state = drm_atomic_state_alloc(plane->dev);
2312 if (!state) {
2313 ret = -ENOMEM;
2314 goto out;
2315 }
2316 state->acquire_ctx = &ctx;
2317
2318 while (1) {
2319 plane_state = drm_atomic_get_plane_state(state, plane);
2320 ret = PTR_ERR_OR_ZERO(plane_state);
2321 if (!ret)
2322 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
2323
2324 /*
2325 * On some platforms we have to configure
2326 * the dst colorkey on the primary plane.
2327 */
2328 if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
2329 struct intel_crtc *crtc =
2330 intel_get_crtc_for_pipe(dev_priv,
2331 to_intel_plane(plane)->pipe);
2332
2333 plane_state = drm_atomic_get_plane_state(state,
2334 crtc->base.primary);
2335 ret = PTR_ERR_OR_ZERO(plane_state);
2336 if (!ret)
2337 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
2338 }
2339
2340 if (!ret)
2341 ret = drm_atomic_commit(state);
2342
2343 if (ret != -EDEADLK)
2344 break;
2345
2346 drm_atomic_state_clear(state);
2347 drm_modeset_backoff(&ctx);
2348 }
2349
2350 drm_atomic_state_put(state);
2351 out:
2352 drm_modeset_drop_locks(&ctx);
2353 drm_modeset_acquire_fini(&ctx);
2354 return ret;
2355 }
2356
2357 static const u32 g4x_plane_formats[] = {
2358 DRM_FORMAT_XRGB8888,
2359 DRM_FORMAT_YUYV,
2360 DRM_FORMAT_YVYU,
2361 DRM_FORMAT_UYVY,
2362 DRM_FORMAT_VYUY,
2363 };
2364
2365 static const u64 i9xx_plane_format_modifiers[] = {
2366 I915_FORMAT_MOD_X_TILED,
2367 DRM_FORMAT_MOD_LINEAR,
2368 DRM_FORMAT_MOD_INVALID
2369 };
2370
2371 static const u32 snb_plane_formats[] = {
2372 DRM_FORMAT_XRGB8888,
2373 DRM_FORMAT_XBGR8888,
2374 DRM_FORMAT_XRGB2101010,
2375 DRM_FORMAT_XBGR2101010,
2376 DRM_FORMAT_XRGB16161616F,
2377 DRM_FORMAT_XBGR16161616F,
2378 DRM_FORMAT_YUYV,
2379 DRM_FORMAT_YVYU,
2380 DRM_FORMAT_UYVY,
2381 DRM_FORMAT_VYUY,
2382 };
2383
2384 static const u32 vlv_plane_formats[] = {
2385 DRM_FORMAT_C8,
2386 DRM_FORMAT_RGB565,
2387 DRM_FORMAT_XRGB8888,
2388 DRM_FORMAT_XBGR8888,
2389 DRM_FORMAT_ARGB8888,
2390 DRM_FORMAT_ABGR8888,
2391 DRM_FORMAT_XBGR2101010,
2392 DRM_FORMAT_ABGR2101010,
2393 DRM_FORMAT_YUYV,
2394 DRM_FORMAT_YVYU,
2395 DRM_FORMAT_UYVY,
2396 DRM_FORMAT_VYUY,
2397 };
2398
2399 static const u32 chv_pipe_b_sprite_formats[] = {
2400 DRM_FORMAT_C8,
2401 DRM_FORMAT_RGB565,
2402 DRM_FORMAT_XRGB8888,
2403 DRM_FORMAT_XBGR8888,
2404 DRM_FORMAT_ARGB8888,
2405 DRM_FORMAT_ABGR8888,
2406 DRM_FORMAT_XRGB2101010,
2407 DRM_FORMAT_XBGR2101010,
2408 DRM_FORMAT_ARGB2101010,
2409 DRM_FORMAT_ABGR2101010,
2410 DRM_FORMAT_YUYV,
2411 DRM_FORMAT_YVYU,
2412 DRM_FORMAT_UYVY,
2413 DRM_FORMAT_VYUY,
2414 };
2415
2416 static const u32 skl_plane_formats[] = {
2417 DRM_FORMAT_C8,
2418 DRM_FORMAT_RGB565,
2419 DRM_FORMAT_XRGB8888,
2420 DRM_FORMAT_XBGR8888,
2421 DRM_FORMAT_ARGB8888,
2422 DRM_FORMAT_ABGR8888,
2423 DRM_FORMAT_XRGB2101010,
2424 DRM_FORMAT_XBGR2101010,
2425 DRM_FORMAT_XRGB16161616F,
2426 DRM_FORMAT_XBGR16161616F,
2427 DRM_FORMAT_YUYV,
2428 DRM_FORMAT_YVYU,
2429 DRM_FORMAT_UYVY,
2430 DRM_FORMAT_VYUY,
2431 };
2432
2433 static const u32 skl_planar_formats[] = {
2434 DRM_FORMAT_C8,
2435 DRM_FORMAT_RGB565,
2436 DRM_FORMAT_XRGB8888,
2437 DRM_FORMAT_XBGR8888,
2438 DRM_FORMAT_ARGB8888,
2439 DRM_FORMAT_ABGR8888,
2440 DRM_FORMAT_XRGB2101010,
2441 DRM_FORMAT_XBGR2101010,
2442 DRM_FORMAT_XRGB16161616F,
2443 DRM_FORMAT_XBGR16161616F,
2444 DRM_FORMAT_YUYV,
2445 DRM_FORMAT_YVYU,
2446 DRM_FORMAT_UYVY,
2447 DRM_FORMAT_VYUY,
2448 DRM_FORMAT_NV12,
2449 };
2450
2451 static const u32 glk_planar_formats[] = {
2452 DRM_FORMAT_C8,
2453 DRM_FORMAT_RGB565,
2454 DRM_FORMAT_XRGB8888,
2455 DRM_FORMAT_XBGR8888,
2456 DRM_FORMAT_ARGB8888,
2457 DRM_FORMAT_ABGR8888,
2458 DRM_FORMAT_XRGB2101010,
2459 DRM_FORMAT_XBGR2101010,
2460 DRM_FORMAT_XRGB16161616F,
2461 DRM_FORMAT_XBGR16161616F,
2462 DRM_FORMAT_YUYV,
2463 DRM_FORMAT_YVYU,
2464 DRM_FORMAT_UYVY,
2465 DRM_FORMAT_VYUY,
2466 DRM_FORMAT_NV12,
2467 DRM_FORMAT_P010,
2468 DRM_FORMAT_P012,
2469 DRM_FORMAT_P016,
2470 };
2471
2472 static const u32 icl_sdr_y_plane_formats[] = {
2473 DRM_FORMAT_C8,
2474 DRM_FORMAT_RGB565,
2475 DRM_FORMAT_XRGB8888,
2476 DRM_FORMAT_XBGR8888,
2477 DRM_FORMAT_ARGB8888,
2478 DRM_FORMAT_ABGR8888,
2479 DRM_FORMAT_XRGB2101010,
2480 DRM_FORMAT_XBGR2101010,
2481 DRM_FORMAT_ARGB2101010,
2482 DRM_FORMAT_ABGR2101010,
2483 DRM_FORMAT_YUYV,
2484 DRM_FORMAT_YVYU,
2485 DRM_FORMAT_UYVY,
2486 DRM_FORMAT_VYUY,
2487 DRM_FORMAT_Y210,
2488 DRM_FORMAT_Y212,
2489 DRM_FORMAT_Y216,
2490 DRM_FORMAT_XVYU2101010,
2491 DRM_FORMAT_XVYU12_16161616,
2492 DRM_FORMAT_XVYU16161616,
2493 };
2494
2495 static const u32 icl_sdr_uv_plane_formats[] = {
2496 DRM_FORMAT_C8,
2497 DRM_FORMAT_RGB565,
2498 DRM_FORMAT_XRGB8888,
2499 DRM_FORMAT_XBGR8888,
2500 DRM_FORMAT_ARGB8888,
2501 DRM_FORMAT_ABGR8888,
2502 DRM_FORMAT_XRGB2101010,
2503 DRM_FORMAT_XBGR2101010,
2504 DRM_FORMAT_ARGB2101010,
2505 DRM_FORMAT_ABGR2101010,
2506 DRM_FORMAT_YUYV,
2507 DRM_FORMAT_YVYU,
2508 DRM_FORMAT_UYVY,
2509 DRM_FORMAT_VYUY,
2510 DRM_FORMAT_NV12,
2511 DRM_FORMAT_P010,
2512 DRM_FORMAT_P012,
2513 DRM_FORMAT_P016,
2514 DRM_FORMAT_Y210,
2515 DRM_FORMAT_Y212,
2516 DRM_FORMAT_Y216,
2517 DRM_FORMAT_XVYU2101010,
2518 DRM_FORMAT_XVYU12_16161616,
2519 DRM_FORMAT_XVYU16161616,
2520 };
2521
2522 static const u32 icl_hdr_plane_formats[] = {
2523 DRM_FORMAT_C8,
2524 DRM_FORMAT_RGB565,
2525 DRM_FORMAT_XRGB8888,
2526 DRM_FORMAT_XBGR8888,
2527 DRM_FORMAT_ARGB8888,
2528 DRM_FORMAT_ABGR8888,
2529 DRM_FORMAT_XRGB2101010,
2530 DRM_FORMAT_XBGR2101010,
2531 DRM_FORMAT_ARGB2101010,
2532 DRM_FORMAT_ABGR2101010,
2533 DRM_FORMAT_XRGB16161616F,
2534 DRM_FORMAT_XBGR16161616F,
2535 DRM_FORMAT_ARGB16161616F,
2536 DRM_FORMAT_ABGR16161616F,
2537 DRM_FORMAT_YUYV,
2538 DRM_FORMAT_YVYU,
2539 DRM_FORMAT_UYVY,
2540 DRM_FORMAT_VYUY,
2541 DRM_FORMAT_NV12,
2542 DRM_FORMAT_P010,
2543 DRM_FORMAT_P012,
2544 DRM_FORMAT_P016,
2545 DRM_FORMAT_Y210,
2546 DRM_FORMAT_Y212,
2547 DRM_FORMAT_Y216,
2548 DRM_FORMAT_XVYU2101010,
2549 DRM_FORMAT_XVYU12_16161616,
2550 DRM_FORMAT_XVYU16161616,
2551 };
2552
2553 static const u64 skl_plane_format_modifiers_noccs[] = {
2554 I915_FORMAT_MOD_Yf_TILED,
2555 I915_FORMAT_MOD_Y_TILED,
2556 I915_FORMAT_MOD_X_TILED,
2557 DRM_FORMAT_MOD_LINEAR,
2558 DRM_FORMAT_MOD_INVALID
2559 };
2560
2561 static const u64 skl_plane_format_modifiers_ccs[] = {
2562 I915_FORMAT_MOD_Yf_TILED_CCS,
2563 I915_FORMAT_MOD_Y_TILED_CCS,
2564 I915_FORMAT_MOD_Yf_TILED,
2565 I915_FORMAT_MOD_Y_TILED,
2566 I915_FORMAT_MOD_X_TILED,
2567 DRM_FORMAT_MOD_LINEAR,
2568 DRM_FORMAT_MOD_INVALID
2569 };
2570
2571 static const u64 gen12_plane_format_modifiers_mc_ccs[] = {
2572 I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
2573 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
2574 I915_FORMAT_MOD_Y_TILED,
2575 I915_FORMAT_MOD_X_TILED,
2576 DRM_FORMAT_MOD_LINEAR,
2577 DRM_FORMAT_MOD_INVALID
2578 };
2579
2580 static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
2581 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
2582 I915_FORMAT_MOD_Y_TILED,
2583 I915_FORMAT_MOD_X_TILED,
2584 DRM_FORMAT_MOD_LINEAR,
2585 DRM_FORMAT_MOD_INVALID
2586 };
2587
2588 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
2589 u32 format, u64 modifier)
2590 {
2591 switch (modifier) {
2592 case DRM_FORMAT_MOD_LINEAR:
2593 case I915_FORMAT_MOD_X_TILED:
2594 break;
2595 default:
2596 return false;
2597 }
2598
2599 switch (format) {
2600 case DRM_FORMAT_XRGB8888:
2601 case DRM_FORMAT_YUYV:
2602 case DRM_FORMAT_YVYU:
2603 case DRM_FORMAT_UYVY:
2604 case DRM_FORMAT_VYUY:
2605 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2606 modifier == I915_FORMAT_MOD_X_TILED)
2607 return true;
2608 /* fall through */
2609 default:
2610 return false;
2611 }
2612 }
2613
2614 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
2615 u32 format, u64 modifier)
2616 {
2617 switch (modifier) {
2618 case DRM_FORMAT_MOD_LINEAR:
2619 case I915_FORMAT_MOD_X_TILED:
2620 break;
2621 default:
2622 return false;
2623 }
2624
2625 switch (format) {
2626 case DRM_FORMAT_XRGB8888:
2627 case DRM_FORMAT_XBGR8888:
2628 case DRM_FORMAT_XRGB2101010:
2629 case DRM_FORMAT_XBGR2101010:
2630 case DRM_FORMAT_XRGB16161616F:
2631 case DRM_FORMAT_XBGR16161616F:
2632 case DRM_FORMAT_YUYV:
2633 case DRM_FORMAT_YVYU:
2634 case DRM_FORMAT_UYVY:
2635 case DRM_FORMAT_VYUY:
2636 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2637 modifier == I915_FORMAT_MOD_X_TILED)
2638 return true;
2639 /* fall through */
2640 default:
2641 return false;
2642 }
2643 }
2644
2645 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
2646 u32 format, u64 modifier)
2647 {
2648 switch (modifier) {
2649 case DRM_FORMAT_MOD_LINEAR:
2650 case I915_FORMAT_MOD_X_TILED:
2651 break;
2652 default:
2653 return false;
2654 }
2655
2656 switch (format) {
2657 case DRM_FORMAT_C8:
2658 case DRM_FORMAT_RGB565:
2659 case DRM_FORMAT_ABGR8888:
2660 case DRM_FORMAT_ARGB8888:
2661 case DRM_FORMAT_XBGR8888:
2662 case DRM_FORMAT_XRGB8888:
2663 case DRM_FORMAT_XBGR2101010:
2664 case DRM_FORMAT_ABGR2101010:
2665 case DRM_FORMAT_XRGB2101010:
2666 case DRM_FORMAT_ARGB2101010:
2667 case DRM_FORMAT_YUYV:
2668 case DRM_FORMAT_YVYU:
2669 case DRM_FORMAT_UYVY:
2670 case DRM_FORMAT_VYUY:
2671 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2672 modifier == I915_FORMAT_MOD_X_TILED)
2673 return true;
2674 /* fall through */
2675 default:
2676 return false;
2677 }
2678 }
2679
2680 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2681 u32 format, u64 modifier)
2682 {
2683 struct intel_plane *plane = to_intel_plane(_plane);
2684
2685 switch (modifier) {
2686 case DRM_FORMAT_MOD_LINEAR:
2687 case I915_FORMAT_MOD_X_TILED:
2688 case I915_FORMAT_MOD_Y_TILED:
2689 case I915_FORMAT_MOD_Yf_TILED:
2690 break;
2691 case I915_FORMAT_MOD_Y_TILED_CCS:
2692 case I915_FORMAT_MOD_Yf_TILED_CCS:
2693 if (!plane->has_ccs)
2694 return false;
2695 break;
2696 default:
2697 return false;
2698 }
2699
2700 switch (format) {
2701 case DRM_FORMAT_XRGB8888:
2702 case DRM_FORMAT_XBGR8888:
2703 case DRM_FORMAT_ARGB8888:
2704 case DRM_FORMAT_ABGR8888:
2705 if (is_ccs_modifier(modifier))
2706 return true;
2707 /* fall through */
2708 case DRM_FORMAT_RGB565:
2709 case DRM_FORMAT_XRGB2101010:
2710 case DRM_FORMAT_XBGR2101010:
2711 case DRM_FORMAT_ARGB2101010:
2712 case DRM_FORMAT_ABGR2101010:
2713 case DRM_FORMAT_YUYV:
2714 case DRM_FORMAT_YVYU:
2715 case DRM_FORMAT_UYVY:
2716 case DRM_FORMAT_VYUY:
2717 case DRM_FORMAT_NV12:
2718 case DRM_FORMAT_P010:
2719 case DRM_FORMAT_P012:
2720 case DRM_FORMAT_P016:
2721 case DRM_FORMAT_XVYU2101010:
2722 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2723 return true;
2724 /* fall through */
2725 case DRM_FORMAT_C8:
2726 case DRM_FORMAT_XBGR16161616F:
2727 case DRM_FORMAT_ABGR16161616F:
2728 case DRM_FORMAT_XRGB16161616F:
2729 case DRM_FORMAT_ARGB16161616F:
2730 case DRM_FORMAT_Y210:
2731 case DRM_FORMAT_Y212:
2732 case DRM_FORMAT_Y216:
2733 case DRM_FORMAT_XVYU12_16161616:
2734 case DRM_FORMAT_XVYU16161616:
2735 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2736 modifier == I915_FORMAT_MOD_X_TILED ||
2737 modifier == I915_FORMAT_MOD_Y_TILED)
2738 return true;
2739 /* fall through */
2740 default:
2741 return false;
2742 }
2743 }
2744
2745 static bool gen12_plane_supports_mc_ccs(enum plane_id plane_id)
2746 {
2747 return plane_id < PLANE_SPRITE4;
2748 }
2749
2750 static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
2751 u32 format, u64 modifier)
2752 {
2753 struct intel_plane *plane = to_intel_plane(_plane);
2754
2755 switch (modifier) {
2756 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
2757 if (!gen12_plane_supports_mc_ccs(plane->id))
2758 return false;
2759 /* fall through */
2760 case DRM_FORMAT_MOD_LINEAR:
2761 case I915_FORMAT_MOD_X_TILED:
2762 case I915_FORMAT_MOD_Y_TILED:
2763 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
2764 break;
2765 default:
2766 return false;
2767 }
2768
2769 switch (format) {
2770 case DRM_FORMAT_XRGB8888:
2771 case DRM_FORMAT_XBGR8888:
2772 case DRM_FORMAT_ARGB8888:
2773 case DRM_FORMAT_ABGR8888:
2774 if (is_ccs_modifier(modifier))
2775 return true;
2776 /* fall through */
2777 case DRM_FORMAT_YUYV:
2778 case DRM_FORMAT_YVYU:
2779 case DRM_FORMAT_UYVY:
2780 case DRM_FORMAT_VYUY:
2781 case DRM_FORMAT_NV12:
2782 case DRM_FORMAT_P010:
2783 case DRM_FORMAT_P012:
2784 case DRM_FORMAT_P016:
2785 if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
2786 return true;
2787 /* fall through */
2788 case DRM_FORMAT_RGB565:
2789 case DRM_FORMAT_XRGB2101010:
2790 case DRM_FORMAT_XBGR2101010:
2791 case DRM_FORMAT_ARGB2101010:
2792 case DRM_FORMAT_ABGR2101010:
2793 case DRM_FORMAT_XVYU2101010:
2794 case DRM_FORMAT_C8:
2795 case DRM_FORMAT_XBGR16161616F:
2796 case DRM_FORMAT_ABGR16161616F:
2797 case DRM_FORMAT_XRGB16161616F:
2798 case DRM_FORMAT_ARGB16161616F:
2799 case DRM_FORMAT_Y210:
2800 case DRM_FORMAT_Y212:
2801 case DRM_FORMAT_Y216:
2802 case DRM_FORMAT_XVYU12_16161616:
2803 case DRM_FORMAT_XVYU16161616:
2804 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2805 modifier == I915_FORMAT_MOD_X_TILED ||
2806 modifier == I915_FORMAT_MOD_Y_TILED)
2807 return true;
2808 /* fall through */
2809 default:
2810 return false;
2811 }
2812 }
2813
2814 static const struct drm_plane_funcs g4x_sprite_funcs = {
2815 .update_plane = drm_atomic_helper_update_plane,
2816 .disable_plane = drm_atomic_helper_disable_plane,
2817 .destroy = intel_plane_destroy,
2818 .atomic_duplicate_state = intel_plane_duplicate_state,
2819 .atomic_destroy_state = intel_plane_destroy_state,
2820 .format_mod_supported = g4x_sprite_format_mod_supported,
2821 };
2822
2823 static const struct drm_plane_funcs snb_sprite_funcs = {
2824 .update_plane = drm_atomic_helper_update_plane,
2825 .disable_plane = drm_atomic_helper_disable_plane,
2826 .destroy = intel_plane_destroy,
2827 .atomic_duplicate_state = intel_plane_duplicate_state,
2828 .atomic_destroy_state = intel_plane_destroy_state,
2829 .format_mod_supported = snb_sprite_format_mod_supported,
2830 };
2831
2832 static const struct drm_plane_funcs vlv_sprite_funcs = {
2833 .update_plane = drm_atomic_helper_update_plane,
2834 .disable_plane = drm_atomic_helper_disable_plane,
2835 .destroy = intel_plane_destroy,
2836 .atomic_duplicate_state = intel_plane_duplicate_state,
2837 .atomic_destroy_state = intel_plane_destroy_state,
2838 .format_mod_supported = vlv_sprite_format_mod_supported,
2839 };
2840
2841 static const struct drm_plane_funcs skl_plane_funcs = {
2842 .update_plane = drm_atomic_helper_update_plane,
2843 .disable_plane = drm_atomic_helper_disable_plane,
2844 .destroy = intel_plane_destroy,
2845 .atomic_duplicate_state = intel_plane_duplicate_state,
2846 .atomic_destroy_state = intel_plane_destroy_state,
2847 .format_mod_supported = skl_plane_format_mod_supported,
2848 };
2849
2850 static const struct drm_plane_funcs gen12_plane_funcs = {
2851 .update_plane = drm_atomic_helper_update_plane,
2852 .disable_plane = drm_atomic_helper_disable_plane,
2853 .destroy = intel_plane_destroy,
2854 .atomic_duplicate_state = intel_plane_duplicate_state,
2855 .atomic_destroy_state = intel_plane_destroy_state,
2856 .format_mod_supported = gen12_plane_format_mod_supported,
2857 };
2858
2859 static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
2860 enum pipe pipe, enum plane_id plane_id)
2861 {
2862 if (!HAS_FBC(dev_priv))
2863 return false;
2864
2865 return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
2866 }
2867
2868 static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
2869 enum pipe pipe, enum plane_id plane_id)
2870 {
2871 /* Display WA #0870: skl, bxt */
2872 if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
2873 return false;
2874
2875 if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
2876 return false;
2877
2878 if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
2879 return false;
2880
2881 return true;
2882 }
2883
2884 static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
2885 enum pipe pipe, enum plane_id plane_id,
2886 int *num_formats)
2887 {
2888 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2889 *num_formats = ARRAY_SIZE(skl_planar_formats);
2890 return skl_planar_formats;
2891 } else {
2892 *num_formats = ARRAY_SIZE(skl_plane_formats);
2893 return skl_plane_formats;
2894 }
2895 }
2896
2897 static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
2898 enum pipe pipe, enum plane_id plane_id,
2899 int *num_formats)
2900 {
2901 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2902 *num_formats = ARRAY_SIZE(glk_planar_formats);
2903 return glk_planar_formats;
2904 } else {
2905 *num_formats = ARRAY_SIZE(skl_plane_formats);
2906 return skl_plane_formats;
2907 }
2908 }
2909
2910 static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
2911 enum pipe pipe, enum plane_id plane_id,
2912 int *num_formats)
2913 {
2914 if (icl_is_hdr_plane(dev_priv, plane_id)) {
2915 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
2916 return icl_hdr_plane_formats;
2917 } else if (icl_is_nv12_y_plane(plane_id)) {
2918 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
2919 return icl_sdr_y_plane_formats;
2920 } else {
2921 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
2922 return icl_sdr_uv_plane_formats;
2923 }
2924 }
2925
2926 static const u64 *gen12_get_plane_modifiers(enum plane_id plane_id)
2927 {
2928 if (gen12_plane_supports_mc_ccs(plane_id))
2929 return gen12_plane_format_modifiers_mc_ccs;
2930 else
2931 return gen12_plane_format_modifiers_rc_ccs;
2932 }
2933
2934 static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
2935 enum pipe pipe, enum plane_id plane_id)
2936 {
2937 if (plane_id == PLANE_CURSOR)
2938 return false;
2939
2940 if (INTEL_GEN(dev_priv) >= 10)
2941 return true;
2942
2943 if (IS_GEMINILAKE(dev_priv))
2944 return pipe != PIPE_C;
2945
2946 return pipe != PIPE_C &&
2947 (plane_id == PLANE_PRIMARY ||
2948 plane_id == PLANE_SPRITE0);
2949 }
2950
2951 struct intel_plane *
2952 skl_universal_plane_create(struct drm_i915_private *dev_priv,
2953 enum pipe pipe, enum plane_id plane_id)
2954 {
2955 const struct drm_plane_funcs *plane_funcs;
2956 struct intel_plane *plane;
2957 enum drm_plane_type plane_type;
2958 unsigned int supported_rotations;
2959 unsigned int possible_crtcs;
2960 const u64 *modifiers;
2961 const u32 *formats;
2962 int num_formats;
2963 int ret;
2964
2965 plane = intel_plane_alloc();
2966 if (IS_ERR(plane))
2967 return plane;
2968
2969 plane->pipe = pipe;
2970 plane->id = plane_id;
2971 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2972
2973 plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
2974 if (plane->has_fbc) {
2975 struct intel_fbc *fbc = &dev_priv->fbc;
2976
2977 fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
2978 }
2979
2980 plane->max_stride = skl_plane_max_stride;
2981 plane->update_plane = skl_update_plane;
2982 plane->disable_plane = skl_disable_plane;
2983 plane->get_hw_state = skl_plane_get_hw_state;
2984 plane->check_plane = skl_plane_check;
2985 plane->min_cdclk = skl_plane_min_cdclk;
2986
2987 if (INTEL_GEN(dev_priv) >= 11)
2988 formats = icl_get_plane_formats(dev_priv, pipe,
2989 plane_id, &num_formats);
2990 else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
2991 formats = glk_get_plane_formats(dev_priv, pipe,
2992 plane_id, &num_formats);
2993 else
2994 formats = skl_get_plane_formats(dev_priv, pipe,
2995 plane_id, &num_formats);
2996
2997 plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
2998 if (INTEL_GEN(dev_priv) >= 12) {
2999 modifiers = gen12_get_plane_modifiers(plane_id);
3000 plane_funcs = &gen12_plane_funcs;
3001 } else {
3002 if (plane->has_ccs)
3003 modifiers = skl_plane_format_modifiers_ccs;
3004 else
3005 modifiers = skl_plane_format_modifiers_noccs;
3006 plane_funcs = &skl_plane_funcs;
3007 }
3008
3009 if (plane_id == PLANE_PRIMARY)
3010 plane_type = DRM_PLANE_TYPE_PRIMARY;
3011 else
3012 plane_type = DRM_PLANE_TYPE_OVERLAY;
3013
3014 possible_crtcs = BIT(pipe);
3015
3016 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
3017 possible_crtcs, plane_funcs,
3018 formats, num_formats, modifiers,
3019 plane_type,
3020 "plane %d%c", plane_id + 1,
3021 pipe_name(pipe));
3022 if (ret)
3023 goto fail;
3024
3025 supported_rotations =
3026 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
3027 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
3028
3029 if (INTEL_GEN(dev_priv) >= 10)
3030 supported_rotations |= DRM_MODE_REFLECT_X;
3031
3032 drm_plane_create_rotation_property(&plane->base,
3033 DRM_MODE_ROTATE_0,
3034 supported_rotations);
3035
3036 drm_plane_create_color_properties(&plane->base,
3037 BIT(DRM_COLOR_YCBCR_BT601) |
3038 BIT(DRM_COLOR_YCBCR_BT709),
3039 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
3040 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
3041 DRM_COLOR_YCBCR_BT709,
3042 DRM_COLOR_YCBCR_LIMITED_RANGE);
3043
3044 drm_plane_create_alpha_property(&plane->base);
3045 drm_plane_create_blend_mode_property(&plane->base,
3046 BIT(DRM_MODE_BLEND_PIXEL_NONE) |
3047 BIT(DRM_MODE_BLEND_PREMULTI) |
3048 BIT(DRM_MODE_BLEND_COVERAGE));
3049
3050 drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
3051
3052 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
3053
3054 return plane;
3055
3056 fail:
3057 intel_plane_free(plane);
3058
3059 return ERR_PTR(ret);
3060 }
3061
3062 struct intel_plane *
3063 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
3064 enum pipe pipe, int sprite)
3065 {
3066 struct intel_plane *plane;
3067 const struct drm_plane_funcs *plane_funcs;
3068 unsigned long possible_crtcs;
3069 unsigned int supported_rotations;
3070 const u64 *modifiers;
3071 const u32 *formats;
3072 int num_formats;
3073 int ret, zpos;
3074
3075 if (INTEL_GEN(dev_priv) >= 9)
3076 return skl_universal_plane_create(dev_priv, pipe,
3077 PLANE_SPRITE0 + sprite);
3078
3079 plane = intel_plane_alloc();
3080 if (IS_ERR(plane))
3081 return plane;
3082
3083 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
3084 plane->max_stride = i9xx_plane_max_stride;
3085 plane->update_plane = vlv_update_plane;
3086 plane->disable_plane = vlv_disable_plane;
3087 plane->get_hw_state = vlv_plane_get_hw_state;
3088 plane->check_plane = vlv_sprite_check;
3089 plane->min_cdclk = vlv_plane_min_cdclk;
3090
3091 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
3092 formats = chv_pipe_b_sprite_formats;
3093 num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
3094 } else {
3095 formats = vlv_plane_formats;
3096 num_formats = ARRAY_SIZE(vlv_plane_formats);
3097 }
3098 modifiers = i9xx_plane_format_modifiers;
3099
3100 plane_funcs = &vlv_sprite_funcs;
3101 } else if (INTEL_GEN(dev_priv) >= 7) {
3102 plane->max_stride = g4x_sprite_max_stride;
3103 plane->update_plane = ivb_update_plane;
3104 plane->disable_plane = ivb_disable_plane;
3105 plane->get_hw_state = ivb_plane_get_hw_state;
3106 plane->check_plane = g4x_sprite_check;
3107
3108 if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
3109 plane->min_cdclk = hsw_plane_min_cdclk;
3110 else
3111 plane->min_cdclk = ivb_sprite_min_cdclk;
3112
3113 formats = snb_plane_formats;
3114 num_formats = ARRAY_SIZE(snb_plane_formats);
3115 modifiers = i9xx_plane_format_modifiers;
3116
3117 plane_funcs = &snb_sprite_funcs;
3118 } else {
3119 plane->max_stride = g4x_sprite_max_stride;
3120 plane->update_plane = g4x_update_plane;
3121 plane->disable_plane = g4x_disable_plane;
3122 plane->get_hw_state = g4x_plane_get_hw_state;
3123 plane->check_plane = g4x_sprite_check;
3124 plane->min_cdclk = g4x_sprite_min_cdclk;
3125
3126 modifiers = i9xx_plane_format_modifiers;
3127 if (IS_GEN(dev_priv, 6)) {
3128 formats = snb_plane_formats;
3129 num_formats = ARRAY_SIZE(snb_plane_formats);
3130
3131 plane_funcs = &snb_sprite_funcs;
3132 } else {
3133 formats = g4x_plane_formats;
3134 num_formats = ARRAY_SIZE(g4x_plane_formats);
3135
3136 plane_funcs = &g4x_sprite_funcs;
3137 }
3138 }
3139
3140 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
3141 supported_rotations =
3142 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
3143 DRM_MODE_REFLECT_X;
3144 } else {
3145 supported_rotations =
3146 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
3147 }
3148
3149 plane->pipe = pipe;
3150 plane->id = PLANE_SPRITE0 + sprite;
3151 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
3152
3153 possible_crtcs = BIT(pipe);
3154
3155 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
3156 possible_crtcs, plane_funcs,
3157 formats, num_formats, modifiers,
3158 DRM_PLANE_TYPE_OVERLAY,
3159 "sprite %c", sprite_name(pipe, sprite));
3160 if (ret)
3161 goto fail;
3162
3163 drm_plane_create_rotation_property(&plane->base,
3164 DRM_MODE_ROTATE_0,
3165 supported_rotations);
3166
3167 drm_plane_create_color_properties(&plane->base,
3168 BIT(DRM_COLOR_YCBCR_BT601) |
3169 BIT(DRM_COLOR_YCBCR_BT709),
3170 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
3171 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
3172 DRM_COLOR_YCBCR_BT709,
3173 DRM_COLOR_YCBCR_LIMITED_RANGE);
3174
3175 zpos = sprite + 1;
3176 drm_plane_create_zpos_immutable_property(&plane->base, zpos);
3177
3178 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
3179
3180 return plane;
3181
3182 fail:
3183 intel_plane_free(plane);
3184
3185 return ERR_PTR(ret);
3186 }
3187