xref: /dragonfly/sys/dev/drm/i915/intel_sprite.c (revision c6f73aab)
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_crtc.h>
34 #include <uapi_drm/drm_fourcc.h>
35 #include <drm/drm_rect.h>
36 #include "intel_drv.h"
37 #include <drm/i915_drm.h>
38 #include "i915_drv.h"
39 
40 static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs)
41 {
42 	/* paranoia */
43 	if (!mode->crtc_htotal)
44 		return 1;
45 
46 	return DIV_ROUND_UP(usecs * mode->crtc_clock, 1000 * mode->crtc_htotal);
47 }
48 
49 static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count)
50 {
51 	struct drm_device *dev = crtc->base.dev;
52 	const struct drm_display_mode *mode = &crtc->config.adjusted_mode;
53 	enum i915_pipe pipe = crtc->pipe;
54 	long timeout = msecs_to_jiffies_timeout(1);
55 	int scanline, min, max, vblank_start;
56 	DEFINE_WAIT(wait);
57 
58 	WARN_ON(!drm_modeset_is_locked(&crtc->base.mutex));
59 
60 	vblank_start = mode->crtc_vblank_start;
61 	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
62 		vblank_start = DIV_ROUND_UP(vblank_start, 2);
63 
64 	/* FIXME needs to be calibrated sensibly */
65 	min = vblank_start - usecs_to_scanlines(mode, 100);
66 	max = vblank_start - 1;
67 
68 	if (min <= 0 || max <= 0)
69 		return false;
70 
71 	if (WARN_ON(drm_vblank_get(dev, pipe)))
72 		return false;
73 
74 	local_irq_disable();
75 
76 	trace_i915_pipe_update_start(crtc, min, max);
77 
78 	for (;;) {
79 		/*
80 		 * prepare_to_wait() has a memory barrier, which guarantees
81 		 * other CPUs can see the task state update by the time we
82 		 * read the scanline.
83 		 */
84 		prepare_to_wait(&crtc->vbl_wait, &wait, TASK_UNINTERRUPTIBLE);
85 
86 		scanline = intel_get_crtc_scanline(crtc);
87 		if (scanline < min || scanline > max)
88 			break;
89 
90 		if (timeout <= 0) {
91 			DRM_ERROR("Potential atomic update failure on pipe %c\n",
92 				  pipe_name(crtc->pipe));
93 			break;
94 		}
95 
96 		local_irq_enable();
97 
98 		timeout = schedule_timeout(timeout);
99 
100 		local_irq_disable();
101 	}
102 
103 	finish_wait(&crtc->vbl_wait, &wait);
104 
105 	drm_vblank_put(dev, pipe);
106 
107 	*start_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
108 
109 	trace_i915_pipe_update_vblank_evaded(crtc, min, max, *start_vbl_count);
110 
111 	return true;
112 }
113 
114 static void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count)
115 {
116 	struct drm_device *dev = crtc->base.dev;
117 	enum i915_pipe pipe = crtc->pipe;
118 	u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
119 
120 	trace_i915_pipe_update_end(crtc, end_vbl_count);
121 
122 	local_irq_enable();
123 
124 	if (start_vbl_count != end_vbl_count)
125 		DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u)\n",
126 			  pipe_name(pipe), start_vbl_count, end_vbl_count);
127 }
128 
129 static void intel_update_primary_plane(struct intel_crtc *crtc)
130 {
131 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
132 	int reg = DSPCNTR(crtc->plane);
133 
134 	if (crtc->primary_enabled)
135 		I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
136 	else
137 		I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
138 }
139 
140 static void
141 vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
142 		 struct drm_framebuffer *fb,
143 		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
144 		 unsigned int crtc_w, unsigned int crtc_h,
145 		 uint32_t x, uint32_t y,
146 		 uint32_t src_w, uint32_t src_h)
147 {
148 	struct drm_device *dev = dplane->dev;
149 	struct drm_i915_private *dev_priv = dev->dev_private;
150 	struct intel_plane *intel_plane = to_intel_plane(dplane);
151 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
152 	int pipe = intel_plane->pipe;
153 	int plane = intel_plane->plane;
154 	u32 sprctl;
155 	unsigned long sprsurf_offset, linear_offset;
156 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
157 	u32 start_vbl_count;
158 	bool atomic_update;
159 
160 	sprctl = I915_READ(SPCNTR(pipe, plane));
161 
162 	/* Mask out pixel format bits in case we change it */
163 	sprctl &= ~SP_PIXFORMAT_MASK;
164 	sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
165 	sprctl &= ~SP_TILED;
166 
167 	switch (fb->pixel_format) {
168 	case DRM_FORMAT_YUYV:
169 		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
170 		break;
171 	case DRM_FORMAT_YVYU:
172 		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
173 		break;
174 	case DRM_FORMAT_UYVY:
175 		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
176 		break;
177 	case DRM_FORMAT_VYUY:
178 		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
179 		break;
180 	case DRM_FORMAT_RGB565:
181 		sprctl |= SP_FORMAT_BGR565;
182 		break;
183 	case DRM_FORMAT_XRGB8888:
184 		sprctl |= SP_FORMAT_BGRX8888;
185 		break;
186 	case DRM_FORMAT_ARGB8888:
187 		sprctl |= SP_FORMAT_BGRA8888;
188 		break;
189 	case DRM_FORMAT_XBGR2101010:
190 		sprctl |= SP_FORMAT_RGBX1010102;
191 		break;
192 	case DRM_FORMAT_ABGR2101010:
193 		sprctl |= SP_FORMAT_RGBA1010102;
194 		break;
195 	case DRM_FORMAT_XBGR8888:
196 		sprctl |= SP_FORMAT_RGBX8888;
197 		break;
198 	case DRM_FORMAT_ABGR8888:
199 		sprctl |= SP_FORMAT_RGBA8888;
200 		break;
201 	default:
202 		/*
203 		 * If we get here one of the upper layers failed to filter
204 		 * out the unsupported plane formats
205 		 */
206 		BUG();
207 		break;
208 	}
209 
210 	/*
211 	 * Enable gamma to match primary/cursor plane behaviour.
212 	 * FIXME should be user controllable via propertiesa.
213 	 */
214 	sprctl |= SP_GAMMA_ENABLE;
215 
216 	if (obj->tiling_mode != I915_TILING_NONE)
217 		sprctl |= SP_TILED;
218 
219 	sprctl |= SP_ENABLE;
220 
221 	intel_update_sprite_watermarks(dplane, crtc, src_w, pixel_size, true,
222 				       src_w != crtc_w || src_h != crtc_h);
223 
224 	/* Sizes are 0 based */
225 	src_w--;
226 	src_h--;
227 	crtc_w--;
228 	crtc_h--;
229 
230 	linear_offset = y * fb->pitches[0] + x * pixel_size;
231 	sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
232 							obj->tiling_mode,
233 							pixel_size,
234 							fb->pitches[0]);
235 	linear_offset -= sprsurf_offset;
236 
237 	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
238 
239 	intel_update_primary_plane(intel_crtc);
240 
241 	I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
242 	I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
243 
244 	if (obj->tiling_mode != I915_TILING_NONE)
245 		I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
246 	else
247 		I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
248 
249 	I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
250 	I915_WRITE(SPCNTR(pipe, plane), sprctl);
251 	I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
252 		   sprsurf_offset);
253 
254 	intel_flush_primary_plane(dev_priv, intel_crtc->plane);
255 
256 	if (atomic_update)
257 		intel_pipe_update_end(intel_crtc, start_vbl_count);
258 }
259 
260 static void
261 vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
262 {
263 	struct drm_device *dev = dplane->dev;
264 	struct drm_i915_private *dev_priv = dev->dev_private;
265 	struct intel_plane *intel_plane = to_intel_plane(dplane);
266 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
267 	int pipe = intel_plane->pipe;
268 	int plane = intel_plane->plane;
269 	u32 start_vbl_count;
270 	bool atomic_update;
271 
272 	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
273 
274 	intel_update_primary_plane(intel_crtc);
275 
276 	I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
277 		   ~SP_ENABLE);
278 	/* Activate double buffered register update */
279 	I915_WRITE(SPSURF(pipe, plane), 0);
280 
281 	intel_flush_primary_plane(dev_priv, intel_crtc->plane);
282 
283 	if (atomic_update)
284 		intel_pipe_update_end(intel_crtc, start_vbl_count);
285 
286 	intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false);
287 }
288 
289 static int
290 vlv_update_colorkey(struct drm_plane *dplane,
291 		    struct drm_intel_sprite_colorkey *key)
292 {
293 	struct drm_device *dev = dplane->dev;
294 	struct drm_i915_private *dev_priv = dev->dev_private;
295 	struct intel_plane *intel_plane = to_intel_plane(dplane);
296 	int pipe = intel_plane->pipe;
297 	int plane = intel_plane->plane;
298 	u32 sprctl;
299 
300 	if (key->flags & I915_SET_COLORKEY_DESTINATION)
301 		return -EINVAL;
302 
303 	I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
304 	I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
305 	I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask);
306 
307 	sprctl = I915_READ(SPCNTR(pipe, plane));
308 	sprctl &= ~SP_SOURCE_KEY;
309 	if (key->flags & I915_SET_COLORKEY_SOURCE)
310 		sprctl |= SP_SOURCE_KEY;
311 	I915_WRITE(SPCNTR(pipe, plane), sprctl);
312 
313 	POSTING_READ(SPKEYMSK(pipe, plane));
314 
315 	return 0;
316 }
317 
318 static void
319 vlv_get_colorkey(struct drm_plane *dplane,
320 		 struct drm_intel_sprite_colorkey *key)
321 {
322 	struct drm_device *dev = dplane->dev;
323 	struct drm_i915_private *dev_priv = dev->dev_private;
324 	struct intel_plane *intel_plane = to_intel_plane(dplane);
325 	int pipe = intel_plane->pipe;
326 	int plane = intel_plane->plane;
327 	u32 sprctl;
328 
329 	key->min_value = I915_READ(SPKEYMINVAL(pipe, plane));
330 	key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane));
331 	key->channel_mask = I915_READ(SPKEYMSK(pipe, plane));
332 
333 	sprctl = I915_READ(SPCNTR(pipe, plane));
334 	if (sprctl & SP_SOURCE_KEY)
335 		key->flags = I915_SET_COLORKEY_SOURCE;
336 	else
337 		key->flags = I915_SET_COLORKEY_NONE;
338 }
339 
340 static void
341 ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
342 		 struct drm_framebuffer *fb,
343 		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
344 		 unsigned int crtc_w, unsigned int crtc_h,
345 		 uint32_t x, uint32_t y,
346 		 uint32_t src_w, uint32_t src_h)
347 {
348 	struct drm_device *dev = plane->dev;
349 	struct drm_i915_private *dev_priv = dev->dev_private;
350 	struct intel_plane *intel_plane = to_intel_plane(plane);
351 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
352 	int pipe = intel_plane->pipe;
353 	u32 sprctl, sprscale = 0;
354 	unsigned long sprsurf_offset, linear_offset;
355 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
356 	u32 start_vbl_count;
357 	bool atomic_update;
358 
359 	sprctl = I915_READ(SPRCTL(pipe));
360 
361 	/* Mask out pixel format bits in case we change it */
362 	sprctl &= ~SPRITE_PIXFORMAT_MASK;
363 	sprctl &= ~SPRITE_RGB_ORDER_RGBX;
364 	sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
365 	sprctl &= ~SPRITE_TILED;
366 
367 	switch (fb->pixel_format) {
368 	case DRM_FORMAT_XBGR8888:
369 		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
370 		break;
371 	case DRM_FORMAT_XRGB8888:
372 		sprctl |= SPRITE_FORMAT_RGBX888;
373 		break;
374 	case DRM_FORMAT_YUYV:
375 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
376 		break;
377 	case DRM_FORMAT_YVYU:
378 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
379 		break;
380 	case DRM_FORMAT_UYVY:
381 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
382 		break;
383 	case DRM_FORMAT_VYUY:
384 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
385 		break;
386 	default:
387 		BUG();
388 	}
389 
390 	/*
391 	 * Enable gamma to match primary/cursor plane behaviour.
392 	 * FIXME should be user controllable via propertiesa.
393 	 */
394 	sprctl |= SPRITE_GAMMA_ENABLE;
395 
396 	if (obj->tiling_mode != I915_TILING_NONE)
397 		sprctl |= SPRITE_TILED;
398 
399 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
400 		sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
401 	else
402 		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
403 
404 	sprctl |= SPRITE_ENABLE;
405 
406 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
407 		sprctl |= SPRITE_PIPE_CSC_ENABLE;
408 
409 	intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
410 				       src_w != crtc_w || src_h != crtc_h);
411 
412 	/* Sizes are 0 based */
413 	src_w--;
414 	src_h--;
415 	crtc_w--;
416 	crtc_h--;
417 
418 	if (crtc_w != src_w || crtc_h != src_h)
419 		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
420 
421 	linear_offset = y * fb->pitches[0] + x * pixel_size;
422 	sprsurf_offset =
423 		intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
424 					       pixel_size, fb->pitches[0]);
425 	linear_offset -= sprsurf_offset;
426 
427 	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
428 
429 	intel_update_primary_plane(intel_crtc);
430 
431 	I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
432 	I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
433 
434 	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
435 	 * register */
436 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
437 		I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
438 	else if (obj->tiling_mode != I915_TILING_NONE)
439 		I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
440 	else
441 		I915_WRITE(SPRLINOFF(pipe), linear_offset);
442 
443 	I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
444 	if (intel_plane->can_scale)
445 		I915_WRITE(SPRSCALE(pipe), sprscale);
446 	I915_WRITE(SPRCTL(pipe), sprctl);
447 	I915_WRITE(SPRSURF(pipe),
448 		   i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
449 
450 	intel_flush_primary_plane(dev_priv, intel_crtc->plane);
451 
452 	if (atomic_update)
453 		intel_pipe_update_end(intel_crtc, start_vbl_count);
454 }
455 
456 static void
457 ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
458 {
459 	struct drm_device *dev = plane->dev;
460 	struct drm_i915_private *dev_priv = dev->dev_private;
461 	struct intel_plane *intel_plane = to_intel_plane(plane);
462 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
463 	int pipe = intel_plane->pipe;
464 	u32 start_vbl_count;
465 	bool atomic_update;
466 
467 	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
468 
469 	intel_update_primary_plane(intel_crtc);
470 
471 	I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
472 	/* Can't leave the scaler enabled... */
473 	if (intel_plane->can_scale)
474 		I915_WRITE(SPRSCALE(pipe), 0);
475 	/* Activate double buffered register update */
476 	I915_WRITE(SPRSURF(pipe), 0);
477 
478 	intel_flush_primary_plane(dev_priv, intel_crtc->plane);
479 
480 	if (atomic_update)
481 		intel_pipe_update_end(intel_crtc, start_vbl_count);
482 
483 	/*
484 	 * Avoid underruns when disabling the sprite.
485 	 * FIXME remove once watermark updates are done properly.
486 	 */
487 	intel_wait_for_vblank(dev, pipe);
488 
489 	intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
490 }
491 
492 static int
493 ivb_update_colorkey(struct drm_plane *plane,
494 		    struct drm_intel_sprite_colorkey *key)
495 {
496 	struct drm_device *dev = plane->dev;
497 	struct drm_i915_private *dev_priv = dev->dev_private;
498 	struct intel_plane *intel_plane;
499 	u32 sprctl;
500 	int ret = 0;
501 
502 	intel_plane = to_intel_plane(plane);
503 
504 	I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
505 	I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
506 	I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
507 
508 	sprctl = I915_READ(SPRCTL(intel_plane->pipe));
509 	sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
510 	if (key->flags & I915_SET_COLORKEY_DESTINATION)
511 		sprctl |= SPRITE_DEST_KEY;
512 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
513 		sprctl |= SPRITE_SOURCE_KEY;
514 	I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
515 
516 	POSTING_READ(SPRKEYMSK(intel_plane->pipe));
517 
518 	return ret;
519 }
520 
521 static void
522 ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
523 {
524 	struct drm_device *dev = plane->dev;
525 	struct drm_i915_private *dev_priv = dev->dev_private;
526 	struct intel_plane *intel_plane;
527 	u32 sprctl;
528 
529 	intel_plane = to_intel_plane(plane);
530 
531 	key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
532 	key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
533 	key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
534 	key->flags = 0;
535 
536 	sprctl = I915_READ(SPRCTL(intel_plane->pipe));
537 
538 	if (sprctl & SPRITE_DEST_KEY)
539 		key->flags = I915_SET_COLORKEY_DESTINATION;
540 	else if (sprctl & SPRITE_SOURCE_KEY)
541 		key->flags = I915_SET_COLORKEY_SOURCE;
542 	else
543 		key->flags = I915_SET_COLORKEY_NONE;
544 }
545 
546 static void
547 ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
548 		 struct drm_framebuffer *fb,
549 		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
550 		 unsigned int crtc_w, unsigned int crtc_h,
551 		 uint32_t x, uint32_t y,
552 		 uint32_t src_w, uint32_t src_h)
553 {
554 	struct drm_device *dev = plane->dev;
555 	struct drm_i915_private *dev_priv = dev->dev_private;
556 	struct intel_plane *intel_plane = to_intel_plane(plane);
557 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
558 	int pipe = intel_plane->pipe;
559 	unsigned long dvssurf_offset, linear_offset;
560 	u32 dvscntr, dvsscale;
561 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
562 	u32 start_vbl_count;
563 	bool atomic_update;
564 
565 	dvscntr = I915_READ(DVSCNTR(pipe));
566 
567 	/* Mask out pixel format bits in case we change it */
568 	dvscntr &= ~DVS_PIXFORMAT_MASK;
569 	dvscntr &= ~DVS_RGB_ORDER_XBGR;
570 	dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
571 	dvscntr &= ~DVS_TILED;
572 
573 	switch (fb->pixel_format) {
574 	case DRM_FORMAT_XBGR8888:
575 		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
576 		break;
577 	case DRM_FORMAT_XRGB8888:
578 		dvscntr |= DVS_FORMAT_RGBX888;
579 		break;
580 	case DRM_FORMAT_YUYV:
581 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
582 		break;
583 	case DRM_FORMAT_YVYU:
584 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
585 		break;
586 	case DRM_FORMAT_UYVY:
587 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
588 		break;
589 	case DRM_FORMAT_VYUY:
590 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
591 		break;
592 	default:
593 		BUG();
594 	}
595 
596 	/*
597 	 * Enable gamma to match primary/cursor plane behaviour.
598 	 * FIXME should be user controllable via propertiesa.
599 	 */
600 	dvscntr |= DVS_GAMMA_ENABLE;
601 
602 	if (obj->tiling_mode != I915_TILING_NONE)
603 		dvscntr |= DVS_TILED;
604 
605 	if (IS_GEN6(dev))
606 		dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
607 	dvscntr |= DVS_ENABLE;
608 
609 	intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
610 				       src_w != crtc_w || src_h != crtc_h);
611 
612 	/* Sizes are 0 based */
613 	src_w--;
614 	src_h--;
615 	crtc_w--;
616 	crtc_h--;
617 
618 	dvsscale = 0;
619 	if (crtc_w != src_w || crtc_h != src_h)
620 		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
621 
622 	linear_offset = y * fb->pitches[0] + x * pixel_size;
623 	dvssurf_offset =
624 		intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
625 					       pixel_size, fb->pitches[0]);
626 	linear_offset -= dvssurf_offset;
627 
628 	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
629 
630 	intel_update_primary_plane(intel_crtc);
631 
632 	I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
633 	I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
634 
635 	if (obj->tiling_mode != I915_TILING_NONE)
636 		I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
637 	else
638 		I915_WRITE(DVSLINOFF(pipe), linear_offset);
639 
640 	I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
641 	I915_WRITE(DVSSCALE(pipe), dvsscale);
642 	I915_WRITE(DVSCNTR(pipe), dvscntr);
643 	I915_WRITE(DVSSURF(pipe),
644 		   i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
645 
646 	intel_flush_primary_plane(dev_priv, intel_crtc->plane);
647 
648 	if (atomic_update)
649 		intel_pipe_update_end(intel_crtc, start_vbl_count);
650 }
651 
652 static void
653 ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
654 {
655 	struct drm_device *dev = plane->dev;
656 	struct drm_i915_private *dev_priv = dev->dev_private;
657 	struct intel_plane *intel_plane = to_intel_plane(plane);
658 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
659 	int pipe = intel_plane->pipe;
660 	u32 start_vbl_count;
661 	bool atomic_update;
662 
663 	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
664 
665 	intel_update_primary_plane(intel_crtc);
666 
667 	I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
668 	/* Disable the scaler */
669 	I915_WRITE(DVSSCALE(pipe), 0);
670 	/* Flush double buffered register updates */
671 	I915_WRITE(DVSSURF(pipe), 0);
672 
673 	intel_flush_primary_plane(dev_priv, intel_crtc->plane);
674 
675 	if (atomic_update)
676 		intel_pipe_update_end(intel_crtc, start_vbl_count);
677 
678 	/*
679 	 * Avoid underruns when disabling the sprite.
680 	 * FIXME remove once watermark updates are done properly.
681 	 */
682 	intel_wait_for_vblank(dev, pipe);
683 
684 	intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
685 }
686 
687 static void
688 intel_post_enable_primary(struct drm_crtc *crtc)
689 {
690 	struct drm_device *dev = crtc->dev;
691 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
692 
693 	/*
694 	 * BDW signals flip done immediately if the plane
695 	 * is disabled, even if the plane enable is already
696 	 * armed to occur at the next vblank :(
697 	 */
698 	if (IS_BROADWELL(dev))
699 		intel_wait_for_vblank(dev, intel_crtc->pipe);
700 
701 	/*
702 	 * FIXME IPS should be fine as long as one plane is
703 	 * enabled, but in practice it seems to have problems
704 	 * when going from primary only to sprite only and vice
705 	 * versa.
706 	 */
707 	hsw_enable_ips(intel_crtc);
708 
709 	mutex_lock(&dev->struct_mutex);
710 	intel_update_fbc(dev);
711 	mutex_unlock(&dev->struct_mutex);
712 }
713 
714 static void
715 intel_pre_disable_primary(struct drm_crtc *crtc)
716 {
717 	struct drm_device *dev = crtc->dev;
718 	struct drm_i915_private *dev_priv = dev->dev_private;
719 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
720 
721 	mutex_lock(&dev->struct_mutex);
722 	if (dev_priv->fbc.plane == intel_crtc->plane)
723 		intel_disable_fbc(dev);
724 	mutex_unlock(&dev->struct_mutex);
725 
726 	/*
727 	 * FIXME IPS should be fine as long as one plane is
728 	 * enabled, but in practice it seems to have problems
729 	 * when going from primary only to sprite only and vice
730 	 * versa.
731 	 */
732 	hsw_disable_ips(intel_crtc);
733 }
734 
735 static int
736 ilk_update_colorkey(struct drm_plane *plane,
737 		    struct drm_intel_sprite_colorkey *key)
738 {
739 	struct drm_device *dev = plane->dev;
740 	struct drm_i915_private *dev_priv = dev->dev_private;
741 	struct intel_plane *intel_plane;
742 	u32 dvscntr;
743 	int ret = 0;
744 
745 	intel_plane = to_intel_plane(plane);
746 
747 	I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
748 	I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
749 	I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
750 
751 	dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
752 	dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
753 	if (key->flags & I915_SET_COLORKEY_DESTINATION)
754 		dvscntr |= DVS_DEST_KEY;
755 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
756 		dvscntr |= DVS_SOURCE_KEY;
757 	I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
758 
759 	POSTING_READ(DVSKEYMSK(intel_plane->pipe));
760 
761 	return ret;
762 }
763 
764 static void
765 ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
766 {
767 	struct drm_device *dev = plane->dev;
768 	struct drm_i915_private *dev_priv = dev->dev_private;
769 	struct intel_plane *intel_plane;
770 	u32 dvscntr;
771 
772 	intel_plane = to_intel_plane(plane);
773 
774 	key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
775 	key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
776 	key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
777 	key->flags = 0;
778 
779 	dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
780 
781 	if (dvscntr & DVS_DEST_KEY)
782 		key->flags = I915_SET_COLORKEY_DESTINATION;
783 	else if (dvscntr & DVS_SOURCE_KEY)
784 		key->flags = I915_SET_COLORKEY_SOURCE;
785 	else
786 		key->flags = I915_SET_COLORKEY_NONE;
787 }
788 
789 static bool
790 format_is_yuv(uint32_t format)
791 {
792 	switch (format) {
793 	case DRM_FORMAT_YUYV:
794 	case DRM_FORMAT_UYVY:
795 	case DRM_FORMAT_VYUY:
796 	case DRM_FORMAT_YVYU:
797 		return true;
798 	default:
799 		return false;
800 	}
801 }
802 
803 static bool colorkey_enabled(struct intel_plane *intel_plane)
804 {
805 	struct drm_intel_sprite_colorkey key;
806 
807 	intel_plane->get_colorkey(&intel_plane->base, &key);
808 
809 	return key.flags != I915_SET_COLORKEY_NONE;
810 }
811 
812 static int
813 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
814 		   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
815 		   unsigned int crtc_w, unsigned int crtc_h,
816 		   uint32_t src_x, uint32_t src_y,
817 		   uint32_t src_w, uint32_t src_h)
818 {
819 	struct drm_device *dev = plane->dev;
820 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
821 	struct intel_plane *intel_plane = to_intel_plane(plane);
822 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
823 	struct drm_i915_gem_object *obj = intel_fb->obj;
824 	struct drm_i915_gem_object *old_obj = intel_plane->obj;
825 	int ret;
826 	bool primary_enabled;
827 	bool visible;
828 	int hscale, vscale;
829 	int max_scale, min_scale;
830 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
831 	struct drm_rect src = {
832 		/* sample coordinates in 16.16 fixed point */
833 		.x1 = src_x,
834 		.x2 = src_x + src_w,
835 		.y1 = src_y,
836 		.y2 = src_y + src_h,
837 	};
838 	struct drm_rect dst = {
839 		/* integer pixels */
840 		.x1 = crtc_x,
841 		.x2 = crtc_x + crtc_w,
842 		.y1 = crtc_y,
843 		.y2 = crtc_y + crtc_h,
844 	};
845 	const struct drm_rect clip = {
846 		.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0,
847 		.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0,
848 	};
849 	const struct {
850 		int crtc_x, crtc_y;
851 		unsigned int crtc_w, crtc_h;
852 		uint32_t src_x, src_y, src_w, src_h;
853 	} orig = {
854 		.crtc_x = crtc_x,
855 		.crtc_y = crtc_y,
856 		.crtc_w = crtc_w,
857 		.crtc_h = crtc_h,
858 		.src_x = src_x,
859 		.src_y = src_y,
860 		.src_w = src_w,
861 		.src_h = src_h,
862 	};
863 
864 	/* Don't modify another pipe's plane */
865 	if (intel_plane->pipe != intel_crtc->pipe) {
866 		DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
867 		return -EINVAL;
868 	}
869 
870 	/* FIXME check all gen limits */
871 	if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) {
872 		DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
873 		return -EINVAL;
874 	}
875 
876 	/* Sprite planes can be linear or x-tiled surfaces */
877 	switch (obj->tiling_mode) {
878 		case I915_TILING_NONE:
879 		case I915_TILING_X:
880 			break;
881 		default:
882 			DRM_DEBUG_KMS("Unsupported tiling mode\n");
883 			return -EINVAL;
884 	}
885 
886 	/*
887 	 * FIXME the following code does a bunch of fuzzy adjustments to the
888 	 * coordinates and sizes. We probably need some way to decide whether
889 	 * more strict checking should be done instead.
890 	 */
891 	max_scale = intel_plane->max_downscale << 16;
892 	min_scale = intel_plane->can_scale ? 1 : (1 << 16);
893 
894 	hscale = drm_rect_calc_hscale_relaxed(&src, &dst, min_scale, max_scale);
895 	BUG_ON(hscale < 0);
896 
897 	vscale = drm_rect_calc_vscale_relaxed(&src, &dst, min_scale, max_scale);
898 	BUG_ON(vscale < 0);
899 
900 	visible = drm_rect_clip_scaled(&src, &dst, &clip, hscale, vscale);
901 
902 	crtc_x = dst.x1;
903 	crtc_y = dst.y1;
904 	crtc_w = drm_rect_width(&dst);
905 	crtc_h = drm_rect_height(&dst);
906 
907 	if (visible) {
908 		/* check again in case clipping clamped the results */
909 		hscale = drm_rect_calc_hscale(&src, &dst, min_scale, max_scale);
910 		if (hscale < 0) {
911 			DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
912 			drm_rect_debug_print(&src, true);
913 			drm_rect_debug_print(&dst, false);
914 
915 			return hscale;
916 		}
917 
918 		vscale = drm_rect_calc_vscale(&src, &dst, min_scale, max_scale);
919 		if (vscale < 0) {
920 			DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
921 			drm_rect_debug_print(&src, true);
922 			drm_rect_debug_print(&dst, false);
923 
924 			return vscale;
925 		}
926 
927 		/* Make the source viewport size an exact multiple of the scaling factors. */
928 		drm_rect_adjust_size(&src,
929 				     drm_rect_width(&dst) * hscale - drm_rect_width(&src),
930 				     drm_rect_height(&dst) * vscale - drm_rect_height(&src));
931 
932 		/* sanity check to make sure the src viewport wasn't enlarged */
933 		WARN_ON(src.x1 < (int) src_x ||
934 			src.y1 < (int) src_y ||
935 			src.x2 > (int) (src_x + src_w) ||
936 			src.y2 > (int) (src_y + src_h));
937 
938 		/*
939 		 * Hardware doesn't handle subpixel coordinates.
940 		 * Adjust to (macro)pixel boundary, but be careful not to
941 		 * increase the source viewport size, because that could
942 		 * push the downscaling factor out of bounds.
943 		 */
944 		src_x = src.x1 >> 16;
945 		src_w = drm_rect_width(&src) >> 16;
946 		src_y = src.y1 >> 16;
947 		src_h = drm_rect_height(&src) >> 16;
948 
949 		if (format_is_yuv(fb->pixel_format)) {
950 			src_x &= ~1;
951 			src_w &= ~1;
952 
953 			/*
954 			 * Must keep src and dst the
955 			 * same if we can't scale.
956 			 */
957 			if (!intel_plane->can_scale)
958 				crtc_w &= ~1;
959 
960 			if (crtc_w == 0)
961 				visible = false;
962 		}
963 	}
964 
965 	/* Check size restrictions when scaling */
966 	if (visible && (src_w != crtc_w || src_h != crtc_h)) {
967 		unsigned int width_bytes;
968 
969 		WARN_ON(!intel_plane->can_scale);
970 
971 		/* FIXME interlacing min height is 6 */
972 
973 		if (crtc_w < 3 || crtc_h < 3)
974 			visible = false;
975 
976 		if (src_w < 3 || src_h < 3)
977 			visible = false;
978 
979 		width_bytes = ((src_x * pixel_size) & 63) + src_w * pixel_size;
980 
981 		if (src_w > 2048 || src_h > 2048 ||
982 		    width_bytes > 4096 || fb->pitches[0] > 4096) {
983 			DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
984 			return -EINVAL;
985 		}
986 	}
987 
988 	dst.x1 = crtc_x;
989 	dst.x2 = crtc_x + crtc_w;
990 	dst.y1 = crtc_y;
991 	dst.y2 = crtc_y + crtc_h;
992 
993 	/*
994 	 * If the sprite is completely covering the primary plane,
995 	 * we can disable the primary and save power.
996 	 */
997 	primary_enabled = !drm_rect_equals(&dst, &clip) || colorkey_enabled(intel_plane);
998 	WARN_ON(!primary_enabled && !visible && intel_crtc->active);
999 
1000 	mutex_lock(&dev->struct_mutex);
1001 
1002 	/* Note that this will apply the VT-d workaround for scanouts,
1003 	 * which is more restrictive than required for sprites. (The
1004 	 * primary plane requires 256KiB alignment with 64 PTE padding,
1005 	 * the sprite planes only require 128KiB alignment and 32 PTE padding.
1006 	 */
1007 	ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
1008 
1009 	mutex_unlock(&dev->struct_mutex);
1010 
1011 	if (ret)
1012 		return ret;
1013 
1014 	intel_plane->crtc_x = orig.crtc_x;
1015 	intel_plane->crtc_y = orig.crtc_y;
1016 	intel_plane->crtc_w = orig.crtc_w;
1017 	intel_plane->crtc_h = orig.crtc_h;
1018 	intel_plane->src_x = orig.src_x;
1019 	intel_plane->src_y = orig.src_y;
1020 	intel_plane->src_w = orig.src_w;
1021 	intel_plane->src_h = orig.src_h;
1022 	intel_plane->obj = obj;
1023 
1024 	if (intel_crtc->active) {
1025 		bool primary_was_enabled = intel_crtc->primary_enabled;
1026 
1027 		intel_crtc->primary_enabled = primary_enabled;
1028 
1029 		if (primary_was_enabled != primary_enabled)
1030 			intel_crtc_wait_for_pending_flips(crtc);
1031 
1032 		if (primary_was_enabled && !primary_enabled)
1033 			intel_pre_disable_primary(crtc);
1034 
1035 		if (visible)
1036 			intel_plane->update_plane(plane, crtc, fb, obj,
1037 						  crtc_x, crtc_y, crtc_w, crtc_h,
1038 						  src_x, src_y, src_w, src_h);
1039 		else
1040 			intel_plane->disable_plane(plane, crtc);
1041 
1042 		if (!primary_was_enabled && primary_enabled)
1043 			intel_post_enable_primary(crtc);
1044 	}
1045 
1046 	/* Unpin old obj after new one is active to avoid ugliness */
1047 	if (old_obj) {
1048 		/*
1049 		 * It's fairly common to simply update the position of
1050 		 * an existing object.  In that case, we don't need to
1051 		 * wait for vblank to avoid ugliness, we only need to
1052 		 * do the pin & ref bookkeeping.
1053 		 */
1054 		if (old_obj != obj && intel_crtc->active)
1055 			intel_wait_for_vblank(dev, intel_crtc->pipe);
1056 
1057 		mutex_lock(&dev->struct_mutex);
1058 		intel_unpin_fb_obj(old_obj);
1059 		mutex_unlock(&dev->struct_mutex);
1060 	}
1061 
1062 	return 0;
1063 }
1064 
1065 static int
1066 intel_disable_plane(struct drm_plane *plane)
1067 {
1068 	struct drm_device *dev = plane->dev;
1069 	struct intel_plane *intel_plane = to_intel_plane(plane);
1070 	struct intel_crtc *intel_crtc;
1071 
1072 	if (!plane->fb)
1073 		return 0;
1074 
1075 	if (WARN_ON(!plane->crtc))
1076 		return -EINVAL;
1077 
1078 	intel_crtc = to_intel_crtc(plane->crtc);
1079 
1080 	if (intel_crtc->active) {
1081 		bool primary_was_enabled = intel_crtc->primary_enabled;
1082 
1083 		intel_crtc->primary_enabled = true;
1084 
1085 		intel_plane->disable_plane(plane, plane->crtc);
1086 
1087 		if (!primary_was_enabled && intel_crtc->primary_enabled)
1088 			intel_post_enable_primary(plane->crtc);
1089 	}
1090 
1091 	if (intel_plane->obj) {
1092 		if (intel_crtc->active)
1093 			intel_wait_for_vblank(dev, intel_plane->pipe);
1094 
1095 		mutex_lock(&dev->struct_mutex);
1096 		intel_unpin_fb_obj(intel_plane->obj);
1097 		mutex_unlock(&dev->struct_mutex);
1098 
1099 		intel_plane->obj = NULL;
1100 	}
1101 
1102 	return 0;
1103 }
1104 
1105 static void intel_destroy_plane(struct drm_plane *plane)
1106 {
1107 	struct intel_plane *intel_plane = to_intel_plane(plane);
1108 	intel_disable_plane(plane);
1109 	drm_plane_cleanup(plane);
1110 	kfree(intel_plane);
1111 }
1112 
1113 int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
1114 			      struct drm_file *file_priv)
1115 {
1116 	struct drm_intel_sprite_colorkey *set = data;
1117 	struct drm_mode_object *obj;
1118 	struct drm_plane *plane;
1119 	struct intel_plane *intel_plane;
1120 	int ret = 0;
1121 
1122 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1123 		return -ENODEV;
1124 
1125 	/* Make sure we don't try to enable both src & dest simultaneously */
1126 	if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1127 		return -EINVAL;
1128 
1129 	drm_modeset_lock_all(dev);
1130 
1131 	obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
1132 	if (!obj) {
1133 		ret = -ENOENT;
1134 		goto out_unlock;
1135 	}
1136 
1137 	plane = obj_to_plane(obj);
1138 	intel_plane = to_intel_plane(plane);
1139 	ret = intel_plane->update_colorkey(plane, set);
1140 
1141 out_unlock:
1142 	drm_modeset_unlock_all(dev);
1143 	return ret;
1144 }
1145 
1146 int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
1147 			      struct drm_file *file_priv)
1148 {
1149 	struct drm_intel_sprite_colorkey *get = data;
1150 	struct drm_mode_object *obj;
1151 	struct drm_plane *plane;
1152 	struct intel_plane *intel_plane;
1153 	int ret = 0;
1154 
1155 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1156 		return -ENODEV;
1157 
1158 	drm_modeset_lock_all(dev);
1159 
1160 	obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
1161 	if (!obj) {
1162 		ret = -ENOENT;
1163 		goto out_unlock;
1164 	}
1165 
1166 	plane = obj_to_plane(obj);
1167 	intel_plane = to_intel_plane(plane);
1168 	intel_plane->get_colorkey(plane, get);
1169 
1170 out_unlock:
1171 	drm_modeset_unlock_all(dev);
1172 	return ret;
1173 }
1174 
1175 void intel_plane_restore(struct drm_plane *plane)
1176 {
1177 	struct intel_plane *intel_plane = to_intel_plane(plane);
1178 
1179 	if (!plane->crtc || !plane->fb)
1180 		return;
1181 
1182 	intel_update_plane(plane, plane->crtc, plane->fb,
1183 			   intel_plane->crtc_x, intel_plane->crtc_y,
1184 			   intel_plane->crtc_w, intel_plane->crtc_h,
1185 			   intel_plane->src_x, intel_plane->src_y,
1186 			   intel_plane->src_w, intel_plane->src_h);
1187 }
1188 
1189 void intel_plane_disable(struct drm_plane *plane)
1190 {
1191 	if (!plane->crtc || !plane->fb)
1192 		return;
1193 
1194 	intel_disable_plane(plane);
1195 }
1196 
1197 static const struct drm_plane_funcs intel_plane_funcs = {
1198 	.update_plane = intel_update_plane,
1199 	.disable_plane = intel_disable_plane,
1200 	.destroy = intel_destroy_plane,
1201 };
1202 
1203 static uint32_t ilk_plane_formats[] = {
1204 	DRM_FORMAT_XRGB8888,
1205 	DRM_FORMAT_YUYV,
1206 	DRM_FORMAT_YVYU,
1207 	DRM_FORMAT_UYVY,
1208 	DRM_FORMAT_VYUY,
1209 };
1210 
1211 static uint32_t snb_plane_formats[] = {
1212 	DRM_FORMAT_XBGR8888,
1213 	DRM_FORMAT_XRGB8888,
1214 	DRM_FORMAT_YUYV,
1215 	DRM_FORMAT_YVYU,
1216 	DRM_FORMAT_UYVY,
1217 	DRM_FORMAT_VYUY,
1218 };
1219 
1220 static uint32_t vlv_plane_formats[] = {
1221 	DRM_FORMAT_RGB565,
1222 	DRM_FORMAT_ABGR8888,
1223 	DRM_FORMAT_ARGB8888,
1224 	DRM_FORMAT_XBGR8888,
1225 	DRM_FORMAT_XRGB8888,
1226 	DRM_FORMAT_XBGR2101010,
1227 	DRM_FORMAT_ABGR2101010,
1228 	DRM_FORMAT_YUYV,
1229 	DRM_FORMAT_YVYU,
1230 	DRM_FORMAT_UYVY,
1231 	DRM_FORMAT_VYUY,
1232 };
1233 
1234 int
1235 intel_plane_init(struct drm_device *dev, enum i915_pipe pipe, int plane)
1236 {
1237 	struct intel_plane *intel_plane;
1238 	unsigned long possible_crtcs;
1239 	const uint32_t *plane_formats;
1240 	int num_plane_formats;
1241 	int ret;
1242 
1243 	if (INTEL_INFO(dev)->gen < 5)
1244 		return -ENODEV;
1245 
1246 	intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
1247 	if (!intel_plane)
1248 		return -ENOMEM;
1249 
1250 	switch (INTEL_INFO(dev)->gen) {
1251 	case 5:
1252 	case 6:
1253 		intel_plane->can_scale = true;
1254 		intel_plane->max_downscale = 16;
1255 		intel_plane->update_plane = ilk_update_plane;
1256 		intel_plane->disable_plane = ilk_disable_plane;
1257 		intel_plane->update_colorkey = ilk_update_colorkey;
1258 		intel_plane->get_colorkey = ilk_get_colorkey;
1259 
1260 		if (IS_GEN6(dev)) {
1261 			plane_formats = snb_plane_formats;
1262 			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1263 		} else {
1264 			plane_formats = ilk_plane_formats;
1265 			num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
1266 		}
1267 		break;
1268 
1269 	case 7:
1270 	case 8:
1271 		if (IS_IVYBRIDGE(dev)) {
1272 			intel_plane->can_scale = true;
1273 			intel_plane->max_downscale = 2;
1274 		} else {
1275 			intel_plane->can_scale = false;
1276 			intel_plane->max_downscale = 1;
1277 		}
1278 
1279 		if (IS_VALLEYVIEW(dev)) {
1280 			intel_plane->update_plane = vlv_update_plane;
1281 			intel_plane->disable_plane = vlv_disable_plane;
1282 			intel_plane->update_colorkey = vlv_update_colorkey;
1283 			intel_plane->get_colorkey = vlv_get_colorkey;
1284 
1285 			plane_formats = vlv_plane_formats;
1286 			num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
1287 		} else {
1288 			intel_plane->update_plane = ivb_update_plane;
1289 			intel_plane->disable_plane = ivb_disable_plane;
1290 			intel_plane->update_colorkey = ivb_update_colorkey;
1291 			intel_plane->get_colorkey = ivb_get_colorkey;
1292 
1293 			plane_formats = snb_plane_formats;
1294 			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1295 		}
1296 		break;
1297 
1298 	default:
1299 		kfree(intel_plane);
1300 		return -ENODEV;
1301 	}
1302 
1303 	intel_plane->pipe = pipe;
1304 	intel_plane->plane = plane;
1305 	possible_crtcs = (1 << pipe);
1306 	ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
1307 			     &intel_plane_funcs,
1308 			     plane_formats, num_plane_formats,
1309 			     false);
1310 	if (ret)
1311 		kfree(intel_plane);
1312 
1313 	return ret;
1314 }
1315