intel_sprite.c 32.2 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
static int usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
			      int usecs)
58 59
{
	/* paranoia */
60
	if (!adjusted_mode->crtc_htotal)
61 62
		return 1;

63 64
	return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
			    1000 * adjusted_mode->crtc_htotal);
65 66
}

67 68 69 70 71 72 73 74 75 76 77 78 79 80
/**
 * 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.
 */
81
void intel_pipe_update_start(struct intel_crtc *crtc)
82 83
{
	struct drm_device *dev = crtc->base.dev;
84
	const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
85 86 87
	enum pipe pipe = crtc->pipe;
	long timeout = msecs_to_jiffies_timeout(1);
	int scanline, min, max, vblank_start;
88
	wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
89 90
	DEFINE_WAIT(wait);

91 92
	vblank_start = adjusted_mode->crtc_vblank_start;
	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
93 94 95
		vblank_start = DIV_ROUND_UP(vblank_start, 2);

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

99 100
	local_irq_disable();

101
	if (min <= 0 || max <= 0)
102
		return;
103

104
	if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
105
		return;
106

107 108 109
	crtc->debug.min_vbl = min;
	crtc->debug.max_vbl = max;
	trace_i915_pipe_update_start(crtc);
110

111 112 113 114 115 116
	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.
		 */
117
		prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135

		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();
	}

136
	finish_wait(wq, &wait);
137

138
	drm_crtc_vblank_put(&crtc->base);
139

140 141 142 143
	crtc->debug.scanline_start = scanline;
	crtc->debug.start_vbl_time = ktime_get();
	crtc->debug.start_vbl_count =
		dev->driver->get_vblank_counter(dev, pipe);
144

145
	trace_i915_pipe_update_vblank_evaded(crtc);
146 147
}

148 149 150 151 152 153 154 155 156
/**
 * 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.
 */
157
void intel_pipe_update_end(struct intel_crtc *crtc)
158 159 160
{
	struct drm_device *dev = crtc->base.dev;
	enum pipe pipe = crtc->pipe;
161
	int scanline_end = intel_get_crtc_scanline(crtc);
162
	u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
163
	ktime_t end_vbl_time = ktime_get();
164

165
	trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
166

167 168
	local_irq_enable();

169 170 171 172 173 174 175 176 177
	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);
	}
178 179
}

180 181 182
static void
skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
		 struct drm_framebuffer *fb,
183
		 int crtc_x, int crtc_y,
184 185 186 187 188 189 190
		 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);
191
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
192 193
	const int pipe = intel_plane->pipe;
	const int plane = intel_plane->plane + 1;
194
	u32 plane_ctl, stride_div, stride;
195
	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
196 197
	const struct drm_intel_sprite_colorkey *key =
		&to_intel_plane_state(drm_plane->state)->ckey;
198
	unsigned long surf_addr;
199 200 201
	u32 tile_height, plane_offset, plane_size;
	unsigned int rotation;
	int x_offset, y_offset;
202 203
	struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config;
	int scaler_id;
204

205
	plane_ctl = PLANE_CTL_ENABLE |
206
		PLANE_CTL_PIPE_GAMMA_ENABLE |
207
		PLANE_CTL_PIPE_CSC_ENABLE;
208

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

212
	rotation = drm_plane->state->rotation;
213
	plane_ctl |= skl_plane_ctl_rotation(rotation);
214

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

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

222 223
	scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;

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

230 231 232 233 234 235 236 237 238 239 240
	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;

241
	surf_addr = intel_plane_obj_offset(intel_plane, obj, 0);
242

