intel_sprite.c 32.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*
 * Copyright © 2011 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Authors:
 *   Jesse Barnes <jbarnes@virtuousgeek.org>
 *
 * New plane/sprite handling.
 *
 * The older chips had a separate interface for programming plane related
 * registers; newer ones are much simpler and we can use the new DRM plane
 * support.
 */
32 33 34
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fourcc.h>
35
#include <drm/drm_rect.h>
36
#include <drm/drm_atomic.h>
37
#include <drm/drm_plane_helper.h>
38
#include "intel_drv.h"
39
#include <drm/i915_drm.h>
40 41
#include "i915_drv.h"

42 43 44 45 46 47 48 49 50 51 52 53 54 55
static bool
format_is_yuv(uint32_t format)
{
	switch (format) {
	case DRM_FORMAT_YUYV:
	case DRM_FORMAT_UYVY:
	case DRM_FORMAT_VYUY:
	case DRM_FORMAT_YVYU:
		return true;
	default:
		return false;
	}
}

56 57 58 59 60 61 62 63 64
static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs)
{
	/* paranoia */
	if (!mode->crtc_htotal)
		return 1;

	return DIV_ROUND_UP(usecs * mode->crtc_clock, 1000 * mode->crtc_htotal);
}

65 66 67 68 69 70 71 72 73 74 75 76 77 78
/**
 * intel_pipe_update_start() - start update of a set of display registers
 * @crtc: the crtc of which the registers are going to be updated
 * @start_vbl_count: vblank counter return pointer used for error checking
 *
 * Mark the start of an update to pipe registers that should be updated
 * atomically regarding vblank. If the next vblank will happens within
 * the next 100 us, this function waits until the vblank passes.
 *
 * After a successful call to this function, interrupts will be disabled
 * until a subsequent call to intel_pipe_update_end(). That is done to
 * avoid random delays. The value written to @start_vbl_count should be
 * supplied to intel_pipe_update_end() for error checking.
 */
79
void intel_pipe_update_start(struct intel_crtc *crtc)
80 81
{
	struct drm_device *dev = crtc->base.dev;
82
	const struct drm_display_mode *mode = &crtc->config->base.adjusted_mode;
83 84 85
	enum pipe pipe = crtc->pipe;
	long timeout = msecs_to_jiffies_timeout(1);
	int scanline, min, max, vblank_start;
86
	wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
87 88 89 90 91 92 93 94 95 96
	DEFINE_WAIT(wait);

	vblank_start = mode->crtc_vblank_start;
	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
		vblank_start = DIV_ROUND_UP(vblank_start, 2);

	/* FIXME needs to be calibrated sensibly */
	min = vblank_start - usecs_to_scanlines(mode, 100);
	max = vblank_start - 1;

97 98
	local_irq_disable();

99
	if (min <= 0 || max <= 0)
100
		return;
101

102
	if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
103
		return;
104

105 106
	trace_i915_pipe_update_start(crtc, min, max);

107 108 109 110 111 112
	for (;;) {
		/*
		 * prepare_to_wait() has a memory barrier, which guarantees
		 * other CPUs can see the task state update by the time we
		 * read the scanline.
		 */
113
		prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131

		scanline = intel_get_crtc_scanline(crtc);
		if (scanline < min || scanline > max)
			break;

		if (timeout <= 0) {
			DRM_ERROR("Potential atomic update failure on pipe %c\n",
				  pipe_name(crtc->pipe));
			break;
		}

		local_irq_enable();

		timeout = schedule_timeout(timeout);

		local_irq_disable();
	}

132
	finish_wait(wq, &wait);
133

134
	drm_crtc_vblank_put(&crtc->base);
135

136 137 138 139 140 141
	crtc->debug.min_vbl = min;
	crtc->debug.max_vbl = max;
	crtc->debug.scanline_start = scanline;
	crtc->debug.start_vbl_time = ktime_get();
	crtc->debug.start_vbl_count =
		dev->driver->get_vblank_counter(dev, pipe);
142

143
	trace_i915_pipe_update_vblank_evaded(crtc, min, max,
144
					     crtc->debug.start_vbl_count);
145 146
}

147 148 149 150 151 152 153 154 155
/**
 * intel_pipe_update_end() - end update of a set of display registers
 * @crtc: the crtc of which the registers were updated
 * @start_vbl_count: start vblank counter (used for error checking)
 *
 * Mark the end of an update started with intel_pipe_update_start(). This
 * re-enables interrupts and verifies the update was actually completed
 * before a vblank using the value of @start_vbl_count.
 */
