Subversion Repositories Kolibri OS

Rev

Rev 5060 | Rev 6084 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2342 Serge 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 
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
 */
3031 serge 32
#include 
33
#include 
34
#include 
4104 Serge 35
#include 
2342 Serge 36
#include "intel_drv.h"
3031 serge 37
#include 
2342 Serge 38
#include "i915_drv.h"
39
 
5354 serge 40
static bool
41
format_is_yuv(uint32_t format)
42
{
43
	switch (format) {
44
	case DRM_FORMAT_YUYV:
45
	case DRM_FORMAT_UYVY:
46
	case DRM_FORMAT_VYUY:
47
	case DRM_FORMAT_YVYU:
48
		return true;
49
	default:
50
		return false;
51
	}
52
}
53
 
5060 serge 54
static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs)
55
{
56
	/* paranoia */
57
	if (!mode->crtc_htotal)
58
		return 1;
59
 
60
	return DIV_ROUND_UP(usecs * mode->crtc_clock, 1000 * mode->crtc_htotal);
61
}
62
 
5354 serge 63
/**
64
 * intel_pipe_update_start() - start update of a set of display registers
65
 * @crtc: the crtc of which the registers are going to be updated
66
 * @start_vbl_count: vblank counter return pointer used for error checking
67
 *
68
 * Mark the start of an update to pipe registers that should be updated
69
 * atomically regarding vblank. If the next vblank will happens within
70
 * the next 100 us, this function waits until the vblank passes.
71
 *
72
 * After a successful call to this function, interrupts will be disabled
73
 * until a subsequent call to intel_pipe_update_end(). That is done to
74
 * avoid random delays. The value written to @start_vbl_count should be
75
 * supplied to intel_pipe_update_end() for error checking.
76
 *
77
 * Return: true if the call was successful
78
 */
79
bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count)
5060 serge 80
{
81
	struct drm_device *dev = crtc->base.dev;
82
	const struct drm_display_mode *mode = &crtc->config.adjusted_mode;
83
	enum pipe pipe = crtc->pipe;
84
	long timeout = msecs_to_jiffies_timeout(1);
85
	int scanline, min, max, vblank_start;
5354 serge 86
	wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
5060 serge 87
	DEFINE_WAIT(wait);
88
 
89
	vblank_start = mode->crtc_vblank_start;
90
	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
91
		vblank_start = DIV_ROUND_UP(vblank_start, 2);
92
 
93
	/* FIXME needs to be calibrated sensibly */
94
	min = vblank_start - usecs_to_scanlines(mode, 100);
95
	max = vblank_start - 1;
96
 
97
	if (min <= 0 || max <= 0)
98
		return false;
99
 
100
//   if (WARN_ON(drm_vblank_get(dev, pipe)))
101
//       return false;
102
 
103
//   local_irq_disable();
104
 
105
//   trace_i915_pipe_update_start(crtc, min, max);
106
 
107
	for (;;) {
108
		/*
109
		 * prepare_to_wait() has a memory barrier, which guarantees
110
		 * other CPUs can see the task state update by the time we
111
		 * read the scanline.
112
		 */
5354 serge 113
		prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
5060 serge 114
 
115
		scanline = intel_get_crtc_scanline(crtc);
116
		if (scanline < min || scanline > max)
117
			break;
118
 
119
		if (timeout <= 0) {
120
			DRM_ERROR("Potential atomic update failure on pipe %c\n",
121
				  pipe_name(crtc->pipe));
122
			break;
123
		}
124
 
125
//       local_irq_enable();
126
 
127
        schedule_timeout(timeout);
128
        timeout = 0;
129
//       local_irq_disable();
130
	}
131
 
5354 serge 132
	finish_wait(wq, &wait);
5060 serge 133
 
134
//   drm_vblank_put(dev, pipe);
135
 
136
	*start_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
137
 
138
//   trace_i915_pipe_update_vblank_evaded(crtc, min, max, *start_vbl_count);
139
 
140
	return true;
141
}
142
 
5354 serge 143
/**
144
 * intel_pipe_update_end() - end update of a set of display registers
145
 * @crtc: the crtc of which the registers were updated
146
 * @start_vbl_count: start vblank counter (used for error checking)
147
 *
148
 * Mark the end of an update started with intel_pipe_update_start(). This
149
 * re-enables interrupts and verifies the update was actually completed
150
 * before a vblank using the value of @start_vbl_count.
151
 */
152
void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count)
5060 serge 153
{
154
	struct drm_device *dev = crtc->base.dev;
155
	enum pipe pipe = crtc->pipe;
156
	u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
157
 
158
//   trace_i915_pipe_update_end(crtc, end_vbl_count);
159
 
160
//   local_irq_enable();
161
 
162
	if (start_vbl_count != end_vbl_count)
163
		DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u)\n",
164
			  pipe_name(pipe), start_vbl_count, end_vbl_count);
165
}
166
 
167
static void intel_update_primary_plane(struct intel_crtc *crtc)
168
{
169
	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
170
	int reg = DSPCNTR(crtc->plane);
171
 
172
	if (crtc->primary_enabled)
173
		I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
174
	else
175
		I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
176
}
177
 
2342 Serge 178
static void
5354 serge 179
skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
180
		 struct drm_framebuffer *fb,
181
		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
182
		 unsigned int crtc_w, unsigned int crtc_h,
183
		 uint32_t x, uint32_t y,
184
		 uint32_t src_w, uint32_t src_h)
185
{
186
	struct drm_device *dev = drm_plane->dev;
187
	struct drm_i915_private *dev_priv = dev->dev_private;
188
	struct intel_plane *intel_plane = to_intel_plane(drm_plane);
189
	const int pipe = intel_plane->pipe;
190
	const int plane = intel_plane->plane + 1;
191
	u32 plane_ctl, stride;
192
	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
193
 
194
	plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
195
 
196
	/* Mask out pixel format bits in case we change it */
197
	plane_ctl &= ~PLANE_CTL_FORMAT_MASK;
198
	plane_ctl &= ~PLANE_CTL_ORDER_RGBX;
199
	plane_ctl &= ~PLANE_CTL_YUV422_ORDER_MASK;
200
	plane_ctl &= ~PLANE_CTL_TILED_MASK;
201
	plane_ctl &= ~PLANE_CTL_ALPHA_MASK;
202
	plane_ctl &= ~PLANE_CTL_ROTATE_MASK;
203
 
204
	/* Trickle feed has to be enabled */
205
	plane_ctl &= ~PLANE_CTL_TRICKLE_FEED_DISABLE;
206
 
207
	switch (fb->pixel_format) {
208
	case DRM_FORMAT_RGB565:
209
		plane_ctl |= PLANE_CTL_FORMAT_RGB_565;
210
		break;
211
	case DRM_FORMAT_XBGR8888:
212
		plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
213
		break;
214
	case DRM_FORMAT_XRGB8888:
215
		plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888;
216
		break;
217
	/*
218
	 * XXX: For ARBG/ABGR formats we default to expecting scanout buffers
219
	 * to be already pre-multiplied. We need to add a knob (or a different
220
	 * DRM_FORMAT) for user-space to configure that.
221
	 */
222
	case DRM_FORMAT_ABGR8888:
223
		plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888 |
224
			     PLANE_CTL_ORDER_RGBX |
225
			     PLANE_CTL_ALPHA_SW_PREMULTIPLY;
226
		break;
227
	case DRM_FORMAT_ARGB8888:
228
		plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888 |
229
			     PLANE_CTL_ALPHA_SW_PREMULTIPLY;
230
		break;
231
	case DRM_FORMAT_YUYV:
232
		plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV;
233
		break;
234
	case DRM_FORMAT_YVYU:
235
		plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YVYU;
236
		break;
237
	case DRM_FORMAT_UYVY:
238
		plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY;
239
		break;
240
	case DRM_FORMAT_VYUY:
241
		plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
242
		break;
243
	default:
244
		BUG();
245
	}
246
 
247
	switch (obj->tiling_mode) {
248
	case I915_TILING_NONE:
249
		stride = fb->pitches[0] >> 6;
250
		break;
251
	case I915_TILING_X:
252
		plane_ctl |= PLANE_CTL_TILED_X;
253
		stride = fb->pitches[0] >> 9;
254
		break;
255
	default:
256
		BUG();
257
	}
258
	if (intel_plane->rotation == BIT(DRM_ROTATE_180))
259
		plane_ctl |= PLANE_CTL_ROTATE_180;
260
 
261
	plane_ctl |= PLANE_CTL_ENABLE;
262
	plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
263
 
264
	intel_update_sprite_watermarks(drm_plane, crtc, src_w, src_h,
265
				       pixel_size, true,
266
				       src_w != crtc_w || src_h != crtc_h);
267
 
268
	/* Sizes are 0 based */
269
	src_w--;
270
	src_h--;
271
	crtc_w--;
272
	crtc_h--;
273
 
274
	I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
275
	I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
276
	I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x);