243 244
	if (intel_rotation_90_or_270(rotation)) {
		/* stride: Surface height in tiles */
245
		tile_height = intel_tile_height(dev, fb->pixel_format,
246
						fb->modifier[0], 0);
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
		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);
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281

	/* 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);
	}

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

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

296
	I915_WRITE(PLANE_CTL(pipe, plane), 0);
297

298 299
	I915_WRITE(PLANE_SURF(pipe, plane), 0);
	POSTING_READ(PLANE_SURF(pipe, plane));
300 301

	intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false);
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 341 342
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));
}

343
static void
344 345
vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
		 struct drm_framebuffer *fb,
346
		 int crtc_x, int crtc_y,
347 348 349 350 351 352 353
		 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);
354
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
355 356 357 358 359
	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);
360 361
	const struct drm_intel_sprite_colorkey *key =
		&to_intel_plane_state(dplane->state)->ckey;
362

363
	sprctl = SP_ENABLE;
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 406 407

	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;
	}

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

414 415 416 417 418 419 420 421 422 423
	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;
424 425
	sprsurf_offset = intel_gen4_compute_page_offset(dev_priv,
							&x, &y,
426 427 428 429 430
							obj->tiling_mode,
							pixel_size,
							fb->pitches[0]);
	linear_offset -= sprsurf_offset;

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

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

439 440 441 442 443 444 445 446 447
	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;

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

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

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

459 460
	I915_WRITE(SPCONSTALPHA(pipe, plane), 0);

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

static void
469
vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
470 471 472 473 474 475 476
{
	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;

477 478
	I915_WRITE(SPCNTR(pipe, plane), 0);

479
	I915_WRITE(SPSURF(pipe, plane), 0);
480
	POSTING_READ(SPSURF(pipe, plane));
481 482
}

483
static void
484 485
ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
		 struct drm_framebuffer *fb,
486
		 int crtc_x, int crtc_y,
487 488 489 490 491 492 493
		 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);
494
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
495
	enum pipe pipe = intel_plane->pipe;
496
	u32 sprctl, sprscale = 0;
497
	unsigned long sprsurf_offset, linear_offset;
V
Ville Syrjälä 已提交
498
	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
499 500
	const struct drm_intel_sprite_colorkey *key =
		&to_intel_plane_state(plane->state)->ckey;
501

502
	sprctl = SPRITE_ENABLE;
503 504 505

	switch (fb->pixel_format) {
	case DRM_FORMAT_XBGR8888:
506
		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
507 508
		break;
	case DRM_FORMAT_XRGB8888:
509
		sprctl |= SPRITE_FORMAT_RGBX888;
510 511 512 513 514 515 516 517 518 519 520 521 522 523
		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:
524
		BUG();
525 526
	}

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

533 534 535
	if (obj->tiling_mode != I915_TILING_NONE)
		sprctl |= SPRITE_TILED;

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

541
	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
542 543
		sprctl |= SPRITE_PIPE_CSC_ENABLE;

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

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

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

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

564
	if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
565 566 567 568 569 570 571 572 573 574 575
		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;
		}
	}

576 577 578 579 580 581 582 583 584 585 586
	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;

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

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

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

static void
609
ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
610 611 612 613 614 615 616 617
{
	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... */
618 619
	if (intel_plane->can_scale)
		I915_WRITE(SPRSCALE(pipe), 0);
620

621 622
	I915_WRITE(SPRSURF(pipe), 0);
	POSTING_READ(SPRSURF(pipe));
623 624 625
}

static void
626 627
ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
		 struct drm_framebuffer *fb,
628
		 int crtc_x, int crtc_y,
629 630 631 632 633 634 635
		 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);
636
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
V
Ville Syrjälä 已提交
637
	int pipe = intel_plane->pipe;
638
	unsigned long dvssurf_offset, linear_offset;
639
	u32 dvscntr, dvsscale;
V
Ville Syrjälä 已提交
640
	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
641 642
	const struct drm_intel_sprite_colorkey *key =
		&to_intel_plane_state(plane->state)->ckey;
643

644
	dvscntr = DVS_ENABLE;
645 646 647

	switch (fb->pixel_format) {
	case DRM_FORMAT_XBGR8888:
648
		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
649 650
		break;
	case DRM_FORMAT_XRGB8888:
651
		dvscntr |= DVS_FORMAT_RGBX888;
652 653 654 655 656 657 658 659 660 661 662 663 664 665
		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:
666
		BUG();
667 668
	}

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

675 676 677
	if (obj->tiling_mode != I915_TILING_NONE)
		dvscntr |= DVS_TILED;

678 679
	if (IS_GEN6(dev))
		dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
680

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

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

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

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

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

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

710 711 712 713 714 715 716 717 718 719 720
	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;

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

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

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

static void
738
ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
739 740 741 742 743 744
{
	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;

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

749
	I915_WRITE(DVSSURF(pipe), 0);
750
	POSTING_READ(DVSSURF(pipe));
751 752 753
}

static int
754
intel_check_sprite_plane(struct drm_plane *plane,
755
			 struct intel_crtc_state *crtc_state,
756
			 struct intel_plane_state *state)
