intel_sprite.c 33.3 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 "intel_frontbuffer.h"
40
#include <drm/i915_drm.h>
41 42
#include "i915_drv.h"

43 44 45 46 47 48 49 50 51 52 53 54 55 56
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;
	}
}

57 58
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
			     int usecs)
59 60
{
	/* paranoia */
61
	if (!adjusted_mode->crtc_htotal)
62 63
		return 1;

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

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

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

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

98 99
	local_irq_disable();

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

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

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

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

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

135
	finish_wait(wq, &wait);
136

137
	drm_crtc_vblank_put(&crtc->base);
138

139 140
	crtc->debug.scanline_start = scanline;
	crtc->debug.start_vbl_time = ktime_get();
141
	crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
142

143
	trace_i915_pipe_update_vblank_evaded(crtc);
144 145
}

146 147 148 149 150 151 152 153 154
/**
 * 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.
 */
155
void intel_pipe_update_end(struct intel_crtc *crtc, struct intel_flip_work *work)
156 157
{
	enum pipe pipe = crtc->pipe;
158
	int scanline_end = intel_get_crtc_scanline(crtc);
159
	u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
160
	ktime_t end_vbl_time = ktime_get();
161

162 163 164 165 166 167
	if (work) {
		work->flip_queued_vblank = end_vbl_count;
		smp_mb__before_atomic();
		atomic_set(&work->pending, 1);
	}

168
	trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
169

170 171 172 173 174 175 176 177 178 179 180 181 182 183
	/* We're still in the vblank-evade critical section, this can't race.
	 * Would be slightly nice to just grab the vblank count and arm the
	 * event outside of the critical section - the spinlock might spin for a
	 * while ... */
	if (crtc->base.state->event) {
		WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);

		spin_lock(&crtc->base.dev->event_lock);
		drm_crtc_arm_vblank_event(&crtc->base, crtc->base.state->event);
		spin_unlock(&crtc->base.dev->event_lock);

		crtc->base.state->event = NULL;
	}

184 185
	local_irq_enable();

186 187 188 189 190 191 192 193 194
	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);
	}
195 196
}

197
static void
198 199 200
skl_update_plane(struct drm_plane *drm_plane,
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
201 202
{
	struct drm_device *dev = drm_plane->dev;
203
	struct drm_i915_private *dev_priv = to_i915(dev);
204
	struct intel_plane *intel_plane = to_intel_plane(drm_plane);
205
	struct drm_framebuffer *fb = plane_state->base.fb;
206 207 208
	const struct skl_wm_values *wm = &dev_priv->wm.skl_results;
	struct drm_crtc *crtc = crtc_state->base.crtc;
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
209 210
	const int pipe = intel_plane->pipe;
	const int plane = intel_plane->plane + 1;
211 212
	const struct skl_plane_wm *p_wm =
		&crtc_state->wm.skl.optimal.planes[plane];
213
	u32 plane_ctl;
214
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
215
	u32 surf_addr = plane_state->main.offset;
216
	unsigned int rotation = plane_state->base.rotation;
217
	u32 stride = skl_plane_stride(fb, 0, rotation);
218 219 220 221
	int crtc_x = plane_state->base.dst.x1;
	int crtc_y = plane_state->base.dst.y1;
	uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
	uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
222 223
	uint32_t x = plane_state->main.x;
	uint32_t y = plane_state->main.y;
224 225
	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
226

227
	plane_ctl = PLANE_CTL_ENABLE |
228
		PLANE_CTL_PIPE_GAMMA_ENABLE |
229
		PLANE_CTL_PIPE_CSC_ENABLE;
230

231 232
	plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
	plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
233

234
	plane_ctl |= skl_plane_ctl_rotation(rotation);
235

236
	if (wm->dirty_pipes & drm_crtc_mask(crtc))
237
		skl_write_plane_wm(intel_crtc, p_wm, &wm->ddb, plane);
238

239 240 241 242 243 244 245 246 247 248 249
	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;

250 251 252 253 254 255 256
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

	I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
257
	I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
258
	I915_WRITE(PLANE_SIZE(pipe, plane), (src_h << 16) | src_w);
259 260

	/* program plane scaler */
261 262
	if (plane_state->scaler_id >= 0) {
		int scaler_id = plane_state->scaler_id;
263
		const struct intel_scaler *scaler;
264 265 266

		DRM_DEBUG_KMS("plane = %d PS_PLANE_SEL(plane) = 0x%x\n", plane,
			PS_PLANE_SEL(plane));
267 268 269 270 271

		scaler = &crtc_state->scaler_state.scalers[scaler_id];

		I915_WRITE(SKL_PS_CTRL(pipe, scaler_id),
			   PS_SCALER_EN | PS_PLANE_SEL(plane) | scaler->mode);
272 273 274 275 276 277 278 279 280 281
		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 284
	I915_WRITE(PLANE_SURF(pipe, plane),
		   intel_fb_gtt_offset(fb, rotation) + surf_addr);
285 286 287 288
	POSTING_READ(PLANE_SURF(pipe, plane));
}

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

298 299 300 301 302 303
	/*
	 * We only populate skl_results on watermark updates, and if the
	 * plane's visiblity isn't actually changing neither is its watermarks.
	 */
	if (!dplane->state->visible)
		skl_write_plane_wm(to_intel_crtc(crtc),
304 305
				   &cstate->wm.skl.optimal.planes[plane],
				   &dev_priv->wm.skl_results.ddb, plane);
306

307
	I915_WRITE(PLANE_CTL(pipe, plane), 0);
308

309 310
	I915_WRITE(PLANE_SURF(pipe, plane), 0);
	POSTING_READ(PLANE_SURF(pipe, plane));
311 312
}

313 314 315
static void
chv_update_csc(struct intel_plane *intel_plane, uint32_t format)
{
316
	struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
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 343 344 345 346 347 348 349 350 351
	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));
}