277
	I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w);
278
	I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
279
	I915_WRITE(PLANE_SURF(pipe, plane), i915_gem_obj_ggtt_offset(obj));
280
	POSTING_READ(PLANE_SURF(pipe, plane));
281
}
282
 
283
static void
284
skl_disable_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc)
285
{
286
	struct drm_device *dev = drm_plane->dev;
287
	struct drm_i915_private *dev_priv = dev->dev_private;
288
	struct intel_plane *intel_plane = to_intel_plane(drm_plane);
289
	const int pipe = intel_plane->pipe;
290
	const int plane = intel_plane->plane + 1;
291
 
292
	I915_WRITE(PLANE_CTL(pipe, plane),
293
		   I915_READ(PLANE_CTL(pipe, plane)) & ~PLANE_CTL_ENABLE);
294
 
295
	/* Activate double buffered register update */
296
	I915_WRITE(PLANE_CTL(pipe, plane), 0);
297
	POSTING_READ(PLANE_CTL(pipe, plane));
298
 
299
	intel_update_sprite_watermarks(drm_plane, crtc, 0, 0, 0, false, false);
300
}
301
 
302
static int
303
skl_update_colorkey(struct drm_plane *drm_plane,
304
		    struct drm_intel_sprite_colorkey *key)
305
{
306
	struct drm_device *dev = drm_plane->dev;
307
	struct drm_i915_private *dev_priv = dev->dev_private;
308
	struct intel_plane *intel_plane = to_intel_plane(drm_plane);
309
	const int pipe = intel_plane->pipe;
310
	const int plane = intel_plane->plane;
311
	u32 plane_ctl;
312
 
313
	I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
314
	I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
315
	I915_WRITE(PLANE_KEYMSK(pipe, plane), key->channel_mask);
316
 
317
	plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
318
	plane_ctl &= ~PLANE_CTL_KEY_ENABLE_MASK;
319
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
320
		plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
321
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
322
		plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
323
	I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
324
 
325
	POSTING_READ(PLANE_CTL(pipe, plane));
326
 
327
	return 0;
328
}
329
 
330
static void
331
skl_get_colorkey(struct drm_plane *drm_plane,
332
		 struct drm_intel_sprite_colorkey *key)
333
{
334
	struct drm_device *dev = drm_plane->dev;
335
	struct drm_i915_private *dev_priv = dev->dev_private;
336
	struct intel_plane *intel_plane = to_intel_plane(drm_plane);
337
	const int pipe = intel_plane->pipe;
338
	const int plane = intel_plane->plane;
339
	u32 plane_ctl;
340
 
341
	key->min_value = I915_READ(PLANE_KEYVAL(pipe, plane));
342
	key->max_value = I915_READ(PLANE_KEYMAX(pipe, plane));
343
	key->channel_mask = I915_READ(PLANE_KEYMSK(pipe, plane));
344
 
345
	plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
346
 
347
	switch (plane_ctl & PLANE_CTL_KEY_ENABLE_MASK) {
348
	case PLANE_CTL_KEY_ENABLE_DESTINATION:
349
		key->flags = I915_SET_COLORKEY_DESTINATION;
350
		break;
351
	case PLANE_CTL_KEY_ENABLE_SOURCE:
352
		key->flags = I915_SET_COLORKEY_SOURCE;
353
		break;
354
	default:
355
		key->flags = I915_SET_COLORKEY_NONE;
356
	}
357
}
358
 
359
static void
360
chv_update_csc(struct intel_plane *intel_plane, uint32_t format)
361
{
362
	struct drm_i915_private *dev_priv = intel_plane->base.dev->dev_private;
363
	int plane = intel_plane->plane;
364
 
365
	/* Seems RGB data bypasses the CSC always */
366
	if (!format_is_yuv(format))
367
		return;
368
 
369
	/*
370
	 * BT.601 limited range YCbCr -> full range RGB
371
	 *
372
	 * |r|   | 6537 4769     0|   |cr  |
373
	 * |g| = |-3330 4769 -1605| x |y-64|
374
	 * |b|   |    0 4769  8263|   |cb  |
375
	 *
376
	 * Cb and Cr apparently come in as signed already, so no
377
	 * need for any offset. For Y we need to remove the offset.
378
	 */
379
	I915_WRITE(SPCSCYGOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(-64));
380
	I915_WRITE(SPCSCCBOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
381
	I915_WRITE(SPCSCCROFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
382
 
383
	I915_WRITE(SPCSCC01(plane), SPCSC_C1(4769) | SPCSC_C0(6537));
384
	I915_WRITE(SPCSCC23(plane), SPCSC_C1(-3330) | SPCSC_C0(0));
385
	I915_WRITE(SPCSCC45(plane), SPCSC_C1(-1605) | SPCSC_C0(4769));
386
	I915_WRITE(SPCSCC67(plane), SPCSC_C1(4769) | SPCSC_C0(0));
387
	I915_WRITE(SPCSCC8(plane), SPCSC_C0(8263));
388
 
389
	I915_WRITE(SPCSCYGICLAMP(plane), SPCSC_IMAX(940) | SPCSC_IMIN(64));
390
	I915_WRITE(SPCSCCBICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
391
	I915_WRITE(SPCSCCRICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
392
 
393
	I915_WRITE(SPCSCYGOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
394
	I915_WRITE(SPCSCCBOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
395
	I915_WRITE(SPCSCCROCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
396
}
397
 
398
static void
4104 Serge 399
vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
400
		 struct drm_framebuffer *fb,
3746 Serge 401
		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
402
		 unsigned int crtc_w, unsigned int crtc_h,
403
		 uint32_t x, uint32_t y,
404
		 uint32_t src_w, uint32_t src_h)
405
{
406
	struct drm_device *dev = dplane->dev;
407
	struct drm_i915_private *dev_priv = dev->dev_private;
408
	struct intel_plane *intel_plane = to_intel_plane(dplane);
5060 serge 409
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
3746 Serge 410
	int pipe = intel_plane->pipe;
411
	int plane = intel_plane->plane;
412
	u32 sprctl;
413
	unsigned long sprsurf_offset, linear_offset;
414
	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
5060 serge 415
	u32 start_vbl_count;
416
	bool atomic_update;
3746 Serge 417
 
418
	sprctl = I915_READ(SPCNTR(pipe, plane));
419
 
420
	/* Mask out pixel format bits in case we change it */
421
	sprctl &= ~SP_PIXFORMAT_MASK;
422
	sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
423
	sprctl &= ~SP_TILED;
5354 serge 424
	sprctl &= ~SP_ROTATE_180;
3746 Serge 425
 
426
	switch (fb->pixel_format) {
427
	case DRM_FORMAT_YUYV:
428
		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
429
		break;
430
	case DRM_FORMAT_YVYU:
431
		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
432
		break;
433
	case DRM_FORMAT_UYVY:
434
		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
435
		break;
436
	case DRM_FORMAT_VYUY:
437
		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
438
		break;
439
	case DRM_FORMAT_RGB565:
440
		sprctl |= SP_FORMAT_BGR565;
441
		break;
442
	case DRM_FORMAT_XRGB8888:
443
		sprctl |= SP_FORMAT_BGRX8888;
444
		break;
445
	case DRM_FORMAT_ARGB8888:
446
		sprctl |= SP_FORMAT_BGRA8888;
447
		break;
448
	case DRM_FORMAT_XBGR2101010:
449
		sprctl |= SP_FORMAT_RGBX1010102;
450
		break;
451
	case DRM_FORMAT_ABGR2101010:
452
		sprctl |= SP_FORMAT_RGBA1010102;
453
		break;
454
	case DRM_FORMAT_XBGR8888:
455
		sprctl |= SP_FORMAT_RGBX8888;
456
		break;
457
	case DRM_FORMAT_ABGR8888:
458
		sprctl |= SP_FORMAT_RGBA8888;
459
		break;
460
	default:
461
		/*
462
		 * If we get here one of the upper layers failed to filter
463
		 * out the unsupported plane formats
464
		 */
465
		BUG();
466
		break;
467
	}
468
 
4560 Serge 469
	/*
470
	 * Enable gamma to match primary/cursor plane behaviour.
471
	 * FIXME should be user controllable via propertiesa.
472
	 */
473
	sprctl |= SP_GAMMA_ENABLE;
474
 
3746 Serge 475
	if (obj->tiling_mode != I915_TILING_NONE)
476
		sprctl |= SP_TILED;
477
 
478
	sprctl |= SP_ENABLE;
479
 
5060 serge 480
	intel_update_sprite_watermarks(dplane, crtc, src_w, src_h,
481
				       pixel_size, true,
4104 Serge 482
				       src_w != crtc_w || src_h != crtc_h);
483
 
3746 Serge 484
	/* Sizes are 0 based */
485
	src_w--;
486
	src_h--;
487
	crtc_w--;
488
	crtc_h--;
489
 
490
	linear_offset = y * fb->pitches[0] + x * pixel_size;
491
	sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
492
							obj->tiling_mode,
493
							pixel_size,
494
							fb->pitches[0]);
495
	linear_offset -= sprsurf_offset;
496
 
5354 serge 497
	if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
498
		sprctl |= SP_ROTATE_180;
499
 
500
		x += src_w;
501
		y += src_h;
502
		linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
503
	}
504
 
5060 serge 505
	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
506
 
507
	intel_update_primary_plane(intel_crtc);
508
 
5354 serge 509
	if (IS_CHERRYVIEW(dev) && pipe == PIPE_B)
510
		chv_update_csc(intel_plane, fb->pixel_format);
511
 
5060 serge 512
	I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
513
	I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
514
 
3746 Serge 515
	if (obj->tiling_mode != I915_TILING_NONE)
516
		I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
517
	else
518
		I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
519
 
5354 serge 520
	I915_WRITE(SPCONSTALPHA(pipe, plane), 0);
521
 
3746 Serge 522
	I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
523
	I915_WRITE(SPCNTR(pipe, plane), sprctl);
4560 Serge 524
	I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
3746 Serge 525
			     sprsurf_offset);
5060 serge 526
 
527
	intel_flush_primary_plane(dev_priv, intel_crtc->plane);
528
 
529
	if (atomic_update)
530
		intel_pipe_update_end(intel_crtc, start_vbl_count);
3746 Serge 531
}
532
 
533
static void
4104 Serge 534
vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
3746 Serge 535
{
536
	struct drm_device *dev = dplane->dev;
537
	struct drm_i915_private *dev_priv = dev->dev_private;
538
	struct intel_plane *intel_plane = to_intel_plane(dplane);
5060 serge 539
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
3746 Serge 540
	int pipe = intel_plane->pipe;
541
	int plane = intel_plane->plane;
5060 serge 542
	u32 start_vbl_count;
543
	bool atomic_update;
3746 Serge 544
 
5060 serge 545
	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
546
 
547
	intel_update_primary_plane(intel_crtc);
548
 
3746 Serge 549
	I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
550
		   ~SP_ENABLE);
551
	/* Activate double buffered register update */
4560 Serge 552
	I915_WRITE(SPSURF(pipe, plane), 0);
4104 Serge 553
 
5060 serge 554
	intel_flush_primary_plane(dev_priv, intel_crtc->plane);
555
 
556
	if (atomic_update)
557
		intel_pipe_update_end(intel_crtc, start_vbl_count);
558
 
559
	intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false);
3746 Serge 560
}
561
 
562
static int
563
vlv_update_colorkey(struct drm_plane *dplane,
564
		    struct drm_intel_sprite_colorkey *key)
565
{
566
	struct drm_device *dev = dplane->dev;
567
	struct drm_i915_private *dev_priv = dev->dev_private;
568
	struct intel_plane *intel_plane = to_intel_plane(dplane);
569
	int pipe = intel_plane->pipe;
570
	int plane = intel_plane->plane;
571
	u32 sprctl;
572
 
573
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
574
		return -EINVAL;
575
 
576
	I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
577
	I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
578
	I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask);
579
 
580
	sprctl = I915_READ(SPCNTR(pipe, plane));
581
	sprctl &= ~SP_SOURCE_KEY;
582
	if (key->flags & I915_SET_COLORKEY_SOURCE)
583
		sprctl |= SP_SOURCE_KEY;
584
	I915_WRITE(SPCNTR(pipe, plane), sprctl);
585
 
586
	POSTING_READ(SPKEYMSK(pipe, plane));
587
 
588
	return 0;
589
}
590
 
