Subversion Repositories Kolibri OS

Rev

Rev 2344 | Go to most recent revision | Details | 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
 */
32
#include "drmP.h"
33
#include "drm_crtc.h"
34
#include "drm_fourcc.h"
35
#include "intel_drv.h"
36
#include "i915_drm.h"
37
#include "i915_drv.h"
38
 
39
static void
40
ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
41
		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
42
		 unsigned int crtc_w, unsigned int crtc_h,
43
		 uint32_t x, uint32_t y,
44
		 uint32_t src_w, uint32_t src_h)
45
{
46
	struct drm_device *dev = plane->dev;
47
	struct drm_i915_private *dev_priv = dev->dev_private;
48
	struct intel_plane *intel_plane = to_intel_plane(plane);
49
	int pipe = intel_plane->pipe;
50
	u32 sprctl, sprscale = 0;
51
	int pixel_size;
52
 
53
	sprctl = I915_READ(SPRCTL(pipe));
54
 
55
	/* Mask out pixel format bits in case we change it */
56
	sprctl &= ~SPRITE_PIXFORMAT_MASK;
57
	sprctl &= ~SPRITE_RGB_ORDER_RGBX;
58
	sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
59
 
60
	switch (fb->pixel_format) {
61
	case DRM_FORMAT_XBGR8888:
62
		sprctl |= SPRITE_FORMAT_RGBX888;
63
		pixel_size = 4;
64
		break;
65
	case DRM_FORMAT_XRGB8888:
66
		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
67
		pixel_size = 4;
68
		break;
69
	case DRM_FORMAT_YUYV:
70
		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
71
		pixel_size = 2;
72
		break;
73
	case DRM_FORMAT_YVYU:
74
		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
75
		pixel_size = 2;
76
		break;
77
	case DRM_FORMAT_UYVY:
78
		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
79
		pixel_size = 2;
80
		break;
81
	case DRM_FORMAT_VYUY:
82
		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
83
		pixel_size = 2;
84
		break;
85
	default:
86
		DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
87
		sprctl |= DVS_FORMAT_RGBX888;
88
		pixel_size = 4;
89
		break;
90
	}
91
 
92
	if (obj->tiling_mode != I915_TILING_NONE)
93
		sprctl |= SPRITE_TILED;
94
 
95
	/* must disable */
96
	sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
97
	sprctl |= SPRITE_ENABLE;
98
	sprctl |= SPRITE_DEST_KEY;
99
 
100
	/* Sizes are 0 based */
101
	src_w--;
102
	src_h--;
103
	crtc_w--;
104
	crtc_h--;
105
 
106
	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
107
 
108
	/*
109
	 * IVB workaround: must disable low power watermarks for at least
110
	 * one frame before enabling scaling.  LP watermarks can be re-enabled
111
	 * when scaling is disabled.
112
	 */
113
	if (crtc_w != src_w || crtc_h != src_h) {
114
		dev_priv->sprite_scaling_enabled = true;
115
		sandybridge_update_wm(dev);
116
		intel_wait_for_vblank(dev, pipe);
117
		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
118
	} else {
119
		dev_priv->sprite_scaling_enabled = false;
120
		/* potentially re-enable LP watermarks */
121
		sandybridge_update_wm(dev);
122
	}
123
 
124
	I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
125
	I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
126
	if (obj->tiling_mode != I915_TILING_NONE) {
127
		I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
128
	} else {
129
		unsigned long offset;
130
 
131
		offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
132
		I915_WRITE(SPRLINOFF(pipe), offset);
133
	}
134
	I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
135
	I915_WRITE(SPRSCALE(pipe), sprscale);
136
	I915_WRITE(SPRCTL(pipe), sprctl);
137
	I915_WRITE(SPRSURF(pipe), obj->gtt_offset);
138
	POSTING_READ(SPRSURF(pipe));
139
}
140
 
141
static void
142
ivb_disable_plane(struct drm_plane *plane)
143
{
144
	struct drm_device *dev = plane->dev;
145
	struct drm_i915_private *dev_priv = dev->dev_private;
146
	struct intel_plane *intel_plane = to_intel_plane(plane);
147
	int pipe = intel_plane->pipe;
148
 
149
	I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
150
	/* Can't leave the scaler enabled... */
151
	I915_WRITE(SPRSCALE(pipe), 0);
152
	/* Activate double buffered register update */
153
	I915_WRITE(SPRSURF(pipe), 0);
154
	POSTING_READ(SPRSURF(pipe));
155
}
156
 