352
static void
353 354 355
vlv_update_plane(struct drm_plane *dplane,
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
356 357
{
	struct drm_device *dev = dplane->dev;
358
	struct drm_i915_private *dev_priv = to_i915(dev);
359
	struct intel_plane *intel_plane = to_intel_plane(dplane);
360
	struct drm_framebuffer *fb = plane_state->base.fb;
361 362 363
	int pipe = intel_plane->pipe;
	int plane = intel_plane->plane;
	u32 sprctl;
364
	u32 sprsurf_offset, linear_offset;
365
	unsigned int rotation = dplane->state->rotation;
366
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
367 368 369 370 371 372 373 374
	int crtc_x = plane_state->base.dst.x1;
	int crtc_y = plane_state->base.dst.y1;
	uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
	uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
	uint32_t x = plane_state->base.src.x1 >> 16;
	uint32_t y = plane_state->base.src.y1 >> 16;
	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
375

376
	sprctl = SP_ENABLE;
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 408 409 410 411 412 413 414 415 416 417 418 419 420

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

421 422 423 424 425 426
	/*
	 * Enable gamma to match primary/cursor plane behaviour.
	 * FIXME should be user controllable via propertiesa.
	 */
	sprctl |= SP_GAMMA_ENABLE;

427
	if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
428 429 430 431 432 433 434 435
		sprctl |= SP_TILED;

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

436 437
	intel_add_fb_offsets(&x, &y, plane_state, 0);
	sprsurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
438

439
	if (rotation == DRM_ROTATE_180) {
440 441 442 443 444 445
		sprctl |= SP_ROTATE_180;

		x += src_w;
		y += src_h;
	}

446
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
447

448 449 450 451 452 453 454 455 456
	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;

457
	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
458 459
		chv_update_csc(intel_plane, fb->pixel_format);

460 461 462
	I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
	I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);

463
	if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
464 465 466 467
		I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
	else
		I915_WRITE(SPLINOFF(pipe, plane), linear_offset);

468 469
	I915_WRITE(SPCONSTALPHA(pipe, plane), 0);

470 471
	I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
	I915_WRITE(SPCNTR(pipe, plane), sprctl);
472 473
	I915_WRITE(SPSURF(pipe, plane),
		   intel_fb_gtt_offset(fb, rotation) + sprsurf_offset);
474
	POSTING_READ(SPSURF(pipe, plane));
475 476 477
}