156
void intel_pipe_update_end(struct intel_crtc *crtc)
157 158 159
{
	struct drm_device *dev = crtc->base.dev;
	enum pipe pipe = crtc->pipe;
160
	int scanline_end = intel_get_crtc_scanline(crtc);
161
	u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
162
	ktime_t end_vbl_time = ktime_get();
163

164 165
	trace_i915_pipe_update_end(crtc, end_vbl_count);

166 167
	local_irq_enable();

168 169 170 171 172 173 174 175 176
	if (crtc->debug.start_vbl_count &&
	    crtc->debug.start_vbl_count != end_vbl_count) {
		DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n",
			  pipe_name(pipe), crtc->debug.start_vbl_count,
			  end_vbl_count,
			  ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
			  crtc->debug.min_vbl, crtc->debug.max_vbl,
			  crtc->debug.scanline_start, scanline_end);
	}
177 178
}

179 180 181
static void
skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
		 struct drm_framebuffer *fb,
182
		 int crtc_x, int crtc_y,
183 184 185 186 187 188 189
		 unsigned int crtc_w, unsigned int crtc_h,
		 uint32_t x, uint32_t y,
		 uint32_t src_w, uint32_t src_h)
{
	struct drm_device *dev = drm_plane->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_plane *intel_plane = to_intel_plane(drm_plane);
190
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
191 192
	const int pipe = intel_plane->pipe;
	const int plane = intel_plane->plane + 1;
193
	u32 plane_ctl, stride_div, stride;
194
	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
195 196
	const struct drm_intel_sprite_colorkey *key =
		&to_intel_plane_state(drm_plane->state)->ckey;
197
	unsigned long surf_addr;
198 199 200
	u32 tile_height, plane_offset, plane_size;
	unsigned int rotation;
	int x_offset, y_offset;
201 202
	struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config;
	int scaler_id;
203

204 205
	plane_ctl = PLANE_CTL_ENABLE |
		PLANE_CTL_PIPE_CSC_ENABLE;
206

207 208
	plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
	plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
209

210
	rotation = drm_plane->state->rotation;
211
	plane_ctl |= skl_plane_ctl_rotation(rotation);
212 213 214 215 216

	intel_update_sprite_watermarks(drm_plane, crtc, src_w, src_h,
				       pixel_size, true,
				       src_w != crtc_w || src_h != crtc_h);

217 218 219
	stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
					       fb->pixel_format);

220 221
	scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;

222 223 224 225 226 227
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

228 229 230 231 232 233 234 235 236 237 238
	if (key->flags) {
		I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
		I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
		I915_WRITE(PLANE_KEYMSK(pipe, plane), key->channel_mask);
	}

	if (key->flags & I915_SET_COLORKEY_DESTINATION)
		plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
		plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;

239 240
	surf_addr = intel_plane_obj_offset(intel_plane, obj);

241 242
	if (intel_rotation_90_or_270(rotation)) {
		/* stride: Surface height in tiles */
243 244
		tile_height = intel_tile_height(dev, fb->pixel_format,
						fb->modifier[0]);
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
		stride = DIV_ROUND_UP(fb->height, tile_height);
		plane_size = (src_w << 16) | src_h;
		x_offset = stride * tile_height - y - (src_h + 1);
		y_offset = x;
	} else {
		stride = fb->pitches[0] / stride_div;
		plane_size = (src_h << 16) | src_w;
		x_offset = x;
		y_offset = y;
	}
	plane_offset = y_offset << 16 | x_offset;

	I915_WRITE(PLANE_OFFSET(pipe, plane), plane_offset);
	I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
	I915_WRITE(PLANE_SIZE(pipe, plane), plane_size);
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279

	/* program plane scaler */
	if (scaler_id >= 0) {
		uint32_t ps_ctrl = 0;

		DRM_DEBUG_KMS("plane = %d PS_PLANE_SEL(plane) = 0x%x\n", plane,
			PS_PLANE_SEL(plane));
		ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(plane) |
			crtc_state->scaler_state.scalers[scaler_id].mode;
		I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
		I915_WRITE(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
		I915_WRITE(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
		I915_WRITE(SKL_PS_WIN_SZ(pipe, scaler_id),
			((crtc_w + 1) << 16)|(crtc_h + 1));

		I915_WRITE(PLANE_POS(pipe, plane), 0);
	} else {
		I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x);
	}

280
	I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
281
	I915_WRITE(PLANE_SURF(pipe, plane), surf_addr);
282 283 284 285
	POSTING_READ(PLANE_SURF(pipe, plane));
}