157
static int
158
ivb_update_colorkey(struct drm_plane *plane,
159
		    struct drm_intel_sprite_colorkey *key)
160
{
161
	struct drm_device *dev = plane->dev;
162
	struct drm_i915_private *dev_priv = dev->dev_private;
163
	struct intel_plane *intel_plane;
164
	u32 sprctl;
165
	int ret = 0;
166
 
167
	intel_plane = to_intel_plane(plane);
168
 
169
	I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
170
	I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
171
	I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
172
 
173
	sprctl = I915_READ(SPRCTL(intel_plane->pipe));
174
	sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
175
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
176
		sprctl |= SPRITE_DEST_KEY;
177
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
178
		sprctl |= SPRITE_SOURCE_KEY;
179
	I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
180
 
181
	POSTING_READ(SPRKEYMSK(intel_plane->pipe));
182
 
183
	return ret;
184
}
185
 
186
static void
187
ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
188
{
189
	struct drm_device *dev = plane->dev;
190
	struct drm_i915_private *dev_priv = dev->dev_private;
191
	struct intel_plane *intel_plane;
192
	u32 sprctl;
193
 
194
	intel_plane = to_intel_plane(plane);
195
 
196
	key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
197
	key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
198
	key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
199
	key->flags = 0;
200
 
201
	sprctl = I915_READ(SPRCTL(intel_plane->pipe));
202
 
203
	if (sprctl & SPRITE_DEST_KEY)
204
		key->flags = I915_SET_COLORKEY_DESTINATION;
205
	else if (sprctl & SPRITE_SOURCE_KEY)
206
		key->flags = I915_SET_COLORKEY_SOURCE;
207
	else
208
		key->flags = I915_SET_COLORKEY_NONE;
209
}
210
 
211
static void
212
snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
213
		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
214
		 unsigned int crtc_w, unsigned int crtc_h,
215
		 uint32_t x, uint32_t y,
216
		 uint32_t src_w, uint32_t src_h)
217
{
218
	struct drm_device *dev = plane->dev;
219
	struct drm_i915_private *dev_priv = dev->dev_private;
220
	struct intel_plane *intel_plane = to_intel_plane(plane);
221
	int pipe = intel_plane->pipe, pixel_size;
222
	u32 dvscntr, dvsscale = 0;
223
 
224
	dvscntr = I915_READ(DVSCNTR(pipe));
225
 
226
	/* Mask out pixel format bits in case we change it */
227
	dvscntr &= ~DVS_PIXFORMAT_MASK;
228
	dvscntr &= ~DVS_RGB_ORDER_RGBX;
229
	dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
230
 
231
	switch (fb->pixel_format) {
232
	case DRM_FORMAT_XBGR8888:
233
		dvscntr |= DVS_FORMAT_RGBX888;
234
		pixel_size = 4;
235
		break;
236
	case DRM_FORMAT_XRGB8888:
237
		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_RGBX;
238
		pixel_size = 4;
239
		break;
240
	case DRM_FORMAT_YUYV:
241
		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
242
		pixel_size = 2;
243
		break;
244
	case DRM_FORMAT_YVYU:
245
		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
246
		pixel_size = 2;
247
		break;
248
	case DRM_FORMAT_UYVY:
249
		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
250
		pixel_size = 2;
251
		break;
252
	case DRM_FORMAT_VYUY:
253
		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
254
		pixel_size = 2;
255
		break;
256
	default:
257
		DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
258
		dvscntr |= DVS_FORMAT_RGBX888;
259
		pixel_size = 4;
260
		break;
261
	}
262
 
263
	if (obj->tiling_mode != I915_TILING_NONE)
264
		dvscntr |= DVS_TILED;
265
 
266
	/* must disable */
267
	dvscntr |= DVS_TRICKLE_FEED_DISABLE;
268
	dvscntr |= DVS_ENABLE;
269
 
270
	/* Sizes are 0 based */
271
	src_w--;
272
	src_h--;
273
	crtc_w--;
274
	crtc_h--;
275
 
276
	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
277
 
278
	if (crtc_w != src_w || crtc_h != src_h)
279
		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
280
 
281
	I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
282
	I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
283
	if (obj->tiling_mode != I915_TILING_NONE) {
284
		I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
285
	} else {
286
		unsigned long offset;
287
 
288
		offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
289
		I915_WRITE(DVSLINOFF(pipe), offset);
290
	}
291
	I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
292
	I915_WRITE(DVSSCALE(pipe), dvsscale);
293
	I915_WRITE(DVSCNTR(pipe), dvscntr);
294
	I915_WRITE(DVSSURF(pipe), obj->gtt_offset);
295
	POSTING_READ(DVSSURF(pipe));
296
}
297
 
