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_damage_helper.h>
38 #include <drm/drm_fourcc.h>
39 #include <drm/drm_plane_helper.h>
40 #include <drm/drm_rect.h>
41 
42 #include "i915_drv.h"
43 #include "i915_trace.h"
44 #include "i915_vgpu.h"
45 #include "intel_atomic_plane.h"
46 #include "intel_display_types.h"
47 #include "intel_frontbuffer.h"
48 #include "intel_sprite.h"
49 #include "i9xx_plane.h"
50 #include "intel_vrr.h"
51 
52 int intel_plane_check_stride(const struct intel_plane_state *plane_state)
53 {
54 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
55 	const struct drm_framebuffer *fb = plane_state->hw.fb;
56 	unsigned int rotation = plane_state->hw.rotation;
57 	u32 stride, max_stride;
58 
59 	/*
60 	 * We ignore stride for all invisible planes that
61 	 * can be remapped. Otherwise we could end up
62 	 * with a false positive when the remapping didn't
63 	 * kick in due the plane being invisible.
64 	 */
65 	if (intel_plane_can_remap(plane_state) &&
66 	    !plane_state->uapi.visible)
67 		return 0;
68 
69 	/* FIXME other color planes? */
70 	stride = plane_state->color_plane[0].stride;
71 	max_stride = plane->max_stride(plane, fb->format->format,
72 				       fb->modifier, rotation);
73 
74 	if (stride > max_stride) {
75 		DRM_DEBUG_KMS("[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n",
76 			      fb->base.id, stride,
77 			      plane->base.base.id, plane->base.name, max_stride);
78 		return -EINVAL;
79 	}
80 
81 	return 0;
82 }
83 
84 int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
85 {
86 	const struct drm_framebuffer *fb = plane_state->hw.fb;
87 	struct drm_rect *src = &plane_state->uapi.src;
88 	u32 src_x, src_y, src_w, src_h, hsub, vsub;
89 	bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
90 
91 	/*
92 	 * FIXME hsub/vsub vs. block size is a mess. Pre-tgl CCS
93 	 * abuses hsub/vsub so we can't use them here. But as they
94 	 * are limited to 32bpp RGB formats we don't actually need
95 	 * to check anything.
96 	 */
97 	if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
98 	    fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)
99 		return 0;
100 
101 	/*
102 	 * Hardware doesn't handle subpixel coordinates.
103 	 * Adjust to (macro)pixel boundary, but be careful not to
104 	 * increase the source viewport size, because that could
105 	 * push the downscaling factor out of bounds.
106 	 */
107 	src_x = src->x1 >> 16;
108 	src_w = drm_rect_width(src) >> 16;
109 	src_y = src->y1 >> 16;
110 	src_h = drm_rect_height(src) >> 16;
111 
112 	drm_rect_init(src, src_x << 16, src_y << 16,
113 		      src_w << 16, src_h << 16);
114 
115 	if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
116 		hsub = 2;
117 		vsub = 2;
118 	} else {
119 		hsub = fb->format->hsub;
120 		vsub = fb->format->vsub;
121 	}
122 
123 	if (rotated)
124 		hsub = vsub = max(hsub, vsub);
125 
126 	if (src_x % hsub || src_w % hsub) {
127 		DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
128 			      src_x, src_w, hsub, yesno(rotated));
129 		return -EINVAL;
130 	}
131 
132 	if (src_y % vsub || src_h % vsub) {
133 		DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
134 			      src_y, src_h, vsub, yesno(rotated));
135 		return -EINVAL;
136 	}
137 
138 	return 0;
139 }
140 
141 static void i9xx_plane_linear_gamma(u16 gamma[8])
142 {
143 	/* The points are not evenly spaced. */
144 	static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
145 	int i;
146 
147 	for (i = 0; i < 8; i++)
148 		gamma[i] = (in[i] << 8) / 32;
149 }
150 
151 static void
152 chv_update_csc(const struct intel_plane_state *plane_state)
153 {
154 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
155 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
156 	const struct drm_framebuffer *fb = plane_state->hw.fb;
157 	enum plane_id plane_id = plane->id;
158 	/*
159 	 * |r|   | c0 c1 c2 |   |cr|
160 	 * |g| = | c3 c4 c5 | x |y |
161 	 * |b|   | c6 c7 c8 |   |cb|
162 	 *
163 	 * Coefficients are s3.12.
164 	 *
165 	 * Cb and Cr apparently come in as signed already, and
166 	 * we always get full range data in on account of CLRC0/1.
167 	 */
168 	static const s16 csc_matrix[][9] = {
169 		/* BT.601 full range YCbCr -> full range RGB */
170 		[DRM_COLOR_YCBCR_BT601] = {
171 			 5743, 4096,     0,
172 			-2925, 4096, -1410,
173 			    0, 4096,  7258,
174 		},
175 		/* BT.709 full range YCbCr -> full range RGB */
176 		[DRM_COLOR_YCBCR_BT709] = {
177 			 6450, 4096,     0,
178 			-1917, 4096,  -767,
179 			    0, 4096,  7601,
180 		},
181 	};
182 	const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
183 
184 	/* Seems RGB data bypasses the CSC always */
185 	if (!fb->format->is_yuv)
186 		return;
187 
188 	intel_de_write_fw(dev_priv, SPCSCYGOFF(plane_id),
189 			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
190 	intel_de_write_fw(dev_priv, SPCSCCBOFF(plane_id),
191 			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
192 	intel_de_write_fw(dev_priv, SPCSCCROFF(plane_id),
193 			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
194 
195 	intel_de_write_fw(dev_priv, SPCSCC01(plane_id),
196 			  SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
197 	intel_de_write_fw(dev_priv, SPCSCC23(plane_id),
198 			  SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
199 	intel_de_write_fw(dev_priv, SPCSCC45(plane_id),
200 			  SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
201 	intel_de_write_fw(dev_priv, SPCSCC67(plane_id),
202 			  SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
203 	intel_de_write_fw(dev_priv, SPCSCC8(plane_id), SPCSC_C0(csc[8]));
204 
205 	intel_de_write_fw(dev_priv, SPCSCYGICLAMP(plane_id),
206 			  SPCSC_IMAX(1023) | SPCSC_IMIN(0));
207 	intel_de_write_fw(dev_priv, SPCSCCBICLAMP(plane_id),
208 			  SPCSC_IMAX(512) | SPCSC_IMIN(-512));
209 	intel_de_write_fw(dev_priv, SPCSCCRICLAMP(plane_id),
210 			  SPCSC_IMAX(512) | SPCSC_IMIN(-512));
211 
212 	intel_de_write_fw(dev_priv, SPCSCYGOCLAMP(plane_id),
213 			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
214 	intel_de_write_fw(dev_priv, SPCSCCBOCLAMP(plane_id),
215 			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
216 	intel_de_write_fw(dev_priv, SPCSCCROCLAMP(plane_id),
217 			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
218 }
219 
220 #define SIN_0 0
221 #define COS_0 1
222 
223 static void
224 vlv_update_clrc(const struct intel_plane_state *plane_state)
225 {
226 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
227 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
228 	const struct drm_framebuffer *fb = plane_state->hw.fb;
229 	enum pipe pipe = plane->pipe;
230 	enum plane_id plane_id = plane->id;
231 	int contrast, brightness, sh_scale, sh_sin, sh_cos;
232 
233 	if (fb->format->is_yuv &&
234 	    plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
235 		/*
236 		 * Expand limited range to full range:
237 		 * Contrast is applied first and is used to expand Y range.
238 		 * Brightness is applied second and is used to remove the
239 		 * offset from Y. Saturation/hue is used to expand CbCr range.
240 		 */
241 		contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
242 		brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
243 		sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
244 		sh_sin = SIN_0 * sh_scale;
245 		sh_cos = COS_0 * sh_scale;
246 	} else {
247 		/* Pass-through everything. */
248 		contrast = 1 << 6;
249 		brightness = 0;
250 		sh_scale = 1 << 7;
251 		sh_sin = SIN_0 * sh_scale;
252 		sh_cos = COS_0 * sh_scale;
253 	}
254 
255 	/* FIXME these register are single buffered :( */
256 	intel_de_write_fw(dev_priv, SPCLRC0(pipe, plane_id),
257 			  SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
258 	intel_de_write_fw(dev_priv, SPCLRC1(pipe, plane_id),
259 			  SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
260 }
261 
262 static void
263 vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
264 		const struct intel_plane_state *plane_state,
265 		unsigned int *num, unsigned int *den)
266 {
267 	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
268 	const struct drm_framebuffer *fb = plane_state->hw.fb;
269 	unsigned int cpp = fb->format->cpp[0];
270 
271 	/*
272 	 * VLV bspec only considers cases where all three planes are
273 	 * enabled, and cases where the primary and one sprite is enabled.
274 	 * Let's assume the case with just two sprites enabled also
275 	 * maps to the latter case.
276 	 */
277 	if (hweight8(active_planes) == 3) {
278 		switch (cpp) {
279 		case 8:
280 			*num = 11;
281 			*den = 8;
282 			break;
283 		case 4:
284 			*num = 18;
285 			*den = 16;
286 			break;
287 		default:
288 			*num = 1;
289 			*den = 1;
290 			break;
291 		}
292 	} else if (hweight8(active_planes) == 2) {
293 		switch (cpp) {
294 		case 8:
295 			*num = 10;
296 			*den = 8;
297 			break;
298 		case 4:
299 			*num = 17;
300 			*den = 16;
301 			break;
302 		default:
303 			*num = 1;
304 			*den = 1;
305 			break;
306 		}
307 	} else {
308 		switch (cpp) {
309 		case 8:
310 			*num = 10;
311 			*den = 8;
312 			break;
313 		default:
314 			*num = 1;
315 			*den = 1;
316 			break;
317 		}
318 	}
319 }
320 
321 int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
322 			const struct intel_plane_state *plane_state)
323 {
324 	unsigned int pixel_rate;
325 	unsigned int num, den;
326 
327 	/*
328 	 * Note that crtc_state->pixel_rate accounts for both
329 	 * horizontal and vertical panel fitter downscaling factors.
330 	 * Pre-HSW bspec tells us to only consider the horizontal
331 	 * downscaling factor here. We ignore that and just consider
332 	 * both for simplicity.
333 	 */
334 	pixel_rate = crtc_state->pixel_rate;
335 
336 	vlv_plane_ratio(crtc_state, plane_state, &num, &den);
337 
338 	return DIV_ROUND_UP(pixel_rate * num, den);
339 }
340 
341 static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
342 {
343 	u32 sprctl = 0;
344 
345 	if (crtc_state->gamma_enable)
346 		sprctl |= SP_GAMMA_ENABLE;
347 
348 	return sprctl;
349 }
350 
351 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
352 			  const struct intel_plane_state *plane_state)
353 {
354 	const struct drm_framebuffer *fb = plane_state->hw.fb;
355 	unsigned int rotation = plane_state->hw.rotation;
356 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
357 	u32 sprctl;
358 
359 	sprctl = SP_ENABLE;
360 
361 	switch (fb->format->format) {
362 	case DRM_FORMAT_YUYV:
363 		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
364 		break;
365 	case DRM_FORMAT_YVYU:
366 		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
367 		break;
368 	case DRM_FORMAT_UYVY:
369 		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
370 		break;
371 	case DRM_FORMAT_VYUY:
372 		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
373 		break;
374 	case DRM_FORMAT_C8:
375 		sprctl |= SP_FORMAT_8BPP;
376 		break;
377 	case DRM_FORMAT_RGB565:
378 		sprctl |= SP_FORMAT_BGR565;
379 		break;
380 	case DRM_FORMAT_XRGB8888:
381 		sprctl |= SP_FORMAT_BGRX8888;
382 		break;
383 	case DRM_FORMAT_ARGB8888:
384 		sprctl |= SP_FORMAT_BGRA8888;
385 		break;
386 	case DRM_FORMAT_XBGR2101010:
387 		sprctl |= SP_FORMAT_RGBX1010102;
388 		break;
389 	case DRM_FORMAT_ABGR2101010:
390 		sprctl |= SP_FORMAT_RGBA1010102;
391 		break;
392 	case DRM_FORMAT_XRGB2101010:
393 		sprctl |= SP_FORMAT_BGRX1010102;
394 		break;
395 	case DRM_FORMAT_ARGB2101010:
396 		sprctl |= SP_FORMAT_BGRA1010102;
397 		break;
398 	case DRM_FORMAT_XBGR8888:
399 		sprctl |= SP_FORMAT_RGBX8888;
400 		break;
401 	case DRM_FORMAT_ABGR8888:
402 		sprctl |= SP_FORMAT_RGBA8888;
403 		break;
404 	default:
405 		MISSING_CASE(fb->format->format);
406 		return 0;
407 	}
408 
409 	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
410 		sprctl |= SP_YUV_FORMAT_BT709;
411 
412 	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
413 		sprctl |= SP_TILED;
414 
415 	if (rotation & DRM_MODE_ROTATE_180)
416 		sprctl |= SP_ROTATE_180;
417 
418 	if (rotation & DRM_MODE_REFLECT_X)
419 		sprctl |= SP_MIRROR;
420 
421 	if (key->flags & I915_SET_COLORKEY_SOURCE)
422 		sprctl |= SP_SOURCE_KEY;
423 
424 	return sprctl;
425 }
426 
427 static void vlv_update_gamma(const struct intel_plane_state *plane_state)
428 {
429 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
430 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
431 	const struct drm_framebuffer *fb = plane_state->hw.fb;
432 	enum pipe pipe = plane->pipe;
433 	enum plane_id plane_id = plane->id;
434 	u16 gamma[8];
435 	int i;
436 
437 	/* Seems RGB data bypasses the gamma always */
438 	if (!fb->format->is_yuv)
439 		return;
440 
441 	i9xx_plane_linear_gamma(gamma);
442 
443 	/* FIXME these register are single buffered :( */
444 	/* The two end points are implicit (0.0 and 1.0) */
445 	for (i = 1; i < 8 - 1; i++)
446 		intel_de_write_fw(dev_priv, SPGAMC(pipe, plane_id, i - 1),
447 				  gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
448 }
449 
450 static void
451 vlv_update_plane(struct intel_plane *plane,
452 		 const struct intel_crtc_state *crtc_state,
453 		 const struct intel_plane_state *plane_state)
454 {
455 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
456 	enum pipe pipe = plane->pipe;
457 	enum plane_id plane_id = plane->id;
458 	u32 sprsurf_offset = plane_state->color_plane[0].offset;
459 	u32 linear_offset;
460 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
461 	int crtc_x = plane_state->uapi.dst.x1;
462 	int crtc_y = plane_state->uapi.dst.y1;
463 	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
464 	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
465 	u32 x = plane_state->color_plane[0].x;
466 	u32 y = plane_state->color_plane[0].y;
467 	unsigned long irqflags;
468 	u32 sprctl;
469 
470 	sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
471 
472 	/* Sizes are 0 based */
473 	crtc_w--;
474 	crtc_h--;
475 
476 	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
477 
478 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
479 
480 	intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id),
481 			  plane_state->color_plane[0].stride);
482 	intel_de_write_fw(dev_priv, SPPOS(pipe, plane_id),
483 			  (crtc_y << 16) | crtc_x);
484 	intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id),
485 			  (crtc_h << 16) | crtc_w);
486 	intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0);
487 
488 	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
489 		chv_update_csc(plane_state);
490 
491 	if (key->flags) {
492 		intel_de_write_fw(dev_priv, SPKEYMINVAL(pipe, plane_id),
493 				  key->min_value);
494 		intel_de_write_fw(dev_priv, SPKEYMSK(pipe, plane_id),
495 				  key->channel_mask);
496 		intel_de_write_fw(dev_priv, SPKEYMAXVAL(pipe, plane_id),
497 				  key->max_value);
498 	}
499 
500 	intel_de_write_fw(dev_priv, SPLINOFF(pipe, plane_id), linear_offset);
501 	intel_de_write_fw(dev_priv, SPTILEOFF(pipe, plane_id), (y << 16) | x);
502 
503 	/*
504 	 * The control register self-arms if the plane was previously
505 	 * disabled. Try to make the plane enable atomic by writing
506 	 * the control register just before the surface register.
507 	 */
508 	intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), sprctl);
509 	intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id),
510 			  intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
511 
512 	vlv_update_clrc(plane_state);
513 	vlv_update_gamma(plane_state);
514 
515 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
516 }
517 
518 static void
519 vlv_disable_plane(struct intel_plane *plane,
520 		  const struct intel_crtc_state *crtc_state)
521 {
522 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
523 	enum pipe pipe = plane->pipe;
524 	enum plane_id plane_id = plane->id;
525 	unsigned long irqflags;
526 
527 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
528 
529 	intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0);
530 	intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0);
531 
532 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
533 }
534 
535 static bool
536 vlv_plane_get_hw_state(struct intel_plane *plane,
537 		       enum pipe *pipe)
538 {
539 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
540 	enum intel_display_power_domain power_domain;
541 	enum plane_id plane_id = plane->id;
542 	intel_wakeref_t wakeref;
543 	bool ret;
544 
545 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
546 	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
547 	if (!wakeref)
548 		return false;
549 
550 	ret = intel_de_read(dev_priv, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
551 
552 	*pipe = plane->pipe;
553 
554 	intel_display_power_put(dev_priv, power_domain, wakeref);
555 
556 	return ret;
557 }
558 
559 static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
560 			    const struct intel_plane_state *plane_state,
561 			    unsigned int *num, unsigned int *den)
562 {
563 	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
564 	const struct drm_framebuffer *fb = plane_state->hw.fb;
565 	unsigned int cpp = fb->format->cpp[0];
566 
567 	if (hweight8(active_planes) == 2) {
568 		switch (cpp) {
569 		case 8:
570 			*num = 10;
571 			*den = 8;
572 			break;
573 		case 4:
574 			*num = 17;
575 			*den = 16;
576 			break;
577 		default:
578 			*num = 1;
579 			*den = 1;
580 			break;
581 		}
582 	} else {
583 		switch (cpp) {
584 		case 8:
585 			*num = 9;
586 			*den = 8;
587 			break;
588 		default:
589 			*num = 1;
590 			*den = 1;
591 			break;
592 		}
593 	}
594 }
595 
596 static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
597 				    const struct intel_plane_state *plane_state,
598 				    unsigned int *num, unsigned int *den)
599 {
600 	const struct drm_framebuffer *fb = plane_state->hw.fb;
601 	unsigned int cpp = fb->format->cpp[0];
602 
603 	switch (cpp) {
604 	case 8:
605 		*num = 12;
606 		*den = 8;
607 		break;
608 	case 4:
609 		*num = 19;
610 		*den = 16;
611 		break;
612 	case 2:
613 		*num = 33;
614 		*den = 32;
615 		break;
616 	default:
617 		*num = 1;
618 		*den = 1;
619 		break;
620 	}
621 }
622 
623 int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
624 			const struct intel_plane_state *plane_state)
625 {
626 	unsigned int pixel_rate;
627 	unsigned int num, den;
628 
629 	/*
630 	 * Note that crtc_state->pixel_rate accounts for both
631 	 * horizontal and vertical panel fitter downscaling factors.
632 	 * Pre-HSW bspec tells us to only consider the horizontal
633 	 * downscaling factor here. We ignore that and just consider
634 	 * both for simplicity.
635 	 */
636 	pixel_rate = crtc_state->pixel_rate;
637 
638 	ivb_plane_ratio(crtc_state, plane_state, &num, &den);
639 
640 	return DIV_ROUND_UP(pixel_rate * num, den);
641 }
642 
643 static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
644 				const struct intel_plane_state *plane_state)
645 {
646 	unsigned int src_w, dst_w, pixel_rate;
647 	unsigned int num, den;
648 
649 	/*
650 	 * Note that crtc_state->pixel_rate accounts for both
651 	 * horizontal and vertical panel fitter downscaling factors.
652 	 * Pre-HSW bspec tells us to only consider the horizontal
653 	 * downscaling factor here. We ignore that and just consider
654 	 * both for simplicity.
655 	 */
656 	pixel_rate = crtc_state->pixel_rate;
657 
658 	src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
659 	dst_w = drm_rect_width(&plane_state->uapi.dst);
660 
661 	if (src_w != dst_w)
662 		ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
663 	else
664 		ivb_plane_ratio(crtc_state, plane_state, &num, &den);
665 
666 	/* Horizontal downscaling limits the maximum pixel rate */
667 	dst_w = min(src_w, dst_w);
668 
669 	return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
670 				den * dst_w);
671 }
672 
673 static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
674 			    const struct intel_plane_state *plane_state,
675 			    unsigned int *num, unsigned int *den)
676 {
677 	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
678 	const struct drm_framebuffer *fb = plane_state->hw.fb;
679 	unsigned int cpp = fb->format->cpp[0];
680 
681 	if (hweight8(active_planes) == 2) {
682 		switch (cpp) {
683 		case 8:
684 			*num = 10;
685 			*den = 8;
686 			break;
687 		default:
688 			*num = 1;
689 			*den = 1;
690 			break;
691 		}
692 	} else {
693 		switch (cpp) {
694 		case 8:
695 			*num = 9;
696 			*den = 8;
697 			break;
698 		default:
699 			*num = 1;
700 			*den = 1;
701 			break;
702 		}
703 	}
704 }
705 
706 int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
707 			const struct intel_plane_state *plane_state)
708 {
709 	unsigned int pixel_rate = crtc_state->pixel_rate;
710 	unsigned int num, den;
711 
712 	hsw_plane_ratio(crtc_state, plane_state, &num, &den);
713 
714 	return DIV_ROUND_UP(pixel_rate * num, den);
715 }
716 
717 static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
718 {
719 	u32 sprctl = 0;
720 
721 	if (crtc_state->gamma_enable)
722 		sprctl |= SPRITE_GAMMA_ENABLE;
723 
724 	if (crtc_state->csc_enable)
725 		sprctl |= SPRITE_PIPE_CSC_ENABLE;
726 
727 	return sprctl;
728 }
729 
730 static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
731 {
732 	struct drm_i915_private *dev_priv =
733 		to_i915(plane_state->uapi.plane->dev);
734 	const struct drm_framebuffer *fb = plane_state->hw.fb;
735 
736 	return fb->format->cpp[0] == 8 &&
737 		(IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
738 }
739 
740 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
741 			  const struct intel_plane_state *plane_state)
742 {
743 	struct drm_i915_private *dev_priv =
744 		to_i915(plane_state->uapi.plane->dev);
745 	const struct drm_framebuffer *fb = plane_state->hw.fb;
746 	unsigned int rotation = plane_state->hw.rotation;
747 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
748 	u32 sprctl;
749 
750 	sprctl = SPRITE_ENABLE;
751 
752 	if (IS_IVYBRIDGE(dev_priv))
753 		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
754 
755 	switch (fb->format->format) {
756 	case DRM_FORMAT_XBGR8888:
757 		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
758 		break;
759 	case DRM_FORMAT_XRGB8888:
760 		sprctl |= SPRITE_FORMAT_RGBX888;
761 		break;
762 	case DRM_FORMAT_XBGR2101010:
763 		sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
764 		break;
765 	case DRM_FORMAT_XRGB2101010:
766 		sprctl |= SPRITE_FORMAT_RGBX101010;
767 		break;
768 	case DRM_FORMAT_XBGR16161616F:
769 		sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
770 		break;
771 	case DRM_FORMAT_XRGB16161616F:
772 		sprctl |= SPRITE_FORMAT_RGBX161616;
773 		break;
774 	case DRM_FORMAT_YUYV:
775 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
776 		break;
777 	case DRM_FORMAT_YVYU:
778 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
779 		break;
780 	case DRM_FORMAT_UYVY:
781 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
782 		break;
783 	case DRM_FORMAT_VYUY:
784 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
785 		break;
786 	default:
787 		MISSING_CASE(fb->format->format);
788 		return 0;
789 	}
790 
791 	if (!ivb_need_sprite_gamma(plane_state))
792 		sprctl |= SPRITE_INT_GAMMA_DISABLE;
793 
794 	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
795 		sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
796 
797 	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
798 		sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
799 
800 	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
801 		sprctl |= SPRITE_TILED;
802 
803 	if (rotation & DRM_MODE_ROTATE_180)
804 		sprctl |= SPRITE_ROTATE_180;
805 
806 	if (key->flags & I915_SET_COLORKEY_DESTINATION)
807 		sprctl |= SPRITE_DEST_KEY;
808 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
809 		sprctl |= SPRITE_SOURCE_KEY;
810 
811 	return sprctl;
812 }
813 
814 static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
815 				    u16 gamma[18])
816 {
817 	int scale, i;
818 
819 	/*
820 	 * WaFP16GammaEnabling:ivb,hsw
821 	 * "Workaround : When using the 64-bit format, the sprite output
822 	 *  on each color channel has one quarter amplitude. It can be
823 	 *  brought up to full amplitude by using sprite internal gamma
824 	 *  correction, pipe gamma correction, or pipe color space
825 	 *  conversion to multiply the sprite output by four."
826 	 */
827 	scale = 4;
828 
829 	for (i = 0; i < 16; i++)
830 		gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
831 
832 	gamma[i] = min((scale * i << 10) / 16, 1 << 10);
833 	i++;
834 
835 	gamma[i] = 3 << 10;
836 	i++;
837 }
838 
839 static void ivb_update_gamma(const struct intel_plane_state *plane_state)
840 {
841 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
842 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
843 	enum pipe pipe = plane->pipe;
844 	u16 gamma[18];
845 	int i;
846 
847 	if (!ivb_need_sprite_gamma(plane_state))
848 		return;
849 
850 	ivb_sprite_linear_gamma(plane_state, gamma);
851 
852 	/* FIXME these register are single buffered :( */
853 	for (i = 0; i < 16; i++)
854 		intel_de_write_fw(dev_priv, SPRGAMC(pipe, i),
855 				  gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
856 
857 	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 0), gamma[i]);
858 	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 1), gamma[i]);
859 	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 2), gamma[i]);
860 	i++;
861 
862 	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 0), gamma[i]);
863 	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 1), gamma[i]);
864 	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 2), gamma[i]);
865 	i++;
866 }
867 
868 static void
869 ivb_update_plane(struct intel_plane *plane,
870 		 const struct intel_crtc_state *crtc_state,
871 		 const struct intel_plane_state *plane_state)
872 {
873 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
874 	enum pipe pipe = plane->pipe;
875 	u32 sprsurf_offset = plane_state->color_plane[0].offset;
876 	u32 linear_offset;
877 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
878 	int crtc_x = plane_state->uapi.dst.x1;
879 	int crtc_y = plane_state->uapi.dst.y1;
880 	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
881 	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
882 	u32 x = plane_state->color_plane[0].x;
883 	u32 y = plane_state->color_plane[0].y;
884 	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
885 	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
886 	u32 sprctl, sprscale = 0;
887 	unsigned long irqflags;
888 
889 	sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
890 
891 	/* Sizes are 0 based */
892 	src_w--;
893 	src_h--;
894 	crtc_w--;
895 	crtc_h--;
896 
897 	if (crtc_w != src_w || crtc_h != src_h)
898 		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
899 
900 	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
901 
902 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
903 
904 	intel_de_write_fw(dev_priv, SPRSTRIDE(pipe),
905 			  plane_state->color_plane[0].stride);
906 	intel_de_write_fw(dev_priv, SPRPOS(pipe), (crtc_y << 16) | crtc_x);
907 	intel_de_write_fw(dev_priv, SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
908 	if (IS_IVYBRIDGE(dev_priv))
909 		intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale);
910 
911 	if (key->flags) {
912 		intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value);
913 		intel_de_write_fw(dev_priv, SPRKEYMSK(pipe),
914 				  key->channel_mask);
915 		intel_de_write_fw(dev_priv, SPRKEYMAX(pipe), key->max_value);
916 	}
917 
918 	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
919 	 * register */
920 	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
921 		intel_de_write_fw(dev_priv, SPROFFSET(pipe), (y << 16) | x);
922 	} else {
923 		intel_de_write_fw(dev_priv, SPRLINOFF(pipe), linear_offset);
924 		intel_de_write_fw(dev_priv, SPRTILEOFF(pipe), (y << 16) | x);
925 	}
926 
927 	/*
928 	 * The control register self-arms if the plane was previously
929 	 * disabled. Try to make the plane enable atomic by writing
930 	 * the control register just before the surface register.
931 	 */
932 	intel_de_write_fw(dev_priv, SPRCTL(pipe), sprctl);
933 	intel_de_write_fw(dev_priv, SPRSURF(pipe),
934 			  intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
935 
936 	ivb_update_gamma(plane_state);
937 
938 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
939 }
940 
941 static void
942 ivb_disable_plane(struct intel_plane *plane,
943 		  const struct intel_crtc_state *crtc_state)
944 {
945 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
946 	enum pipe pipe = plane->pipe;
947 	unsigned long irqflags;
948 
949 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
950 
951 	intel_de_write_fw(dev_priv, SPRCTL(pipe), 0);
952 	/* Disable the scaler */
953 	if (IS_IVYBRIDGE(dev_priv))
954 		intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0);
955 	intel_de_write_fw(dev_priv, SPRSURF(pipe), 0);
956 
957 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
958 }
959 
960 static bool
961 ivb_plane_get_hw_state(struct intel_plane *plane,
962 		       enum pipe *pipe)
963 {
964 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
965 	enum intel_display_power_domain power_domain;
966 	intel_wakeref_t wakeref;
967 	bool ret;
968 
969 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
970 	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
971 	if (!wakeref)
972 		return false;
973 
974 	ret =  intel_de_read(dev_priv, SPRCTL(plane->pipe)) & SPRITE_ENABLE;
975 
976 	*pipe = plane->pipe;
977 
978 	intel_display_power_put(dev_priv, power_domain, wakeref);
979 
980 	return ret;
981 }
982 
983 static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
984 				const struct intel_plane_state *plane_state)
985 {
986 	const struct drm_framebuffer *fb = plane_state->hw.fb;
987 	unsigned int hscale, pixel_rate;
988 	unsigned int limit, decimate;
989 
990 	/*
991 	 * Note that crtc_state->pixel_rate accounts for both
992 	 * horizontal and vertical panel fitter downscaling factors.
993 	 * Pre-HSW bspec tells us to only consider the horizontal
994 	 * downscaling factor here. We ignore that and just consider
995 	 * both for simplicity.
996 	 */
997 	pixel_rate = crtc_state->pixel_rate;
998 
999 	/* Horizontal downscaling limits the maximum pixel rate */
1000 	hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
1001 				      &plane_state->uapi.dst,
1002 				      0, INT_MAX);
1003 	hscale = max(hscale, 0x10000u);
1004 
1005 	/* Decimation steps at 2x,4x,8x,16x */
1006 	decimate = ilog2(hscale >> 16);
1007 	hscale >>= decimate;
1008 
1009 	/* Starting limit is 90% of cdclk */
1010 	limit = 9;
1011 
1012 	/* -10% per decimation step */
1013 	limit -= decimate;
1014 
1015 	/* -10% for RGB */
1016 	if (!fb->format->is_yuv)
1017 		limit--;
1018 
1019 	/*
1020 	 * We should also do -10% if sprite scaling is enabled
1021 	 * on the other pipe, but we can't really check for that,
1022 	 * so we ignore it.
1023 	 */
1024 
1025 	return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
1026 				limit << 16);
1027 }
1028 
1029 static unsigned int
1030 g4x_sprite_max_stride(struct intel_plane *plane,
1031 		      u32 pixel_format, u64 modifier,
1032 		      unsigned int rotation)
1033 {
1034 	const struct drm_format_info *info = drm_format_info(pixel_format);
1035 	int cpp = info->cpp[0];
1036 
1037 	/* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
1038 	if (modifier == I915_FORMAT_MOD_X_TILED)
1039 		return min(4096 * cpp, 16 * 1024);
1040 	else
1041 		return 16 * 1024;
1042 }
1043 
1044 static unsigned int
1045 hsw_sprite_max_stride(struct intel_plane *plane,
1046 		      u32 pixel_format, u64 modifier,
1047 		      unsigned int rotation)
1048 {
1049 	const struct drm_format_info *info = drm_format_info(pixel_format);
1050 	int cpp = info->cpp[0];
1051 
1052 	/* Limit to 8k pixels to guarantee OFFSET.x doesn't get too big. */
1053 	return min(8192 * cpp, 16 * 1024);
1054 }
1055 
1056 static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1057 {
1058 	u32 dvscntr = 0;
1059 
1060 	if (crtc_state->gamma_enable)
1061 		dvscntr |= DVS_GAMMA_ENABLE;
1062 
1063 	if (crtc_state->csc_enable)
1064 		dvscntr |= DVS_PIPE_CSC_ENABLE;
1065 
1066 	return dvscntr;
1067 }
1068 
1069 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1070 			  const struct intel_plane_state *plane_state)
1071 {
1072 	struct drm_i915_private *dev_priv =
1073 		to_i915(plane_state->uapi.plane->dev);
1074 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1075 	unsigned int rotation = plane_state->hw.rotation;
1076 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1077 	u32 dvscntr;
1078 
1079 	dvscntr = DVS_ENABLE;
1080 
1081 	if (IS_GEN(dev_priv, 6))
1082 		dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1083 
1084 	switch (fb->format->format) {
1085 	case DRM_FORMAT_XBGR8888:
1086 		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1087 		break;
1088 	case DRM_FORMAT_XRGB8888:
1089 		dvscntr |= DVS_FORMAT_RGBX888;
1090 		break;
1091 	case DRM_FORMAT_XBGR2101010:
1092 		dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
1093 		break;
1094 	case DRM_FORMAT_XRGB2101010:
1095 		dvscntr |= DVS_FORMAT_RGBX101010;
1096 		break;
1097 	case DRM_FORMAT_XBGR16161616F:
1098 		dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1099 		break;
1100 	case DRM_FORMAT_XRGB16161616F:
1101 		dvscntr |= DVS_FORMAT_RGBX161616;
1102 		break;
1103 	case DRM_FORMAT_YUYV:
1104 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1105 		break;
1106 	case DRM_FORMAT_YVYU:
1107 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1108 		break;
1109 	case DRM_FORMAT_UYVY:
1110 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1111 		break;
1112 	case DRM_FORMAT_VYUY:
1113 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1114 		break;
1115 	default:
1116 		MISSING_CASE(fb->format->format);
1117 		return 0;
1118 	}
1119 
1120 	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1121 		dvscntr |= DVS_YUV_FORMAT_BT709;
1122 
1123 	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1124 		dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1125 
1126 	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1127 		dvscntr |= DVS_TILED;
1128 
1129 	if (rotation & DRM_MODE_ROTATE_180)
1130 		dvscntr |= DVS_ROTATE_180;
1131 
1132 	if (key->flags & I915_SET_COLORKEY_DESTINATION)
1133 		dvscntr |= DVS_DEST_KEY;
1134 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
1135 		dvscntr |= DVS_SOURCE_KEY;
1136 
1137 	return dvscntr;
1138 }
1139 
1140 static void g4x_update_gamma(const struct intel_plane_state *plane_state)
1141 {
1142 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1143 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1144 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1145 	enum pipe pipe = plane->pipe;
1146 	u16 gamma[8];
1147 	int i;
1148 
1149 	/* Seems RGB data bypasses the gamma always */
1150 	if (!fb->format->is_yuv)
1151 		return;
1152 
1153 	i9xx_plane_linear_gamma(gamma);
1154 
1155 	/* FIXME these register are single buffered :( */
1156 	/* The two end points are implicit (0.0 and 1.0) */
1157 	for (i = 1; i < 8 - 1; i++)
1158 		intel_de_write_fw(dev_priv, DVSGAMC_G4X(pipe, i - 1),
1159 				  gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
1160 }
1161 
1162 static void ilk_sprite_linear_gamma(u16 gamma[17])
1163 {
1164 	int i;
1165 
1166 	for (i = 0; i < 17; i++)
1167 		gamma[i] = (i << 10) / 16;
1168 }
1169 
1170 static void ilk_update_gamma(const struct intel_plane_state *plane_state)
1171 {
1172 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1173 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1174 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1175 	enum pipe pipe = plane->pipe;
1176 	u16 gamma[17];
1177 	int i;
1178 
1179 	/* Seems RGB data bypasses the gamma always */
1180 	if (!fb->format->is_yuv)
1181 		return;
1182 
1183 	ilk_sprite_linear_gamma(gamma);
1184 
1185 	/* FIXME these register are single buffered :( */
1186 	for (i = 0; i < 16; i++)
1187 		intel_de_write_fw(dev_priv, DVSGAMC_ILK(pipe, i),
1188 				  gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
1189 
1190 	intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1191 	intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1192 	intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1193 	i++;
1194 }
1195 
1196 static void
1197 g4x_update_plane(struct intel_plane *plane,
1198 		 const struct intel_crtc_state *crtc_state,
1199 		 const struct intel_plane_state *plane_state)
1200 {
1201 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1202 	enum pipe pipe = plane->pipe;
1203 	u32 dvssurf_offset = plane_state->color_plane[0].offset;
1204 	u32 linear_offset;
1205 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1206 	int crtc_x = plane_state->uapi.dst.x1;
1207 	int crtc_y = plane_state->uapi.dst.y1;
1208 	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1209 	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1210 	u32 x = plane_state->color_plane[0].x;
1211 	u32 y = plane_state->color_plane[0].y;
1212 	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1213 	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1214 	u32 dvscntr, dvsscale = 0;
1215 	unsigned long irqflags;
1216 
1217 	dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1218 
1219 	/* Sizes are 0 based */
1220 	src_w--;
1221 	src_h--;
1222 	crtc_w--;
1223 	crtc_h--;
1224 
1225 	if (crtc_w != src_w || crtc_h != src_h)
1226 		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
1227 
1228 	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1229 
1230 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1231 
1232 	intel_de_write_fw(dev_priv, DVSSTRIDE(pipe),
1233 			  plane_state->color_plane[0].stride);
1234 	intel_de_write_fw(dev_priv, DVSPOS(pipe), (crtc_y << 16) | crtc_x);
1235 	intel_de_write_fw(dev_priv, DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
1236 	intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale);
1237 
1238 	if (key->flags) {
1239 		intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value);
1240 		intel_de_write_fw(dev_priv, DVSKEYMSK(pipe),
1241 				  key->channel_mask);
1242 		intel_de_write_fw(dev_priv, DVSKEYMAX(pipe), key->max_value);
1243 	}
1244 
1245 	intel_de_write_fw(dev_priv, DVSLINOFF(pipe), linear_offset);
1246 	intel_de_write_fw(dev_priv, DVSTILEOFF(pipe), (y << 16) | x);
1247 
1248 	/*
1249 	 * The control register self-arms if the plane was previously
1250 	 * disabled. Try to make the plane enable atomic by writing
1251 	 * the control register just before the surface register.
1252 	 */
1253 	intel_de_write_fw(dev_priv, DVSCNTR(pipe), dvscntr);
1254 	intel_de_write_fw(dev_priv, DVSSURF(pipe),
1255 			  intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1256 
1257 	if (IS_G4X(dev_priv))
1258 		g4x_update_gamma(plane_state);
1259 	else
1260 		ilk_update_gamma(plane_state);
1261 
1262 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1263 }
1264 
1265 static void
1266 g4x_disable_plane(struct intel_plane *plane,
1267 		  const struct intel_crtc_state *crtc_state)
1268 {
1269 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1270 	enum pipe pipe = plane->pipe;
1271 	unsigned long irqflags;
1272 
1273 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1274 
1275 	intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0);
1276 	/* Disable the scaler */
1277 	intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0);
1278 	intel_de_write_fw(dev_priv, DVSSURF(pipe), 0);
1279 
1280 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1281 }
1282 
1283 static bool
1284 g4x_plane_get_hw_state(struct intel_plane *plane,
1285 		       enum pipe *pipe)
1286 {
1287 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1288 	enum intel_display_power_domain power_domain;
1289 	intel_wakeref_t wakeref;
1290 	bool ret;
1291 
1292 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1293 	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1294 	if (!wakeref)
1295 		return false;
1296 
1297 	ret = intel_de_read(dev_priv, DVSCNTR(plane->pipe)) & DVS_ENABLE;
1298 
1299 	*pipe = plane->pipe;
1300 
1301 	intel_display_power_put(dev_priv, power_domain, wakeref);
1302 
1303 	return ret;
1304 }
1305 
1306 static bool g4x_fb_scalable(const struct drm_framebuffer *fb)
1307 {
1308 	if (!fb)
1309 		return false;
1310 
1311 	switch (fb->format->format) {
1312 	case DRM_FORMAT_C8:
1313 	case DRM_FORMAT_XRGB16161616F:
1314 	case DRM_FORMAT_ARGB16161616F:
1315 	case DRM_FORMAT_XBGR16161616F:
1316 	case DRM_FORMAT_ABGR16161616F:
1317 		return false;
1318 	default:
1319 		return true;
1320 	}
1321 }
1322 
1323 static int
1324 g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1325 			 struct intel_plane_state *plane_state)
1326 {
1327 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1328 	const struct drm_rect *src = &plane_state->uapi.src;
1329 	const struct drm_rect *dst = &plane_state->uapi.dst;
1330 	int src_x, src_w, src_h, crtc_w, crtc_h;
1331 	const struct drm_display_mode *adjusted_mode =
1332 		&crtc_state->hw.adjusted_mode;
1333 	unsigned int stride = plane_state->color_plane[0].stride;
1334 	unsigned int cpp = fb->format->cpp[0];
1335 	unsigned int width_bytes;
1336 	int min_width, min_height;
1337 
1338 	crtc_w = drm_rect_width(dst);
1339 	crtc_h = drm_rect_height(dst);
1340 
1341 	src_x = src->x1 >> 16;
1342 	src_w = drm_rect_width(src) >> 16;
1343 	src_h = drm_rect_height(src) >> 16;
1344 
1345 	if (src_w == crtc_w && src_h == crtc_h)
1346 		return 0;
1347 
1348 	min_width = 3;
1349 
1350 	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1351 		if (src_h & 1) {
1352 			DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
1353 			return -EINVAL;
1354 		}
1355 		min_height = 6;
1356 	} else {
1357 		min_height = 3;
1358 	}
1359 
1360 	width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1361 
1362 	if (src_w < min_width || src_h < min_height ||
1363 	    src_w > 2048 || src_h > 2048) {
1364 		DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1365 			      src_w, src_h, min_width, min_height, 2048, 2048);
1366 		return -EINVAL;
1367 	}
1368 
1369 	if (width_bytes > 4096) {
1370 		DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1371 			      width_bytes, 4096);
1372 		return -EINVAL;
1373 	}
1374 
1375 	if (stride > 4096) {
1376 		DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
1377 			      stride, 4096);
1378 		return -EINVAL;
1379 	}
1380 
1381 	return 0;
1382 }
1383 
1384 static int
1385 g4x_sprite_check(struct intel_crtc_state *crtc_state,
1386 		 struct intel_plane_state *plane_state)
1387 {
1388 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1389 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1390 	int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1391 	int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1392 	int ret;
1393 
1394 	if (g4x_fb_scalable(plane_state->hw.fb)) {
1395 		if (INTEL_GEN(dev_priv) < 7) {
1396 			min_scale = 1;
1397 			max_scale = 16 << 16;
1398 		} else if (IS_IVYBRIDGE(dev_priv)) {
1399 			min_scale = 1;
1400 			max_scale = 2 << 16;
1401 		}
1402 	}
1403 
1404 	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1405 						min_scale, max_scale, true);
1406 	if (ret)
1407 		return ret;
1408 
1409 	ret = i9xx_check_plane_surface(plane_state);
1410 	if (ret)
1411 		return ret;
1412 
1413 	if (!plane_state->uapi.visible)
1414 		return 0;
1415 
1416 	ret = intel_plane_check_src_coordinates(plane_state);
1417 	if (ret)
1418 		return ret;
1419 
1420 	ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1421 	if (ret)
1422 		return ret;
1423 
1424 	if (INTEL_GEN(dev_priv) >= 7)
1425 		plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1426 	else
1427 		plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1428 
1429 	return 0;
1430 }
1431 
1432 int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1433 {
1434 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1435 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1436 	unsigned int rotation = plane_state->hw.rotation;
1437 
1438 	/* CHV ignores the mirror bit when the rotate bit is set :( */
1439 	if (IS_CHERRYVIEW(dev_priv) &&
1440 	    rotation & DRM_MODE_ROTATE_180 &&
1441 	    rotation & DRM_MODE_REFLECT_X) {
1442 		drm_dbg_kms(&dev_priv->drm,
1443 			    "Cannot rotate and reflect at the same time\n");
1444 		return -EINVAL;
1445 	}
1446 
1447 	return 0;
1448 }
1449 
1450 static int
1451 vlv_sprite_check(struct intel_crtc_state *crtc_state,
1452 		 struct intel_plane_state *plane_state)
1453 {
1454 	int ret;
1455 
1456 	ret = chv_plane_check_rotation(plane_state);
1457 	if (ret)
1458 		return ret;
1459 
1460 	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1461 						DRM_PLANE_HELPER_NO_SCALING,
1462 						DRM_PLANE_HELPER_NO_SCALING,
1463 						true);
1464 	if (ret)
1465 		return ret;
1466 
1467 	ret = i9xx_check_plane_surface(plane_state);
1468 	if (ret)
1469 		return ret;
1470 
1471 	if (!plane_state->uapi.visible)
1472 		return 0;
1473 
1474 	ret = intel_plane_check_src_coordinates(plane_state);
1475 	if (ret)
1476 		return ret;
1477 
1478 	plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1479 
1480 	return 0;
1481 }
1482 
1483 static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1484 {
1485 	return INTEL_GEN(dev_priv) >= 9;
1486 }
1487 
1488 static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1489 				 const struct drm_intel_sprite_colorkey *set)
1490 {
1491 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1492 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1493 	struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1494 
1495 	*key = *set;
1496 
1497 	/*
1498 	 * We want src key enabled on the
1499 	 * sprite and not on the primary.
1500 	 */
1501 	if (plane->id == PLANE_PRIMARY &&
1502 	    set->flags & I915_SET_COLORKEY_SOURCE)
1503 		key->flags = 0;
1504 
1505 	/*
1506 	 * On SKL+ we want dst key enabled on
1507 	 * the primary and not on the sprite.
1508 	 */
1509 	if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1510 	    set->flags & I915_SET_COLORKEY_DESTINATION)
1511 		key->flags = 0;
1512 }
1513 
1514 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1515 				    struct drm_file *file_priv)
1516 {
1517 	struct drm_i915_private *dev_priv = to_i915(dev);
1518 	struct drm_intel_sprite_colorkey *set = data;
1519 	struct drm_plane *plane;
1520 	struct drm_plane_state *plane_state;
1521 	struct drm_atomic_state *state;
1522 	struct drm_modeset_acquire_ctx ctx;
1523 	int ret = 0;
1524 
1525 	/* ignore the pointless "none" flag */
1526 	set->flags &= ~I915_SET_COLORKEY_NONE;
1527 
1528 	if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1529 		return -EINVAL;
1530 
1531 	/* Make sure we don't try to enable both src & dest simultaneously */
1532 	if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1533 		return -EINVAL;
1534 
1535 	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1536 	    set->flags & I915_SET_COLORKEY_DESTINATION)
1537 		return -EINVAL;
1538 
1539 	plane = drm_plane_find(dev, file_priv, set->plane_id);
1540 	if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1541 		return -ENOENT;
1542 
1543 	/*
1544 	 * SKL+ only plane 2 can do destination keying against plane 1.
1545 	 * Also multiple planes can't do destination keying on the same
1546 	 * pipe simultaneously.
1547 	 */
1548 	if (INTEL_GEN(dev_priv) >= 9 &&
1549 	    to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1550 	    set->flags & I915_SET_COLORKEY_DESTINATION)
1551 		return -EINVAL;
1552 
1553 	drm_modeset_acquire_init(&ctx, 0);
1554 
1555 	state = drm_atomic_state_alloc(plane->dev);
1556 	if (!state) {
1557 		ret = -ENOMEM;
1558 		goto out;
1559 	}
1560 	state->acquire_ctx = &ctx;
1561 
1562 	while (1) {
1563 		plane_state = drm_atomic_get_plane_state(state, plane);
1564 		ret = PTR_ERR_OR_ZERO(plane_state);
1565 		if (!ret)
1566 			intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1567 
1568 		/*
1569 		 * On some platforms we have to configure
1570 		 * the dst colorkey on the primary plane.
1571 		 */
1572 		if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1573 			struct intel_crtc *crtc =
1574 				intel_get_crtc_for_pipe(dev_priv,
1575 							to_intel_plane(plane)->pipe);
1576 
1577 			plane_state = drm_atomic_get_plane_state(state,
1578 								 crtc->base.primary);
1579 			ret = PTR_ERR_OR_ZERO(plane_state);
1580 			if (!ret)
1581 				intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1582 		}
1583 
1584 		if (!ret)
1585 			ret = drm_atomic_commit(state);
1586 
1587 		if (ret != -EDEADLK)
1588 			break;
1589 
1590 		drm_atomic_state_clear(state);
1591 		drm_modeset_backoff(&ctx);
1592 	}
1593 
1594 	drm_atomic_state_put(state);
1595 out:
1596 	drm_modeset_drop_locks(&ctx);
1597 	drm_modeset_acquire_fini(&ctx);
1598 	return ret;
1599 }
1600 
1601 static const u32 g4x_plane_formats[] = {
1602 	DRM_FORMAT_XRGB8888,
1603 	DRM_FORMAT_YUYV,
1604 	DRM_FORMAT_YVYU,
1605 	DRM_FORMAT_UYVY,
1606 	DRM_FORMAT_VYUY,
1607 };
1608 
1609 static const u64 i9xx_plane_format_modifiers[] = {
1610 	I915_FORMAT_MOD_X_TILED,
1611 	DRM_FORMAT_MOD_LINEAR,
1612 	DRM_FORMAT_MOD_INVALID
1613 };
1614 
1615 static const u32 snb_plane_formats[] = {
1616 	DRM_FORMAT_XRGB8888,
1617 	DRM_FORMAT_XBGR8888,
1618 	DRM_FORMAT_XRGB2101010,
1619 	DRM_FORMAT_XBGR2101010,
1620 	DRM_FORMAT_XRGB16161616F,
1621 	DRM_FORMAT_XBGR16161616F,
1622 	DRM_FORMAT_YUYV,
1623 	DRM_FORMAT_YVYU,
1624 	DRM_FORMAT_UYVY,
1625 	DRM_FORMAT_VYUY,
1626 };
1627 
1628 static const u32 vlv_plane_formats[] = {
1629 	DRM_FORMAT_C8,
1630 	DRM_FORMAT_RGB565,
1631 	DRM_FORMAT_XRGB8888,
1632 	DRM_FORMAT_XBGR8888,
1633 	DRM_FORMAT_ARGB8888,
1634 	DRM_FORMAT_ABGR8888,
1635 	DRM_FORMAT_XBGR2101010,
1636 	DRM_FORMAT_ABGR2101010,
1637 	DRM_FORMAT_YUYV,
1638 	DRM_FORMAT_YVYU,
1639 	DRM_FORMAT_UYVY,
1640 	DRM_FORMAT_VYUY,
1641 };
1642 
1643 static const u32 chv_pipe_b_sprite_formats[] = {
1644 	DRM_FORMAT_C8,
1645 	DRM_FORMAT_RGB565,
1646 	DRM_FORMAT_XRGB8888,
1647 	DRM_FORMAT_XBGR8888,
1648 	DRM_FORMAT_ARGB8888,
1649 	DRM_FORMAT_ABGR8888,
1650 	DRM_FORMAT_XRGB2101010,
1651 	DRM_FORMAT_XBGR2101010,
1652 	DRM_FORMAT_ARGB2101010,
1653 	DRM_FORMAT_ABGR2101010,
1654 	DRM_FORMAT_YUYV,
1655 	DRM_FORMAT_YVYU,
1656 	DRM_FORMAT_UYVY,
1657 	DRM_FORMAT_VYUY,
1658 };
1659 
1660 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1661 					    u32 format, u64 modifier)
1662 {
1663 	switch (modifier) {
1664 	case DRM_FORMAT_MOD_LINEAR:
1665 	case I915_FORMAT_MOD_X_TILED:
1666 		break;
1667 	default:
1668 		return false;
1669 	}
1670 
1671 	switch (format) {
1672 	case DRM_FORMAT_XRGB8888:
1673 	case DRM_FORMAT_YUYV:
1674 	case DRM_FORMAT_YVYU:
1675 	case DRM_FORMAT_UYVY:
1676 	case DRM_FORMAT_VYUY:
1677 		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1678 		    modifier == I915_FORMAT_MOD_X_TILED)
1679 			return true;
1680 		fallthrough;
1681 	default:
1682 		return false;
1683 	}
1684 }
1685 
1686 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1687 					    u32 format, u64 modifier)
1688 {
1689 	switch (modifier) {
1690 	case DRM_FORMAT_MOD_LINEAR:
1691 	case I915_FORMAT_MOD_X_TILED:
1692 		break;
1693 	default:
1694 		return false;
1695 	}
1696 
1697 	switch (format) {
1698 	case DRM_FORMAT_XRGB8888:
1699 	case DRM_FORMAT_XBGR8888:
1700 	case DRM_FORMAT_XRGB2101010:
1701 	case DRM_FORMAT_XBGR2101010:
1702 	case DRM_FORMAT_XRGB16161616F:
1703 	case DRM_FORMAT_XBGR16161616F:
1704 	case DRM_FORMAT_YUYV:
1705 	case DRM_FORMAT_YVYU:
1706 	case DRM_FORMAT_UYVY:
1707 	case DRM_FORMAT_VYUY:
1708 		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1709 		    modifier == I915_FORMAT_MOD_X_TILED)
1710 			return true;
1711 		fallthrough;
1712 	default:
1713 		return false;
1714 	}
1715 }
1716 
1717 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1718 					    u32 format, u64 modifier)
1719 {
1720 	switch (modifier) {
1721 	case DRM_FORMAT_MOD_LINEAR:
1722 	case I915_FORMAT_MOD_X_TILED:
1723 		break;
1724 	default:
1725 		return false;
1726 	}
1727 
1728 	switch (format) {
1729 	case DRM_FORMAT_C8:
1730 	case DRM_FORMAT_RGB565:
1731 	case DRM_FORMAT_ABGR8888:
1732 	case DRM_FORMAT_ARGB8888:
1733 	case DRM_FORMAT_XBGR8888:
1734 	case DRM_FORMAT_XRGB8888:
1735 	case DRM_FORMAT_XBGR2101010:
1736 	case DRM_FORMAT_ABGR2101010:
1737 	case DRM_FORMAT_XRGB2101010:
1738 	case DRM_FORMAT_ARGB2101010:
1739 	case DRM_FORMAT_YUYV:
1740 	case DRM_FORMAT_YVYU:
1741 	case DRM_FORMAT_UYVY:
1742 	case DRM_FORMAT_VYUY:
1743 		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1744 		    modifier == I915_FORMAT_MOD_X_TILED)
1745 			return true;
1746 		fallthrough;
1747 	default:
1748 		return false;
1749 	}
1750 }
1751 
1752 static const struct drm_plane_funcs g4x_sprite_funcs = {
1753 	.update_plane = drm_atomic_helper_update_plane,
1754 	.disable_plane = drm_atomic_helper_disable_plane,
1755 	.destroy = intel_plane_destroy,
1756 	.atomic_duplicate_state = intel_plane_duplicate_state,
1757 	.atomic_destroy_state = intel_plane_destroy_state,
1758 	.format_mod_supported = g4x_sprite_format_mod_supported,
1759 };
1760 
1761 static const struct drm_plane_funcs snb_sprite_funcs = {
1762 	.update_plane = drm_atomic_helper_update_plane,
1763 	.disable_plane = drm_atomic_helper_disable_plane,
1764 	.destroy = intel_plane_destroy,
1765 	.atomic_duplicate_state = intel_plane_duplicate_state,
1766 	.atomic_destroy_state = intel_plane_destroy_state,
1767 	.format_mod_supported = snb_sprite_format_mod_supported,
1768 };
1769 
1770 static const struct drm_plane_funcs vlv_sprite_funcs = {
1771 	.update_plane = drm_atomic_helper_update_plane,
1772 	.disable_plane = drm_atomic_helper_disable_plane,
1773 	.destroy = intel_plane_destroy,
1774 	.atomic_duplicate_state = intel_plane_duplicate_state,
1775 	.atomic_destroy_state = intel_plane_destroy_state,
1776 	.format_mod_supported = vlv_sprite_format_mod_supported,
1777 };
1778 
1779 struct intel_plane *
1780 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1781 			  enum pipe pipe, int sprite)
1782 {
1783 	struct intel_plane *plane;
1784 	const struct drm_plane_funcs *plane_funcs;
1785 	unsigned int supported_rotations;
1786 	const u64 *modifiers;
1787 	const u32 *formats;
1788 	int num_formats;
1789 	int ret, zpos;
1790 
1791 	plane = intel_plane_alloc();
1792 	if (IS_ERR(plane))
1793 		return plane;
1794 
1795 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1796 		plane->update_plane = vlv_update_plane;
1797 		plane->disable_plane = vlv_disable_plane;
1798 		plane->get_hw_state = vlv_plane_get_hw_state;
1799 		plane->check_plane = vlv_sprite_check;
1800 		plane->max_stride = i965_plane_max_stride;
1801 		plane->min_cdclk = vlv_plane_min_cdclk;
1802 
1803 		if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1804 			formats = chv_pipe_b_sprite_formats;
1805 			num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
1806 		} else {
1807 			formats = vlv_plane_formats;
1808 			num_formats = ARRAY_SIZE(vlv_plane_formats);
1809 		}
1810 		modifiers = i9xx_plane_format_modifiers;
1811 
1812 		plane_funcs = &vlv_sprite_funcs;
1813 	} else if (INTEL_GEN(dev_priv) >= 7) {
1814 		plane->update_plane = ivb_update_plane;
1815 		plane->disable_plane = ivb_disable_plane;
1816 		plane->get_hw_state = ivb_plane_get_hw_state;
1817 		plane->check_plane = g4x_sprite_check;
1818 
1819 		if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
1820 			plane->max_stride = hsw_sprite_max_stride;
1821 			plane->min_cdclk = hsw_plane_min_cdclk;
1822 		} else {
1823 			plane->max_stride = g4x_sprite_max_stride;
1824 			plane->min_cdclk = ivb_sprite_min_cdclk;
1825 		}
1826 
1827 		formats = snb_plane_formats;
1828 		num_formats = ARRAY_SIZE(snb_plane_formats);
1829 		modifiers = i9xx_plane_format_modifiers;
1830 
1831 		plane_funcs = &snb_sprite_funcs;
1832 	} else {
1833 		plane->update_plane = g4x_update_plane;
1834 		plane->disable_plane = g4x_disable_plane;
1835 		plane->get_hw_state = g4x_plane_get_hw_state;
1836 		plane->check_plane = g4x_sprite_check;
1837 		plane->max_stride = g4x_sprite_max_stride;
1838 		plane->min_cdclk = g4x_sprite_min_cdclk;
1839 
1840 		modifiers = i9xx_plane_format_modifiers;
1841 		if (IS_GEN(dev_priv, 6)) {
1842 			formats = snb_plane_formats;
1843 			num_formats = ARRAY_SIZE(snb_plane_formats);
1844 
1845 			plane_funcs = &snb_sprite_funcs;
1846 		} else {
1847 			formats = g4x_plane_formats;
1848 			num_formats = ARRAY_SIZE(g4x_plane_formats);
1849 
1850 			plane_funcs = &g4x_sprite_funcs;
1851 		}
1852 	}
1853 
1854 	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1855 		supported_rotations =
1856 			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1857 			DRM_MODE_REFLECT_X;
1858 	} else {
1859 		supported_rotations =
1860 			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1861 	}
1862 
1863 	plane->pipe = pipe;
1864 	plane->id = PLANE_SPRITE0 + sprite;
1865 	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
1866 
1867 	ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
1868 				       0, plane_funcs,
1869 				       formats, num_formats, modifiers,
1870 				       DRM_PLANE_TYPE_OVERLAY,
1871 				       "sprite %c", sprite_name(pipe, sprite));
1872 	if (ret)
1873 		goto fail;
1874 
1875 	drm_plane_create_rotation_property(&plane->base,
1876 					   DRM_MODE_ROTATE_0,
1877 					   supported_rotations);
1878 
1879 	drm_plane_create_color_properties(&plane->base,
1880 					  BIT(DRM_COLOR_YCBCR_BT601) |
1881 					  BIT(DRM_COLOR_YCBCR_BT709),
1882 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1883 					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1884 					  DRM_COLOR_YCBCR_BT709,
1885 					  DRM_COLOR_YCBCR_LIMITED_RANGE);
1886 
1887 	zpos = sprite + 1;
1888 	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
1889 
1890 	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
1891 
1892 	return plane;
1893 
1894 fail:
1895 	intel_plane_free(plane);
1896 
1897 	return ERR_PTR(ret);
1898 }
1899