591
static void
592
vlv_get_colorkey(struct drm_plane *dplane,
593
		 struct drm_intel_sprite_colorkey *key)
594
{
595
	struct drm_device *dev = dplane->dev;
596
	struct drm_i915_private *dev_priv = dev->dev_private;
597
	struct intel_plane *intel_plane = to_intel_plane(dplane);
598
	int pipe = intel_plane->pipe;
599
	int plane = intel_plane->plane;
600
	u32 sprctl;
601
 
602
	key->min_value = I915_READ(SPKEYMINVAL(pipe, plane));
603
	key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane));
604
	key->channel_mask = I915_READ(SPKEYMSK(pipe, plane));
605
 
606
	sprctl = I915_READ(SPCNTR(pipe, plane));
607
	if (sprctl & SP_SOURCE_KEY)
608
		key->flags = I915_SET_COLORKEY_SOURCE;
609
	else
610
		key->flags = I915_SET_COLORKEY_NONE;
611
}
612
 
613
static void
4104 Serge 614
ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
615
		 struct drm_framebuffer *fb,
2342 Serge 616
		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
617
		 unsigned int crtc_w, unsigned int crtc_h,
618
		 uint32_t x, uint32_t y,
619
		 uint32_t src_w, uint32_t src_h)
620
{
621
	struct drm_device *dev = plane->dev;
622
	struct drm_i915_private *dev_priv = dev->dev_private;
623
	struct intel_plane *intel_plane = to_intel_plane(plane);
5060 serge 624
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
2342 Serge 625
	int pipe = intel_plane->pipe;
626
	u32 sprctl, sprscale = 0;
3243 Serge 627
	unsigned long sprsurf_offset, linear_offset;
628
	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
5060 serge 629
	u32 start_vbl_count;
630
	bool atomic_update;
2342 Serge 631
 
632
	sprctl = I915_READ(SPRCTL(pipe));
633
 
634
	/* Mask out pixel format bits in case we change it */
635
	sprctl &= ~SPRITE_PIXFORMAT_MASK;
636
	sprctl &= ~SPRITE_RGB_ORDER_RGBX;
637
	sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
3031 serge 638
	sprctl &= ~SPRITE_TILED;
5354 serge 639
	sprctl &= ~SPRITE_ROTATE_180;
2342 Serge 640
 
641
	switch (fb->pixel_format) {
642
	case DRM_FORMAT_XBGR8888:
3031 serge 643
		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
2342 Serge 644
		break;
645
	case DRM_FORMAT_XRGB8888:
3031 serge 646
		sprctl |= SPRITE_FORMAT_RGBX888;
2342 Serge 647
		break;
648
	case DRM_FORMAT_YUYV:
649
		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
650
		break;
651
	case DRM_FORMAT_YVYU:
652
		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
653
		break;
654
	case DRM_FORMAT_UYVY:
655
		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
656
		break;
657
	case DRM_FORMAT_VYUY:
658
		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
659
		break;
660
	default:
3243 Serge 661
		BUG();
2342 Serge 662
	}
663
 
4560 Serge 664
	/*
665
	 * Enable gamma to match primary/cursor plane behaviour.
666
	 * FIXME should be user controllable via propertiesa.
667
	 */
668
	sprctl |= SPRITE_GAMMA_ENABLE;
669
 
2342 Serge 670
	if (obj->tiling_mode != I915_TILING_NONE)
671
		sprctl |= SPRITE_TILED;
672
 
4560 Serge 673
	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
4104 Serge 674
		sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
675
	else
2342 Serge 676
	sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
4104 Serge 677
 
2342 Serge 678
	sprctl |= SPRITE_ENABLE;
679
 
4560 Serge 680
	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
3480 Serge 681
		sprctl |= SPRITE_PIPE_CSC_ENABLE;
682
 
5060 serge 683
	intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size,
684
				       true,
4104 Serge 685
				       src_w != crtc_w || src_h != crtc_h);
686
 
2342 Serge 687
	/* Sizes are 0 based */
688
	src_w--;
689
	src_h--;
690
	crtc_w--;
691
	crtc_h--;
692
 
4560 Serge 693
	if (crtc_w != src_w || crtc_h != src_h)
2342 Serge 694
		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
695
 
3243 Serge 696
	linear_offset = y * fb->pitches[0] + x * pixel_size;
697
	sprsurf_offset =
3480 Serge 698
		intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
3243 Serge 699
						 pixel_size, fb->pitches[0]);
700
	linear_offset -= sprsurf_offset;
701
 
5354 serge 702
	if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