298
static void
299
snb_disable_plane(struct drm_plane *plane)
300
{
301
	struct drm_device *dev = plane->dev;
302
	struct drm_i915_private *dev_priv = dev->dev_private;
303
	struct intel_plane *intel_plane = to_intel_plane(plane);
304
	int pipe = intel_plane->pipe;
305
 
306
	I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
307
	/* Disable the scaler */
308
	I915_WRITE(DVSSCALE(pipe), 0);
309
	/* Flush double buffered register updates */
310
	I915_WRITE(DVSSURF(pipe), 0);
311
	POSTING_READ(DVSSURF(pipe));
312
}
313
 
314
static void
315
intel_enable_primary(struct drm_crtc *crtc)
316
{
317
	struct drm_device *dev = crtc->dev;
318
	struct drm_i915_private *dev_priv = dev->dev_private;
319
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
320
	int reg = DSPCNTR(intel_crtc->plane);
321
 
322
	I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
323
}
324
 
325
static void
326
intel_disable_primary(struct drm_crtc *crtc)
327
{
328
	struct drm_device *dev = crtc->dev;
329
	struct drm_i915_private *dev_priv = dev->dev_private;
330
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
331
	int reg = DSPCNTR(intel_crtc->plane);
332
 
333
	I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
334
}
335
 
336
static int
337
snb_update_colorkey(struct drm_plane *plane,
338
		    struct drm_intel_sprite_colorkey *key)
339
{
340
	struct drm_device *dev = plane->dev;
341
	struct drm_i915_private *dev_priv = dev->dev_private;
342
	struct intel_plane *intel_plane;
343
	u32 dvscntr;
344
	int ret = 0;
345
 
346
	intel_plane = to_intel_plane(plane);
347
 
348
	I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
349
	I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
350
	I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
351
 
352
	dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
353
	dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
354
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
355
		dvscntr |= DVS_DEST_KEY;
356
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
357
		dvscntr |= DVS_SOURCE_KEY;
358
	I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
359
 
360
	POSTING_READ(DVSKEYMSK(intel_plane->pipe));
361
 
362
	return ret;
363
}
364
 
365
static void
366
snb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
367
{
368
	struct drm_device *dev = plane->dev;
369
	struct drm_i915_private *dev_priv = dev->dev_private;
370
	struct intel_plane *intel_plane;
371
	u32 dvscntr;
372
 
373
	intel_plane = to_intel_plane(plane);
374
 
375
	key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
376
	key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
377
	key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
378
	key->flags = 0;
379
 
380
	dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
381
 
382
	if (dvscntr & DVS_DEST_KEY)
383
		key->flags = I915_SET_COLORKEY_DESTINATION;
384
	else if (dvscntr & DVS_SOURCE_KEY)
385
		key->flags = I915_SET_COLORKEY_SOURCE;
386
	else
387
		key->flags = I915_SET_COLORKEY_NONE;
388
}
389
 
390
static int
391
intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
392
		   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
393
		   unsigned int crtc_w, unsigned int crtc_h,
394
		   uint32_t src_x, uint32_t src_y,
395
		   uint32_t src_w, uint32_t src_h)
396
{
397
	struct drm_device *dev = plane->dev;
398
	struct drm_i915_private *dev_priv = dev->dev_private;
399
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
400
	struct intel_plane *intel_plane = to_intel_plane(plane);
401
	struct intel_framebuffer *intel_fb;
402
	struct drm_i915_gem_object *obj, *old_obj;
403
	int pipe = intel_plane->pipe;
404
	int ret = 0;
405
	int x = src_x >> 16, y = src_y >> 16;
406
	int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
407
	bool disable_primary = false;
408
 
409
	intel_fb = to_intel_framebuffer(fb);
410
	obj = intel_fb->obj;
411
 
412
	old_obj = intel_plane->obj;
413
 
414
	/* Pipe must be running... */
415
	if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE))
