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