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