static void
286
skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
287
{
288
	struct drm_device *dev = dplane->dev;
289
	struct drm_i915_private *dev_priv = dev->dev_private;
290
	struct intel_plane *intel_plane = to_intel_plane(dplane);
291 292 293
	const int pipe = intel_plane->pipe;
	const int plane = intel_plane->plane + 1;

294
	I915_WRITE(PLANE_CTL(pipe, plane), 0);
295

296 297
	I915_WRITE(PLANE_SURF(pipe, plane), 0);
	POSTING_READ(PLANE_SURF(pipe, plane));
298

299
	intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false);
300 301
}

302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
static void
chv_update_csc(struct intel_plane *intel_plane, uint32_t format)
{
	struct drm_i915_private *dev_priv = intel_plane->base.dev->dev_private;
	int plane = intel_plane->plane;

	/* Seems RGB data bypasses the CSC always */
	if (!format_is_yuv(format))
		return;

	/*
	 * BT.601 limited range YCbCr -> full range RGB
	 *
	 * |r|   | 6537 4769     0|   |cr  |
	 * |g| = |-3330 4769 -1605| x |y-64|
	 * |b|   |    0 4769  8263|   |cb  |
	 *
	 * Cb and Cr apparently come in as signed already, so no
	 * need for any offset. For Y we need to remove the offset.
	 */
	I915_WRITE(SPCSCYGOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(-64));
	I915_WRITE(SPCSCCBOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
	I915_WRITE(SPCSCCROFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));

	I915_WRITE(SPCSCC01(plane), SPCSC_C1(4769) | SPCSC_C0(6537));
	I915_WRITE(SPCSCC23(plane), SPCSC_C1(-3330) | SPCSC_C0(0));
	I915_WRITE(SPCSCC45(plane), SPCSC_C1(-1605) | SPCSC_C0(4769));
	I915_WRITE(SPCSCC67(plane), SPCSC_C1(4769) | SPCSC_C0(0));
	I915_WRITE(SPCSCC8(plane), SPCSC_C0(8263));

	I915_WRITE(SPCSCYGICLAMP(plane), SPCSC_IMAX(940) | SPCSC_IMIN(64));
	I915_WRITE(SPCSCCBICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
	I915_WRITE(SPCSCCRICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));

	I915_WRITE(SPCSCYGOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
	I915_WRITE(SPCSCCBOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
	I915_WRITE(SPCSCCROCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
}

341
static void
342 343
vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
		 struct drm_framebuffer *fb,
344
		 int crtc_x, int crtc_y,
345 346 347 348 349 350 351
		 unsigned int crtc_w, unsigned int crtc_h,
		 uint32_t x, uint32_t y,
		 uint32_t src_w, uint32_t src_h)
{
	struct drm_device *dev = dplane->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_plane *intel_plane = to_intel_plane(dplane);
352
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
353 354 355 356 357
	int pipe = intel_plane->pipe;
	int plane = intel_plane->plane;
	u32 sprctl;
	unsigned long sprsurf_offset, linear_offset;
	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
358 359
	const struct drm_intel_sprite_colorkey *key =
		&to_intel_plane_state(dplane->state)->ckey;
360

361
	sprctl = SP_ENABLE;
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405

	switch (fb->pixel_format) {
	case DRM_FORMAT_YUYV:
		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
		break;
	case DRM_FORMAT_YVYU:
		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
		break;
	case DRM_FORMAT_UYVY:
		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
		break;
	case DRM_FORMAT_VYUY:
		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
		break;
	case DRM_FORMAT_RGB565:
		sprctl |= SP_FORMAT_BGR565;
		break;
	case DRM_FORMAT_XRGB8888:
		sprctl |= SP_FORMAT_BGRX8888;
		break;
	case DRM_FORMAT_ARGB8888:
		sprctl |= SP_FORMAT_BGRA8888;
		break;
	case DRM_FORMAT_XBGR2101010:
		sprctl |= SP_FORMAT_RGBX1010102;
		break;
	case DRM_FORMAT_ABGR2101010:
		sprctl |= SP_FORMAT_RGBA1010102;
		break;
	case DRM_FORMAT_XBGR8888:
		sprctl |= SP_FORMAT_RGBX8888;
		break;
	case DRM_FORMAT_ABGR8888:
		sprctl |= SP_FORMAT_RGBA8888;
		break;
	default:
		/*
		 * If we get here one of the upper layers failed to filter
		 * out the unsupported plane formats
		 */
		BUG();
		break;
	}

406 407 408 409 410 411
	/*
	 * Enable gamma to match primary/cursor plane behaviour.
	 * FIXME should be user controllable via propertiesa.
	 */
	sprctl |= SP_GAMMA_ENABLE;

412 413 414 415 416 417 418 419 420 421
	if (obj->tiling_mode != I915_TILING_NONE)
		sprctl |= SP_TILED;

	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

	linear_offset = y * fb->pitches[0] + x * pixel_size;
422 423
	sprsurf_offset = intel_gen4_compute_page_offset(dev_priv,
							&x, &y,
424 425 426 427 428
							obj->tiling_mode,
							pixel_size,
							fb->pitches[0]);
	linear_offset -= sprsurf_offset;

429
	if (dplane->state->rotation == BIT(DRM_ROTATE_180)) {
430 431 432 433 434 435 436
		sprctl |= SP_ROTATE_180;

		x += src_w;
		y += src_h;
		linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
	}

437 438 439 440 441 442 443 444 445
	if (key->flags) {
		I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
		I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
		I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask);
	}

	if (key->flags & I915_SET_COLORKEY_SOURCE)
		sprctl |= SP_SOURCE_KEY;

446 447 448
	if (IS_CHERRYVIEW(dev) && pipe == PIPE_B)
		chv_update_csc(intel_plane, fb->pixel_format);

449 450 451
	I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
	I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);

452 453 454 455 456
	if (obj->tiling_mode != I915_TILING_NONE)
		I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
	else
		I915_WRITE(SPLINOFF(pipe, plane), linear_offset);

457 458
	I915_WRITE(SPCONSTALPHA(pipe, plane), 0);

459 460
	I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
	I915_WRITE(SPCNTR(pipe, plane), sprctl);
461 462
	I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
		   sprsurf_offset);