416
		return -EINVAL;
417
 
418
	if (crtc_x >= primary_w || crtc_y >= primary_h)
419
		return -EINVAL;
420
 
421
	/* Don't modify another pipe's plane */
422
	if (intel_plane->pipe != intel_crtc->pipe)
423
		return -EINVAL;
424
 
425
	/*
426
	 * Clamp the width & height into the visible area.  Note we don't
427
	 * try to scale the source if part of the visible region is offscreen.
428
	 * The caller must handle that by adjusting source offset and size.
429
	 */
430
	if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) {
431
		crtc_w += crtc_x;
432
		crtc_x = 0;
433
	}
434
	if ((crtc_x + crtc_w) <= 0) /* Nothing to display */
435
		goto out;
436
	if ((crtc_x + crtc_w) > primary_w)
437
		crtc_w = primary_w - crtc_x;
438
 
439
	if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) {
440
		crtc_h += crtc_y;
441
		crtc_y = 0;
442
	}
443
	if ((crtc_y + crtc_h) <= 0) /* Nothing to display */
444
		goto out;
445
	if (crtc_y + crtc_h > primary_h)
446
		crtc_h = primary_h - crtc_y;
447
 
448
	if (!crtc_w || !crtc_h) /* Again, nothing to display */
449
		goto out;
450
 
451
	/*
452
	 * We can take a larger source and scale it down, but
453
	 * only so much...  16x is the max on SNB.
454
	 */
455
	if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale)
456
		return -EINVAL;
457
 
458
	/*
459
	 * If the sprite is completely covering the primary plane,
460
	 * we can disable the primary and save power.
461
	 */
462
	if ((crtc_x == 0) && (crtc_y == 0) &&
463
	    (crtc_w == primary_w) && (crtc_h == primary_h))
464
		disable_primary = true;
465
 
466
	mutex_lock(&dev->struct_mutex);
467
 
468
	ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
469
	if (ret)
470
		goto out_unlock;
471
 
472
	intel_plane->obj = obj;
473
 
474
	/*
475
	 * Be sure to re-enable the primary before the sprite is no longer
476
	 * covering it fully.
477
	 */
478
	if (!disable_primary && intel_plane->primary_disabled) {
479
		intel_enable_primary(crtc);
480
		intel_plane->primary_disabled = false;
481
	}
482
 
483
	intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y,
484
				  crtc_w, crtc_h, x, y, src_w, src_h);
485
 
486
	if (disable_primary) {
487
		intel_disable_primary(crtc);
488
		intel_plane->primary_disabled = true;
489
	}
490
 
491
	/* Unpin old obj after new one is active to avoid ugliness */
492
	if (old_obj) {
493
		/*
494
		 * It's fairly common to simply update the position of
495
		 * an existing object.  In that case, we don't need to
496
		 * wait for vblank to avoid ugliness, we only need to
497
		 * do the pin & ref bookkeeping.
498
		 */
499
		if (old_obj != obj) {
500
			mutex_unlock(&dev->struct_mutex);
501
			intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
502
			mutex_lock(&dev->struct_mutex);
503
		}
504
//       i915_gem_object_unpin(old_obj);
505
	}
506
 
507
out_unlock:
508
	mutex_unlock(&dev->struct_mutex);
509
out:
510
	return ret;
511
}
512
 
513
static int
514
intel_disable_plane(struct drm_plane *plane)
515
{
516
	struct drm_device *dev = plane->dev;
517
	struct intel_plane *intel_plane = to_intel_plane(plane);
518
	int ret = 0;
519
 
520
	if (intel_plane->primary_disabled) {
521
		intel_enable_primary(plane->crtc);
522
		intel_plane->primary_disabled = false;
523
	}
524
 
525
	intel_plane->disable_plane(plane);
526
 
527
	if (!intel_plane->obj)
528
		goto out;
529
 
530
	mutex_lock(&dev->struct_mutex);
531
//   i915_gem_object_unpin(intel_plane->obj);
532
	intel_plane->obj = NULL;
533
	mutex_unlock(&dev->struct_mutex);
534
out:
535
 
536
	return ret;
537
}
538
 