703
		sprctl |= SPRITE_ROTATE_180;
704
 
705
		/* HSW and BDW does this automagically in hardware */
706
		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
707
			x += src_w;
708
			y += src_h;
709
			linear_offset += src_h * fb->pitches[0] +
710
				src_w * pixel_size;
711
		}
712
	}
713
 
5060 serge 714
	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
715
 
716
	intel_update_primary_plane(intel_crtc);
717
 
718
	I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
719
	I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
720
 
3243 Serge 721
	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
722
	 * register */
4560 Serge 723
	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
3243 Serge 724
		I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
725
	else if (obj->tiling_mode != I915_TILING_NONE)
2342 Serge 726
		I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
3243 Serge 727
	else
728
		I915_WRITE(SPRLINOFF(pipe), linear_offset);
2342 Serge 729
 
730
	I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
3243 Serge 731
	if (intel_plane->can_scale)
2342 Serge 732
	I915_WRITE(SPRSCALE(pipe), sprscale);
733
	I915_WRITE(SPRCTL(pipe), sprctl);
4560 Serge 734
	I915_WRITE(SPRSURF(pipe),
4104 Serge 735
			     i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
5060 serge 736
 
737
	intel_flush_primary_plane(dev_priv, intel_crtc->plane);
738
 
739
	if (atomic_update)
740
		intel_pipe_update_end(intel_crtc, start_vbl_count);
2342 Serge 741
}
742
 
743
static void
4104 Serge 744
ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
2342 Serge 745
{
746
	struct drm_device *dev = plane->dev;
747
	struct drm_i915_private *dev_priv = dev->dev_private;
748
	struct intel_plane *intel_plane = to_intel_plane(plane);
5060 serge 749
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
2342 Serge 750
	int pipe = intel_plane->pipe;
5060 serge 751
	u32 start_vbl_count;
752
	bool atomic_update;
2342 Serge 753
 
5060 serge 754
	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
755
 
756
	intel_update_primary_plane(intel_crtc);
757
 
2342 Serge 758
	I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
759
	/* Can't leave the scaler enabled... */
3243 Serge 760
	if (intel_plane->can_scale)
2342 Serge 761
	I915_WRITE(SPRSCALE(pipe), 0);
762
	/* Activate double buffered register update */
4560 Serge 763
	I915_WRITE(SPRSURF(pipe), 0);
3031 serge 764
 
5060 serge 765
	intel_flush_primary_plane(dev_priv, intel_crtc->plane);
766
 
767
	if (atomic_update)
768
		intel_pipe_update_end(intel_crtc, start_vbl_count);
769
 
4560 Serge 770
	/*
771
	 * Avoid underruns when disabling the sprite.
772
	 * FIXME remove once watermark updates are done properly.
773
	 */
774
	intel_wait_for_vblank(dev, pipe);
3480 Serge 775
 
5060 serge 776
	intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
2342 Serge 777
}
778
 
779
static int
780
ivb_update_colorkey(struct drm_plane *plane,
781
		    struct drm_intel_sprite_colorkey *key)
782
{
783
	struct drm_device *dev = plane->dev;
784
	struct drm_i915_private *dev_priv = dev->dev_private;
785
	struct intel_plane *intel_plane;
786
	u32 sprctl;
787
	int ret = 0;
788
 
789
	intel_plane = to_intel_plane(plane);
790
 
791
	I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
792
	I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
793
	I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
794
 
795
	sprctl = I915_READ(SPRCTL(intel_plane->pipe));
796
	sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
797
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
798
		sprctl |= SPRITE_DEST_KEY;
799
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
800
		sprctl |= SPRITE_SOURCE_KEY;
801
	I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
802
 
803
	POSTING_READ(SPRKEYMSK(intel_plane->pipe));
804
 
805
	return ret;
806
}
807
 
808
static void
809
ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
810
{
811
	struct drm_device *dev = plane->dev;
812
	struct drm_i915_private *dev_priv = dev->dev_private;
813
	struct intel_plane *intel_plane;
814
	u32 sprctl;
815
 
816
	intel_plane = to_intel_plane(plane);
817
 
818
	key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
819
	key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
820
	key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
821
	key->flags = 0;
822
 
823
	sprctl = I915_READ(SPRCTL(intel_plane->pipe));
824
 
825
	if (sprctl & SPRITE_DEST_KEY)
826
		key->flags = I915_SET_COLORKEY_DESTINATION;
827
	else if (sprctl & SPRITE_SOURCE_KEY)
828
		key->flags = I915_SET_COLORKEY_SOURCE;
829
	else
830
		key->flags = I915_SET_COLORKEY_NONE;
831
}
832
 
833
static void
4104 Serge 834
ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
835
		 struct drm_framebuffer *fb,
2342 Serge 836
		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
837
		 unsigned int crtc_w, unsigned int crtc_h,
838
		 uint32_t x, uint32_t y,
839
		 uint32_t src_w, uint32_t src_h)
840
{
841
	struct drm_device *dev = plane->dev;
842
	struct drm_i915_private *dev_priv = dev->dev_private;
843
	struct intel_plane *intel_plane = to_intel_plane(plane);
5060 serge 844
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
3243 Serge 845
	int pipe = intel_plane->pipe;
846
	unsigned long dvssurf_offset, linear_offset;
3031 serge 847
	u32 dvscntr, dvsscale;
3243 Serge 848
	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
5060 serge 849
	u32 start_vbl_count;
850
	bool atomic_update;
2342 Serge 851
 
852
	dvscntr = I915_READ(DVSCNTR(pipe));
853
 
854
	/* Mask out pixel format bits in case we change it */
855
	dvscntr &= ~DVS_PIXFORMAT_MASK;
3031 serge 856
	dvscntr &= ~DVS_RGB_ORDER_XBGR;
2342 Serge 857
	dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
3031 serge 858
	dvscntr &= ~DVS_TILED;
5354 serge 859
	dvscntr &= ~DVS_ROTATE_180;
2342 Serge 860
 
861
	switch (fb->pixel_format) {
862
	case DRM_FORMAT_XBGR8888:
3031 serge 863
		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
2342 Serge 864
		break;
865
	case DRM_FORMAT_XRGB8888:
3031 serge 866
		dvscntr |= DVS_FORMAT_RGBX888;
2342 Serge 867
		break;
868
	case DRM_FORMAT_YUYV:
869
		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
870
		break;
871
	case DRM_FORMAT_YVYU:
872
		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
873
		break;
874
	case DRM_FORMAT_UYVY:
875
		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
876
		break;
877
	case DRM_FORMAT_VYUY:
878
		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
879
		break;
880
	default:
3243 Serge 881
		BUG();
2342 Serge 882
	}
883
 
4560 Serge 884
	/*
885
	 * Enable gamma to match primary/cursor plane behaviour.
886
	 * FIXME should be user controllable via propertiesa.
887
	 */
888
	dvscntr |= DVS_GAMMA_ENABLE;
889
 
2342 Serge 890
	if (obj->tiling_mode != I915_TILING_NONE)
891
		dvscntr |= DVS_TILED;
892
 
3031 serge 893
	if (IS_GEN6(dev))
894
		dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
2342 Serge 895
	dvscntr |= DVS_ENABLE;
896
 
5060 serge 897
	intel_update_sprite_watermarks(plane, crtc, src_w, src_h,
898
				       pixel_size, true,
4104 Serge 899
				       src_w != crtc_w || src_h != crtc_h);
900
 
2342 Serge 901
	/* Sizes are 0 based */
902
	src_w--;
903
	src_h--;
904
	crtc_w--;
905
	crtc_h--;
906
 
3031 serge 907
	dvsscale = 0;
4560 Serge 908
	if (crtc_w != src_w || crtc_h != src_h)
2342 Serge 909
		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
910
 
3243 Serge 911
	linear_offset = y * fb->pitches[0] + x * pixel_size;
912
	dvssurf_offset =
3480 Serge 913
		intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
3243 Serge 914
						 pixel_size, fb->pitches[0]);
915
	linear_offset -= dvssurf_offset;
916
 
5354 serge 917
	if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
918
		dvscntr |= DVS_ROTATE_180;
919
 
920
		x += src_w;
921
		y += src_h;
922
		linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
923
	}
924
 
5060 serge 925
	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
926
 
927
	intel_update_primary_plane(intel_crtc);
928
 
929
	I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
930
	I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
931
 
3243 Serge 932
	if (obj->tiling_mode != I915_TILING_NONE)
2342 Serge 933
		I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
3243 Serge 934
	else
935
		I915_WRITE(DVSLINOFF(pipe), linear_offset);
2342 Serge 936
 
937
	I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