757
{
758
	struct drm_device *dev = plane->dev;
759 760
	struct drm_crtc *crtc = state->base.crtc;
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
761
	struct intel_plane *intel_plane = to_intel_plane(plane);
762
	struct drm_framebuffer *fb = state->base.fb;
763 764 765 766 767 768
	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;
769 770
	int hscale, vscale;
	int max_scale, min_scale;
771
	bool can_scale;
772 773 774 775
	int pixel_size;

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

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

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

791 792 793
	/* setup can_scale, min_scale, max_scale */
	if (INTEL_INFO(dev)->gen >= 9) {
		/* use scaler when colorkey is not required */
794
		if (state->ckey.flags == I915_SET_COLORKEY_NONE) {
795 796 797 798 799 800 801 802 803 804 805 806 807 808
			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);
	}

809 810 811 812 813
	/*
	 * 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.
	 */
814
	drm_rect_rotate(src, fb->width << 16, fb->height << 16,
815
			state->base.rotation);
816

817
	hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale);
818
	BUG_ON(hscale < 0);
819

820
	vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale);
821
	BUG_ON(vscale < 0);
822

823
	state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
824

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

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

			return hscale;
		}

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

			return vscale;
		}

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

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

858
		/* sanity check to make sure the src viewport wasn't enlarged */
859 860 861 862
		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);
863 864 865 866 867 868 869

		/*
		 * 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.
		 */
870 871 872 873
		src_x = src->x1 >> 16;
		src_w = drm_rect_width(src) >> 16;
		src_y = src->y1 >> 16;
		src_h = drm_rect_height(src) >> 16;
874 875 876 877 878 879 880 881 882

		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.
			 */
883
			if (!can_scale)
884 885 886
				crtc_w &= ~1;

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

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

895
		WARN_ON(!can_scale);
896 897 898 899

		/* FIXME interlacing min height is 6 */

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

		if (src_w < 3 || src_h < 3)
903
			state->visible = false;
904

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

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

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

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

	return 0;
}

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

939 940
	crtc = crtc ? crtc : plane->crtc;

941
	if (!crtc->state->active)
942 943 944 945 946 947 948 949 950 951 952 953
		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 {
954
		intel_plane->disable_plane(plane, crtc);
955
	}
956 957
}

958 959 960 961 962
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;
963 964 965
	struct drm_plane_state *plane_state;
	struct drm_atomic_state *state;
	struct drm_modeset_acquire_ctx ctx;
966 967 968 969 970 971
	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;

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

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

980
	drm_modeset_acquire_init(&ctx, 0);
981

982 983 984 985
	state = drm_atomic_state_alloc(plane->dev);
	if (!state) {
		ret = -ENOMEM;
		goto out;
986
	}
987 988 989 990 991 992 993 994 995
	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);
		}
996

997 998
		if (ret != -EDEADLK)
			break;
999

1000 1001 1002
		drm_atomic_state_clear(state);
		drm_modeset_backoff(&ctx);
	}
1003

1004 1005
	if (ret)
		drm_atomic_state_free(state);
1006

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

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

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

1030
static const uint32_t vlv_plane_formats[] = {
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
	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,
};

1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
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,
};

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

1066
	if (INTEL_INFO(dev)->gen < 5)
1067 1068
		return -ENODEV;

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

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

1080 1081 1082
	switch (INTEL_INFO(dev)->gen) {
	case 5:
	case 6:
1083
		intel_plane->can_scale = true;
1084
		intel_plane->max_downscale = 16;
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
		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 已提交
1098
	case 8:
1099
		if (IS_IVYBRIDGE(dev)) {
1100
			intel_plane->can_scale = true;
1101 1102 1103 1104 1105
			intel_plane->max_downscale = 2;
		} else {
			intel_plane->can_scale = false;
			intel_plane->max_downscale = 1;
		}
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119

		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);
		}
1120
		break;
1121
	case 9:
1122
		intel_plane->can_scale = true;
1123 1124
		intel_plane->update_plane = skl_update_plane;
		intel_plane->disable_plane = skl_disable_plane;
1125
		state->scaler_id = -1;
1126 1127 1128 1129

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

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

1150
	intel_create_rotation_property(dev, intel_plane);
1151

1152 1153
	drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);

1154
out:
1155 1156
	return ret;
}