539
static void intel_destroy_plane(struct drm_plane *plane)
540
{
541
	struct intel_plane *intel_plane = to_intel_plane(plane);
542
	intel_disable_plane(plane);
543
	drm_plane_cleanup(plane);
544
	kfree(intel_plane);
545
}
546
 
547
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
548
			      struct drm_file *file_priv)
549
{
550
	struct drm_intel_sprite_colorkey *set = data;
551
	struct drm_i915_private *dev_priv = dev->dev_private;
552
	struct drm_mode_object *obj;
553
	struct drm_plane *plane;
554
	struct intel_plane *intel_plane;
555
	int ret = 0;
556
 
557
	if (!dev_priv)
558
		return -EINVAL;
559
 
560
	/* Make sure we don't try to enable both src & dest simultaneously */
561
	if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
562
		return -EINVAL;
563
 
564
	mutex_lock(&dev->mode_config.mutex);
565
 
566
	obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
567
	if (!obj) {
568
		ret = -EINVAL;
569
		goto out_unlock;
570
	}
571
 
572
	plane = obj_to_plane(obj);
573
	intel_plane = to_intel_plane(plane);
574
	ret = intel_plane->update_colorkey(plane, set);
575
 
576
out_unlock:
577
	mutex_unlock(&dev->mode_config.mutex);
578
	return ret;
579
}
580
 
581
int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
582
			      struct drm_file *file_priv)
583
{
584
	struct drm_intel_sprite_colorkey *get = data;
585
	struct drm_i915_private *dev_priv = dev->dev_private;
586
	struct drm_mode_object *obj;
587
	struct drm_plane *plane;
588
	struct intel_plane *intel_plane;
589
	int ret = 0;
590
 
591
	if (!dev_priv)
592
		return -EINVAL;
593
 
594
	mutex_lock(&dev->mode_config.mutex);
595
 
596
	obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
597
	if (!obj) {
598
		ret = -EINVAL;
599
		goto out_unlock;
600
	}
601
 
602
	plane = obj_to_plane(obj);
603
	intel_plane = to_intel_plane(plane);
604
	intel_plane->get_colorkey(plane, get);
605
 
606
out_unlock:
607
	mutex_unlock(&dev->mode_config.mutex);
608
	return ret;
609
}
610
 
611
static const struct drm_plane_funcs intel_plane_funcs = {
612
	.update_plane = intel_update_plane,
613
	.disable_plane = intel_disable_plane,
614
	.destroy = intel_destroy_plane,
615
};
616
 
617
static uint32_t snb_plane_formats[] = {
618
	DRM_FORMAT_XBGR8888,
619
	DRM_FORMAT_XRGB8888,
620
	DRM_FORMAT_YUYV,
621
	DRM_FORMAT_YVYU,
622
	DRM_FORMAT_UYVY,
623
	DRM_FORMAT_VYUY,
624
};
625
 
626
int
627
intel_plane_init(struct drm_device *dev, enum pipe pipe)
628
{
629
	struct intel_plane *intel_plane;
630
	unsigned long possible_crtcs;
631
	int ret;
632
 
633
	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
634
		return -ENODEV;
635
 
636
	intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
637
	if (!intel_plane)
638
		return -ENOMEM;
639
 
640
	if (IS_GEN6(dev)) {
641
		intel_plane->max_downscale = 16;
642
		intel_plane->update_plane = snb_update_plane;
643
		intel_plane->disable_plane = snb_disable_plane;
644
		intel_plane->update_colorkey = snb_update_colorkey;
645
		intel_plane->get_colorkey = snb_get_colorkey;
646
	} else if (IS_GEN7(dev)) {
647
		intel_plane->max_downscale = 2;
648
		intel_plane->update_plane = ivb_update_plane;
649
		intel_plane->disable_plane = ivb_disable_plane;
650
		intel_plane->update_colorkey = ivb_update_colorkey;
651
		intel_plane->get_colorkey = ivb_get_colorkey;
652
	}
653
 
654
	intel_plane->pipe = pipe;
655
	possible_crtcs = (1 << pipe);
656
	ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
657
			     &intel_plane_funcs, snb_plane_formats,
658
			     ARRAY_SIZE(snb_plane_formats), false);
659
	if (ret)
660
		kfree(intel_plane);
661
 
662
	return ret;
663
}
664