938
	I915_WRITE(DVSSCALE(pipe), dvsscale);
939
	I915_WRITE(DVSCNTR(pipe), dvscntr);
4560 Serge 940
	I915_WRITE(DVSSURF(pipe),
4104 Serge 941
			     i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
5060 serge 942
 
943
	intel_flush_primary_plane(dev_priv, intel_crtc->plane);
944
 
945
	if (atomic_update)
946
		intel_pipe_update_end(intel_crtc, start_vbl_count);
2342 Serge 947
}
948
 
949
static void
4104 Serge 950
ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
2342 Serge 951
{
952
	struct drm_device *dev = plane->dev;
953
	struct drm_i915_private *dev_priv = dev->dev_private;
954
	struct intel_plane *intel_plane = to_intel_plane(plane);
5060 serge 955
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
2342 Serge 956
	int pipe = intel_plane->pipe;
5060 serge 957
	u32 start_vbl_count;
958
	bool atomic_update;
2342 Serge 959
 
5060 serge 960
	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
961
 
962
	intel_update_primary_plane(intel_crtc);
963
 
2342 Serge 964
	I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
965
	/* Disable the scaler */
966
	I915_WRITE(DVSSCALE(pipe), 0);
967
	/* Flush double buffered register updates */
4560 Serge 968
	I915_WRITE(DVSSURF(pipe), 0);
4104 Serge 969
 
5060 serge 970
	intel_flush_primary_plane(dev_priv, intel_crtc->plane);
971
 
972
	if (atomic_update)
973
		intel_pipe_update_end(intel_crtc, start_vbl_count);
974
 
4560 Serge 975
	/*
976
	 * Avoid underruns when disabling the sprite.
977
	 * FIXME remove once watermark updates are done properly.
978
	 */
979
	intel_wait_for_vblank(dev, pipe);
980
 
5060 serge 981
	intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
2342 Serge 982
}
983
 
984
static void
5060 serge 985
intel_post_enable_primary(struct drm_crtc *crtc)
2342 Serge 986
{
987
	struct drm_device *dev = crtc->dev;
988
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
989
 
4560 Serge 990
	/*
5354 serge 991
	 * BDW signals flip done immediately if the plane
992
	 * is disabled, even if the plane enable is already
993
	 * armed to occur at the next vblank :(
994
	 */
995
	if (IS_BROADWELL(dev))
996
		intel_wait_for_vblank(dev, intel_crtc->pipe);
997
 
998
	/*
4560 Serge 999
	 * FIXME IPS should be fine as long as one plane is
1000
	 * enabled, but in practice it seems to have problems
1001
	 * when going from primary only to sprite only and vice
1002
	 * versa.
1003
	 */
1004
		hsw_enable_ips(intel_crtc);
1005
 
1006
	mutex_lock(&dev->struct_mutex);
1007
	intel_update_fbc(dev);
1008
	mutex_unlock(&dev->struct_mutex);
2342 Serge 1009
}
1010
 
1011
static void
5060 serge 1012
intel_pre_disable_primary(struct drm_crtc *crtc)
2342 Serge 1013
{
1014
	struct drm_device *dev = crtc->dev;
1015
	struct drm_i915_private *dev_priv = dev->dev_private;
1016
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1017
 
4560 Serge 1018
	mutex_lock(&dev->struct_mutex);
1019
	if (dev_priv->fbc.plane == intel_crtc->plane)
1020
		intel_disable_fbc(dev);
1021
	mutex_unlock(&dev->struct_mutex);
1022
 
1023
	/*
1024
	 * FIXME IPS should be fine as long as one plane is
1025
	 * enabled, but in practice it seems to have problems
1026
	 * when going from primary only to sprite only and vice
1027
	 * versa.
1028
	 */
1029
	hsw_disable_ips(intel_crtc);
2342 Serge 1030
}
1031
 
1032
static int
3031 serge 1033
ilk_update_colorkey(struct drm_plane *plane,
2342 Serge 1034
		    struct drm_intel_sprite_colorkey *key)
1035
{
1036
	struct drm_device *dev = plane->dev;
1037
	struct drm_i915_private *dev_priv = dev->dev_private;
1038
	struct intel_plane *intel_plane;
1039
	u32 dvscntr;
1040
	int ret = 0;
1041
 
1042
	intel_plane = to_intel_plane(plane);
1043
 
1044
	I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
1045
	I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
1046
	I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
1047
 
1048
	dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
1049
	dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
1050
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
1051
		dvscntr |= DVS_DEST_KEY;
1052
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
1053
		dvscntr |= DVS_SOURCE_KEY;
1054
	I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
1055
 
1056
	POSTING_READ(DVSKEYMSK(intel_plane->pipe));
1057
 
1058
	return ret;
1059
}
1060
 
1061
static void
3031 serge 1062
ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
2342 Serge 1063
{
1064
	struct drm_device *dev = plane->dev;
1065
	struct drm_i915_private *dev_priv = dev->dev_private;
1066
	struct intel_plane *intel_plane;
1067
	u32 dvscntr;
1068
 
1069
	intel_plane = to_intel_plane(plane);
1070
 
1071
	key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
1072
	key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
1073
	key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
1074
	key->flags = 0;
1075
 
1076
	dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
1077
 
1078
	if (dvscntr & DVS_DEST_KEY)
1079
		key->flags = I915_SET_COLORKEY_DESTINATION;
1080
	else if (dvscntr & DVS_SOURCE_KEY)
1081
		key->flags = I915_SET_COLORKEY_SOURCE;
1082
	else
1083
		key->flags = I915_SET_COLORKEY_NONE;
1084
}
1085
 
4560 Serge 1086
static bool colorkey_enabled(struct intel_plane *intel_plane)
1087
{
1088
	struct drm_intel_sprite_colorkey key;
1089
 
1090
	intel_plane->get_colorkey(&intel_plane->base, &key);
1091
 
1092
	return key.flags != I915_SET_COLORKEY_NONE;
1093
}
1094
 
2342 Serge 1095
static int
5354 serge 1096
intel_check_sprite_plane(struct drm_plane *plane,
1097
			 struct intel_plane_state *state)
2342 Serge 1098
{
5354 serge 1099
	struct intel_crtc *intel_crtc = to_intel_crtc(state->crtc);
2342 Serge 1100
	struct intel_plane *intel_plane = to_intel_plane(plane);
5354 serge 1101
	struct drm_framebuffer *fb = state->fb;
1102
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
1103
	int crtc_x, crtc_y;
1104
	unsigned int crtc_w, crtc_h;
1105
	uint32_t src_x, src_y, src_w, src_h;
1106
	struct drm_rect *src = &state->src;
1107
	struct drm_rect *dst = &state->dst;
1108
	struct drm_rect *orig_src = &state->orig_src;
1109
	const struct drm_rect *clip = &state->clip;
4104 Serge 1110
	int hscale, vscale;
1111
	int max_scale, min_scale;
1112
	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
2342 Serge 1113
 
4104 Serge 1114
	/* Don't modify another pipe's plane */
1115
	if (intel_plane->pipe != intel_crtc->pipe) {
1116
		DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
2342 Serge 1117
		return -EINVAL;
4104 Serge 1118
	}
2342 Serge 1119
 
4104 Serge 1120
	/* FIXME check all gen limits */
1121
	if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) {
1122
		DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
2342 Serge 1123
		return -EINVAL;
4104 Serge 1124
	}
2342 Serge 1125
 
3243 Serge 1126
	/* Sprite planes can be linear or x-tiled surfaces */
1127
	switch (obj->tiling_mode) {
1128
		case I915_TILING_NONE:
1129
		case I915_TILING_X:
1130
			break;
1131
		default:
4104 Serge 1132
			DRM_DEBUG_KMS("Unsupported tiling mode\n");
3243 Serge 1133
			return -EINVAL;
1134
	}
1135
 
2342 Serge 1136
	/*
4104 Serge 1137
	 * FIXME the following code does a bunch of fuzzy adjustments to the
1138
	 * coordinates and sizes. We probably need some way to decide whether
1139
	 * more strict checking should be done instead.
2342 Serge 1140
	 */
4104 Serge 1141
	max_scale = intel_plane->max_downscale << 16;
1142
	min_scale = intel_plane->can_scale ? 1 : (1 << 16);
1143
 
5354 serge 1144
	drm_rect_rotate(src, fb->width << 16, fb->height << 16,
1145
			intel_plane->rotation);
1146
 
1147
	hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale);
4104 Serge 1148
	BUG_ON(hscale < 0);
1149
 
5354 serge 1150
	vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale);
4104 Serge 1151
	BUG_ON(vscale < 0);
1152
 