static void
478
vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
479 480
{
	struct drm_device *dev = dplane->dev;
481
	struct drm_i915_private *dev_priv = to_i915(dev);
482 483 484 485
	struct intel_plane *intel_plane = to_intel_plane(dplane);
	int pipe = intel_plane->pipe;
	int plane = intel_plane->plane;

486 487
	I915_WRITE(SPCNTR(pipe, plane), 0);

488
	I915_WRITE(SPSURF(pipe, plane), 0);
489
	POSTING_READ(SPSURF(pipe, plane));
490 491
}

492
static void
493 494 495
ivb_update_plane(struct drm_plane *plane,
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
496 497
{
	struct drm_device *dev = plane->dev;
498
	struct drm_i915_private *dev_priv = to_i915(dev);
499
	struct intel_plane *intel_plane = to_intel_plane(plane);
500
	struct drm_framebuffer *fb = plane_state->base.fb;
501
	enum pipe pipe = intel_plane->pipe;
502
	u32 sprctl, sprscale = 0;
503
	u32 sprsurf_offset, linear_offset;
504
	unsigned int rotation = plane_state->base.rotation;
505
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
506 507 508 509 510 511 512 513
	int crtc_x = plane_state->base.dst.x1;
	int crtc_y = plane_state->base.dst.y1;
	uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
	uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
	uint32_t x = plane_state->base.src.x1 >> 16;
	uint32_t y = plane_state->base.src.y1 >> 16;
	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
514

515
	sprctl = SPRITE_ENABLE;
516 517 518

	switch (fb->pixel_format) {
	case DRM_FORMAT_XBGR8888:
519
		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
520 521
		break;
	case DRM_FORMAT_XRGB8888:
522
		sprctl |= SPRITE_FORMAT_RGBX888;
523 524 525 526 527 528 529 530 531 532 533 534 535 536
		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:
537
		BUG();
538 539
	}

540 541 542 543 544 545
	/*
	 * Enable gamma to match primary/cursor plane behaviour.
	 * FIXME should be user controllable via propertiesa.
	 */
	sprctl |= SPRITE_GAMMA_ENABLE;

546
	if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
547 548
		sprctl |= SPRITE_TILED;

549
	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
550 551 552 553
		sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
	else
		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;

554
	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
555 556
		sprctl |= SPRITE_PIPE_CSC_ENABLE;

557 558 559 560 561 562
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

563
	if (crtc_w != src_w || crtc_h != src_h)
564 565
		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;

566 567
	intel_add_fb_offsets(&x, &y, plane_state, 0);
	sprsurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
568

569
	if (rotation == DRM_ROTATE_180) {
570 571 572
		sprctl |= SPRITE_ROTATE_180;

		/* HSW and BDW does this automagically in hardware */
573
		if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) {
574 575 576 577 578
			x += src_w;
			y += src_h;
		}
	}

579
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
580

581 582 583 584 585 586 587 588 589 590 591
	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;

592 593 594
	I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
	I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);

595 596
	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
	 * register */
597
	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
598
		I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
599
	else if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
600
		I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
601 602
	else
		I915_WRITE(SPRLINOFF(pipe), linear_offset);
603

604
	I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
605 606
	if (intel_plane->can_scale)
		I915_WRITE(SPRSCALE(pipe), sprscale);
607
	I915_WRITE(SPRCTL(pipe), sprctl);
608
	I915_WRITE(SPRSURF(pipe),
609
		   intel_fb_gtt_offset(fb, rotation) + sprsurf_offset);
610
	POSTING_READ(SPRSURF(pipe));
611 612 613
}

static void
614
ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
615 616
{
	struct drm_device *dev = plane->dev;
617
	struct drm_i915_private *dev_priv = to_i915(dev);
618 619 620
	struct intel_plane *intel_plane = to_intel_plane(plane);
	int pipe = intel_plane->pipe;

621
	I915_WRITE(SPRCTL(pipe), 0);
622
	/* Can't leave the scaler enabled... */
623 624
	if (intel_plane->can_scale)
		I915_WRITE(SPRSCALE(pipe), 0);
625

626 627
	I915_WRITE(SPRSURF(pipe), 0);
	POSTING_READ(SPRSURF(pipe));
628 629 630
}