463
	POSTING_READ(SPSURF(pipe, plane));
464 465 466
}

static void
467
vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
468 469 470 471 472 473 474
{
	struct drm_device *dev = dplane->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_plane *intel_plane = to_intel_plane(dplane);
	int pipe = intel_plane->pipe;
	int plane = intel_plane->plane;

475 476
	I915_WRITE(SPCNTR(pipe, plane), 0);

477
	I915_WRITE(SPSURF(pipe, plane), 0);
478
	POSTING_READ(SPSURF(pipe, plane));
479 480
}

481
static void
482 483
ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
		 struct drm_framebuffer *fb,
484
		 int crtc_x, int crtc_y,
485 486 487 488 489 490 491
		 unsigned int crtc_w, unsigned int crtc_h,
		 uint32_t x, uint32_t y,
		 uint32_t src_w, uint32_t src_h)
{
	struct drm_device *dev = plane->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_plane *intel_plane = to_intel_plane(plane);
492
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
493
	enum pipe pipe = intel_plane->pipe;
494
	u32 sprctl, sprscale = 0;
495
	unsigned long sprsurf_offset, linear_offset;
V
Ville Syrjälä 已提交
496
	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
497 498
	const struct drm_intel_sprite_colorkey *key =
		&to_intel_plane_state(plane->state)->ckey;
499

500
	sprctl = SPRITE_ENABLE;
501 502 503

	switch (fb->pixel_format) {
	case DRM_FORMAT_XBGR8888:
504
		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
505 506
		break;
	case DRM_FORMAT_XRGB8888:
507
		sprctl |= SPRITE_FORMAT_RGBX888;
508 509 510 511 512 513 514 515 516 517 518 519 520 521
		break;
	case DRM_FORMAT_YUYV:
		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
		break;
	case DRM_FORMAT_YVYU:
		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
		break;
	case DRM_FORMAT_UYVY:
		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
		break;
	case DRM_FORMAT_VYUY:
		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
		break;
	default:
522
		BUG();
523 524
	}

525 526 527 528 529 530
	/*
	 * Enable gamma to match primary/cursor plane behaviour.
	 * FIXME should be user controllable via propertiesa.
	 */
	sprctl |= SPRITE_GAMMA_ENABLE;

531 532 533
	if (obj->tiling_mode != I915_TILING_NONE)
		sprctl |= SPRITE_TILED;

534
	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
535 536 537 538
		sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
	else
		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;

539
	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
540 541
		sprctl |= SPRITE_PIPE_CSC_ENABLE;

542 543
	intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size,
				       true,
544 545
				       src_w != crtc_w || src_h != crtc_h);

546 547 548 549 550 551
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

552
	if (crtc_w != src_w || crtc_h != src_h)
553 554
		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;

555
	linear_offset = y * fb->pitches[0] + x * pixel_size;
556
	sprsurf_offset =
557 558
		intel_gen4_compute_page_offset(dev_priv,
					       &x, &y, obj->tiling_mode,
559
					       pixel_size, fb->pitches[0]);
560 561
	linear_offset -= sprsurf_offset;

562
	if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
563 564 565 566 567 568 569 570 571 572 573
		sprctl |= SPRITE_ROTATE_180;

		/* HSW and BDW does this automagically in hardware */
		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
			x += src_w;
			y += src_h;
			linear_offset += src_h * fb->pitches[0] +
				src_w * pixel_size;
		}
	}

