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