static void
631 632 633
ilk_update_plane(struct drm_plane *plane,
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
634 635
{
	struct drm_device *dev = plane->dev;
636
	struct drm_i915_private *dev_priv = to_i915(dev);
637
	struct intel_plane *intel_plane = to_intel_plane(plane);
638
	struct drm_framebuffer *fb = plane_state->base.fb;
V
Ville Syrjälä 已提交
639
	int pipe = intel_plane->pipe;
640
	u32 dvscntr, dvsscale;
641
	u32 dvssurf_offset, linear_offset;
642
	unsigned int rotation = plane_state->base.rotation;
643
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
644 645 646 647 648 649 650 651
	int crtc_x = plane_state->base.dst.x1;
	int crtc_y = plane_state->base.dst.y1;
	uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
	uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
	uint32_t x = plane_state->base.src.x1 >> 16;
	uint32_t y = plane_state->base.src.y1 >> 16;
	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
652

653
	dvscntr = DVS_ENABLE;
654 655 656

	switch (fb->pixel_format) {
	case DRM_FORMAT_XBGR8888:
657
		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
658 659
		break;
	case DRM_FORMAT_XRGB8888:
660
		dvscntr |= DVS_FORMAT_RGBX888;
661 662 663 664 665 666 667 668 669 670 671 672 673 674
		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:
675
		BUG();
676 677
	}

678 679 680 681 682 683
	/*
	 * Enable gamma to match primary/cursor plane behaviour.
	 * FIXME should be user controllable via propertiesa.
	 */
	dvscntr |= DVS_GAMMA_ENABLE;

684
	if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
685 686
		dvscntr |= DVS_TILED;

687
	if (IS_GEN6(dev_priv))
688
		dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
689 690 691 692 693 694 695

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

696
	dvsscale = 0;
697
	if (crtc_w != src_w || crtc_h != src_h)
698 699
		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;

700 701
	intel_add_fb_offsets(&x, &y, plane_state, 0);
	dvssurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
702

703
	if (rotation == DRM_ROTATE_180) {
704 705 706 707 708 709
		dvscntr |= DVS_ROTATE_180;

		x += src_w;
		y += src_h;
	}

710
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
711

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

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

726
	if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
727
		I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
728 729
	else
		I915_WRITE(DVSLINOFF(pipe), linear_offset);
730 731 732 733

	I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
	I915_WRITE(DVSSCALE(pipe), dvsscale);
	I915_WRITE(DVSCNTR(pipe), dvscntr);
734
	I915_WRITE(DVSSURF(pipe),
735
		   intel_fb_gtt_offset(fb, rotation) + dvssurf_offset);
736
	POSTING_READ(DVSSURF(pipe));
737 738 739
}

static void
740
ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
741 742
{
	struct drm_device *dev = plane->dev;
743
	struct drm_i915_private *dev_priv = to_i915(dev);
744 745 746
	struct intel_plane *intel_plane = to_intel_plane(plane);
	int pipe = intel_plane->pipe;

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

751
	I915_WRITE(DVSSURF(pipe), 0);
752
	POSTING_READ(DVSSURF(pipe));
753 754 755
}

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

776 777 778 779 780 781 782 783 784 785
	src->x1 = state->base.src_x;
	src->y1 = state->base.src_y;
	src->x2 = state->base.src_x + state->base.src_w;
	src->y2 = state->base.src_y + state->base.src_h;

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

786
	if (!fb) {
787
		state->base.visible = false;
788
		return 0;
789
	}
790

791 792 793
	/* Don't modify another pipe's plane */
	if (intel_plane->pipe != intel_crtc->pipe) {
		DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
794
		return -EINVAL;
795
	}
796

797 798 799
	/* FIXME check all gen limits */
	if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) {
		DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
800
		return -EINVAL;
801
	}
802

803
	/* setup can_scale, min_scale, max_scale */
804
	if (INTEL_GEN(dev_priv) >= 9) {
805
		/* use scaler when colorkey is not required */
806
		if (state->ckey.flags == I915_SET_COLORKEY_NONE) {
807 808 809 810 811 812 813 814 815 816 817 818 819 820
			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);
	}