574 575 576 577 578 579 580 581 582 583 584
	if (key->flags) {
		I915_WRITE(SPRKEYVAL(pipe), key->min_value);
		I915_WRITE(SPRKEYMAX(pipe), key->max_value);
		I915_WRITE(SPRKEYMSK(pipe), key->channel_mask);
	}

	if (key->flags & I915_SET_COLORKEY_DESTINATION)
		sprctl |= SPRITE_DEST_KEY;
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
		sprctl |= SPRITE_SOURCE_KEY;

585 586 587
	I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
	I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);

588 589
	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
	 * register */
590
	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
591
		I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
592
	else if (obj->tiling_mode != I915_TILING_NONE)
593
		I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
594 595
	else
		I915_WRITE(SPRLINOFF(pipe), linear_offset);
596

597
	I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
598 599
	if (intel_plane->can_scale)
		I915_WRITE(SPRSCALE(pipe), sprscale);
600
	I915_WRITE(SPRCTL(pipe), sprctl);
601 602
	I915_WRITE(SPRSURF(pipe),
		   i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
603
	POSTING_READ(SPRSURF(pipe));
604 605 606
}

static void
607
ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
608 609 610 611 612 613 614 615
{
	struct drm_device *dev = plane->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_plane *intel_plane = to_intel_plane(plane);
	int pipe = intel_plane->pipe;

	I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
	/* Can't leave the scaler enabled... */
616 617
	if (intel_plane->can_scale)
		I915_WRITE(SPRSCALE(pipe), 0);
618

619 620
	I915_WRITE(SPRSURF(pipe), 0);
	POSTING_READ(SPRSURF(pipe));
621 622 623
}

static void
624 625
ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
		 struct drm_framebuffer *fb,
626
		 int crtc_x, int crtc_y,
627 628 629 630 631 632 633
		 unsigned int crtc_w, unsigned int crtc_h,
		 uint32_t x, uint32_t y,
		 uint32_t src_w, uint32_t src_h)
{
	struct drm_device *dev = plane->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_plane *intel_plane = to_intel_plane(plane);
634
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
V
Ville Syrjälä 已提交
635
	int pipe = intel_plane->pipe;
636
	unsigned long dvssurf_offset, linear_offset;
637
	u32 dvscntr, dvsscale;
V
Ville Syrjälä 已提交
638
	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
639 640
	const struct drm_intel_sprite_colorkey *key =
		&to_intel_plane_state(plane->state)->ckey;
641

642
	dvscntr = DVS_ENABLE;
643 644 645

	switch (fb->pixel_format) {
	case DRM_FORMAT_XBGR8888:
646
		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
647 648
		break;
	case DRM_FORMAT_XRGB8888:
649
		dvscntr |= DVS_FORMAT_RGBX888;
650 651 652 653 654 655 656 657 658 659 660 661 662 663
		break;
	case DRM_FORMAT_YUYV:
		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
		break;
	case DRM_FORMAT_YVYU:
		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
		break;
	case DRM_FORMAT_UYVY:
		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
		break;
	case DRM_FORMAT_VYUY:
		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
		break;
	default:
664
		BUG();
665 666
	}

667 668 669 670 671 672
	/*
	 * Enable gamma to match primary/cursor plane behaviour.
	 * FIXME should be user controllable via propertiesa.
	 */
	dvscntr |= DVS_GAMMA_ENABLE;

673 674 675
	if (obj->tiling_mode != I915_TILING_NONE)
		dvscntr |= DVS_TILED;

676 677
	if (IS_GEN6(dev))
		dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
678

679 680
	intel_update_sprite_watermarks(plane, crtc, src_w, src_h,
				       pixel_size, true,
681 682
				       src_w != crtc_w || src_h != crtc_h);

683 684 685 686 687 688
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

689
	dvsscale = 0;
690
	if (crtc_w != src_w || crtc_h != src_h)
691 692
		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;

693
	linear_offset = y * fb->pitches[0] + x * pixel_size;
694
	dvssurf_offset =
695 696
		intel_gen4_compute_page_offset(dev_priv,
					       &x, &y, obj->tiling_mode,
697
					       pixel_size, fb->pitches[0]);
698 699
	linear_offset -= dvssurf_offset;

700
	if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
701 702 703 704 705 706 707
		dvscntr |= DVS_ROTATE_180;

		x += src_w;
		y += src_h;
		linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
	}

708 709 710 711 712 713 714 715 716 717 718
	if (key->flags) {
		I915_WRITE(DVSKEYVAL(pipe), key->min_value);
		I915_WRITE(DVSKEYMAX(pipe), key->max_value);
		I915_WRITE(DVSKEYMSK(pipe), key->channel_mask);
	}

	if (key->flags & I915_SET_COLORKEY_DESTINATION)
		dvscntr |= DVS_DEST_KEY;
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
		dvscntr |= DVS_SOURCE_KEY;

