Loading...
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
51bool 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
64int 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 */
95void 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
192irq_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 */
204void 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
253int 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
285int 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
334bool 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
340static unsigned int
341skl_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
358static void
359skl_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
420static void
421icl_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
538static void
539skl_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
649static void
650skl_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
665static void
666icl_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
674static void
675skl_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
696static bool
697skl_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
720static 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
730static void
731chv_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
789static void
790vlv_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
828static 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
838static 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
905static 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
930static void
931vlv_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
993static void
994vlv_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
1010static bool
1011vlv_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
1034static 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
1047static 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
1108static 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
1119static 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
1147static void
1148ivb_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
1218static void
1219ivb_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
1237static bool
1238ivb_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
1260static unsigned int
1261g4x_sprite_max_stride(struct intel_plane *plane,
1262 u32 pixel_format, u64 modifier,
1263 unsigned int rotation)
1264{
1265 return 16384;
1266}
1267
1268static 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
1281static 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
1340static 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
1364static 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
1372static 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
1400static void
1401g4x_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
1467static void
1468g4x_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
1485static bool
1486g4x_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
1508static 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
1521static int
1522g4x_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
1582static int
1583g4x_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
1632int 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
1649static int
1650vlv_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
1683static 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
1757static 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
1787static 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
1804static 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
1863static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1864{
1865 return INTEL_GEN(dev_priv) >= 9;
1866}
1867
1868static 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
1894int 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);
1975out:
1976 drm_modeset_drop_locks(&ctx);
1977 drm_modeset_acquire_fini(&ctx);
1978 return ret;
1979}
1980
1981static 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
1989static const u64 i9xx_plane_format_modifiers[] = {
1990 I915_FORMAT_MOD_X_TILED,
1991 DRM_FORMAT_MOD_LINEAR,
1992 DRM_FORMAT_MOD_INVALID
1993};
1994
1995static 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
2004static 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
2018static 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
2033static 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
2049static 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
2068static 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
2089static 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
2114static 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
2143static 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
2151static 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
2161static 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
2187static 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
2214static 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
2246static 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
2309static 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
2318static 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
2327static 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
2336static 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
2345static 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
2354static 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
2370static 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
2383static 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
2396static 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
2412static 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
2429struct intel_plane *
2430skl_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
2526fail:
2527 intel_plane_free(plane);
2528
2529 return ERR_PTR(ret);
2530}
2531
2532struct intel_plane *
2533intel_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
2637fail:
2638 intel_plane_free(plane);
2639
2640 return ERR_PTR(ret);
2641}
1/*
2 * Copyright © 2011 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Jesse Barnes <jbarnes@virtuousgeek.org>
25 *
26 * New plane/sprite handling.
27 *
28 * The older chips had a separate interface for programming plane related
29 * registers; newer ones are much simpler and we can use the new DRM plane
30 * support.
31 */
32
33#include <linux/string_helpers.h>
34
35#include <drm/drm_atomic_helper.h>
36#include <drm/drm_blend.h>
37#include <drm/drm_color_mgmt.h>
38#include <drm/drm_fourcc.h>
39#include <drm/drm_rect.h>
40
41#include "i915_drv.h"
42#include "i915_reg.h"
43#include "i9xx_plane.h"
44#include "intel_atomic_plane.h"
45#include "intel_de.h"
46#include "intel_display_types.h"
47#include "intel_fb.h"
48#include "intel_frontbuffer.h"
49#include "intel_sprite.h"
50
51static char sprite_name(struct drm_i915_private *i915, enum pipe pipe, int sprite)
52{
53 return pipe * DISPLAY_RUNTIME_INFO(i915)->num_sprites[pipe] + sprite + 'A';
54}
55
56static void i9xx_plane_linear_gamma(u16 gamma[8])
57{
58 /* The points are not evenly spaced. */
59 static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
60 int i;
61
62 for (i = 0; i < 8; i++)
63 gamma[i] = (in[i] << 8) / 32;
64}
65
66static void
67chv_sprite_update_csc(const struct intel_plane_state *plane_state)
68{
69 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
70 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
71 const struct drm_framebuffer *fb = plane_state->hw.fb;
72 enum plane_id plane_id = plane->id;
73 /*
74 * |r| | c0 c1 c2 | |cr|
75 * |g| = | c3 c4 c5 | x |y |
76 * |b| | c6 c7 c8 | |cb|
77 *
78 * Coefficients are s3.12.
79 *
80 * Cb and Cr apparently come in as signed already, and
81 * we always get full range data in on account of CLRC0/1.
82 */
83 static const s16 csc_matrix[][9] = {
84 /* BT.601 full range YCbCr -> full range RGB */
85 [DRM_COLOR_YCBCR_BT601] = {
86 5743, 4096, 0,
87 -2925, 4096, -1410,
88 0, 4096, 7258,
89 },
90 /* BT.709 full range YCbCr -> full range RGB */
91 [DRM_COLOR_YCBCR_BT709] = {
92 6450, 4096, 0,
93 -1917, 4096, -767,
94 0, 4096, 7601,
95 },
96 };
97 const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
98
99 /* Seems RGB data bypasses the CSC always */
100 if (!fb->format->is_yuv)
101 return;
102
103 intel_de_write_fw(dev_priv, SPCSCYGOFF(plane_id),
104 SPCSC_OOFF(0) | SPCSC_IOFF(0));
105 intel_de_write_fw(dev_priv, SPCSCCBOFF(plane_id),
106 SPCSC_OOFF(0) | SPCSC_IOFF(0));
107 intel_de_write_fw(dev_priv, SPCSCCROFF(plane_id),
108 SPCSC_OOFF(0) | SPCSC_IOFF(0));
109
110 intel_de_write_fw(dev_priv, SPCSCC01(plane_id),
111 SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
112 intel_de_write_fw(dev_priv, SPCSCC23(plane_id),
113 SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
114 intel_de_write_fw(dev_priv, SPCSCC45(plane_id),
115 SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
116 intel_de_write_fw(dev_priv, SPCSCC67(plane_id),
117 SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
118 intel_de_write_fw(dev_priv, SPCSCC8(plane_id), SPCSC_C0(csc[8]));
119
120 intel_de_write_fw(dev_priv, SPCSCYGICLAMP(plane_id),
121 SPCSC_IMAX(1023) | SPCSC_IMIN(0));
122 intel_de_write_fw(dev_priv, SPCSCCBICLAMP(plane_id),
123 SPCSC_IMAX(512) | SPCSC_IMIN(-512));
124 intel_de_write_fw(dev_priv, SPCSCCRICLAMP(plane_id),
125 SPCSC_IMAX(512) | SPCSC_IMIN(-512));
126
127 intel_de_write_fw(dev_priv, SPCSCYGOCLAMP(plane_id),
128 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
129 intel_de_write_fw(dev_priv, SPCSCCBOCLAMP(plane_id),
130 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
131 intel_de_write_fw(dev_priv, SPCSCCROCLAMP(plane_id),
132 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
133}
134
135#define SIN_0 0
136#define COS_0 1
137
138static void
139vlv_sprite_update_clrc(const struct intel_plane_state *plane_state)
140{
141 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
142 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
143 const struct drm_framebuffer *fb = plane_state->hw.fb;
144 enum pipe pipe = plane->pipe;
145 enum plane_id plane_id = plane->id;
146 int contrast, brightness, sh_scale, sh_sin, sh_cos;
147
148 if (fb->format->is_yuv &&
149 plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
150 /*
151 * Expand limited range to full range:
152 * Contrast is applied first and is used to expand Y range.
153 * Brightness is applied second and is used to remove the
154 * offset from Y. Saturation/hue is used to expand CbCr range.
155 */
156 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
157 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
158 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
159 sh_sin = SIN_0 * sh_scale;
160 sh_cos = COS_0 * sh_scale;
161 } else {
162 /* Pass-through everything. */
163 contrast = 1 << 6;
164 brightness = 0;
165 sh_scale = 1 << 7;
166 sh_sin = SIN_0 * sh_scale;
167 sh_cos = COS_0 * sh_scale;
168 }
169
170 /* FIXME these register are single buffered :( */
171 intel_de_write_fw(dev_priv, SPCLRC0(pipe, plane_id),
172 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
173 intel_de_write_fw(dev_priv, SPCLRC1(pipe, plane_id),
174 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
175}
176
177static void
178vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
179 const struct intel_plane_state *plane_state,
180 unsigned int *num, unsigned int *den)
181{
182 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
183 const struct drm_framebuffer *fb = plane_state->hw.fb;
184 unsigned int cpp = fb->format->cpp[0];
185
186 /*
187 * VLV bspec only considers cases where all three planes are
188 * enabled, and cases where the primary and one sprite is enabled.
189 * Let's assume the case with just two sprites enabled also
190 * maps to the latter case.
191 */
192 if (hweight8(active_planes) == 3) {
193 switch (cpp) {
194 case 8:
195 *num = 11;
196 *den = 8;
197 break;
198 case 4:
199 *num = 18;
200 *den = 16;
201 break;
202 default:
203 *num = 1;
204 *den = 1;
205 break;
206 }
207 } else if (hweight8(active_planes) == 2) {
208 switch (cpp) {
209 case 8:
210 *num = 10;
211 *den = 8;
212 break;
213 case 4:
214 *num = 17;
215 *den = 16;
216 break;
217 default:
218 *num = 1;
219 *den = 1;
220 break;
221 }
222 } else {
223 switch (cpp) {
224 case 8:
225 *num = 10;
226 *den = 8;
227 break;
228 default:
229 *num = 1;
230 *den = 1;
231 break;
232 }
233 }
234}
235
236int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
237 const struct intel_plane_state *plane_state)
238{
239 unsigned int pixel_rate;
240 unsigned int num, den;
241
242 /*
243 * Note that crtc_state->pixel_rate accounts for both
244 * horizontal and vertical panel fitter downscaling factors.
245 * Pre-HSW bspec tells us to only consider the horizontal
246 * downscaling factor here. We ignore that and just consider
247 * both for simplicity.
248 */
249 pixel_rate = crtc_state->pixel_rate;
250
251 vlv_plane_ratio(crtc_state, plane_state, &num, &den);
252
253 return DIV_ROUND_UP(pixel_rate * num, den);
254}
255
256static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
257{
258 u32 sprctl = 0;
259
260 if (crtc_state->gamma_enable)
261 sprctl |= SP_PIPE_GAMMA_ENABLE;
262
263 return sprctl;
264}
265
266static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
267 const struct intel_plane_state *plane_state)
268{
269 const struct drm_framebuffer *fb = plane_state->hw.fb;
270 unsigned int rotation = plane_state->hw.rotation;
271 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
272 u32 sprctl;
273
274 sprctl = SP_ENABLE;
275
276 switch (fb->format->format) {
277 case DRM_FORMAT_YUYV:
278 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
279 break;
280 case DRM_FORMAT_YVYU:
281 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
282 break;
283 case DRM_FORMAT_UYVY:
284 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
285 break;
286 case DRM_FORMAT_VYUY:
287 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
288 break;
289 case DRM_FORMAT_C8:
290 sprctl |= SP_FORMAT_8BPP;
291 break;
292 case DRM_FORMAT_RGB565:
293 sprctl |= SP_FORMAT_BGR565;
294 break;
295 case DRM_FORMAT_XRGB8888:
296 sprctl |= SP_FORMAT_BGRX8888;
297 break;
298 case DRM_FORMAT_ARGB8888:
299 sprctl |= SP_FORMAT_BGRA8888;
300 break;
301 case DRM_FORMAT_XBGR2101010:
302 sprctl |= SP_FORMAT_RGBX1010102;
303 break;
304 case DRM_FORMAT_ABGR2101010:
305 sprctl |= SP_FORMAT_RGBA1010102;
306 break;
307 case DRM_FORMAT_XRGB2101010:
308 sprctl |= SP_FORMAT_BGRX1010102;
309 break;
310 case DRM_FORMAT_ARGB2101010:
311 sprctl |= SP_FORMAT_BGRA1010102;
312 break;
313 case DRM_FORMAT_XBGR8888:
314 sprctl |= SP_FORMAT_RGBX8888;
315 break;
316 case DRM_FORMAT_ABGR8888:
317 sprctl |= SP_FORMAT_RGBA8888;
318 break;
319 default:
320 MISSING_CASE(fb->format->format);
321 return 0;
322 }
323
324 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
325 sprctl |= SP_YUV_FORMAT_BT709;
326
327 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
328 sprctl |= SP_TILED;
329
330 if (rotation & DRM_MODE_ROTATE_180)
331 sprctl |= SP_ROTATE_180;
332
333 if (rotation & DRM_MODE_REFLECT_X)
334 sprctl |= SP_MIRROR;
335
336 if (key->flags & I915_SET_COLORKEY_SOURCE)
337 sprctl |= SP_SOURCE_KEY;
338
339 return sprctl;
340}
341
342static void vlv_sprite_update_gamma(const struct intel_plane_state *plane_state)
343{
344 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
345 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
346 const struct drm_framebuffer *fb = plane_state->hw.fb;
347 enum pipe pipe = plane->pipe;
348 enum plane_id plane_id = plane->id;
349 u16 gamma[8];
350 int i;
351
352 /* Seems RGB data bypasses the gamma always */
353 if (!fb->format->is_yuv)
354 return;
355
356 i9xx_plane_linear_gamma(gamma);
357
358 /* FIXME these register are single buffered :( */
359 /* The two end points are implicit (0.0 and 1.0) */
360 for (i = 1; i < 8 - 1; i++)
361 intel_de_write_fw(dev_priv, SPGAMC(pipe, plane_id, i - 1),
362 gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
363}
364
365static void
366vlv_sprite_update_noarm(struct intel_plane *plane,
367 const struct intel_crtc_state *crtc_state,
368 const struct intel_plane_state *plane_state)
369{
370 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
371 enum pipe pipe = plane->pipe;
372 enum plane_id plane_id = plane->id;
373 int crtc_x = plane_state->uapi.dst.x1;
374 int crtc_y = plane_state->uapi.dst.y1;
375 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
376 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
377
378 intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id),
379 plane_state->view.color_plane[0].mapping_stride);
380 intel_de_write_fw(dev_priv, SPPOS(pipe, plane_id),
381 SP_POS_Y(crtc_y) | SP_POS_X(crtc_x));
382 intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id),
383 SP_HEIGHT(crtc_h - 1) | SP_WIDTH(crtc_w - 1));
384}
385
386static void
387vlv_sprite_update_arm(struct intel_plane *plane,
388 const struct intel_crtc_state *crtc_state,
389 const struct intel_plane_state *plane_state)
390{
391 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
392 enum pipe pipe = plane->pipe;
393 enum plane_id plane_id = plane->id;
394 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
395 u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
396 u32 x = plane_state->view.color_plane[0].x;
397 u32 y = plane_state->view.color_plane[0].y;
398 u32 sprctl, linear_offset;
399
400 sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
401
402 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
403
404 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
405 chv_sprite_update_csc(plane_state);
406
407 if (key->flags) {
408 intel_de_write_fw(dev_priv, SPKEYMINVAL(pipe, plane_id),
409 key->min_value);
410 intel_de_write_fw(dev_priv, SPKEYMSK(pipe, plane_id),
411 key->channel_mask);
412 intel_de_write_fw(dev_priv, SPKEYMAXVAL(pipe, plane_id),
413 key->max_value);
414 }
415
416 intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0);
417
418 intel_de_write_fw(dev_priv, SPLINOFF(pipe, plane_id), linear_offset);
419 intel_de_write_fw(dev_priv, SPTILEOFF(pipe, plane_id),
420 SP_OFFSET_Y(y) | SP_OFFSET_X(x));
421
422 /*
423 * The control register self-arms if the plane was previously
424 * disabled. Try to make the plane enable atomic by writing
425 * the control register just before the surface register.
426 */
427 intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), sprctl);
428 intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id),
429 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
430
431 vlv_sprite_update_clrc(plane_state);
432 vlv_sprite_update_gamma(plane_state);
433}
434
435static void
436vlv_sprite_disable_arm(struct intel_plane *plane,
437 const struct intel_crtc_state *crtc_state)
438{
439 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
440 enum pipe pipe = plane->pipe;
441 enum plane_id plane_id = plane->id;
442
443 intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0);
444 intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0);
445}
446
447static bool
448vlv_sprite_get_hw_state(struct intel_plane *plane,
449 enum pipe *pipe)
450{
451 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
452 enum intel_display_power_domain power_domain;
453 enum plane_id plane_id = plane->id;
454 intel_wakeref_t wakeref;
455 bool ret;
456
457 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
458 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
459 if (!wakeref)
460 return false;
461
462 ret = intel_de_read(dev_priv, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
463
464 *pipe = plane->pipe;
465
466 intel_display_power_put(dev_priv, power_domain, wakeref);
467
468 return ret;
469}
470
471static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
472 const struct intel_plane_state *plane_state,
473 unsigned int *num, unsigned int *den)
474{
475 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
476 const struct drm_framebuffer *fb = plane_state->hw.fb;
477 unsigned int cpp = fb->format->cpp[0];
478
479 if (hweight8(active_planes) == 2) {
480 switch (cpp) {
481 case 8:
482 *num = 10;
483 *den = 8;
484 break;
485 case 4:
486 *num = 17;
487 *den = 16;
488 break;
489 default:
490 *num = 1;
491 *den = 1;
492 break;
493 }
494 } else {
495 switch (cpp) {
496 case 8:
497 *num = 9;
498 *den = 8;
499 break;
500 default:
501 *num = 1;
502 *den = 1;
503 break;
504 }
505 }
506}
507
508static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
509 const struct intel_plane_state *plane_state,
510 unsigned int *num, unsigned int *den)
511{
512 const struct drm_framebuffer *fb = plane_state->hw.fb;
513 unsigned int cpp = fb->format->cpp[0];
514
515 switch (cpp) {
516 case 8:
517 *num = 12;
518 *den = 8;
519 break;
520 case 4:
521 *num = 19;
522 *den = 16;
523 break;
524 case 2:
525 *num = 33;
526 *den = 32;
527 break;
528 default:
529 *num = 1;
530 *den = 1;
531 break;
532 }
533}
534
535int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
536 const struct intel_plane_state *plane_state)
537{
538 unsigned int pixel_rate;
539 unsigned int num, den;
540
541 /*
542 * Note that crtc_state->pixel_rate accounts for both
543 * horizontal and vertical panel fitter downscaling factors.
544 * Pre-HSW bspec tells us to only consider the horizontal
545 * downscaling factor here. We ignore that and just consider
546 * both for simplicity.
547 */
548 pixel_rate = crtc_state->pixel_rate;
549
550 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
551
552 return DIV_ROUND_UP(pixel_rate * num, den);
553}
554
555static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
556 const struct intel_plane_state *plane_state)
557{
558 unsigned int src_w, dst_w, pixel_rate;
559 unsigned int num, den;
560
561 /*
562 * Note that crtc_state->pixel_rate accounts for both
563 * horizontal and vertical panel fitter downscaling factors.
564 * Pre-HSW bspec tells us to only consider the horizontal
565 * downscaling factor here. We ignore that and just consider
566 * both for simplicity.
567 */
568 pixel_rate = crtc_state->pixel_rate;
569
570 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
571 dst_w = drm_rect_width(&plane_state->uapi.dst);
572
573 if (src_w != dst_w)
574 ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
575 else
576 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
577
578 /* Horizontal downscaling limits the maximum pixel rate */
579 dst_w = min(src_w, dst_w);
580
581 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
582 den * dst_w);
583}
584
585static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
586 const struct intel_plane_state *plane_state,
587 unsigned int *num, unsigned int *den)
588{
589 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
590 const struct drm_framebuffer *fb = plane_state->hw.fb;
591 unsigned int cpp = fb->format->cpp[0];
592
593 if (hweight8(active_planes) == 2) {
594 switch (cpp) {
595 case 8:
596 *num = 10;
597 *den = 8;
598 break;
599 default:
600 *num = 1;
601 *den = 1;
602 break;
603 }
604 } else {
605 switch (cpp) {
606 case 8:
607 *num = 9;
608 *den = 8;
609 break;
610 default:
611 *num = 1;
612 *den = 1;
613 break;
614 }
615 }
616}
617
618int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
619 const struct intel_plane_state *plane_state)
620{
621 unsigned int pixel_rate = crtc_state->pixel_rate;
622 unsigned int num, den;
623
624 hsw_plane_ratio(crtc_state, plane_state, &num, &den);
625
626 return DIV_ROUND_UP(pixel_rate * num, den);
627}
628
629static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
630{
631 u32 sprctl = 0;
632
633 if (crtc_state->gamma_enable)
634 sprctl |= SPRITE_PIPE_GAMMA_ENABLE;
635
636 if (crtc_state->csc_enable)
637 sprctl |= SPRITE_PIPE_CSC_ENABLE;
638
639 return sprctl;
640}
641
642static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
643{
644 struct drm_i915_private *dev_priv =
645 to_i915(plane_state->uapi.plane->dev);
646 const struct drm_framebuffer *fb = plane_state->hw.fb;
647
648 return fb->format->cpp[0] == 8 &&
649 (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
650}
651
652static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
653 const struct intel_plane_state *plane_state)
654{
655 struct drm_i915_private *dev_priv =
656 to_i915(plane_state->uapi.plane->dev);
657 const struct drm_framebuffer *fb = plane_state->hw.fb;
658 unsigned int rotation = plane_state->hw.rotation;
659 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
660 u32 sprctl;
661
662 sprctl = SPRITE_ENABLE;
663
664 if (IS_IVYBRIDGE(dev_priv))
665 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
666
667 switch (fb->format->format) {
668 case DRM_FORMAT_XBGR8888:
669 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
670 break;
671 case DRM_FORMAT_XRGB8888:
672 sprctl |= SPRITE_FORMAT_RGBX888;
673 break;
674 case DRM_FORMAT_XBGR2101010:
675 sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
676 break;
677 case DRM_FORMAT_XRGB2101010:
678 sprctl |= SPRITE_FORMAT_RGBX101010;
679 break;
680 case DRM_FORMAT_XBGR16161616F:
681 sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
682 break;
683 case DRM_FORMAT_XRGB16161616F:
684 sprctl |= SPRITE_FORMAT_RGBX161616;
685 break;
686 case DRM_FORMAT_YUYV:
687 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
688 break;
689 case DRM_FORMAT_YVYU:
690 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
691 break;
692 case DRM_FORMAT_UYVY:
693 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
694 break;
695 case DRM_FORMAT_VYUY:
696 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
697 break;
698 default:
699 MISSING_CASE(fb->format->format);
700 return 0;
701 }
702
703 if (!ivb_need_sprite_gamma(plane_state))
704 sprctl |= SPRITE_PLANE_GAMMA_DISABLE;
705
706 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
707 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
708
709 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
710 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
711
712 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
713 sprctl |= SPRITE_TILED;
714
715 if (rotation & DRM_MODE_ROTATE_180)
716 sprctl |= SPRITE_ROTATE_180;
717
718 if (key->flags & I915_SET_COLORKEY_DESTINATION)
719 sprctl |= SPRITE_DEST_KEY;
720 else if (key->flags & I915_SET_COLORKEY_SOURCE)
721 sprctl |= SPRITE_SOURCE_KEY;
722
723 return sprctl;
724}
725
726static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
727 u16 gamma[18])
728{
729 int scale, i;
730
731 /*
732 * WaFP16GammaEnabling:ivb,hsw
733 * "Workaround : When using the 64-bit format, the sprite output
734 * on each color channel has one quarter amplitude. It can be
735 * brought up to full amplitude by using sprite internal gamma
736 * correction, pipe gamma correction, or pipe color space
737 * conversion to multiply the sprite output by four."
738 */
739 scale = 4;
740
741 for (i = 0; i < 16; i++)
742 gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
743
744 gamma[i] = min((scale * i << 10) / 16, 1 << 10);
745 i++;
746
747 gamma[i] = 3 << 10;
748 i++;
749}
750
751static void ivb_sprite_update_gamma(const struct intel_plane_state *plane_state)
752{
753 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
754 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
755 enum pipe pipe = plane->pipe;
756 u16 gamma[18];
757 int i;
758
759 if (!ivb_need_sprite_gamma(plane_state))
760 return;
761
762 ivb_sprite_linear_gamma(plane_state, gamma);
763
764 /* FIXME these register are single buffered :( */
765 for (i = 0; i < 16; i++)
766 intel_de_write_fw(dev_priv, SPRGAMC(pipe, i),
767 gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
768
769 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 0), gamma[i]);
770 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 1), gamma[i]);
771 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 2), gamma[i]);
772 i++;
773
774 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 0), gamma[i]);
775 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 1), gamma[i]);
776 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 2), gamma[i]);
777 i++;
778}
779
780static void
781ivb_sprite_update_noarm(struct intel_plane *plane,
782 const struct intel_crtc_state *crtc_state,
783 const struct intel_plane_state *plane_state)
784{
785 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
786 enum pipe pipe = plane->pipe;
787 int crtc_x = plane_state->uapi.dst.x1;
788 int crtc_y = plane_state->uapi.dst.y1;
789 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
790 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
791 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
792 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
793 u32 sprscale = 0;
794
795 if (crtc_w != src_w || crtc_h != src_h)
796 sprscale = SPRITE_SCALE_ENABLE |
797 SPRITE_SRC_WIDTH(src_w - 1) |
798 SPRITE_SRC_HEIGHT(src_h - 1);
799
800 intel_de_write_fw(dev_priv, SPRSTRIDE(pipe),
801 plane_state->view.color_plane[0].mapping_stride);
802 intel_de_write_fw(dev_priv, SPRPOS(pipe),
803 SPRITE_POS_Y(crtc_y) | SPRITE_POS_X(crtc_x));
804 intel_de_write_fw(dev_priv, SPRSIZE(pipe),
805 SPRITE_HEIGHT(crtc_h - 1) | SPRITE_WIDTH(crtc_w - 1));
806 if (IS_IVYBRIDGE(dev_priv))
807 intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale);
808}
809
810static void
811ivb_sprite_update_arm(struct intel_plane *plane,
812 const struct intel_crtc_state *crtc_state,
813 const struct intel_plane_state *plane_state)
814{
815 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
816 enum pipe pipe = plane->pipe;
817 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
818 u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
819 u32 x = plane_state->view.color_plane[0].x;
820 u32 y = plane_state->view.color_plane[0].y;
821 u32 sprctl, linear_offset;
822
823 sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
824
825 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
826
827 if (key->flags) {
828 intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value);
829 intel_de_write_fw(dev_priv, SPRKEYMSK(pipe),
830 key->channel_mask);
831 intel_de_write_fw(dev_priv, SPRKEYMAX(pipe), key->max_value);
832 }
833
834 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
835 * register */
836 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
837 intel_de_write_fw(dev_priv, SPROFFSET(pipe),
838 SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
839 } else {
840 intel_de_write_fw(dev_priv, SPRLINOFF(pipe), linear_offset);
841 intel_de_write_fw(dev_priv, SPRTILEOFF(pipe),
842 SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
843 }
844
845 /*
846 * The control register self-arms if the plane was previously
847 * disabled. Try to make the plane enable atomic by writing
848 * the control register just before the surface register.
849 */
850 intel_de_write_fw(dev_priv, SPRCTL(pipe), sprctl);
851 intel_de_write_fw(dev_priv, SPRSURF(pipe),
852 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
853
854 ivb_sprite_update_gamma(plane_state);
855}
856
857static void
858ivb_sprite_disable_arm(struct intel_plane *plane,
859 const struct intel_crtc_state *crtc_state)
860{
861 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
862 enum pipe pipe = plane->pipe;
863
864 intel_de_write_fw(dev_priv, SPRCTL(pipe), 0);
865 /* Disable the scaler */
866 if (IS_IVYBRIDGE(dev_priv))
867 intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0);
868 intel_de_write_fw(dev_priv, SPRSURF(pipe), 0);
869}
870
871static bool
872ivb_sprite_get_hw_state(struct intel_plane *plane,
873 enum pipe *pipe)
874{
875 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
876 enum intel_display_power_domain power_domain;
877 intel_wakeref_t wakeref;
878 bool ret;
879
880 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
881 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
882 if (!wakeref)
883 return false;
884
885 ret = intel_de_read(dev_priv, SPRCTL(plane->pipe)) & SPRITE_ENABLE;
886
887 *pipe = plane->pipe;
888
889 intel_display_power_put(dev_priv, power_domain, wakeref);
890
891 return ret;
892}
893
894static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
895 const struct intel_plane_state *plane_state)
896{
897 const struct drm_framebuffer *fb = plane_state->hw.fb;
898 unsigned int hscale, pixel_rate;
899 unsigned int limit, decimate;
900
901 /*
902 * Note that crtc_state->pixel_rate accounts for both
903 * horizontal and vertical panel fitter downscaling factors.
904 * Pre-HSW bspec tells us to only consider the horizontal
905 * downscaling factor here. We ignore that and just consider
906 * both for simplicity.
907 */
908 pixel_rate = crtc_state->pixel_rate;
909
910 /* Horizontal downscaling limits the maximum pixel rate */
911 hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
912 &plane_state->uapi.dst,
913 0, INT_MAX);
914 hscale = max(hscale, 0x10000u);
915
916 /* Decimation steps at 2x,4x,8x,16x */
917 decimate = ilog2(hscale >> 16);
918 hscale >>= decimate;
919
920 /* Starting limit is 90% of cdclk */
921 limit = 9;
922
923 /* -10% per decimation step */
924 limit -= decimate;
925
926 /* -10% for RGB */
927 if (!fb->format->is_yuv)
928 limit--;
929
930 /*
931 * We should also do -10% if sprite scaling is enabled
932 * on the other pipe, but we can't really check for that,
933 * so we ignore it.
934 */
935
936 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
937 limit << 16);
938}
939
940static unsigned int
941g4x_sprite_max_stride(struct intel_plane *plane,
942 u32 pixel_format, u64 modifier,
943 unsigned int rotation)
944{
945 const struct drm_format_info *info = drm_format_info(pixel_format);
946 int cpp = info->cpp[0];
947
948 /* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
949 if (modifier == I915_FORMAT_MOD_X_TILED)
950 return min(4096 * cpp, 16 * 1024);
951 else
952 return 16 * 1024;
953}
954
955static unsigned int
956hsw_sprite_max_stride(struct intel_plane *plane,
957 u32 pixel_format, u64 modifier,
958 unsigned int rotation)
959{
960 const struct drm_format_info *info = drm_format_info(pixel_format);
961 int cpp = info->cpp[0];
962
963 /* Limit to 8k pixels to guarantee OFFSET.x doesn't get too big. */
964 return min(8192 * cpp, 16 * 1024);
965}
966
967static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
968{
969 u32 dvscntr = 0;
970
971 if (crtc_state->gamma_enable)
972 dvscntr |= DVS_PIPE_GAMMA_ENABLE;
973
974 if (crtc_state->csc_enable)
975 dvscntr |= DVS_PIPE_CSC_ENABLE;
976
977 return dvscntr;
978}
979
980static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
981 const struct intel_plane_state *plane_state)
982{
983 struct drm_i915_private *dev_priv =
984 to_i915(plane_state->uapi.plane->dev);
985 const struct drm_framebuffer *fb = plane_state->hw.fb;
986 unsigned int rotation = plane_state->hw.rotation;
987 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
988 u32 dvscntr;
989
990 dvscntr = DVS_ENABLE;
991
992 if (IS_SANDYBRIDGE(dev_priv))
993 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
994
995 switch (fb->format->format) {
996 case DRM_FORMAT_XBGR8888:
997 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
998 break;
999 case DRM_FORMAT_XRGB8888:
1000 dvscntr |= DVS_FORMAT_RGBX888;
1001 break;
1002 case DRM_FORMAT_XBGR2101010:
1003 dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
1004 break;
1005 case DRM_FORMAT_XRGB2101010:
1006 dvscntr |= DVS_FORMAT_RGBX101010;
1007 break;
1008 case DRM_FORMAT_XBGR16161616F:
1009 dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1010 break;
1011 case DRM_FORMAT_XRGB16161616F:
1012 dvscntr |= DVS_FORMAT_RGBX161616;
1013 break;
1014 case DRM_FORMAT_YUYV:
1015 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1016 break;
1017 case DRM_FORMAT_YVYU:
1018 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1019 break;
1020 case DRM_FORMAT_UYVY:
1021 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1022 break;
1023 case DRM_FORMAT_VYUY:
1024 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1025 break;
1026 default:
1027 MISSING_CASE(fb->format->format);
1028 return 0;
1029 }
1030
1031 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1032 dvscntr |= DVS_YUV_FORMAT_BT709;
1033
1034 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1035 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1036
1037 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1038 dvscntr |= DVS_TILED;
1039
1040 if (rotation & DRM_MODE_ROTATE_180)
1041 dvscntr |= DVS_ROTATE_180;
1042
1043 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1044 dvscntr |= DVS_DEST_KEY;
1045 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1046 dvscntr |= DVS_SOURCE_KEY;
1047
1048 return dvscntr;
1049}
1050
1051static void g4x_sprite_update_gamma(const struct intel_plane_state *plane_state)
1052{
1053 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1054 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1055 const struct drm_framebuffer *fb = plane_state->hw.fb;
1056 enum pipe pipe = plane->pipe;
1057 u16 gamma[8];
1058 int i;
1059
1060 /* Seems RGB data bypasses the gamma always */
1061 if (!fb->format->is_yuv)
1062 return;
1063
1064 i9xx_plane_linear_gamma(gamma);
1065
1066 /* FIXME these register are single buffered :( */
1067 /* The two end points are implicit (0.0 and 1.0) */
1068 for (i = 1; i < 8 - 1; i++)
1069 intel_de_write_fw(dev_priv, DVSGAMC_G4X(pipe, i - 1),
1070 gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
1071}
1072
1073static void ilk_sprite_linear_gamma(u16 gamma[17])
1074{
1075 int i;
1076
1077 for (i = 0; i < 17; i++)
1078 gamma[i] = (i << 10) / 16;
1079}
1080
1081static void ilk_sprite_update_gamma(const struct intel_plane_state *plane_state)
1082{
1083 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1084 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1085 const struct drm_framebuffer *fb = plane_state->hw.fb;
1086 enum pipe pipe = plane->pipe;
1087 u16 gamma[17];
1088 int i;
1089
1090 /* Seems RGB data bypasses the gamma always */
1091 if (!fb->format->is_yuv)
1092 return;
1093
1094 ilk_sprite_linear_gamma(gamma);
1095
1096 /* FIXME these register are single buffered :( */
1097 for (i = 0; i < 16; i++)
1098 intel_de_write_fw(dev_priv, DVSGAMC_ILK(pipe, i),
1099 gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
1100
1101 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1102 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1103 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1104 i++;
1105}
1106
1107static void
1108g4x_sprite_update_noarm(struct intel_plane *plane,
1109 const struct intel_crtc_state *crtc_state,
1110 const struct intel_plane_state *plane_state)
1111{
1112 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1113 enum pipe pipe = plane->pipe;
1114 int crtc_x = plane_state->uapi.dst.x1;
1115 int crtc_y = plane_state->uapi.dst.y1;
1116 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1117 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1118 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1119 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1120 u32 dvsscale = 0;
1121
1122 if (crtc_w != src_w || crtc_h != src_h)
1123 dvsscale = DVS_SCALE_ENABLE |
1124 DVS_SRC_WIDTH(src_w - 1) |
1125 DVS_SRC_HEIGHT(src_h - 1);
1126
1127 intel_de_write_fw(dev_priv, DVSSTRIDE(pipe),
1128 plane_state->view.color_plane[0].mapping_stride);
1129 intel_de_write_fw(dev_priv, DVSPOS(pipe),
1130 DVS_POS_Y(crtc_y) | DVS_POS_X(crtc_x));
1131 intel_de_write_fw(dev_priv, DVSSIZE(pipe),
1132 DVS_HEIGHT(crtc_h - 1) | DVS_WIDTH(crtc_w - 1));
1133 intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale);
1134}
1135
1136static void
1137g4x_sprite_update_arm(struct intel_plane *plane,
1138 const struct intel_crtc_state *crtc_state,
1139 const struct intel_plane_state *plane_state)
1140{
1141 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1142 enum pipe pipe = plane->pipe;
1143 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1144 u32 dvssurf_offset = plane_state->view.color_plane[0].offset;
1145 u32 x = plane_state->view.color_plane[0].x;
1146 u32 y = plane_state->view.color_plane[0].y;
1147 u32 dvscntr, linear_offset;
1148
1149 dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1150
1151 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1152
1153 if (key->flags) {
1154 intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value);
1155 intel_de_write_fw(dev_priv, DVSKEYMSK(pipe),
1156 key->channel_mask);
1157 intel_de_write_fw(dev_priv, DVSKEYMAX(pipe), key->max_value);
1158 }
1159
1160 intel_de_write_fw(dev_priv, DVSLINOFF(pipe), linear_offset);
1161 intel_de_write_fw(dev_priv, DVSTILEOFF(pipe),
1162 DVS_OFFSET_Y(y) | DVS_OFFSET_X(x));
1163
1164 /*
1165 * The control register self-arms if the plane was previously
1166 * disabled. Try to make the plane enable atomic by writing
1167 * the control register just before the surface register.
1168 */
1169 intel_de_write_fw(dev_priv, DVSCNTR(pipe), dvscntr);
1170 intel_de_write_fw(dev_priv, DVSSURF(pipe),
1171 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1172
1173 if (IS_G4X(dev_priv))
1174 g4x_sprite_update_gamma(plane_state);
1175 else
1176 ilk_sprite_update_gamma(plane_state);
1177}
1178
1179static void
1180g4x_sprite_disable_arm(struct intel_plane *plane,
1181 const struct intel_crtc_state *crtc_state)
1182{
1183 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1184 enum pipe pipe = plane->pipe;
1185
1186 intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0);
1187 /* Disable the scaler */
1188 intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0);
1189 intel_de_write_fw(dev_priv, DVSSURF(pipe), 0);
1190}
1191
1192static bool
1193g4x_sprite_get_hw_state(struct intel_plane *plane,
1194 enum pipe *pipe)
1195{
1196 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1197 enum intel_display_power_domain power_domain;
1198 intel_wakeref_t wakeref;
1199 bool ret;
1200
1201 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1202 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1203 if (!wakeref)
1204 return false;
1205
1206 ret = intel_de_read(dev_priv, DVSCNTR(plane->pipe)) & DVS_ENABLE;
1207
1208 *pipe = plane->pipe;
1209
1210 intel_display_power_put(dev_priv, power_domain, wakeref);
1211
1212 return ret;
1213}
1214
1215static bool g4x_fb_scalable(const struct drm_framebuffer *fb)
1216{
1217 if (!fb)
1218 return false;
1219
1220 switch (fb->format->format) {
1221 case DRM_FORMAT_C8:
1222 case DRM_FORMAT_XRGB16161616F:
1223 case DRM_FORMAT_ARGB16161616F:
1224 case DRM_FORMAT_XBGR16161616F:
1225 case DRM_FORMAT_ABGR16161616F:
1226 return false;
1227 default:
1228 return true;
1229 }
1230}
1231
1232static int
1233g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1234 struct intel_plane_state *plane_state)
1235{
1236 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1237 const struct drm_framebuffer *fb = plane_state->hw.fb;
1238 const struct drm_rect *src = &plane_state->uapi.src;
1239 const struct drm_rect *dst = &plane_state->uapi.dst;
1240 int src_x, src_w, src_h, crtc_w, crtc_h;
1241 const struct drm_display_mode *adjusted_mode =
1242 &crtc_state->hw.adjusted_mode;
1243 unsigned int stride = plane_state->view.color_plane[0].mapping_stride;
1244 unsigned int cpp = fb->format->cpp[0];
1245 unsigned int width_bytes;
1246 int min_width, min_height;
1247
1248 crtc_w = drm_rect_width(dst);
1249 crtc_h = drm_rect_height(dst);
1250
1251 src_x = src->x1 >> 16;
1252 src_w = drm_rect_width(src) >> 16;
1253 src_h = drm_rect_height(src) >> 16;
1254
1255 if (src_w == crtc_w && src_h == crtc_h)
1256 return 0;
1257
1258 min_width = 3;
1259
1260 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1261 if (src_h & 1) {
1262 drm_dbg_kms(&i915->drm, "Source height must be even with interlaced modes\n");
1263 return -EINVAL;
1264 }
1265 min_height = 6;
1266 } else {
1267 min_height = 3;
1268 }
1269
1270 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1271
1272 if (src_w < min_width || src_h < min_height ||
1273 src_w > 2048 || src_h > 2048) {
1274 drm_dbg_kms(&i915->drm, "Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1275 src_w, src_h, min_width, min_height, 2048, 2048);
1276 return -EINVAL;
1277 }
1278
1279 if (width_bytes > 4096) {
1280 drm_dbg_kms(&i915->drm, "Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1281 width_bytes, 4096);
1282 return -EINVAL;
1283 }
1284
1285 if (stride > 4096) {
1286 drm_dbg_kms(&i915->drm, "Stride (%u) exceeds hardware max with scaling (%u)\n",
1287 stride, 4096);
1288 return -EINVAL;
1289 }
1290
1291 return 0;
1292}
1293
1294static int
1295g4x_sprite_check(struct intel_crtc_state *crtc_state,
1296 struct intel_plane_state *plane_state)
1297{
1298 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1299 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1300 int min_scale = DRM_PLANE_NO_SCALING;
1301 int max_scale = DRM_PLANE_NO_SCALING;
1302 int ret;
1303
1304 if (g4x_fb_scalable(plane_state->hw.fb)) {
1305 if (DISPLAY_VER(dev_priv) < 7) {
1306 min_scale = 1;
1307 max_scale = 16 << 16;
1308 } else if (IS_IVYBRIDGE(dev_priv)) {
1309 min_scale = 1;
1310 max_scale = 2 << 16;
1311 }
1312 }
1313
1314 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1315 min_scale, max_scale, true);
1316 if (ret)
1317 return ret;
1318
1319 ret = i9xx_check_plane_surface(plane_state);
1320 if (ret)
1321 return ret;
1322
1323 if (!plane_state->uapi.visible)
1324 return 0;
1325
1326 ret = intel_plane_check_src_coordinates(plane_state);
1327 if (ret)
1328 return ret;
1329
1330 ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1331 if (ret)
1332 return ret;
1333
1334 if (DISPLAY_VER(dev_priv) >= 7)
1335 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1336 else
1337 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1338
1339 return 0;
1340}
1341
1342int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1343{
1344 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1345 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1346 unsigned int rotation = plane_state->hw.rotation;
1347
1348 /* CHV ignores the mirror bit when the rotate bit is set :( */
1349 if (IS_CHERRYVIEW(dev_priv) &&
1350 rotation & DRM_MODE_ROTATE_180 &&
1351 rotation & DRM_MODE_REFLECT_X) {
1352 drm_dbg_kms(&dev_priv->drm,
1353 "Cannot rotate and reflect at the same time\n");
1354 return -EINVAL;
1355 }
1356
1357 return 0;
1358}
1359
1360static int
1361vlv_sprite_check(struct intel_crtc_state *crtc_state,
1362 struct intel_plane_state *plane_state)
1363{
1364 int ret;
1365
1366 ret = chv_plane_check_rotation(plane_state);
1367 if (ret)
1368 return ret;
1369
1370 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1371 DRM_PLANE_NO_SCALING,
1372 DRM_PLANE_NO_SCALING,
1373 true);
1374 if (ret)
1375 return ret;
1376
1377 ret = i9xx_check_plane_surface(plane_state);
1378 if (ret)
1379 return ret;
1380
1381 if (!plane_state->uapi.visible)
1382 return 0;
1383
1384 ret = intel_plane_check_src_coordinates(plane_state);
1385 if (ret)
1386 return ret;
1387
1388 plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1389
1390 return 0;
1391}
1392
1393static const u32 g4x_sprite_formats[] = {
1394 DRM_FORMAT_XRGB8888,
1395 DRM_FORMAT_YUYV,
1396 DRM_FORMAT_YVYU,
1397 DRM_FORMAT_UYVY,
1398 DRM_FORMAT_VYUY,
1399};
1400
1401static const u32 snb_sprite_formats[] = {
1402 DRM_FORMAT_XRGB8888,
1403 DRM_FORMAT_XBGR8888,
1404 DRM_FORMAT_XRGB2101010,
1405 DRM_FORMAT_XBGR2101010,
1406 DRM_FORMAT_XRGB16161616F,
1407 DRM_FORMAT_XBGR16161616F,
1408 DRM_FORMAT_YUYV,
1409 DRM_FORMAT_YVYU,
1410 DRM_FORMAT_UYVY,
1411 DRM_FORMAT_VYUY,
1412};
1413
1414static const u32 vlv_sprite_formats[] = {
1415 DRM_FORMAT_C8,
1416 DRM_FORMAT_RGB565,
1417 DRM_FORMAT_XRGB8888,
1418 DRM_FORMAT_XBGR8888,
1419 DRM_FORMAT_ARGB8888,
1420 DRM_FORMAT_ABGR8888,
1421 DRM_FORMAT_XBGR2101010,
1422 DRM_FORMAT_ABGR2101010,
1423 DRM_FORMAT_YUYV,
1424 DRM_FORMAT_YVYU,
1425 DRM_FORMAT_UYVY,
1426 DRM_FORMAT_VYUY,
1427};
1428
1429static const u32 chv_pipe_b_sprite_formats[] = {
1430 DRM_FORMAT_C8,
1431 DRM_FORMAT_RGB565,
1432 DRM_FORMAT_XRGB8888,
1433 DRM_FORMAT_XBGR8888,
1434 DRM_FORMAT_ARGB8888,
1435 DRM_FORMAT_ABGR8888,
1436 DRM_FORMAT_XRGB2101010,
1437 DRM_FORMAT_XBGR2101010,
1438 DRM_FORMAT_ARGB2101010,
1439 DRM_FORMAT_ABGR2101010,
1440 DRM_FORMAT_YUYV,
1441 DRM_FORMAT_YVYU,
1442 DRM_FORMAT_UYVY,
1443 DRM_FORMAT_VYUY,
1444};
1445
1446static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1447 u32 format, u64 modifier)
1448{
1449 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1450 return false;
1451
1452 switch (format) {
1453 case DRM_FORMAT_XRGB8888:
1454 case DRM_FORMAT_YUYV:
1455 case DRM_FORMAT_YVYU:
1456 case DRM_FORMAT_UYVY:
1457 case DRM_FORMAT_VYUY:
1458 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1459 modifier == I915_FORMAT_MOD_X_TILED)
1460 return true;
1461 fallthrough;
1462 default:
1463 return false;
1464 }
1465}
1466
1467static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1468 u32 format, u64 modifier)
1469{
1470 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1471 return false;
1472
1473 switch (format) {
1474 case DRM_FORMAT_XRGB8888:
1475 case DRM_FORMAT_XBGR8888:
1476 case DRM_FORMAT_XRGB2101010:
1477 case DRM_FORMAT_XBGR2101010:
1478 case DRM_FORMAT_XRGB16161616F:
1479 case DRM_FORMAT_XBGR16161616F:
1480 case DRM_FORMAT_YUYV:
1481 case DRM_FORMAT_YVYU:
1482 case DRM_FORMAT_UYVY:
1483 case DRM_FORMAT_VYUY:
1484 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1485 modifier == I915_FORMAT_MOD_X_TILED)
1486 return true;
1487 fallthrough;
1488 default:
1489 return false;
1490 }
1491}
1492
1493static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1494 u32 format, u64 modifier)
1495{
1496 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1497 return false;
1498
1499 switch (format) {
1500 case DRM_FORMAT_C8:
1501 case DRM_FORMAT_RGB565:
1502 case DRM_FORMAT_ABGR8888:
1503 case DRM_FORMAT_ARGB8888:
1504 case DRM_FORMAT_XBGR8888:
1505 case DRM_FORMAT_XRGB8888:
1506 case DRM_FORMAT_XBGR2101010:
1507 case DRM_FORMAT_ABGR2101010:
1508 case DRM_FORMAT_XRGB2101010:
1509 case DRM_FORMAT_ARGB2101010:
1510 case DRM_FORMAT_YUYV:
1511 case DRM_FORMAT_YVYU:
1512 case DRM_FORMAT_UYVY:
1513 case DRM_FORMAT_VYUY:
1514 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1515 modifier == I915_FORMAT_MOD_X_TILED)
1516 return true;
1517 fallthrough;
1518 default:
1519 return false;
1520 }
1521}
1522
1523static const struct drm_plane_funcs g4x_sprite_funcs = {
1524 .update_plane = drm_atomic_helper_update_plane,
1525 .disable_plane = drm_atomic_helper_disable_plane,
1526 .destroy = intel_plane_destroy,
1527 .atomic_duplicate_state = intel_plane_duplicate_state,
1528 .atomic_destroy_state = intel_plane_destroy_state,
1529 .format_mod_supported = g4x_sprite_format_mod_supported,
1530};
1531
1532static const struct drm_plane_funcs snb_sprite_funcs = {
1533 .update_plane = drm_atomic_helper_update_plane,
1534 .disable_plane = drm_atomic_helper_disable_plane,
1535 .destroy = intel_plane_destroy,
1536 .atomic_duplicate_state = intel_plane_duplicate_state,
1537 .atomic_destroy_state = intel_plane_destroy_state,
1538 .format_mod_supported = snb_sprite_format_mod_supported,
1539};
1540
1541static const struct drm_plane_funcs vlv_sprite_funcs = {
1542 .update_plane = drm_atomic_helper_update_plane,
1543 .disable_plane = drm_atomic_helper_disable_plane,
1544 .destroy = intel_plane_destroy,
1545 .atomic_duplicate_state = intel_plane_duplicate_state,
1546 .atomic_destroy_state = intel_plane_destroy_state,
1547 .format_mod_supported = vlv_sprite_format_mod_supported,
1548};
1549
1550struct intel_plane *
1551intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1552 enum pipe pipe, int sprite)
1553{
1554 struct intel_plane *plane;
1555 const struct drm_plane_funcs *plane_funcs;
1556 unsigned int supported_rotations;
1557 const u64 *modifiers;
1558 const u32 *formats;
1559 int num_formats;
1560 int ret, zpos;
1561
1562 plane = intel_plane_alloc();
1563 if (IS_ERR(plane))
1564 return plane;
1565
1566 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1567 plane->update_noarm = vlv_sprite_update_noarm;
1568 plane->update_arm = vlv_sprite_update_arm;
1569 plane->disable_arm = vlv_sprite_disable_arm;
1570 plane->get_hw_state = vlv_sprite_get_hw_state;
1571 plane->check_plane = vlv_sprite_check;
1572 plane->max_stride = i965_plane_max_stride;
1573 plane->min_cdclk = vlv_plane_min_cdclk;
1574
1575 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1576 formats = chv_pipe_b_sprite_formats;
1577 num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
1578 } else {
1579 formats = vlv_sprite_formats;
1580 num_formats = ARRAY_SIZE(vlv_sprite_formats);
1581 }
1582
1583 plane_funcs = &vlv_sprite_funcs;
1584 } else if (DISPLAY_VER(dev_priv) >= 7) {
1585 plane->update_noarm = ivb_sprite_update_noarm;
1586 plane->update_arm = ivb_sprite_update_arm;
1587 plane->disable_arm = ivb_sprite_disable_arm;
1588 plane->get_hw_state = ivb_sprite_get_hw_state;
1589 plane->check_plane = g4x_sprite_check;
1590
1591 if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
1592 plane->max_stride = hsw_sprite_max_stride;
1593 plane->min_cdclk = hsw_plane_min_cdclk;
1594 } else {
1595 plane->max_stride = g4x_sprite_max_stride;
1596 plane->min_cdclk = ivb_sprite_min_cdclk;
1597 }
1598
1599 formats = snb_sprite_formats;
1600 num_formats = ARRAY_SIZE(snb_sprite_formats);
1601
1602 plane_funcs = &snb_sprite_funcs;
1603 } else {
1604 plane->update_noarm = g4x_sprite_update_noarm;
1605 plane->update_arm = g4x_sprite_update_arm;
1606 plane->disable_arm = g4x_sprite_disable_arm;
1607 plane->get_hw_state = g4x_sprite_get_hw_state;
1608 plane->check_plane = g4x_sprite_check;
1609 plane->max_stride = g4x_sprite_max_stride;
1610 plane->min_cdclk = g4x_sprite_min_cdclk;
1611
1612 if (IS_SANDYBRIDGE(dev_priv)) {
1613 formats = snb_sprite_formats;
1614 num_formats = ARRAY_SIZE(snb_sprite_formats);
1615
1616 plane_funcs = &snb_sprite_funcs;
1617 } else {
1618 formats = g4x_sprite_formats;
1619 num_formats = ARRAY_SIZE(g4x_sprite_formats);
1620
1621 plane_funcs = &g4x_sprite_funcs;
1622 }
1623 }
1624
1625 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1626 supported_rotations =
1627 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1628 DRM_MODE_REFLECT_X;
1629 } else {
1630 supported_rotations =
1631 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1632 }
1633
1634 plane->pipe = pipe;
1635 plane->id = PLANE_SPRITE0 + sprite;
1636 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
1637
1638 modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X);
1639
1640 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
1641 0, plane_funcs,
1642 formats, num_formats, modifiers,
1643 DRM_PLANE_TYPE_OVERLAY,
1644 "sprite %c", sprite_name(dev_priv, pipe, sprite));
1645 kfree(modifiers);
1646
1647 if (ret)
1648 goto fail;
1649
1650 drm_plane_create_rotation_property(&plane->base,
1651 DRM_MODE_ROTATE_0,
1652 supported_rotations);
1653
1654 drm_plane_create_color_properties(&plane->base,
1655 BIT(DRM_COLOR_YCBCR_BT601) |
1656 BIT(DRM_COLOR_YCBCR_BT709),
1657 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1658 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1659 DRM_COLOR_YCBCR_BT709,
1660 DRM_COLOR_YCBCR_LIMITED_RANGE);
1661
1662 zpos = sprite + 1;
1663 drm_plane_create_zpos_immutable_property(&plane->base, zpos);
1664
1665 intel_plane_helper_add(plane);
1666
1667 return plane;
1668
1669fail:
1670 intel_plane_free(plane);
1671
1672 return ERR_PTR(ret);
1673}