Subversion Repositories Kolibri OS

Rev

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