5354 serge 1153
	state->visible =  drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
4104 Serge 1154
 
5354 serge 1155
	crtc_x = dst->x1;
1156
	crtc_y = dst->y1;
1157
	crtc_w = drm_rect_width(dst);
1158
	crtc_h = drm_rect_height(dst);
4104 Serge 1159
 
5354 serge 1160
	if (state->visible) {
4104 Serge 1161
		/* check again in case clipping clamped the results */
5354 serge 1162
		hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
4104 Serge 1163
		if (hscale < 0) {
1164
			DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
5354 serge 1165
			drm_rect_debug_print(src, true);
1166
			drm_rect_debug_print(dst, false);
4104 Serge 1167
 
1168
			return hscale;
2342 Serge 1169
	}
1170
 
5354 serge 1171
		vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
4104 Serge 1172
		if (vscale < 0) {
1173
			DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
5354 serge 1174
			drm_rect_debug_print(src, true);
1175
			drm_rect_debug_print(dst, false);
4104 Serge 1176
 
1177
			return vscale;
2342 Serge 1178
	}
1179
 
4104 Serge 1180
		/* Make the source viewport size an exact multiple of the scaling factors. */
5354 serge 1181
		drm_rect_adjust_size(src,
1182
				     drm_rect_width(dst) * hscale - drm_rect_width(src),
1183
				     drm_rect_height(dst) * vscale - drm_rect_height(src));
2342 Serge 1184
 
5354 serge 1185
		drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16,
1186
				    intel_plane->rotation);
1187
 
4104 Serge 1188
		/* sanity check to make sure the src viewport wasn't enlarged */
5354 serge 1189
		WARN_ON(src->x1 < (int) orig_src->x1 ||
1190
			src->y1 < (int) orig_src->y1 ||
1191
			src->x2 > (int) orig_src->x2 ||
1192
			src->y2 > (int) orig_src->y2);
4104 Serge 1193
 
2342 Serge 1194
	/*
4104 Serge 1195
		 * Hardware doesn't handle subpixel coordinates.
1196
		 * Adjust to (macro)pixel boundary, but be careful not to
1197
		 * increase the source viewport size, because that could
1198
		 * push the downscaling factor out of bounds.
3243 Serge 1199
	 */
5354 serge 1200
		src_x = src->x1 >> 16;
1201
		src_w = drm_rect_width(src) >> 16;
1202
		src_y = src->y1 >> 16;
1203
		src_h = drm_rect_height(src) >> 16;
3243 Serge 1204
 
4104 Serge 1205
		if (format_is_yuv(fb->pixel_format)) {
1206
			src_x &= ~1;
1207
			src_w &= ~1;
1208
 
3243 Serge 1209
	/*
4104 Serge 1210
			 * Must keep src and dst the
1211
			 * same if we can't scale.
2342 Serge 1212
	 */
4104 Serge 1213
			if (!intel_plane->can_scale)
1214
				crtc_w &= ~1;
1215
 
1216
			if (crtc_w == 0)
5354 serge 1217
				state->visible = false;
4104 Serge 1218
		}
1219
	}
1220
 
1221
	/* Check size restrictions when scaling */
5354 serge 1222
	if (state->visible && (src_w != crtc_w || src_h != crtc_h)) {
4104 Serge 1223
		unsigned int width_bytes;
1224
 
1225
		WARN_ON(!intel_plane->can_scale);
1226
 
1227
		/* FIXME interlacing min height is 6 */
1228
 
1229
		if (crtc_w < 3 || crtc_h < 3)
5354 serge 1230
			state->visible = false;
4104 Serge 1231
 
1232
		if (src_w < 3 || src_h < 3)
5354 serge 1233
			state->visible = false;
4104 Serge 1234
 
5354 serge 1235
		width_bytes = ((src_x * pixel_size) & 63) +
1236
					src_w * pixel_size;
4104 Serge 1237
 
1238
		if (src_w > 2048 || src_h > 2048 ||
1239
		    width_bytes > 4096 || fb->pitches[0] > 4096) {
1240
			DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
2342 Serge 1241
		return -EINVAL;
4104 Serge 1242
		}
1243
	}
2342 Serge 1244
 
5354 serge 1245
	if (state->visible) {
1246
		src->x1 = src_x;
1247
		src->x2 = src_x + src_w;
1248
		src->y1 = src_y;
1249
		src->y2 = src_y + src_h;
1250
	}
4104 Serge 1251
 
5354 serge 1252
	dst->x1 = crtc_x;
1253
	dst->x2 = crtc_x + crtc_w;
1254
	dst->y1 = crtc_y;
1255
	dst->y2 = crtc_y + crtc_h;
2342 Serge 1256
 
5354 serge 1257
	return 0;
1258
}
1259
 
1260
static int
1261
intel_prepare_sprite_plane(struct drm_plane *plane,
1262
			   struct intel_plane_state *state)
1263
{
1264
	struct drm_device *dev = plane->dev;
1265
	struct drm_crtc *crtc = state->crtc;
1266
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1267
	struct intel_plane *intel_plane = to_intel_plane(plane);
1268
	enum pipe pipe = intel_crtc->pipe;
1269
	struct drm_framebuffer *fb = state->fb;
1270
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
1271
	struct drm_i915_gem_object *old_obj = intel_plane->obj;
1272
	int ret;
1273
 
1274
	if (old_obj != obj) {
2342 Serge 1275
	mutex_lock(&dev->struct_mutex);
1276
 
3746 Serge 1277
	/* Note that this will apply the VT-d workaround for scanouts,
1278
	 * which is more restrictive than required for sprites. (The
1279
	 * primary plane requires 256KiB alignment with 64 PTE padding,
5354 serge 1280
		 * the sprite planes only require 128KiB alignment and 32 PTE
1281
		 * padding.
3746 Serge 1282
	 */
5354 serge 1283
		ret = intel_pin_and_fence_fb_obj(plane, fb, NULL);
1284
		if (ret == 0)
5060 serge 1285
	i915_gem_track_fb(old_obj, obj,
1286
			  INTEL_FRONTBUFFER_SPRITE(pipe));
4560 Serge 1287
	mutex_unlock(&dev->struct_mutex);
2342 Serge 1288
	if (ret)
4560 Serge 1289
		return ret;
5354 serge 1290
	}
2342 Serge 1291
 
5354 serge 1292
	return 0;
1293
}
1294
 
1295
static void
1296
intel_commit_sprite_plane(struct drm_plane *plane,
1297
			  struct intel_plane_state *state)
1298
{
1299
	struct drm_device *dev = plane->dev;
1300
	struct drm_crtc *crtc = state->crtc;
1301
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1302
	struct intel_plane *intel_plane = to_intel_plane(plane);
1303
	enum pipe pipe = intel_crtc->pipe;
1304
	struct drm_framebuffer *fb = state->fb;
1305
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
1306
	struct drm_i915_gem_object *old_obj = intel_plane->obj;
1307
	int crtc_x, crtc_y;
1308
	unsigned int crtc_w, crtc_h;
1309
	uint32_t src_x, src_y, src_w, src_h;
1310
	struct drm_rect *dst = &state->dst;
1311
	const struct drm_rect *clip = &state->clip;
1312
	bool primary_enabled;
1313
 
1314
	/*
1315
	 * If the sprite is completely covering the primary plane,
1316
	 * we can disable the primary and save power.
1317
	 */
1318
	primary_enabled = !drm_rect_equals(dst, clip) || colorkey_enabled(intel_plane);
1319
	WARN_ON(!primary_enabled && !state->visible && intel_crtc->active);
1320
 
1321
	intel_plane->crtc_x = state->orig_dst.x1;
1322
	intel_plane->crtc_y = state->orig_dst.y1;
1323
	intel_plane->crtc_w = drm_rect_width(&state->orig_dst);
1324
	intel_plane->crtc_h = drm_rect_height(&state->orig_dst);
1325
	intel_plane->src_x = state->orig_src.x1;
1326
	intel_plane->src_y = state->orig_src.y1;
1327
	intel_plane->src_w = drm_rect_width(&state->orig_src);
1328
	intel_plane->src_h = drm_rect_height(&state->orig_src);
2342 Serge 1329
	intel_plane->obj = obj;
1330
 
4560 Serge 1331
	if (intel_crtc->active) {
5060 serge 1332
		bool primary_was_enabled = intel_crtc->primary_enabled;
2342 Serge 1333
 
5060 serge 1334
		intel_crtc->primary_enabled = primary_enabled;
1335
 
1336
//       if (primary_was_enabled != primary_enabled)
5354 serge 1337
//           intel_crtc_wait_for_pending_flips(crtc);
5060 serge 1338
 
1339
		if (primary_was_enabled && !primary_enabled)
1340
			intel_pre_disable_primary(crtc);
1341
 
5354 serge 1342
		if (state->visible) {
1343
			crtc_x = state->dst.x1;
1344
			crtc_y = state->dst.y1;
1345
			crtc_w = drm_rect_width(&state->dst);
1346
			crtc_h = drm_rect_height(&state->dst);
1347
			src_x = state->src.x1;
1348
			src_y = state->src.y1;
1349
			src_w = drm_rect_width(&state->src);
1350
			src_h = drm_rect_height(&state->src);
4104 Serge 1351
		intel_plane->update_plane(plane, crtc, fb, obj,
1352
					  crtc_x, crtc_y, crtc_w, crtc_h,
1353
					  src_x, src_y, src_w, src_h);
5354 serge 1354
		} else {
4104 Serge 1355
		intel_plane->disable_plane(plane, crtc);
5354 serge 1356
		}
2342 Serge 1357
 
5354 serge 1358
 
1359
		intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_SPRITE(pipe));
1360
 
5060 serge 1361
		if (!primary_was_enabled && primary_enabled)
1362
			intel_post_enable_primary(crtc);
4560 Serge 1363
	}