719 720 721
	I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
	I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);

722
	if (obj->tiling_mode != I915_TILING_NONE)
723
		I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
724 725
	else
		I915_WRITE(DVSLINOFF(pipe), linear_offset);
726 727 728 729

	I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
	I915_WRITE(DVSSCALE(pipe), dvsscale);
	I915_WRITE(DVSCNTR(pipe), dvscntr);
730 731
	I915_WRITE(DVSSURF(pipe),
		   i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
732
	POSTING_READ(DVSSURF(pipe));
733 734 735
}

static void
736
ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
737 738 739 740 741 742
{
	struct drm_device *dev = plane->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_plane *intel_plane = to_intel_plane(plane);
	int pipe = intel_plane->pipe;

743
	I915_WRITE(DVSCNTR(pipe), 0);
744 745
	/* Disable the scaler */
	I915_WRITE(DVSSCALE(pipe), 0);
746

747
	I915_WRITE(DVSSURF(pipe), 0);
748
	POSTING_READ(DVSSURF(pipe));
749 750 751
}

static int
752
intel_check_sprite_plane(struct drm_plane *plane,
753
			 struct intel_crtc_state *crtc_state,
754
			 struct intel_plane_state *state)
755
{
756
	struct drm_device *dev = plane->dev;
757 758
	struct drm_crtc *crtc = state->base.crtc;
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
759
	struct intel_plane *intel_plane = to_intel_plane(plane);
760
	struct drm_framebuffer *fb = state->base.fb;
761 762 763 764 765 766
	int crtc_x, crtc_y;
	unsigned int crtc_w, crtc_h;
	uint32_t src_x, src_y, src_w, src_h;
	struct drm_rect *src = &state->src;
	struct drm_rect *dst = &state->dst;
	const struct drm_rect *clip = &state->clip;
767 768
	int hscale, vscale;
	int max_scale, min_scale;
769
	bool can_scale;
770 771 772 773
	int pixel_size;

	if (!fb) {
		state->visible = false;
774
		return 0;
775
	}
776

777 778 779
	/* Don't modify another pipe's plane */
	if (intel_plane->pipe != intel_crtc->pipe) {
		DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
780
		return -EINVAL;
781
	}
782

783 784 785
	/* FIXME check all gen limits */
	if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) {
		DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
786
		return -EINVAL;
787
	}
788

789 790 791
	/* setup can_scale, min_scale, max_scale */
	if (INTEL_INFO(dev)->gen >= 9) {
		/* use scaler when colorkey is not required */
792
		if (state->ckey.flags == I915_SET_COLORKEY_NONE) {
793 794 795 796 797 798 799 800 801 802 803 804 805 806
			can_scale = 1;
			min_scale = 1;
			max_scale = skl_max_scale(intel_crtc, crtc_state);
		} else {
			can_scale = 0;
			min_scale = DRM_PLANE_HELPER_NO_SCALING;
			max_scale = DRM_PLANE_HELPER_NO_SCALING;
		}
	} else {
		can_scale = intel_plane->can_scale;
		max_scale = intel_plane->max_downscale << 16;
		min_scale = intel_plane->can_scale ? 1 : (1 << 16);
	}

807 808 809 810 811
	/*
	 * FIXME the following code does a bunch of fuzzy adjustments to the
	 * coordinates and sizes. We probably need some way to decide whether
	 * more strict checking should be done instead.
	 */
812
	drm_rect_rotate(src, fb->width << 16, fb->height << 16,
813
			state->base.rotation);
814

815
	hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale);
816
	BUG_ON(hscale < 0);
817

818
	vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale);
819
	BUG_ON(vscale < 0);
820

821
	state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
822

823 824 825 826
	crtc_x = dst->x1;
	crtc_y = dst->y1;
	crtc_w = drm_rect_width(dst);
	crtc_h = drm_rect_height(dst);
827

828
	if (state->visible) {
829
		/* check again in case clipping clamped the results */
830
		hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
831 832
		if (hscale < 0) {
			DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
833 834
			drm_rect_debug_print(src, true);
			drm_rect_debug_print(dst, false);
835 836 837 838

			return hscale;
		}

839
		vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
840 841
		if (vscale < 0) {
			DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
842 843
			drm_rect_debug_print(src, true);
			drm_rect_debug_print(dst, false);
844 845 846 847

			return vscale;
		}

848
		/* Make the source viewport size an exact multiple of the scaling factors. */
849 850 851
		drm_rect_adjust_size(src,
				     drm_rect_width(dst) * hscale - drm_rect_width(src),
				     drm_rect_height(dst) * vscale - drm_rect_height(src));
852

853
		drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16,
854
				    state->base.rotation);
