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