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