821 822 823 824 825
	/*
	 * 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.
	 */
826
	drm_rect_rotate(src, fb->width << 16, fb->height << 16,
827
			state->base.rotation);
828

829
	hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale);
830
	BUG_ON(hscale < 0);
831

832
	vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale);
833
	BUG_ON(vscale < 0);
834

835
	state->base.visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
836

837 838 839 840
	crtc_x = dst->x1;
	crtc_y = dst->y1;
	crtc_w = drm_rect_width(dst);
	crtc_h = drm_rect_height(dst);
841

842
	if (state->base.visible) {
843
		/* check again in case clipping clamped the results */
844
		hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
845 846
		if (hscale < 0) {
			DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
847 848
			drm_rect_debug_print("src: ", src, true);
			drm_rect_debug_print("dst: ", dst, false);
849 850 851 852

			return hscale;
		}

853
		vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
854 855
		if (vscale < 0) {
			DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
856 857
			drm_rect_debug_print("src: ", src, true);
			drm_rect_debug_print("dst: ", dst, false);
858 859 860 861

			return vscale;
		}

862
		/* Make the source viewport size an exact multiple of the scaling factors. */
863 864 865
		drm_rect_adjust_size(src,
				     drm_rect_width(dst) * hscale - drm_rect_width(src),
				     drm_rect_height(dst) * vscale - drm_rect_height(src));
866

867
		drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16,
868
				    state->base.rotation);
869

870
		/* sanity check to make sure the src viewport wasn't enlarged */
871 872 873 874
		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);
875 876 877 878 879 880 881

		/*
		 * 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.
		 */
882 883 884 885
		src_x = src->x1 >> 16;
		src_w = drm_rect_width(src) >> 16;
		src_y = src->y1 >> 16;
		src_h = drm_rect_height(src) >> 16;
886 887 888 889 890 891 892 893 894

		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.
			 */
895
			if (!can_scale)
896 897 898
				crtc_w &= ~1;

			if (crtc_w == 0)
899
				state->base.visible = false;
900 901 902 903
		}
	}

	/* Check size restrictions when scaling */
904
	if (state->base.visible && (src_w != crtc_w || src_h != crtc_h)) {
905
		unsigned int width_bytes;
906
		int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
907

908
		WARN_ON(!can_scale);
909 910 911 912

		/* FIXME interlacing min height is 6 */

		if (crtc_w < 3 || crtc_h < 3)
913
			state->base.visible = false;
914 915

		if (src_w < 3 || src_h < 3)
916
			state->base.visible = false;
917

918
		width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
919

920
		if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 ||
921
		    width_bytes > 4096 || fb->pitches[0] > 4096)) {
922 923 924 925 926
			DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
			return -EINVAL;
		}
	}

927
	if (state->base.visible) {
928 929 930 931
		src->x1 = src_x << 16;
		src->x2 = (src_x + src_w) << 16;
		src->y1 = src_y << 16;
		src->y2 = (src_y + src_h) << 16;
932 933 934 935 936 937 938
	}

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

939
	if (INTEL_GEN(dev_priv) >= 9) {
940 941 942 943 944
		ret = skl_check_plane_surface(state);
		if (ret)
			return ret;
	}

945 946 947
	return 0;
}

948 949 950
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
			      struct drm_file *file_priv)
{
951
	struct drm_i915_private *dev_priv = to_i915(dev);
952 953
	struct drm_intel_sprite_colorkey *set = data;
	struct drm_plane *plane;
954 955 956
	struct drm_plane_state *plane_state;
	struct drm_atomic_state *state;
	struct drm_modeset_acquire_ctx ctx;
957 958 959 960 961 962
	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;

963
	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
964 965 966
	    set->flags & I915_SET_COLORKEY_DESTINATION)
		return -EINVAL;

R
Rob Clark 已提交
967
	plane = drm_plane_find(dev, set->plane_id);
968 969
	if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
		return -ENOENT;
970

971
	drm_modeset_acquire_init(&ctx, 0);
972