2342 Serge 1364
 
1365
	/* Unpin old obj after new one is active to avoid ugliness */
5354 serge 1366
	if (old_obj && old_obj != obj) {
1367
 
2342 Serge 1368
		/*
1369
		 * It's fairly common to simply update the position of
1370
		 * an existing object.  In that case, we don't need to
1371
		 * wait for vblank to avoid ugliness, we only need to
1372
		 * do the pin & ref bookkeeping.
1373
		 */
5354 serge 1374
		if (intel_crtc->active)
4560 Serge 1375
			intel_wait_for_vblank(dev, intel_crtc->pipe);
1376
 
2342 Serge 1377
			mutex_lock(&dev->struct_mutex);
3031 serge 1378
		intel_unpin_fb_obj(old_obj);
4560 Serge 1379
		mutex_unlock(&dev->struct_mutex);
2342 Serge 1380
	}
5354 serge 1381
}
2342 Serge 1382
 
5354 serge 1383
static int
1384
intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
1385
		   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
1386
		   unsigned int crtc_w, unsigned int crtc_h,
1387
		   uint32_t src_x, uint32_t src_y,
1388
		   uint32_t src_w, uint32_t src_h)
1389
{
1390
	struct intel_plane_state state;
1391
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1392
	int ret;
1393
 
1394
	state.crtc = crtc;
1395
	state.fb = fb;
1396
 
1397
	/* sample coordinates in 16.16 fixed point */
1398
	state.src.x1 = src_x;
1399
	state.src.x2 = src_x + src_w;
1400
	state.src.y1 = src_y;
1401
	state.src.y2 = src_y + src_h;
1402
 
1403
	/* integer pixels */
1404
	state.dst.x1 = crtc_x;
1405
	state.dst.x2 = crtc_x + crtc_w;
1406
	state.dst.y1 = crtc_y;
1407
	state.dst.y2 = crtc_y + crtc_h;
1408
 
1409
	state.clip.x1 = 0;
1410
	state.clip.y1 = 0;
1411
	state.clip.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0;
1412
	state.clip.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0;
1413
	state.orig_src = state.src;
1414
	state.orig_dst = state.dst;
1415
 
1416
	ret = intel_check_sprite_plane(plane, &state);
1417
	if (ret)
1418
		return ret;
1419
 
1420
	ret = intel_prepare_sprite_plane(plane, &state);
1421
	if (ret)
1422
		return ret;
1423
 
1424
	intel_commit_sprite_plane(plane, &state);
4560 Serge 1425
	return 0;
2342 Serge 1426
}
1427
 
1428
static int
1429
intel_disable_plane(struct drm_plane *plane)
1430
{
1431
	struct drm_device *dev = plane->dev;
1432
	struct intel_plane *intel_plane = to_intel_plane(plane);
4560 Serge 1433
	struct intel_crtc *intel_crtc;
5060 serge 1434
	enum pipe pipe;
2342 Serge 1435
 
4104 Serge 1436
	if (!plane->fb)
1437
		return 0;
1438
 
1439
	if (WARN_ON(!plane->crtc))
1440
		return -EINVAL;
1441
 
4560 Serge 1442
	intel_crtc = to_intel_crtc(plane->crtc);
5060 serge 1443
	pipe = intel_crtc->pipe;
4560 Serge 1444
 
1445
	if (intel_crtc->active) {
5060 serge 1446
		bool primary_was_enabled = intel_crtc->primary_enabled;
1447
 
1448
		intel_crtc->primary_enabled = true;
1449
 
4104 Serge 1450
	intel_plane->disable_plane(plane, plane->crtc);
5060 serge 1451
 
1452
		if (!primary_was_enabled && intel_crtc->primary_enabled)
1453
			intel_post_enable_primary(plane->crtc);
4560 Serge 1454
	}
2342 Serge 1455
 
4560 Serge 1456
	if (intel_plane->obj) {
1457
		if (intel_crtc->active)
3746 Serge 1458
	intel_wait_for_vblank(dev, intel_plane->pipe);
1459
 
2342 Serge 1460
	mutex_lock(&dev->struct_mutex);
3031 serge 1461
	intel_unpin_fb_obj(intel_plane->obj);
5060 serge 1462
		i915_gem_track_fb(intel_plane->obj, NULL,
1463
				  INTEL_FRONTBUFFER_SPRITE(pipe));
4560 Serge 1464
		mutex_unlock(&dev->struct_mutex);
1465
 
2342 Serge 1466
	intel_plane->obj = NULL;
4560 Serge 1467
	}
2342 Serge 1468
 
4560 Serge 1469
	return 0;
2342 Serge 1470
}
1471
 
1472
static void intel_destroy_plane(struct drm_plane *plane)
1473
{
1474
	struct intel_plane *intel_plane = to_intel_plane(plane);
1475
	intel_disable_plane(plane);
1476
	drm_plane_cleanup(plane);
1477
	kfree(intel_plane);
1478
}
1479
 
1480
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
1481
			      struct drm_file *file_priv)
1482
{
1483
	struct drm_intel_sprite_colorkey *set = data;
1484
	struct drm_plane *plane;
1485
	struct intel_plane *intel_plane;
1486
	int ret = 0;
1487
 
3482 Serge 1488
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1489
		return -ENODEV;
2342 Serge 1490
 
1491
	/* Make sure we don't try to enable both src & dest simultaneously */
1492
	if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1493
		return -EINVAL;
1494
 
3480 Serge 1495
	drm_modeset_lock_all(dev);
2342 Serge 1496
 
5060 serge 1497
	plane = drm_plane_find(dev, set->plane_id);
1498
	if (!plane) {
4560 Serge 1499
		ret = -ENOENT;
2342 Serge 1500
		goto out_unlock;
1501
	}
1502
 
1503
	intel_plane = to_intel_plane(plane);
1504
	ret = intel_plane->update_colorkey(plane, set);
1505
 
1506
out_unlock:
3480 Serge 1507
	drm_modeset_unlock_all(dev);
2342 Serge 1508
	return ret;
1509
}
1510
 
1511
int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
1512
			      struct drm_file *file_priv)
1513
{
1514
	struct drm_intel_sprite_colorkey *get = data;
1515
	struct drm_plane *plane;
1516
	struct intel_plane *intel_plane;
1517
	int ret = 0;
1518
 
3482 Serge 1519
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1520
		return -ENODEV;
2342 Serge 1521
 
3480 Serge 1522
	drm_modeset_lock_all(dev);
2342 Serge 1523
 
5060 serge 1524
	plane = drm_plane_find(dev, get->plane_id);
1525
	if (!plane) {
4560 Serge 1526
		ret = -ENOENT;
2342 Serge 1527
		goto out_unlock;
1528
	}
1529
 
1530
	intel_plane = to_intel_plane(plane);
1531
	intel_plane->get_colorkey(plane, get);
1532
 
1533
out_unlock:
3480 Serge 1534
	drm_modeset_unlock_all(dev);
2342 Serge 1535
	return ret;
1536
}
1537
 
5354 serge 1538
int intel_plane_set_property(struct drm_plane *plane,
1539
			     struct drm_property *prop,
1540
			     uint64_t val)