855

856
		/* sanity check to make sure the src viewport wasn't enlarged */
857 858 859 860
		WARN_ON(src->x1 < (int) state->base.src_x ||
			src->y1 < (int) state->base.src_y ||
			src->x2 > (int) state->base.src_x + state->base.src_w ||
			src->y2 > (int) state->base.src_y + state->base.src_h);
861 862 863 864 865 866 867

		/*
		 * Hardware doesn't handle subpixel coordinates.
		 * Adjust to (macro)pixel boundary, but be careful not to
		 * increase the source viewport size, because that could
		 * push the downscaling factor out of bounds.
		 */
868 869 870 871
		src_x = src->x1 >> 16;
		src_w = drm_rect_width(src) >> 16;
		src_y = src->y1 >> 16;
		src_h = drm_rect_height(src) >> 16;
872 873 874 875 876 877 878 879 880

		if (format_is_yuv(fb->pixel_format)) {
			src_x &= ~1;
			src_w &= ~1;

			/*
			 * Must keep src and dst the
			 * same if we can't scale.
			 */
881
			if (!can_scale)
882 883 884
				crtc_w &= ~1;

			if (crtc_w == 0)
885
				state->visible = false;
886 887 888 889
		}
	}

	/* Check size restrictions when scaling */
890
	if (state->visible && (src_w != crtc_w || src_h != crtc_h)) {
891 892
		unsigned int width_bytes;

893
		WARN_ON(!can_scale);
894 895 896 897

		/* FIXME interlacing min height is 6 */

		if (crtc_w < 3 || crtc_h < 3)
898
			state->visible = false;
899 900

		if (src_w < 3 || src_h < 3)
901
			state->visible = false;
902

903
		pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
904 905
		width_bytes = ((src_x * pixel_size) & 63) +
					src_w * pixel_size;
906

907 908
		if (INTEL_INFO(dev)->gen < 9 && (src_w > 2048 || src_h > 2048 ||
		    width_bytes > 4096 || fb->pitches[0] > 4096)) {
909 910 911 912 913
			DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
			return -EINVAL;
		}
	}

914
	if (state->visible) {
915 916 917 918
		src->x1 = src_x << 16;
		src->x2 = (src_x + src_w) << 16;
		src->y1 = src_y << 16;
		src->y2 = (src_y + src_h) << 16;
919 920 921 922 923 924 925 926 927 928
	}

	dst->x1 = crtc_x;
	dst->x2 = crtc_x + crtc_w;
	dst->y1 = crtc_y;
	dst->y2 = crtc_y + crtc_h;

	return 0;
}

929 930 931 932
static void
intel_commit_sprite_plane(struct drm_plane *plane,
			  struct intel_plane_state *state)
{
933
	struct drm_crtc *crtc = state->base.crtc;
934
	struct intel_plane *intel_plane = to_intel_plane(plane);
935
	struct drm_framebuffer *fb = state->base.fb;
936

937 938
	crtc = crtc ? crtc : plane->crtc;

939
	if (!crtc->state->active)
940 941 942 943 944 945 946 947 948 949 950 951
		return;

	if (state->visible) {
		intel_plane->update_plane(plane, crtc, fb,
					  state->dst.x1, state->dst.y1,
					  drm_rect_width(&state->dst),
					  drm_rect_height(&state->dst),
					  state->src.x1 >> 16,
					  state->src.y1 >> 16,
					  drm_rect_width(&state->src) >> 16,
					  drm_rect_height(&state->src) >> 16);
	} else {
952
		intel_plane->disable_plane(plane, crtc);
953
	}
954 955
}

956 957 958 959 960
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
			      struct drm_file *file_priv)
{
	struct drm_intel_sprite_colorkey *set = data;
	struct drm_plane *plane;
961 962 963
	struct drm_plane_state *plane_state;
	struct drm_atomic_state *state;
	struct drm_modeset_acquire_ctx ctx;
964 965 966 967 968 969
	int ret = 0;

	/* Make sure we don't try to enable both src & dest simultaneously */
	if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
		return -EINVAL;

970 971 972 973
	if (IS_VALLEYVIEW(dev) &&
	    set->flags & I915_SET_COLORKEY_DESTINATION)
		return -EINVAL;

R
Rob Clark 已提交
974
	plane = drm_plane_find(dev, set->plane_id);
975 976
	if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
		return -ENOENT;
977

978
	drm_modeset_acquire_init(&ctx, 0);
979

980 981 982 983
	state = drm_atomic_state_alloc(plane->dev);
	if (!state) {
		ret = -ENOMEM;
		goto out;
984
	}
985 986 987 988 989 990 991 992 993
	state->acquire_ctx = &ctx;

