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 #include <drm/drmP.h>
33 #include <drm/drm_atomic_helper.h>
34 #include <drm/drm_crtc.h>
35 #include <drm/drm_fourcc.h>
36 #include <drm/drm_rect.h>
37 #include <drm/drm_atomic.h>
38 #include <drm/drm_plane_helper.h>
39 #include "intel_drv.h"
40 #include "intel_frontbuffer.h"
41 #include <drm/i915_drm.h>
42 #include "i915_drv.h"
43 
intel_usecs_to_scanlines(const struct drm_display_mode * adjusted_mode,int usecs)44 int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
45 			     int usecs)
46 {
47 	/* paranoia */
48 	if (!adjusted_mode->crtc_htotal)
49 		return 1;
50 
51 	return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
52 			    1000 * adjusted_mode->crtc_htotal);
53 }
54 
55 /* FIXME: We should instead only take spinlocks once for the entire update
56  * instead of once per mmio. */
57 #if IS_ENABLED(CONFIG_PROVE_LOCKING)
58 #define VBLANK_EVASION_TIME_US 250
59 #else
60 #define VBLANK_EVASION_TIME_US 100
61 #endif
62 
63 /**
64  * intel_pipe_update_start() - start update of a set of display registers
65  * @new_crtc_state: the new crtc state
66  *
67  * Mark the start of an update to pipe registers that should be updated
68  * atomically regarding vblank. If the next vblank will happens within
69  * the next 100 us, this function waits until the vblank passes.
70  *
71  * After a successful call to this function, interrupts will be disabled
72  * until a subsequent call to intel_pipe_update_end(). That is done to
73  * avoid random delays.
74  */
intel_pipe_update_start(const struct intel_crtc_state * new_crtc_state)75 void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
76 {
77 	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
78 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
79 	const struct drm_display_mode *adjusted_mode = &new_crtc_state->base.adjusted_mode;
80 	long timeout = msecs_to_jiffies_timeout(1);
81 	int scanline, min, max, vblank_start;
82 	wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
83 	bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
84 		intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
85 	DEFINE_WAIT(wait);
86 
87 	vblank_start = adjusted_mode->crtc_vblank_start;
88 	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
89 		vblank_start = DIV_ROUND_UP(vblank_start, 2);
90 
91 	/* FIXME needs to be calibrated sensibly */
92 	min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
93 						      VBLANK_EVASION_TIME_US);
94 	max = vblank_start - 1;
95 
96 	if (min <= 0 || max <= 0)
97 		goto irq_disable;
98 
99 	if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
100 		goto irq_disable;
101 
102 	/*
103 	 * Wait for psr to idle out after enabling the VBL interrupts
104 	 * VBL interrupts will start the PSR exit and prevent a PSR
105 	 * re-entry as well.
106 	 */
107 	if (intel_psr_wait_for_idle(new_crtc_state))
108 		DRM_ERROR("PSR idle timed out, atomic update may fail\n");
109 
110 	local_irq_disable();
111 
112 	crtc->debug.min_vbl = min;
113 	crtc->debug.max_vbl = max;
114 	trace_i915_pipe_update_start(crtc);
115 
116 	for (;;) {
117 		/*
118 		 * prepare_to_wait() has a memory barrier, which guarantees
119 		 * other CPUs can see the task state update by the time we
120 		 * read the scanline.
121 		 */
122 		prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
123 
124 		scanline = intel_get_crtc_scanline(crtc);
125 		if (scanline < min || scanline > max)
126 			break;
127 
128 		if (!timeout) {
129 			DRM_ERROR("Potential atomic update failure on pipe %c\n",
130 				  pipe_name(crtc->pipe));
131 			break;
132 		}
133 
134 		local_irq_enable();
135 
136 		timeout = schedule_timeout(timeout);
137 
138 		local_irq_disable();
139 	}
140 
141 	finish_wait(wq, &wait);
142 
143 	drm_crtc_vblank_put(&crtc->base);
144 
145 	/*
146 	 * On VLV/CHV DSI the scanline counter would appear to
147 	 * increment approx. 1/3 of a scanline before start of vblank.
148 	 * The registers still get latched at start of vblank however.
149 	 * This means we must not write any registers on the first
150 	 * line of vblank (since not the whole line is actually in
151 	 * vblank). And unfortunately we can't use the interrupt to
152 	 * wait here since it will fire too soon. We could use the
153 	 * frame start interrupt instead since it will fire after the
154 	 * critical scanline, but that would require more changes
155 	 * in the interrupt code. So for now we'll just do the nasty
156 	 * thing and poll for the bad scanline to pass us by.
157 	 *
158 	 * FIXME figure out if BXT+ DSI suffers from this as well
159 	 */
160 	while (need_vlv_dsi_wa && scanline == vblank_start)
161 		scanline = intel_get_crtc_scanline(crtc);
162 
163 	crtc->debug.scanline_start = scanline;
164 	crtc->debug.start_vbl_time = ktime_get();
165 	crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
166 
167 	trace_i915_pipe_update_vblank_evaded(crtc);
168 	return;
169 
170 irq_disable:
171 	local_irq_disable();
172 }
173 
174 /**
175  * intel_pipe_update_end() - end update of a set of display registers
176  * @new_crtc_state: the new crtc state
177  *
178  * Mark the end of an update started with intel_pipe_update_start(). This
179  * re-enables interrupts and verifies the update was actually completed
180  * before a vblank.
181  */
intel_pipe_update_end(struct intel_crtc_state * new_crtc_state)182 void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
183 {
184 	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
185 	enum pipe pipe = crtc->pipe;
186 	int scanline_end = intel_get_crtc_scanline(crtc);
187 	u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
188 	ktime_t end_vbl_time = ktime_get();
189 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
190 
191 	trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
192 
193 	/* We're still in the vblank-evade critical section, this can't race.
194 	 * Would be slightly nice to just grab the vblank count and arm the
195 	 * event outside of the critical section - the spinlock might spin for a
196 	 * while ... */
197 	if (new_crtc_state->base.event) {
198 		WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);
199 
200 		spin_lock(&crtc->base.dev->event_lock);
201 		drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event);
202 		spin_unlock(&crtc->base.dev->event_lock);
203 
204 		new_crtc_state->base.event = NULL;
205 	}
206 
207 	local_irq_enable();
208 
209 	if (intel_vgpu_active(dev_priv))
210 		return;
211 
212 	if (crtc->debug.start_vbl_count &&
213 	    crtc->debug.start_vbl_count != end_vbl_count) {
214 		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",
215 			  pipe_name(pipe), crtc->debug.start_vbl_count,
216 			  end_vbl_count,
217 			  ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
218 			  crtc->debug.min_vbl, crtc->debug.max_vbl,
219 			  crtc->debug.scanline_start, scanline_end);
220 	}
221 #ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
222 	else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
223 		 VBLANK_EVASION_TIME_US)
224 		DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
225 			 pipe_name(pipe),
226 			 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
227 			 VBLANK_EVASION_TIME_US);
228 #endif
229 }
230 
231 void
skl_update_plane(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)232 skl_update_plane(struct intel_plane *plane,
233 		 const struct intel_crtc_state *crtc_state,
234 		 const struct intel_plane_state *plane_state)
235 {
236 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
237 	const struct drm_framebuffer *fb = plane_state->base.fb;
238 	enum plane_id plane_id = plane->id;
239 	enum pipe pipe = plane->pipe;
240 	u32 plane_ctl = plane_state->ctl;
241 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
242 	u32 surf_addr = plane_state->main.offset;
243 	unsigned int rotation = plane_state->base.rotation;
244 	u32 stride = skl_plane_stride(fb, 0, rotation);
245 	u32 aux_stride = skl_plane_stride(fb, 1, rotation);
246 	int crtc_x = plane_state->base.dst.x1;
247 	int crtc_y = plane_state->base.dst.y1;
248 	uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
249 	uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
250 	uint32_t x = plane_state->main.x;
251 	uint32_t y = plane_state->main.y;
252 	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
253 	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
254 	unsigned long irqflags;
255 
256 	/* Sizes are 0 based */
257 	src_w--;
258 	src_h--;
259 	crtc_w--;
260 	crtc_h--;
261 
262 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
263 
264 	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
265 		I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id),
266 			      plane_state->color_ctl);
267 
268 	if (key->flags) {
269 		I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
270 		I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), key->max_value);
271 		I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), key->channel_mask);
272 	}
273 
274 	I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
275 	I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
276 	I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
277 	I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
278 		      (plane_state->aux.offset - surf_addr) | aux_stride);
279 	I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
280 		      (plane_state->aux.y << 16) | plane_state->aux.x);
281 
282 	/* program plane scaler */
283 	if (plane_state->scaler_id >= 0) {
284 		int scaler_id = plane_state->scaler_id;
285 		const struct intel_scaler *scaler =
286 			&crtc_state->scaler_state.scalers[scaler_id];
287 		u16 y_hphase, uv_rgb_hphase;
288 		u16 y_vphase, uv_rgb_vphase;
289 
290 		/* TODO: handle sub-pixel coordinates */
291 		if (fb->format->format == DRM_FORMAT_NV12) {
292 			y_hphase = skl_scaler_calc_phase(1, false);
293 			y_vphase = skl_scaler_calc_phase(1, false);
294 
295 			/* MPEG2 chroma siting convention */
296 			uv_rgb_hphase = skl_scaler_calc_phase(2, true);
297 			uv_rgb_vphase = skl_scaler_calc_phase(2, false);
298 		} else {
299 			/* not used */
300 			y_hphase = 0;
301 			y_vphase = 0;
302 
303 			uv_rgb_hphase = skl_scaler_calc_phase(1, false);
304 			uv_rgb_vphase = skl_scaler_calc_phase(1, false);
305 		}
306 
307 		I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
308 			      PS_SCALER_EN | PS_PLANE_SEL(plane_id) | scaler->mode);
309 		I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
310 		I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
311 			      PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
312 		I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
313 			      PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
314 		I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
315 		I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id),
316 			      ((crtc_w + 1) << 16)|(crtc_h + 1));
317 
318 		I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0);
319 	} else {
320 		I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
321 	}
322 
323 	I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
324 	I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
325 		      intel_plane_ggtt_offset(plane_state) + surf_addr);
326 	POSTING_READ_FW(PLANE_SURF(pipe, plane_id));
327 
328 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
329 }
330 
331 void
skl_disable_plane(struct intel_plane * plane,struct intel_crtc * crtc)332 skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
333 {
334 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
335 	enum plane_id plane_id = plane->id;
336 	enum pipe pipe = plane->pipe;
337 	unsigned long irqflags;
338 
339 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
340 
341 	I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
342 
343 	I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
344 	POSTING_READ_FW(PLANE_SURF(pipe, plane_id));
345 
346 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
347 }
348 
349 bool
skl_plane_get_hw_state(struct intel_plane * plane,enum pipe * pipe)350 skl_plane_get_hw_state(struct intel_plane *plane,
351 		       enum pipe *pipe)
352 {
353 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
354 	enum intel_display_power_domain power_domain;
355 	enum plane_id plane_id = plane->id;
356 	bool ret;
357 
358 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
359 	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
360 		return false;
361 
362 	ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
363 
364 	*pipe = plane->pipe;
365 
366 	intel_display_power_put(dev_priv, power_domain);
367 
368 	return ret;
369 }
370 
371 static void
chv_update_csc(const struct intel_plane_state * plane_state)372 chv_update_csc(const struct intel_plane_state *plane_state)
373 {
374 	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
375 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
376 	const struct drm_framebuffer *fb = plane_state->base.fb;
377 	enum plane_id plane_id = plane->id;
378 	/*
379 	 * |r|   | c0 c1 c2 |   |cr|
380 	 * |g| = | c3 c4 c5 | x |y |
381 	 * |b|   | c6 c7 c8 |   |cb|
382 	 *
383 	 * Coefficients are s3.12.
384 	 *
385 	 * Cb and Cr apparently come in as signed already, and
386 	 * we always get full range data in on account of CLRC0/1.
387 	 */
388 	static const s16 csc_matrix[][9] = {
389 		/* BT.601 full range YCbCr -> full range RGB */
390 		[DRM_COLOR_YCBCR_BT601] = {
391 			 5743, 4096,     0,
392 			-2925, 4096, -1410,
393 			    0, 4096,  7258,
394 		},
395 		/* BT.709 full range YCbCr -> full range RGB */
396 		[DRM_COLOR_YCBCR_BT709] = {
397 			 6450, 4096,     0,
398 			-1917, 4096,  -767,
399 			    0, 4096,  7601,
400 		},
401 	};
402 	const s16 *csc = csc_matrix[plane_state->base.color_encoding];
403 
404 	/* Seems RGB data bypasses the CSC always */
405 	if (!fb->format->is_yuv)
406 		return;
407 
408 	I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
409 	I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
410 	I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
411 
412 	I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
413 	I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
414 	I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
415 	I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
416 	I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8]));
417 
418 	I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
419 	I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
420 	I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
421 
422 	I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
423 	I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
424 	I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
425 }
426 
427 #define SIN_0 0
428 #define COS_0 1
429 
430 static void
vlv_update_clrc(const struct intel_plane_state * plane_state)431 vlv_update_clrc(const struct intel_plane_state *plane_state)
432 {
433 	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
434 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
435 	const struct drm_framebuffer *fb = plane_state->base.fb;
436 	enum pipe pipe = plane->pipe;
437 	enum plane_id plane_id = plane->id;
438 	int contrast, brightness, sh_scale, sh_sin, sh_cos;
439 
440 	if (fb->format->is_yuv &&
441 	    plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
442 		/*
443 		 * Expand limited range to full range:
444 		 * Contrast is applied first and is used to expand Y range.
445 		 * Brightness is applied second and is used to remove the
446 		 * offset from Y. Saturation/hue is used to expand CbCr range.
447 		 */
448 		contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
449 		brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
450 		sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
451 		sh_sin = SIN_0 * sh_scale;
452 		sh_cos = COS_0 * sh_scale;
453 	} else {
454 		/* Pass-through everything. */
455 		contrast = 1 << 6;
456 		brightness = 0;
457 		sh_scale = 1 << 7;
458 		sh_sin = SIN_0 * sh_scale;
459 		sh_cos = COS_0 * sh_scale;
460 	}
461 
462 	/* FIXME these register are single buffered :( */
463 	I915_WRITE_FW(SPCLRC0(pipe, plane_id),
464 		      SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
465 	I915_WRITE_FW(SPCLRC1(pipe, plane_id),
466 		      SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
467 }
468 
vlv_sprite_ctl(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)469 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
470 			  const struct intel_plane_state *plane_state)
471 {
472 	const struct drm_framebuffer *fb = plane_state->base.fb;
473 	unsigned int rotation = plane_state->base.rotation;
474 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
475 	u32 sprctl;
476 
477 	sprctl = SP_ENABLE | SP_GAMMA_ENABLE;
478 
479 	switch (fb->format->format) {
480 	case DRM_FORMAT_YUYV:
481 		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
482 		break;
483 	case DRM_FORMAT_YVYU:
484 		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
485 		break;
486 	case DRM_FORMAT_UYVY:
487 		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
488 		break;
489 	case DRM_FORMAT_VYUY:
490 		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
491 		break;
492 	case DRM_FORMAT_RGB565:
493 		sprctl |= SP_FORMAT_BGR565;
494 		break;
495 	case DRM_FORMAT_XRGB8888:
496 		sprctl |= SP_FORMAT_BGRX8888;
497 		break;
498 	case DRM_FORMAT_ARGB8888:
499 		sprctl |= SP_FORMAT_BGRA8888;
500 		break;
501 	case DRM_FORMAT_XBGR2101010:
502 		sprctl |= SP_FORMAT_RGBX1010102;
503 		break;
504 	case DRM_FORMAT_ABGR2101010:
505 		sprctl |= SP_FORMAT_RGBA1010102;
506 		break;
507 	case DRM_FORMAT_XBGR8888:
508 		sprctl |= SP_FORMAT_RGBX8888;
509 		break;
510 	case DRM_FORMAT_ABGR8888:
511 		sprctl |= SP_FORMAT_RGBA8888;
512 		break;
513 	default:
514 		MISSING_CASE(fb->format->format);
515 		return 0;
516 	}
517 
518 	if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
519 		sprctl |= SP_YUV_FORMAT_BT709;
520 
521 	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
522 		sprctl |= SP_TILED;
523 
524 	if (rotation & DRM_MODE_ROTATE_180)
525 		sprctl |= SP_ROTATE_180;
526 
527 	if (rotation & DRM_MODE_REFLECT_X)
528 		sprctl |= SP_MIRROR;
529 
530 	if (key->flags & I915_SET_COLORKEY_SOURCE)
531 		sprctl |= SP_SOURCE_KEY;
532 
533 	return sprctl;
534 }
535 
536 static void
vlv_update_plane(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)537 vlv_update_plane(struct intel_plane *plane,
538 		 const struct intel_crtc_state *crtc_state,
539 		 const struct intel_plane_state *plane_state)
540 {
541 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
542 	const struct drm_framebuffer *fb = plane_state->base.fb;
543 	enum pipe pipe = plane->pipe;
544 	enum plane_id plane_id = plane->id;
545 	u32 sprctl = plane_state->ctl;
546 	u32 sprsurf_offset = plane_state->main.offset;
547 	u32 linear_offset;
548 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
549 	int crtc_x = plane_state->base.dst.x1;
550 	int crtc_y = plane_state->base.dst.y1;
551 	uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
552 	uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
553 	uint32_t x = plane_state->main.x;
554 	uint32_t y = plane_state->main.y;
555 	unsigned long irqflags;
556 
557 	/* Sizes are 0 based */
558 	crtc_w--;
559 	crtc_h--;
560 
561 	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
562 
563 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
564 
565 	vlv_update_clrc(plane_state);
566 
567 	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
568 		chv_update_csc(plane_state);
569 
570 	if (key->flags) {
571 		I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
572 		I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
573 		I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
574 	}
575 	I915_WRITE_FW(SPSTRIDE(pipe, plane_id), fb->pitches[0]);
576 	I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
577 
578 	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
579 		I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
580 	else
581 		I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
582 
583 	I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
584 
585 	I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
586 	I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
587 	I915_WRITE_FW(SPSURF(pipe, plane_id),
588 		      intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
589 	POSTING_READ_FW(SPSURF(pipe, plane_id));
590 
591 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
592 }
593 
594 static void
vlv_disable_plane(struct intel_plane * plane,struct intel_crtc * crtc)595 vlv_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
596 {
597 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
598 	enum pipe pipe = plane->pipe;
599 	enum plane_id plane_id = plane->id;
600 	unsigned long irqflags;
601 
602 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
603 
604 	I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
605 
606 	I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
607 	POSTING_READ_FW(SPSURF(pipe, plane_id));
608 
609 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
610 }
611 
612 static bool
vlv_plane_get_hw_state(struct intel_plane * plane,enum pipe * pipe)613 vlv_plane_get_hw_state(struct intel_plane *plane,
614 		       enum pipe *pipe)
615 {
616 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
617 	enum intel_display_power_domain power_domain;
618 	enum plane_id plane_id = plane->id;
619 	bool ret;
620 
621 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
622 	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
623 		return false;
624 
625 	ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
626 
627 	*pipe = plane->pipe;
628 
629 	intel_display_power_put(dev_priv, power_domain);
630 
631 	return ret;
632 }
633 
ivb_sprite_ctl(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)634 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
635 			  const struct intel_plane_state *plane_state)
636 {
637 	struct drm_i915_private *dev_priv =
638 		to_i915(plane_state->base.plane->dev);
639 	const struct drm_framebuffer *fb = plane_state->base.fb;
640 	unsigned int rotation = plane_state->base.rotation;
641 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
642 	u32 sprctl;
643 
644 	sprctl = SPRITE_ENABLE | SPRITE_GAMMA_ENABLE;
645 
646 	if (IS_IVYBRIDGE(dev_priv))
647 		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
648 
649 	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
650 		sprctl |= SPRITE_PIPE_CSC_ENABLE;
651 
652 	switch (fb->format->format) {
653 	case DRM_FORMAT_XBGR8888:
654 		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
655 		break;
656 	case DRM_FORMAT_XRGB8888:
657 		sprctl |= SPRITE_FORMAT_RGBX888;
658 		break;
659 	case DRM_FORMAT_YUYV:
660 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
661 		break;
662 	case DRM_FORMAT_YVYU:
663 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
664 		break;
665 	case DRM_FORMAT_UYVY:
666 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
667 		break;
668 	case DRM_FORMAT_VYUY:
669 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
670 		break;
671 	default:
672 		MISSING_CASE(fb->format->format);
673 		return 0;
674 	}
675 
676 	if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
677 		sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
678 
679 	if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
680 		sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
681 
682 	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
683 		sprctl |= SPRITE_TILED;
684 
685 	if (rotation & DRM_MODE_ROTATE_180)
686 		sprctl |= SPRITE_ROTATE_180;
687 
688 	if (key->flags & I915_SET_COLORKEY_DESTINATION)
689 		sprctl |= SPRITE_DEST_KEY;
690 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
691 		sprctl |= SPRITE_SOURCE_KEY;
692 
693 	return sprctl;
694 }
695 
696 static void
ivb_update_plane(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)697 ivb_update_plane(struct intel_plane *plane,
698 		 const struct intel_crtc_state *crtc_state,
699 		 const struct intel_plane_state *plane_state)
700 {
701 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
702 	const struct drm_framebuffer *fb = plane_state->base.fb;
703 	enum pipe pipe = plane->pipe;
704 	u32 sprctl = plane_state->ctl, sprscale = 0;
705 	u32 sprsurf_offset = plane_state->main.offset;
706 	u32 linear_offset;
707 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
708 	int crtc_x = plane_state->base.dst.x1;
709 	int crtc_y = plane_state->base.dst.y1;
710 	uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
711 	uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
712 	uint32_t x = plane_state->main.x;
713 	uint32_t y = plane_state->main.y;
714 	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
715 	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
716 	unsigned long irqflags;
717 
718 	/* Sizes are 0 based */
719 	src_w--;
720 	src_h--;
721 	crtc_w--;
722 	crtc_h--;
723 
724 	if (crtc_w != src_w || crtc_h != src_h)
725 		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
726 
727 	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
728 
729 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
730 
731 	if (key->flags) {
732 		I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
733 		I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
734 		I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
735 	}
736 
737 	I915_WRITE_FW(SPRSTRIDE(pipe), fb->pitches[0]);
738 	I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
739 
740 	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
741 	 * register */
742 	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
743 		I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
744 	else if (fb->modifier == I915_FORMAT_MOD_X_TILED)
745 		I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
746 	else
747 		I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
748 
749 	I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
750 	if (plane->can_scale)
751 		I915_WRITE_FW(SPRSCALE(pipe), sprscale);
752 	I915_WRITE_FW(SPRCTL(pipe), sprctl);
753 	I915_WRITE_FW(SPRSURF(pipe),
754 		      intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
755 	POSTING_READ_FW(SPRSURF(pipe));
756 
757 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
758 }
759 
760 static void
ivb_disable_plane(struct intel_plane * plane,struct intel_crtc * crtc)761 ivb_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
762 {
763 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
764 	enum pipe pipe = plane->pipe;
765 	unsigned long irqflags;
766 
767 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
768 
769 	I915_WRITE_FW(SPRCTL(pipe), 0);
770 	/* Can't leave the scaler enabled... */
771 	if (plane->can_scale)
772 		I915_WRITE_FW(SPRSCALE(pipe), 0);
773 
774 	I915_WRITE_FW(SPRSURF(pipe), 0);
775 	POSTING_READ_FW(SPRSURF(pipe));
776 
777 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
778 }
779 
780 static bool
ivb_plane_get_hw_state(struct intel_plane * plane,enum pipe * pipe)781 ivb_plane_get_hw_state(struct intel_plane *plane,
782 		       enum pipe *pipe)
783 {
784 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
785 	enum intel_display_power_domain power_domain;
786 	bool ret;
787 
788 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
789 	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
790 		return false;
791 
792 	ret =  I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
793 
794 	*pipe = plane->pipe;
795 
796 	intel_display_power_put(dev_priv, power_domain);
797 
798 	return ret;
799 }
800 
g4x_sprite_ctl(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)801 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
802 			  const struct intel_plane_state *plane_state)
803 {
804 	struct drm_i915_private *dev_priv =
805 		to_i915(plane_state->base.plane->dev);
806 	const struct drm_framebuffer *fb = plane_state->base.fb;
807 	unsigned int rotation = plane_state->base.rotation;
808 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
809 	u32 dvscntr;
810 
811 	dvscntr = DVS_ENABLE | DVS_GAMMA_ENABLE;
812 
813 	if (IS_GEN6(dev_priv))
814 		dvscntr |= DVS_TRICKLE_FEED_DISABLE;
815 
816 	switch (fb->format->format) {
817 	case DRM_FORMAT_XBGR8888:
818 		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
819 		break;
820 	case DRM_FORMAT_XRGB8888:
821 		dvscntr |= DVS_FORMAT_RGBX888;
822 		break;
823 	case DRM_FORMAT_YUYV:
824 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
825 		break;
826 	case DRM_FORMAT_YVYU:
827 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
828 		break;
829 	case DRM_FORMAT_UYVY:
830 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
831 		break;
832 	case DRM_FORMAT_VYUY:
833 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
834 		break;
835 	default:
836 		MISSING_CASE(fb->format->format);
837 		return 0;
838 	}
839 
840 	if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
841 		dvscntr |= DVS_YUV_FORMAT_BT709;
842 
843 	if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
844 		dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
845 
846 	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
847 		dvscntr |= DVS_TILED;
848 
849 	if (rotation & DRM_MODE_ROTATE_180)
850 		dvscntr |= DVS_ROTATE_180;
851 
852 	if (key->flags & I915_SET_COLORKEY_DESTINATION)
853 		dvscntr |= DVS_DEST_KEY;
854 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
855 		dvscntr |= DVS_SOURCE_KEY;
856 
857 	return dvscntr;
858 }
859 
860 static void
g4x_update_plane(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)861 g4x_update_plane(struct intel_plane *plane,
862 		 const struct intel_crtc_state *crtc_state,
863 		 const struct intel_plane_state *plane_state)
864 {
865 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
866 	const struct drm_framebuffer *fb = plane_state->base.fb;
867 	enum pipe pipe = plane->pipe;
868 	u32 dvscntr = plane_state->ctl, dvsscale = 0;
869 	u32 dvssurf_offset = plane_state->main.offset;
870 	u32 linear_offset;
871 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
872 	int crtc_x = plane_state->base.dst.x1;
873 	int crtc_y = plane_state->base.dst.y1;
874 	uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
875 	uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
876 	uint32_t x = plane_state->main.x;
877 	uint32_t y = plane_state->main.y;
878 	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
879 	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
880 	unsigned long irqflags;
881 
882 	/* Sizes are 0 based */
883 	src_w--;
884 	src_h--;
885 	crtc_w--;
886 	crtc_h--;
887 
888 	if (crtc_w != src_w || crtc_h != src_h)
889 		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
890 
891 	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
892 
893 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
894 
895 	if (key->flags) {
896 		I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
897 		I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
898 		I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
899 	}
900 
901 	I915_WRITE_FW(DVSSTRIDE(pipe), fb->pitches[0]);
902 	I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
903 
904 	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
905 		I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
906 	else
907 		I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
908 
909 	I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
910 	I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
911 	I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
912 	I915_WRITE_FW(DVSSURF(pipe),
913 		      intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
914 	POSTING_READ_FW(DVSSURF(pipe));
915 
916 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
917 }
918 
919 static void
g4x_disable_plane(struct intel_plane * plane,struct intel_crtc * crtc)920 g4x_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
921 {
922 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
923 	enum pipe pipe = plane->pipe;
924 	unsigned long irqflags;
925 
926 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
927 
928 	I915_WRITE_FW(DVSCNTR(pipe), 0);
929 	/* Disable the scaler */
930 	I915_WRITE_FW(DVSSCALE(pipe), 0);
931 
932 	I915_WRITE_FW(DVSSURF(pipe), 0);
933 	POSTING_READ_FW(DVSSURF(pipe));
934 
935 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
936 }
937 
938 static bool
g4x_plane_get_hw_state(struct intel_plane * plane,enum pipe * pipe)939 g4x_plane_get_hw_state(struct intel_plane *plane,
940 		       enum pipe *pipe)
941 {
942 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
943 	enum intel_display_power_domain power_domain;
944 	bool ret;
945 
946 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
947 	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
948 		return false;
949 
950 	ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
951 
952 	*pipe = plane->pipe;
953 
954 	intel_display_power_put(dev_priv, power_domain);
955 
956 	return ret;
957 }
958 
959 static int
intel_check_sprite_plane(struct intel_plane * plane,struct intel_crtc_state * crtc_state,struct intel_plane_state * state)960 intel_check_sprite_plane(struct intel_plane *plane,
961 			 struct intel_crtc_state *crtc_state,
962 			 struct intel_plane_state *state)
963 {
964 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
965 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
966 	struct drm_framebuffer *fb = state->base.fb;
967 	int max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384;
968 	int max_scale, min_scale;
969 	bool can_scale;
970 	int ret;
971 	uint32_t pixel_format = 0;
972 
973 	if (!fb) {
974 		state->base.visible = false;
975 		return 0;
976 	}
977 
978 	/* Don't modify another pipe's plane */
979 	if (plane->pipe != crtc->pipe) {
980 		DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
981 		return -EINVAL;
982 	}
983 
984 	/* FIXME check all gen limits */
985 	if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > max_stride) {
986 		DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
987 		return -EINVAL;
988 	}
989 
990 	/* setup can_scale, min_scale, max_scale */
991 	if (INTEL_GEN(dev_priv) >= 9) {
992 		if (state->base.fb)
993 			pixel_format = state->base.fb->format->format;
994 		/* use scaler when colorkey is not required */
995 		if (!state->ckey.flags) {
996 			can_scale = 1;
997 			min_scale = 1;
998 			max_scale =
999 				skl_max_scale(crtc, crtc_state, pixel_format);
1000 		} else {
1001 			can_scale = 0;
1002 			min_scale = DRM_PLANE_HELPER_NO_SCALING;
1003 			max_scale = DRM_PLANE_HELPER_NO_SCALING;
1004 		}
1005 	} else {
1006 		can_scale = plane->can_scale;
1007 		max_scale = plane->max_downscale << 16;
1008 		min_scale = plane->can_scale ? 1 : (1 << 16);
1009 	}
1010 
1011 	ret = drm_atomic_helper_check_plane_state(&state->base,
1012 						  &crtc_state->base,
1013 						  min_scale, max_scale,
1014 						  true, true);
1015 	if (ret)
1016 		return ret;
1017 
1018 	if (state->base.visible) {
1019 		struct drm_rect *src = &state->base.src;
1020 		struct drm_rect *dst = &state->base.dst;
1021 		unsigned int crtc_w = drm_rect_width(dst);
1022 		unsigned int crtc_h = drm_rect_height(dst);
1023 		uint32_t src_x, src_y, src_w, src_h;
1024 
1025 		/*
1026 		 * Hardware doesn't handle subpixel coordinates.
1027 		 * Adjust to (macro)pixel boundary, but be careful not to
1028 		 * increase the source viewport size, because that could
1029 		 * push the downscaling factor out of bounds.
1030 		 */
1031 		src_x = src->x1 >> 16;
1032 		src_w = drm_rect_width(src) >> 16;
1033 		src_y = src->y1 >> 16;
1034 		src_h = drm_rect_height(src) >> 16;
1035 
1036 		src->x1 = src_x << 16;
1037 		src->x2 = (src_x + src_w) << 16;
1038 		src->y1 = src_y << 16;
1039 		src->y2 = (src_y + src_h) << 16;
1040 
1041 		if (fb->format->is_yuv &&
1042     		    fb->format->format != DRM_FORMAT_NV12 &&
1043 		    (src_x % 2 || src_w % 2)) {
1044 			DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",
1045 				      src_x, src_w);
1046 			return -EINVAL;
1047 		}
1048 
1049 		/* Check size restrictions when scaling */
1050 		if (src_w != crtc_w || src_h != crtc_h) {
1051 			unsigned int width_bytes;
1052 			int cpp = fb->format->cpp[0];
1053 
1054 			WARN_ON(!can_scale);
1055 
1056 			width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1057 
1058 			/* FIXME interlacing min height is 6 */
1059 			if (INTEL_GEN(dev_priv) < 9 && (
1060 			     src_w < 3 || src_h < 3 ||
1061 			     src_w > 2048 || src_h > 2048 ||
1062 			     crtc_w < 3 || crtc_h < 3 ||
1063 			     width_bytes > 4096 || fb->pitches[0] > 4096)) {
1064 				DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
1065 				return -EINVAL;
1066 			}
1067 		}
1068 	}
1069 
1070 	if (INTEL_GEN(dev_priv) >= 9) {
1071 		ret = skl_check_plane_surface(crtc_state, state);
1072 		if (ret)
1073 			return ret;
1074 
1075 		state->ctl = skl_plane_ctl(crtc_state, state);
1076 	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1077 		ret = i9xx_check_plane_surface(state);
1078 		if (ret)
1079 			return ret;
1080 
1081 		state->ctl = vlv_sprite_ctl(crtc_state, state);
1082 	} else if (INTEL_GEN(dev_priv) >= 7) {
1083 		ret = i9xx_check_plane_surface(state);
1084 		if (ret)
1085 			return ret;
1086 
1087 		state->ctl = ivb_sprite_ctl(crtc_state, state);
1088 	} else {
1089 		ret = i9xx_check_plane_surface(state);
1090 		if (ret)
1091 			return ret;
1092 
1093 		state->ctl = g4x_sprite_ctl(crtc_state, state);
1094 	}
1095 
1096 	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1097 		state->color_ctl = glk_plane_color_ctl(crtc_state, state);
1098 
1099 	return 0;
1100 }
1101 
has_dst_key_in_primary_plane(struct drm_i915_private * dev_priv)1102 static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1103 {
1104 	return INTEL_GEN(dev_priv) >= 9;
1105 }
1106 
intel_plane_set_ckey(struct intel_plane_state * plane_state,const struct drm_intel_sprite_colorkey * set)1107 static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1108 				 const struct drm_intel_sprite_colorkey *set)
1109 {
1110 	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1111 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1112 	struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1113 
1114 	*key = *set;
1115 
1116 	/*
1117 	 * We want src key enabled on the
1118 	 * sprite and not on the primary.
1119 	 */
1120 	if (plane->id == PLANE_PRIMARY &&
1121 	    set->flags & I915_SET_COLORKEY_SOURCE)
1122 		key->flags = 0;
1123 
1124 	/*
1125 	 * On SKL+ we want dst key enabled on
1126 	 * the primary and not on the sprite.
1127 	 */
1128 	if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1129 	    set->flags & I915_SET_COLORKEY_DESTINATION)
1130 		key->flags = 0;
1131 }
1132 
intel_sprite_set_colorkey_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1133 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1134 				    struct drm_file *file_priv)
1135 {
1136 	struct drm_i915_private *dev_priv = to_i915(dev);
1137 	struct drm_intel_sprite_colorkey *set = data;
1138 	struct drm_plane *plane;
1139 	struct drm_plane_state *plane_state;
1140 	struct drm_atomic_state *state;
1141 	struct drm_modeset_acquire_ctx ctx;
1142 	int ret = 0;
1143 
1144 	/* ignore the pointless "none" flag */
1145 	set->flags &= ~I915_SET_COLORKEY_NONE;
1146 
1147 	if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1148 		return -EINVAL;
1149 
1150 	/* Make sure we don't try to enable both src & dest simultaneously */
1151 	if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1152 		return -EINVAL;
1153 
1154 	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1155 	    set->flags & I915_SET_COLORKEY_DESTINATION)
1156 		return -EINVAL;
1157 
1158 	plane = drm_plane_find(dev, file_priv, set->plane_id);
1159 	if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1160 		return -ENOENT;
1161 
1162 	/*
1163 	 * SKL+ only plane 2 can do destination keying against plane 1.
1164 	 * Also multiple planes can't do destination keying on the same
1165 	 * pipe simultaneously.
1166 	 */
1167 	if (INTEL_GEN(dev_priv) >= 9 &&
1168 	    to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1169 	    set->flags & I915_SET_COLORKEY_DESTINATION)
1170 		return -EINVAL;
1171 
1172 	drm_modeset_acquire_init(&ctx, 0);
1173 
1174 	state = drm_atomic_state_alloc(plane->dev);
1175 	if (!state) {
1176 		ret = -ENOMEM;
1177 		goto out;
1178 	}
1179 	state->acquire_ctx = &ctx;
1180 
1181 	while (1) {
1182 		plane_state = drm_atomic_get_plane_state(state, plane);
1183 		ret = PTR_ERR_OR_ZERO(plane_state);
1184 		if (!ret)
1185 			intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1186 
1187 		/*
1188 		 * On some platforms we have to configure
1189 		 * the dst colorkey on the primary plane.
1190 		 */
1191 		if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1192 			struct intel_crtc *crtc =
1193 				intel_get_crtc_for_pipe(dev_priv,
1194 							to_intel_plane(plane)->pipe);
1195 
1196 			plane_state = drm_atomic_get_plane_state(state,
1197 								 crtc->base.primary);
1198 			ret = PTR_ERR_OR_ZERO(plane_state);
1199 			if (!ret)
1200 				intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1201 		}
1202 
1203 		if (!ret)
1204 			ret = drm_atomic_commit(state);
1205 
1206 		if (ret != -EDEADLK)
1207 			break;
1208 
1209 		drm_atomic_state_clear(state);
1210 		drm_modeset_backoff(&ctx);
1211 	}
1212 
1213 	drm_atomic_state_put(state);
1214 out:
1215 	drm_modeset_drop_locks(&ctx);
1216 	drm_modeset_acquire_fini(&ctx);
1217 	return ret;
1218 }
1219 
1220 static const uint32_t g4x_plane_formats[] = {
1221 	DRM_FORMAT_XRGB8888,
1222 	DRM_FORMAT_YUYV,
1223 	DRM_FORMAT_YVYU,
1224 	DRM_FORMAT_UYVY,
1225 	DRM_FORMAT_VYUY,
1226 };
1227 
1228 static const uint64_t i9xx_plane_format_modifiers[] = {
1229 	I915_FORMAT_MOD_X_TILED,
1230 	DRM_FORMAT_MOD_LINEAR,
1231 	DRM_FORMAT_MOD_INVALID
1232 };
1233 
1234 static const uint32_t snb_plane_formats[] = {
1235 	DRM_FORMAT_XBGR8888,
1236 	DRM_FORMAT_XRGB8888,
1237 	DRM_FORMAT_YUYV,
1238 	DRM_FORMAT_YVYU,
1239 	DRM_FORMAT_UYVY,
1240 	DRM_FORMAT_VYUY,
1241 };
1242 
1243 static const uint32_t vlv_plane_formats[] = {
1244 	DRM_FORMAT_RGB565,
1245 	DRM_FORMAT_ABGR8888,
1246 	DRM_FORMAT_ARGB8888,
1247 	DRM_FORMAT_XBGR8888,
1248 	DRM_FORMAT_XRGB8888,
1249 	DRM_FORMAT_XBGR2101010,
1250 	DRM_FORMAT_ABGR2101010,
1251 	DRM_FORMAT_YUYV,
1252 	DRM_FORMAT_YVYU,
1253 	DRM_FORMAT_UYVY,
1254 	DRM_FORMAT_VYUY,
1255 };
1256 
1257 static uint32_t skl_plane_formats[] = {
1258 	DRM_FORMAT_RGB565,
1259 	DRM_FORMAT_ABGR8888,
1260 	DRM_FORMAT_ARGB8888,
1261 	DRM_FORMAT_XBGR8888,
1262 	DRM_FORMAT_XRGB8888,
1263 	DRM_FORMAT_YUYV,
1264 	DRM_FORMAT_YVYU,
1265 	DRM_FORMAT_UYVY,
1266 	DRM_FORMAT_VYUY,
1267 };
1268 
1269 static uint32_t skl_planar_formats[] = {
1270 	DRM_FORMAT_RGB565,
1271 	DRM_FORMAT_ABGR8888,
1272 	DRM_FORMAT_ARGB8888,
1273 	DRM_FORMAT_XBGR8888,
1274 	DRM_FORMAT_XRGB8888,
1275 	DRM_FORMAT_YUYV,
1276 	DRM_FORMAT_YVYU,
1277 	DRM_FORMAT_UYVY,
1278 	DRM_FORMAT_VYUY,
1279 	DRM_FORMAT_NV12,
1280 };
1281 
1282 static const uint64_t skl_plane_format_modifiers_noccs[] = {
1283 	I915_FORMAT_MOD_Yf_TILED,
1284 	I915_FORMAT_MOD_Y_TILED,
1285 	I915_FORMAT_MOD_X_TILED,
1286 	DRM_FORMAT_MOD_LINEAR,
1287 	DRM_FORMAT_MOD_INVALID
1288 };
1289 
1290 static const uint64_t skl_plane_format_modifiers_ccs[] = {
1291 	I915_FORMAT_MOD_Yf_TILED_CCS,
1292 	I915_FORMAT_MOD_Y_TILED_CCS,
1293 	I915_FORMAT_MOD_Yf_TILED,
1294 	I915_FORMAT_MOD_Y_TILED,
1295 	I915_FORMAT_MOD_X_TILED,
1296 	DRM_FORMAT_MOD_LINEAR,
1297 	DRM_FORMAT_MOD_INVALID
1298 };
1299 
g4x_sprite_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)1300 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1301 					    u32 format, u64 modifier)
1302 {
1303 	switch (modifier) {
1304 	case DRM_FORMAT_MOD_LINEAR:
1305 	case I915_FORMAT_MOD_X_TILED:
1306 		break;
1307 	default:
1308 		return false;
1309 	}
1310 
1311 	switch (format) {
1312 	case DRM_FORMAT_XRGB8888:
1313 	case DRM_FORMAT_YUYV:
1314 	case DRM_FORMAT_YVYU:
1315 	case DRM_FORMAT_UYVY:
1316 	case DRM_FORMAT_VYUY:
1317 		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1318 		    modifier == I915_FORMAT_MOD_X_TILED)
1319 			return true;
1320 		/* fall through */
1321 	default:
1322 		return false;
1323 	}
1324 }
1325 
snb_sprite_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)1326 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1327 					    u32 format, u64 modifier)
1328 {
1329 	switch (modifier) {
1330 	case DRM_FORMAT_MOD_LINEAR:
1331 	case I915_FORMAT_MOD_X_TILED:
1332 		break;
1333 	default:
1334 		return false;
1335 	}
1336 
1337 	switch (format) {
1338 	case DRM_FORMAT_XRGB8888:
1339 	case DRM_FORMAT_XBGR8888:
1340 	case DRM_FORMAT_YUYV:
1341 	case DRM_FORMAT_YVYU:
1342 	case DRM_FORMAT_UYVY:
1343 	case DRM_FORMAT_VYUY:
1344 		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1345 		    modifier == I915_FORMAT_MOD_X_TILED)
1346 			return true;
1347 		/* fall through */
1348 	default:
1349 		return false;
1350 	}
1351 }
1352 
vlv_sprite_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)1353 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1354 					    u32 format, u64 modifier)
1355 {
1356 	switch (modifier) {
1357 	case DRM_FORMAT_MOD_LINEAR:
1358 	case I915_FORMAT_MOD_X_TILED:
1359 		break;
1360 	default:
1361 		return false;
1362 	}
1363 
1364 	switch (format) {
1365 	case DRM_FORMAT_RGB565:
1366 	case DRM_FORMAT_ABGR8888:
1367 	case DRM_FORMAT_ARGB8888:
1368 	case DRM_FORMAT_XBGR8888:
1369 	case DRM_FORMAT_XRGB8888:
1370 	case DRM_FORMAT_XBGR2101010:
1371 	case DRM_FORMAT_ABGR2101010:
1372 	case DRM_FORMAT_YUYV:
1373 	case DRM_FORMAT_YVYU:
1374 	case DRM_FORMAT_UYVY:
1375 	case DRM_FORMAT_VYUY:
1376 		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1377 		    modifier == I915_FORMAT_MOD_X_TILED)
1378 			return true;
1379 		/* fall through */
1380 	default:
1381 		return false;
1382 	}
1383 }
1384 
skl_plane_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)1385 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
1386 					   u32 format, u64 modifier)
1387 {
1388 	struct intel_plane *plane = to_intel_plane(_plane);
1389 
1390 	switch (modifier) {
1391 	case DRM_FORMAT_MOD_LINEAR:
1392 	case I915_FORMAT_MOD_X_TILED:
1393 	case I915_FORMAT_MOD_Y_TILED:
1394 	case I915_FORMAT_MOD_Yf_TILED:
1395 		break;
1396 	case I915_FORMAT_MOD_Y_TILED_CCS:
1397 	case I915_FORMAT_MOD_Yf_TILED_CCS:
1398 		if (!plane->has_ccs)
1399 			return false;
1400 		break;
1401 	default:
1402 		return false;
1403 	}
1404 
1405 	switch (format) {
1406 	case DRM_FORMAT_XRGB8888:
1407 	case DRM_FORMAT_XBGR8888:
1408 	case DRM_FORMAT_ARGB8888:
1409 	case DRM_FORMAT_ABGR8888:
1410 		if (modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
1411 		    modifier == I915_FORMAT_MOD_Y_TILED_CCS)
1412 			return true;
1413 		/* fall through */
1414 	case DRM_FORMAT_RGB565:
1415 	case DRM_FORMAT_XRGB2101010:
1416 	case DRM_FORMAT_XBGR2101010:
1417 	case DRM_FORMAT_YUYV:
1418 	case DRM_FORMAT_YVYU:
1419 	case DRM_FORMAT_UYVY:
1420 	case DRM_FORMAT_VYUY:
1421 	case DRM_FORMAT_NV12:
1422 		if (modifier == I915_FORMAT_MOD_Yf_TILED)
1423 			return true;
1424 		/* fall through */
1425 	case DRM_FORMAT_C8:
1426 		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1427 		    modifier == I915_FORMAT_MOD_X_TILED ||
1428 		    modifier == I915_FORMAT_MOD_Y_TILED)
1429 			return true;
1430 		/* fall through */
1431 	default:
1432 		return false;
1433 	}
1434 }
1435 
1436 static const struct drm_plane_funcs g4x_sprite_funcs = {
1437 	.update_plane = drm_atomic_helper_update_plane,
1438 	.disable_plane = drm_atomic_helper_disable_plane,
1439 	.destroy = intel_plane_destroy,
1440 	.atomic_get_property = intel_plane_atomic_get_property,
1441 	.atomic_set_property = intel_plane_atomic_set_property,
1442 	.atomic_duplicate_state = intel_plane_duplicate_state,
1443 	.atomic_destroy_state = intel_plane_destroy_state,
1444 	.format_mod_supported = g4x_sprite_format_mod_supported,
1445 };
1446 
1447 static const struct drm_plane_funcs snb_sprite_funcs = {
1448 	.update_plane = drm_atomic_helper_update_plane,
1449 	.disable_plane = drm_atomic_helper_disable_plane,
1450 	.destroy = intel_plane_destroy,
1451 	.atomic_get_property = intel_plane_atomic_get_property,
1452 	.atomic_set_property = intel_plane_atomic_set_property,
1453 	.atomic_duplicate_state = intel_plane_duplicate_state,
1454 	.atomic_destroy_state = intel_plane_destroy_state,
1455 	.format_mod_supported = snb_sprite_format_mod_supported,
1456 };
1457 
1458 static const struct drm_plane_funcs vlv_sprite_funcs = {
1459 	.update_plane = drm_atomic_helper_update_plane,
1460 	.disable_plane = drm_atomic_helper_disable_plane,
1461 	.destroy = intel_plane_destroy,
1462 	.atomic_get_property = intel_plane_atomic_get_property,
1463 	.atomic_set_property = intel_plane_atomic_set_property,
1464 	.atomic_duplicate_state = intel_plane_duplicate_state,
1465 	.atomic_destroy_state = intel_plane_destroy_state,
1466 	.format_mod_supported = vlv_sprite_format_mod_supported,
1467 };
1468 
1469 static const struct drm_plane_funcs skl_plane_funcs = {
1470 	.update_plane = drm_atomic_helper_update_plane,
1471 	.disable_plane = drm_atomic_helper_disable_plane,
1472 	.destroy = intel_plane_destroy,
1473 	.atomic_get_property = intel_plane_atomic_get_property,
1474 	.atomic_set_property = intel_plane_atomic_set_property,
1475 	.atomic_duplicate_state = intel_plane_duplicate_state,
1476 	.atomic_destroy_state = intel_plane_destroy_state,
1477 	.format_mod_supported = skl_plane_format_mod_supported,
1478 };
1479 
skl_plane_has_ccs(struct drm_i915_private * dev_priv,enum pipe pipe,enum plane_id plane_id)1480 bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
1481 		       enum pipe pipe, enum plane_id plane_id)
1482 {
1483 	if (plane_id == PLANE_CURSOR)
1484 		return false;
1485 
1486 	if (INTEL_GEN(dev_priv) >= 10)
1487 		return true;
1488 
1489 	if (IS_GEMINILAKE(dev_priv))
1490 		return pipe != PIPE_C;
1491 
1492 	return pipe != PIPE_C &&
1493 		(plane_id == PLANE_PRIMARY ||
1494 		 plane_id == PLANE_SPRITE0);
1495 }
1496 
1497 struct intel_plane *
intel_sprite_plane_create(struct drm_i915_private * dev_priv,enum pipe pipe,int plane)1498 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1499 			  enum pipe pipe, int plane)
1500 {
1501 	struct intel_plane *intel_plane = NULL;
1502 	struct intel_plane_state *state = NULL;
1503 	const struct drm_plane_funcs *plane_funcs;
1504 	unsigned long possible_crtcs;
1505 	const uint32_t *plane_formats;
1506 	const uint64_t *modifiers;
1507 	unsigned int supported_rotations;
1508 	int num_plane_formats;
1509 	int ret;
1510 
1511 	intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
1512 	if (!intel_plane) {
1513 		ret = -ENOMEM;
1514 		goto fail;
1515 	}
1516 
1517 	state = intel_create_plane_state(&intel_plane->base);
1518 	if (!state) {
1519 		ret = -ENOMEM;
1520 		goto fail;
1521 	}
1522 	intel_plane->base.state = &state->base;
1523 
1524 	if (INTEL_GEN(dev_priv) >= 9) {
1525 		intel_plane->can_scale = true;
1526 		state->scaler_id = -1;
1527 
1528 		intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe,
1529 							 PLANE_SPRITE0 + plane);
1530 
1531 		intel_plane->update_plane = skl_update_plane;
1532 		intel_plane->disable_plane = skl_disable_plane;
1533 		intel_plane->get_hw_state = skl_plane_get_hw_state;
1534 
1535 		if (skl_plane_has_planar(dev_priv, pipe,
1536 					 PLANE_SPRITE0 + plane)) {
1537 			plane_formats = skl_planar_formats;
1538 			num_plane_formats = ARRAY_SIZE(skl_planar_formats);
1539 		} else {
1540 			plane_formats = skl_plane_formats;
1541 			num_plane_formats = ARRAY_SIZE(skl_plane_formats);
1542 		}
1543 
1544 		if (intel_plane->has_ccs)
1545 			modifiers = skl_plane_format_modifiers_ccs;
1546 		else
1547 			modifiers = skl_plane_format_modifiers_noccs;
1548 
1549 		plane_funcs = &skl_plane_funcs;
1550 	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1551 		intel_plane->can_scale = false;
1552 		intel_plane->max_downscale = 1;
1553 
1554 		intel_plane->update_plane = vlv_update_plane;
1555 		intel_plane->disable_plane = vlv_disable_plane;
1556 		intel_plane->get_hw_state = vlv_plane_get_hw_state;
1557 
1558 		plane_formats = vlv_plane_formats;
1559 		num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
1560 		modifiers = i9xx_plane_format_modifiers;
1561 
1562 		plane_funcs = &vlv_sprite_funcs;
1563 	} else if (INTEL_GEN(dev_priv) >= 7) {
1564 		if (IS_IVYBRIDGE(dev_priv)) {
1565 			intel_plane->can_scale = true;
1566 			intel_plane->max_downscale = 2;
1567 		} else {
1568 			intel_plane->can_scale = false;
1569 			intel_plane->max_downscale = 1;
1570 		}
1571 
1572 		intel_plane->update_plane = ivb_update_plane;
1573 		intel_plane->disable_plane = ivb_disable_plane;
1574 		intel_plane->get_hw_state = ivb_plane_get_hw_state;
1575 
1576 		plane_formats = snb_plane_formats;
1577 		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1578 		modifiers = i9xx_plane_format_modifiers;
1579 
1580 		plane_funcs = &snb_sprite_funcs;
1581 	} else {
1582 		intel_plane->can_scale = true;
1583 		intel_plane->max_downscale = 16;
1584 
1585 		intel_plane->update_plane = g4x_update_plane;
1586 		intel_plane->disable_plane = g4x_disable_plane;
1587 		intel_plane->get_hw_state = g4x_plane_get_hw_state;
1588 
1589 		modifiers = i9xx_plane_format_modifiers;
1590 		if (IS_GEN6(dev_priv)) {
1591 			plane_formats = snb_plane_formats;
1592 			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1593 
1594 			plane_funcs = &snb_sprite_funcs;
1595 		} else {
1596 			plane_formats = g4x_plane_formats;
1597 			num_plane_formats = ARRAY_SIZE(g4x_plane_formats);
1598 
1599 			plane_funcs = &g4x_sprite_funcs;
1600 		}
1601 	}
1602 
1603 	if (INTEL_GEN(dev_priv) >= 9) {
1604 		supported_rotations =
1605 			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
1606 			DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
1607 	} else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1608 		supported_rotations =
1609 			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1610 			DRM_MODE_REFLECT_X;
1611 	} else {
1612 		supported_rotations =
1613 			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1614 	}
1615 
1616 	intel_plane->pipe = pipe;
1617 	intel_plane->i9xx_plane = plane;
1618 	intel_plane->id = PLANE_SPRITE0 + plane;
1619 	intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id);
1620 	intel_plane->check_plane = intel_check_sprite_plane;
1621 
1622 	possible_crtcs = (1 << pipe);
1623 
1624 	if (INTEL_GEN(dev_priv) >= 9)
1625 		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
1626 					       possible_crtcs, plane_funcs,
1627 					       plane_formats, num_plane_formats,
1628 					       modifiers,
1629 					       DRM_PLANE_TYPE_OVERLAY,
1630 					       "plane %d%c", plane + 2, pipe_name(pipe));
1631 	else
1632 		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
1633 					       possible_crtcs, plane_funcs,
1634 					       plane_formats, num_plane_formats,
1635 					       modifiers,
1636 					       DRM_PLANE_TYPE_OVERLAY,
1637 					       "sprite %c", sprite_name(pipe, plane));
1638 	if (ret)
1639 		goto fail;
1640 
1641 	drm_plane_create_rotation_property(&intel_plane->base,
1642 					   DRM_MODE_ROTATE_0,
1643 					   supported_rotations);
1644 
1645 	drm_plane_create_color_properties(&intel_plane->base,
1646 					  BIT(DRM_COLOR_YCBCR_BT601) |
1647 					  BIT(DRM_COLOR_YCBCR_BT709),
1648 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1649 					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1650 					  DRM_COLOR_YCBCR_BT709,
1651 					  DRM_COLOR_YCBCR_LIMITED_RANGE);
1652 
1653 	drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
1654 
1655 	return intel_plane;
1656 
1657 fail:
1658 	kfree(state);
1659 	kfree(intel_plane);
1660 
1661 	return ERR_PTR(ret);
1662 }
1663