3746 Serge 1541
{
5354 serge 1542
	struct drm_device *dev = plane->dev;
3746 Serge 1543
	struct intel_plane *intel_plane = to_intel_plane(plane);
5354 serge 1544
	uint64_t old_val;
1545
	int ret = -ENOENT;
3746 Serge 1546
 
5354 serge 1547
	if (prop == dev->mode_config.rotation_property) {
1548
		/* exactly one rotation angle please */
1549
		if (hweight32(val & 0xf) != 1)
1550
			return -EINVAL;
1551
 
1552
		if (intel_plane->rotation == val)
1553
			return 0;
1554
 
1555
		old_val = intel_plane->rotation;
1556
		intel_plane->rotation = val;
1557
		ret = intel_plane_restore(plane);
1558
		if (ret)
1559
			intel_plane->rotation = old_val;
1560
	}
1561
 
1562
	return ret;
1563
}
1564
 
1565
int intel_plane_restore(struct drm_plane *plane)
1566
{
1567
	struct intel_plane *intel_plane = to_intel_plane(plane);
1568
 
3746 Serge 1569
	if (!plane->crtc || !plane->fb)
5354 serge 1570
		return 0;
3746 Serge 1571
 
5354 serge 1572
	return plane->funcs->update_plane(plane, plane->crtc, plane->fb,
3746 Serge 1573
			   intel_plane->crtc_x, intel_plane->crtc_y,
1574
			   intel_plane->crtc_w, intel_plane->crtc_h,
1575
			   intel_plane->src_x, intel_plane->src_y,
1576
			   intel_plane->src_w, intel_plane->src_h);
1577
}
1578
 
4104 Serge 1579
void intel_plane_disable(struct drm_plane *plane)
1580
{
1581
	if (!plane->crtc || !plane->fb)
1582
		return;
1583
 
1584
	intel_disable_plane(plane);
1585
}
1586
 
2342 Serge 1587
static const struct drm_plane_funcs intel_plane_funcs = {
1588
	.update_plane = intel_update_plane,
1589
	.disable_plane = intel_disable_plane,
1590
	.destroy = intel_destroy_plane,
5354 serge 1591
	.set_property = intel_plane_set_property,
2342 Serge 1592
};
1593
 
3031 serge 1594
static uint32_t ilk_plane_formats[] = {
1595
	DRM_FORMAT_XRGB8888,
1596
	DRM_FORMAT_YUYV,
1597
	DRM_FORMAT_YVYU,
1598
	DRM_FORMAT_UYVY,
1599
	DRM_FORMAT_VYUY,
1600
};
1601
 
2342 Serge 1602
static uint32_t snb_plane_formats[] = {
1603
	DRM_FORMAT_XBGR8888,
1604
	DRM_FORMAT_XRGB8888,
1605
	DRM_FORMAT_YUYV,
1606
	DRM_FORMAT_YVYU,
1607
	DRM_FORMAT_UYVY,
1608
	DRM_FORMAT_VYUY,
1609
};
1610
 
3746 Serge 1611
static uint32_t vlv_plane_formats[] = {
1612
	DRM_FORMAT_RGB565,
1613
	DRM_FORMAT_ABGR8888,
1614
	DRM_FORMAT_ARGB8888,
1615
	DRM_FORMAT_XBGR8888,
1616
	DRM_FORMAT_XRGB8888,
1617
	DRM_FORMAT_XBGR2101010,
1618
	DRM_FORMAT_ABGR2101010,
1619
	DRM_FORMAT_YUYV,
1620
	DRM_FORMAT_YVYU,
1621
	DRM_FORMAT_UYVY,
1622
	DRM_FORMAT_VYUY,
1623
};
1624
 
5354 serge 1625
static uint32_t skl_plane_formats[] = {
1626
	DRM_FORMAT_RGB565,
1627
	DRM_FORMAT_ABGR8888,
1628
	DRM_FORMAT_ARGB8888,
1629
	DRM_FORMAT_XBGR8888,
1630
	DRM_FORMAT_XRGB8888,
1631
	DRM_FORMAT_YUYV,
1632
	DRM_FORMAT_YVYU,
1633
	DRM_FORMAT_UYVY,
1634
	DRM_FORMAT_VYUY,
1635
};
1636
 
2342 Serge 1637
int
3746 Serge 1638
intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
2342 Serge 1639
{
1640
	struct intel_plane *intel_plane;
1641
	unsigned long possible_crtcs;
3031 serge 1642
	const uint32_t *plane_formats;
1643
	int num_plane_formats;
2342 Serge 1644
	int ret;
1645
 
3031 serge 1646
	if (INTEL_INFO(dev)->gen < 5)
2342 Serge 1647
		return -ENODEV;
1648
 
4560 Serge 1649
	intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
2342 Serge 1650
	if (!intel_plane)
1651
		return -ENOMEM;
1652
 
3031 serge 1653
	switch (INTEL_INFO(dev)->gen) {
1654
	case 5:
1655
	case 6:
3243 Serge 1656
		intel_plane->can_scale = true;
3031 serge 1657
		intel_plane->max_downscale = 16;
1658
		intel_plane->update_plane = ilk_update_plane;
1659
		intel_plane->disable_plane = ilk_disable_plane;
1660
		intel_plane->update_colorkey = ilk_update_colorkey;
1661
		intel_plane->get_colorkey = ilk_get_colorkey;
1662
 
2342 Serge 1663
	if (IS_GEN6(dev)) {
3031 serge 1664
			plane_formats = snb_plane_formats;
1665
			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1666
		} else {
1667
			plane_formats = ilk_plane_formats;
1668
			num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
1669
		}
1670
		break;
1671
 
1672
	case 7:
4560 Serge 1673
	case 8:
4104 Serge 1674
		if (IS_IVYBRIDGE(dev)) {
1675
			intel_plane->can_scale = true;
1676
			intel_plane->max_downscale = 2;
1677
		} else {
3243 Serge 1678
			intel_plane->can_scale = false;
4104 Serge 1679
			intel_plane->max_downscale = 1;
1680
		}
3746 Serge 1681
 
1682
		if (IS_VALLEYVIEW(dev)) {
1683
			intel_plane->update_plane = vlv_update_plane;
1684
			intel_plane->disable_plane = vlv_disable_plane;
1685
			intel_plane->update_colorkey = vlv_update_colorkey;
1686
			intel_plane->get_colorkey = vlv_get_colorkey;
1687
 
1688
			plane_formats = vlv_plane_formats;
1689
			num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
1690
		} else {
2342 Serge 1691
		intel_plane->update_plane = ivb_update_plane;
1692
		intel_plane->disable_plane = ivb_disable_plane;
1693
		intel_plane->update_colorkey = ivb_update_colorkey;
1694
		intel_plane->get_colorkey = ivb_get_colorkey;
3031 serge 1695
 
1696
		plane_formats = snb_plane_formats;
1697
		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
3746 Serge 1698
		}
3031 serge 1699
		break;
5354 serge 1700
	case 9:
1701
		/*
1702
		 * FIXME: Skylake planes can be scaled (with some restrictions),
1703
		 * but this is for another time.
1704
		 */
1705
		intel_plane->can_scale = false;
1706
		intel_plane->max_downscale = 1;
1707
		intel_plane->update_plane = skl_update_plane;
1708
		intel_plane->disable_plane = skl_disable_plane;
1709
		intel_plane->update_colorkey = skl_update_colorkey;
1710
		intel_plane->get_colorkey = skl_get_colorkey;
3031 serge 1711
 
5354 serge 1712
		plane_formats = skl_plane_formats;
1713
		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
1714
		break;
3031 serge 1715
	default:
1716
		kfree(intel_plane);
1717
		return -ENODEV;
2342 Serge 1718
	}
1719
 
1720
	intel_plane->pipe = pipe;
3746 Serge 1721
	intel_plane->plane = plane;
5354 serge 1722
	intel_plane->rotation = BIT(DRM_ROTATE_0);
2342 Serge 1723
	possible_crtcs = (1 << pipe);
5354 serge 1724
	ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
3031 serge 1725
			     &intel_plane_funcs,
1726
			     plane_formats, num_plane_formats,
5354 serge 1727
				       DRM_PLANE_TYPE_OVERLAY);
1728
	if (ret) {
2342 Serge 1729
		kfree(intel_plane);
5354 serge 1730
		goto out;
1731
	}
2342 Serge 1732
 
5354 serge 1733
	if (!dev->mode_config.rotation_property)
1734
		dev->mode_config.rotation_property =
1735
			drm_mode_create_rotation_property(dev,
1736
							  BIT(DRM_ROTATE_0) |
1737
							  BIT(DRM_ROTATE_180));
1738
 
1739
	if (dev->mode_config.rotation_property)
1740
		drm_object_attach_property(&intel_plane->base.base,
1741
					   dev->mode_config.rotation_property,
1742
					   intel_plane->rotation);
1743
 
1744
 out:
2342 Serge 1745
	return ret;
1746
}