973 974 975 976
	state = drm_atomic_state_alloc(plane->dev);
	if (!state) {
		ret = -ENOMEM;
		goto out;
977
	}
978 979 980 981 982 983 984 985 986
	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);
		}
987

988 989
		if (ret != -EDEADLK)
			break;
990

991 992 993
		drm_atomic_state_clear(state);
		drm_modeset_backoff(&ctx);
	}
994

995 996
	if (ret)
		drm_atomic_state_free(state);
997

998 999 1000 1001
out:
	drm_modeset_drop_locks(&ctx);
	drm_modeset_acquire_fini(&ctx);
	return ret;
1002 1003
}

1004
static const uint32_t ilk_plane_formats[] = {
1005 1006 1007 1008 1009 1010 1011
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

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

1021
static const uint32_t vlv_plane_formats[] = {
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
	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,
};

1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
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,
};

1047
int
1048
intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
1049
{
1050
	struct drm_i915_private *dev_priv = to_i915(dev);
1051 1052
	struct intel_plane *intel_plane = NULL;
	struct intel_plane_state *state = NULL;
1053
	unsigned long possible_crtcs;
1054 1055
	const uint32_t *plane_formats;
	int num_plane_formats;
1056 1057
	int ret;

1058
	if (INTEL_INFO(dev)->gen < 5)
1059 1060
		return -ENODEV;

1061
	intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
1062 1063 1064 1065
	if (!intel_plane) {
		ret = -ENOMEM;
		goto fail;
	}
1066

1067 1068
	state = intel_create_plane_state(&intel_plane->base);
	if (!state) {
1069 1070
		ret = -ENOMEM;
		goto fail;
1071
	}
1072
	intel_plane->base.state = &state->base;
1073

1074 1075 1076
	switch (INTEL_INFO(dev)->gen) {
	case 5:
	case 6:
1077
		intel_plane->can_scale = true;
1078
		intel_plane->max_downscale = 16;
1079 1080 1081
		intel_plane->update_plane = ilk_update_plane;
		intel_plane->disable_plane = ilk_disable_plane;

1082
		if (IS_GEN6(dev_priv)) {
1083 1084 1085 1086 1087 1088 1089 1090 1091
			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 已提交
1092
	case 8:
1093
		if (IS_IVYBRIDGE(dev_priv)) {
1094
			intel_plane->can_scale = true;
1095 1096 1097 1098 1099
			intel_plane->max_downscale = 2;
		} else {
			intel_plane->can_scale = false;
			intel_plane->max_downscale = 1;
		}
1100

1101
		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
			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);
		}
1114
		break;
1115
	case 9:
1116
		intel_plane->can_scale = true;
1117 1118
		intel_plane->update_plane = skl_update_plane;
		intel_plane->disable_plane = skl_disable_plane;
1119
		state->scaler_id = -1;
1120 1121 1122 1123

		plane_formats = skl_plane_formats;
		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
		break;
1124
	default:
1125 1126 1127
		MISSING_CASE(INTEL_INFO(dev)->gen);
		ret = -ENODEV;
		goto fail;
1128 1129 1130
	}

	intel_plane->pipe = pipe;
1131
	intel_plane->plane = plane;
1132
	intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane);
1133
	intel_plane->check_plane = intel_check_sprite_plane;
1134

1135
	possible_crtcs = (1 << pipe);
1136

1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
	if (INTEL_INFO(dev)->gen >= 9)
		ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
					       &intel_plane_funcs,
					       plane_formats, num_plane_formats,
					       DRM_PLANE_TYPE_OVERLAY,
					       "plane %d%c", plane + 2, pipe_name(pipe));
	else
		ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
					       &intel_plane_funcs,
					       plane_formats, num_plane_formats,
					       DRM_PLANE_TYPE_OVERLAY,
					       "sprite %c", sprite_name(pipe, plane));
1149 1150
	if (ret)
		goto fail;
1151

1152
	intel_create_rotation_property(dev, intel_plane);
1153

1154 1155
	drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);

1156 1157 1158 1159 1160 1161
	return 0;

fail:
	kfree(state);
	kfree(intel_plane);

1162 1163
	return ret;
}