	while (1) {
		plane_state = drm_atomic_get_plane_state(state, plane);
		ret = PTR_ERR_OR_ZERO(plane_state);
		if (!ret) {
			to_intel_plane_state(plane_state)->ckey = *set;
			ret = drm_atomic_commit(state);
		}
994

995 996
		if (ret != -EDEADLK)
			break;
997

998 999 1000
		drm_atomic_state_clear(state);
		drm_modeset_backoff(&ctx);
	}
1001

1002 1003
	if (ret)
		drm_atomic_state_free(state);
1004

1005 1006 1007 1008
out:
	drm_modeset_drop_locks(&ctx);
	drm_modeset_acquire_fini(&ctx);
	return ret;
1009 1010
}

1011
static const uint32_t ilk_plane_formats[] = {
1012 1013 1014 1015 1016 1017 1018
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

1019
static const uint32_t snb_plane_formats[] = {
1020 1021 1022 1023 1024 1025 1026 1027
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

1028
static const uint32_t vlv_plane_formats[] = {
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
	DRM_FORMAT_RGB565,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_XBGR2101010,
	DRM_FORMAT_ABGR2101010,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
static uint32_t skl_plane_formats[] = {
	DRM_FORMAT_RGB565,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

1054
int
1055
intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
1056 1057
{
	struct intel_plane *intel_plane;
1058
	struct intel_plane_state *state;
1059
	unsigned long possible_crtcs;
1060 1061
	const uint32_t *plane_formats;
	int num_plane_formats;
1062 1063
	int ret;

1064
	if (INTEL_INFO(dev)->gen < 5)
1065 1066
		return -ENODEV;

1067
	intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
1068 1069 1070
	if (!intel_plane)
		return -ENOMEM;

1071 1072
	state = intel_create_plane_state(&intel_plane->base);
	if (!state) {
1073 1074 1075
		kfree(intel_plane);
		return -ENOMEM;
	}
1076
	intel_plane->base.state = &state->base;
1077

1078 1079 1080
	switch (INTEL_INFO(dev)->gen) {
	case 5:
	case 6:
1081
		intel_plane->can_scale = true;
1082
		intel_plane->max_downscale = 16;
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
		intel_plane->update_plane = ilk_update_plane;
		intel_plane->disable_plane = ilk_disable_plane;

		if (IS_GEN6(dev)) {
			plane_formats = snb_plane_formats;
			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
		} else {
			plane_formats = ilk_plane_formats;
			num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
		}
		break;

	case 7:
B
Ben Widawsky 已提交
1096
	case 8:
1097
		if (IS_IVYBRIDGE(dev)) {
1098
			intel_plane->can_scale = true;
1099 1100 1101 1102 1103
			intel_plane->max_downscale = 2;
		} else {
			intel_plane->can_scale = false;
			intel_plane->max_downscale = 1;
		}
1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117

		if (IS_VALLEYVIEW(dev)) {
			intel_plane->update_plane = vlv_update_plane;
			intel_plane->disable_plane = vlv_disable_plane;

			plane_formats = vlv_plane_formats;
			num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
		} else {
			intel_plane->update_plane = ivb_update_plane;
			intel_plane->disable_plane = ivb_disable_plane;

			plane_formats = snb_plane_formats;
			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
		}
1118
		break;
1119
	case 9:
1120
		intel_plane->can_scale = true;
1121 1122
		intel_plane->update_plane = skl_update_plane;
		intel_plane->disable_plane = skl_disable_plane;
1123
		state->scaler_id = -1;
1124 1125 1126 1127

		plane_formats = skl_plane_formats;
		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
		break;
1128
	default:
1129
		kfree(intel_plane);
1130
		return -ENODEV;
1131 1132 1133
	}

	intel_plane->pipe = pipe;
1134
	intel_plane->plane = plane;
1135
	intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane);
1136 1137
	intel_plane->check_plane = intel_check_sprite_plane;
	intel_plane->commit_plane = intel_commit_sprite_plane;
1138
	possible_crtcs = (1 << pipe);
1139
	ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
1140
				       &intel_plane_funcs,
1141 1142
				       plane_formats, num_plane_formats,
				       DRM_PLANE_TYPE_OVERLAY);
1143
	if (ret) {
1144
		kfree(intel_plane);
1145 1146 1147
		goto out;
	}

1148
	intel_create_rotation_property(dev, intel_plane);
1149

1150 1151
	drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);

1152
out:
1153 1154
	return ret;
}