Subversion Repositories Kolibri OS

Rev

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