intel_sprite.c 39.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
#include <drm/drmP.h>
33
#include <drm/drm_atomic_helper.h>
34 35
#include <drm/drm_crtc.h>
#include <drm/drm_fourcc.h>
36
#include <drm/drm_rect.h>
37
#include <drm/drm_atomic.h>
38
#include <drm/drm_plane_helper.h>
39
#include "intel_drv.h"
40
#include "intel_frontbuffer.h"
41
#include <drm/i915_drm.h>
42 43
#include "i915_drv.h"

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

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

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

69 70 71 72 73
/* FIXME: We should instead only take spinlocks once for the entire update
 * instead of once per mmio. */
#if IS_ENABLED(CONFIG_PROVE_LOCKING)
#define VBLANK_EVASION_TIME_US 250
#else
74
#define VBLANK_EVASION_TIME_US 100
75
#endif
76

77 78
/**
 * intel_pipe_update_start() - start update of a set of display registers
79
 * @new_crtc_state: the new crtc state
80 81 82 83 84 85 86
 *
 * 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
87
 * avoid random delays.
88
 */
89
void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
90
{
91
	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
92
	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
93
	const struct drm_display_mode *adjusted_mode = &new_crtc_state->base.adjusted_mode;
94 95
	long timeout = msecs_to_jiffies_timeout(1);
	int scanline, min, max, vblank_start;
96
	wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
97
	bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
98
		intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
99 100
	DEFINE_WAIT(wait);

101 102
	vblank_start = adjusted_mode->crtc_vblank_start;
	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
103 104 105
		vblank_start = DIV_ROUND_UP(vblank_start, 2);

	/* FIXME needs to be calibrated sensibly */
106 107
	min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
						      VBLANK_EVASION_TIME_US);
108 109
	max = vblank_start - 1;

110 111
	local_irq_disable();

112
	if (min <= 0 || max <= 0)
113
		return;
114

115
	if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
116
		return;
117

118 119 120
	crtc->debug.min_vbl = min;
	crtc->debug.max_vbl = max;
	trace_i915_pipe_update_start(crtc);
121

122 123 124 125 126 127
	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.
		 */
128
		prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

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

147
	finish_wait(wq, &wait);
148

149
	drm_crtc_vblank_put(&crtc->base);
150

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
	/*
	 * On VLV/CHV DSI the scanline counter would appear to
	 * increment approx. 1/3 of a scanline before start of vblank.
	 * The registers still get latched at start of vblank however.
	 * This means we must not write any registers on the first
	 * line of vblank (since not the whole line is actually in
	 * vblank). And unfortunately we can't use the interrupt to
	 * wait here since it will fire too soon. We could use the
	 * frame start interrupt instead since it will fire after the
	 * critical scanline, but that would require more changes
	 * in the interrupt code. So for now we'll just do the nasty
	 * thing and poll for the bad scanline to pass us by.
	 *
	 * FIXME figure out if BXT+ DSI suffers from this as well
	 */
	while (need_vlv_dsi_wa && scanline == vblank_start)
		scanline = intel_get_crtc_scanline(crtc);

169 170
	crtc->debug.scanline_start = scanline;
	crtc->debug.start_vbl_time = ktime_get();
171
	crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
172

173
	trace_i915_pipe_update_vblank_evaded(crtc);
174 175
}

176 177
/**
 * intel_pipe_update_end() - end update of a set of display registers
178
 * @new_crtc_state: the new crtc state
179 180 181
 *
 * Mark the end of an update started with intel_pipe_update_start(). This
 * re-enables interrupts and verifies the update was actually completed
182
 * before a vblank.
183
 */
184
void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
185
{
186
	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
187
	enum pipe pipe = crtc->pipe;
188
	int scanline_end = intel_get_crtc_scanline(crtc);
189
	u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
190
	ktime_t end_vbl_time = ktime_get();
191
	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
192

193
	trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
194

195 196 197 198
	/* 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 ... */
199
	if (new_crtc_state->base.event) {
200 201 202
		WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);

		spin_lock(&crtc->base.dev->event_lock);
203
		drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event);
204 205
		spin_unlock(&crtc->base.dev->event_lock);

206
		new_crtc_state->base.event = NULL;
207 208
	}

209 210
	local_irq_enable();

211 212 213
	if (intel_vgpu_active(dev_priv))
		return;

214 215 216 217 218 219 220 221
	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);
222 223 224 225
	}
#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
	else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
		 VBLANK_EVASION_TIME_US)
226 227 228 229
		DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
			 pipe_name(pipe),
			 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
			 VBLANK_EVASION_TIME_US);
230
#endif
231 232
}

233
void
234
skl_update_plane(struct intel_plane *plane,
235 236
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
237
{
238 239 240 241
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	const struct drm_framebuffer *fb = plane_state->base.fb;
	enum plane_id plane_id = plane->id;
	enum pipe pipe = plane->pipe;
242
	u32 plane_ctl = plane_state->ctl;
243
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
244
	u32 surf_addr = plane_state->main.offset;
245
	unsigned int rotation = plane_state->base.rotation;
246
	u32 stride = skl_plane_stride(fb, 0, rotation);
247
	u32 aux_stride = skl_plane_stride(fb, 1, rotation);
248 249 250 251
	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);
252 253
	uint32_t x = plane_state->main.x;
	uint32_t y = plane_state->main.y;
254 255
	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
256
	unsigned long irqflags;
257

258 259 260 261 262 263
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

264 265
	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);

266
	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
267
		I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id),
268
			      plane_state->color_ctl);
269
	if (key->flags) {
270 271 272
		I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
		I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), key->max_value);
		I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), key->channel_mask);
273 274
	}

275 276 277
	I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
	I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
	I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
278 279 280 281
	I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
		      (plane_state->aux.offset - surf_addr) | aux_stride);
	I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
		      (plane_state->aux.y << 16) | plane_state->aux.x);
282 283

	/* program plane scaler */
284 285
	if (plane_state->scaler_id >= 0) {
		int scaler_id = plane_state->scaler_id;
286
		const struct intel_scaler *scaler;
287

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

290 291 292 293 294 295
		I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
			      PS_SCALER_EN | PS_PLANE_SEL(plane_id) | scaler->mode);
		I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
		I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
		I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id),
			      ((crtc_w + 1) << 16)|(crtc_h + 1));
296

297
		I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0);
298
	} else {
299
		I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
300 301
	}

302 303 304 305 306 307
	I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
	I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
		      intel_plane_ggtt_offset(plane_state) + surf_addr);
	POSTING_READ_FW(PLANE_SURF(pipe, plane_id));

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
308 309
}

310
void
311
skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
312
{
313 314 315
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum plane_id plane_id = plane->id;
	enum pipe pipe = plane->pipe;
316 317 318
	unsigned long irqflags;

	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
319

320
	I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
321

322 323 324 325
	I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
	POSTING_READ_FW(PLANE_SURF(pipe, plane_id));

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
326 327
}

328
static void
329
chv_update_csc(struct intel_plane *plane, uint32_t format)
330
{
331 332
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum plane_id plane_id = plane->id;
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347

	/* 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.
	 */
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
	I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(-64));
	I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
	I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));

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

	I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(940) | SPCSC_IMIN(64));
	I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
	I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448));

	I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
	I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
	I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
365 366
}

367 368
static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
			  const struct intel_plane_state *plane_state)
369
{
370
	const struct drm_framebuffer *fb = plane_state->base.fb;
371
	unsigned int rotation = plane_state->base.rotation;
372
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
373
	u32 sprctl;
374

375
	sprctl = SP_ENABLE | SP_GAMMA_ENABLE;
376

V
Ville Syrjälä 已提交
377
	switch (fb->format->format) {
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
	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:
412 413
		MISSING_CASE(fb->format->format);
		return 0;
414 415
	}

V
Ville Syrjälä 已提交
416
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
417 418
		sprctl |= SP_TILED;

419
	if (rotation & DRM_MODE_ROTATE_180)
420 421
		sprctl |= SP_ROTATE_180;

422
	if (rotation & DRM_MODE_REFLECT_X)
423 424
		sprctl |= SP_MIRROR;

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

428 429 430 431
	return sprctl;
}

static void
432
vlv_update_plane(struct intel_plane *plane,
433 434 435
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
436 437 438 439
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	const struct drm_framebuffer *fb = plane_state->base.fb;
	enum pipe pipe = plane->pipe;
	enum plane_id plane_id = plane->id;
440
	u32 sprctl = plane_state->ctl;
441 442
	u32 sprsurf_offset = plane_state->main.offset;
	u32 linear_offset;
443 444 445 446 447
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
	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);
448 449
	uint32_t x = plane_state->main.x;
	uint32_t y = plane_state->main.y;
450 451
	unsigned long irqflags;

452 453 454 455
	/* Sizes are 0 based */
	crtc_w--;
	crtc_h--;

456
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
457

458 459
	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);

460
	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
461
		chv_update_csc(plane, fb->format->format);
462

463
	if (key->flags) {
464 465 466
		I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
		I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
		I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
467
	}
468 469
	I915_WRITE_FW(SPSTRIDE(pipe, plane_id), fb->pitches[0]);
	I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
470

V
Ville Syrjälä 已提交
471
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
472
		I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
473
	else
474
		I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
475

476
	I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
477

478 479 480 481 482 483 484
	I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
	I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
	I915_WRITE_FW(SPSURF(pipe, plane_id),
		      intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
	POSTING_READ_FW(SPSURF(pipe, plane_id));

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
485 486 487
}

static void
488
vlv_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
489
{
490 491 492
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
	enum plane_id plane_id = plane->id;
493 494 495
	unsigned long irqflags;

	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
496

497
	I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
498

499 500 501 502
	I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
	POSTING_READ_FW(SPSURF(pipe, plane_id));

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
503 504
}

505 506
static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
			  const struct intel_plane_state *plane_state)
507
{
508 509 510
	struct drm_i915_private *dev_priv =
		to_i915(plane_state->base.plane->dev);
	const struct drm_framebuffer *fb = plane_state->base.fb;
511
	unsigned int rotation = plane_state->base.rotation;
512
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
513 514 515
	u32 sprctl;

	sprctl = SPRITE_ENABLE | SPRITE_GAMMA_ENABLE;
516

517 518 519 520 521
	if (IS_IVYBRIDGE(dev_priv))
		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;

	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
		sprctl |= SPRITE_PIPE_CSC_ENABLE;
522

V
Ville Syrjälä 已提交
523
	switch (fb->format->format) {
524
	case DRM_FORMAT_XBGR8888:
525
		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
526 527
		break;
	case DRM_FORMAT_XRGB8888:
528
		sprctl |= SPRITE_FORMAT_RGBX888;
529 530 531 532 533 534 535 536 537 538 539 540 541 542
		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:
543 544
		MISSING_CASE(fb->format->format);
		return 0;
545 546
	}

V
Ville Syrjälä 已提交
547
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
548 549
		sprctl |= SPRITE_TILED;

550
	if (rotation & DRM_MODE_ROTATE_180)
551 552
		sprctl |= SPRITE_ROTATE_180;

553 554 555 556 557
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
		sprctl |= SPRITE_DEST_KEY;
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
		sprctl |= SPRITE_SOURCE_KEY;

558 559 560 561
	return sprctl;
}

static void
562
ivb_update_plane(struct intel_plane *plane,
563 564 565
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
566 567 568
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	const struct drm_framebuffer *fb = plane_state->base.fb;
	enum pipe pipe = plane->pipe;
569
	u32 sprctl = plane_state->ctl, sprscale = 0;
570 571
	u32 sprsurf_offset = plane_state->main.offset;
	u32 linear_offset;
572 573 574 575 576
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
	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);
577 578
	uint32_t x = plane_state->main.x;
	uint32_t y = plane_state->main.y;
579 580 581 582
	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
	unsigned long irqflags;

583 584 585 586 587 588
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

589
	if (crtc_w != src_w || crtc_h != src_h)
590 591
		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;

592
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
593

594 595
	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);

596
	if (key->flags) {
597 598 599
		I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
		I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
		I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
600 601
	}

602 603
	I915_WRITE_FW(SPRSTRIDE(pipe), fb->pitches[0]);
	I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
604

605 606
	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
	 * register */
607
	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
608
		I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
V
Ville Syrjälä 已提交
609
	else if (fb->modifier == I915_FORMAT_MOD_X_TILED)
610
		I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
611
	else
612
		I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
613

614
	I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
615
	if (plane->can_scale)
616 617 618 619 620 621 622
		I915_WRITE_FW(SPRSCALE(pipe), sprscale);
	I915_WRITE_FW(SPRCTL(pipe), sprctl);
	I915_WRITE_FW(SPRSURF(pipe),
		      intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
	POSTING_READ_FW(SPRSURF(pipe));

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
623 624 625
}

static void
626
ivb_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
627
{
628 629
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
630 631 632
	unsigned long irqflags;

	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
633

634
	I915_WRITE_FW(SPRCTL(pipe), 0);
635
	/* Can't leave the scaler enabled... */
636
	if (plane->can_scale)
637
		I915_WRITE_FW(SPRSCALE(pipe), 0);
638

639 640 641 642
	I915_WRITE_FW(SPRSURF(pipe), 0);
	POSTING_READ_FW(SPRSURF(pipe));

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
643 644
}

645
static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
646
			  const struct intel_plane_state *plane_state)
647
{
648 649 650
	struct drm_i915_private *dev_priv =
		to_i915(plane_state->base.plane->dev);
	const struct drm_framebuffer *fb = plane_state->base.fb;
651
	unsigned int rotation = plane_state->base.rotation;
652
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
653 654 655
	u32 dvscntr;

	dvscntr = DVS_ENABLE | DVS_GAMMA_ENABLE;
656

657 658
	if (IS_GEN6(dev_priv))
		dvscntr |= DVS_TRICKLE_FEED_DISABLE;
659

V
Ville Syrjälä 已提交
660
	switch (fb->format->format) {
661
	case DRM_FORMAT_XBGR8888:
662
		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
663 664
		break;
	case DRM_FORMAT_XRGB8888:
665
		dvscntr |= DVS_FORMAT_RGBX888;
666 667 668 669 670 671 672 673 674 675 676 677 678 679
		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:
680 681
		MISSING_CASE(fb->format->format);
		return 0;
682 683
	}

V
Ville Syrjälä 已提交
684
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
685 686
		dvscntr |= DVS_TILED;

687
	if (rotation & DRM_MODE_ROTATE_180)
688 689
		dvscntr |= DVS_ROTATE_180;

690 691 692 693 694
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
		dvscntr |= DVS_DEST_KEY;
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
		dvscntr |= DVS_SOURCE_KEY;

695 696 697 698
	return dvscntr;
}

static void
699
g4x_update_plane(struct intel_plane *plane,
700 701 702
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
703 704 705
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	const struct drm_framebuffer *fb = plane_state->base.fb;
	enum pipe pipe = plane->pipe;
706 707 708
	u32 dvscntr = plane_state->ctl, dvsscale = 0;
	u32 dvssurf_offset = plane_state->main.offset;
	u32 linear_offset;
709 710 711 712 713
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
	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);
714 715
	uint32_t x = plane_state->main.x;
	uint32_t y = plane_state->main.y;
716 717 718 719
	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
	unsigned long irqflags;

720 721 722 723 724 725
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

726
	if (crtc_w != src_w || crtc_h != src_h)
727 728
		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;

729
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
730

731 732
	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);

733
	if (key->flags) {
734 735 736
		I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
		I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
		I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
737 738
	}

739 740
	I915_WRITE_FW(DVSSTRIDE(pipe), fb->pitches[0]);
	I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
741

V
Ville Syrjälä 已提交
742
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
743
		I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
744
	else
745 746 747 748 749 750 751 752 753 754
		I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);

	I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
	I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
	I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
	I915_WRITE_FW(DVSSURF(pipe),
		      intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
	POSTING_READ_FW(DVSSURF(pipe));

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
755 756 757
}

static void
758
g4x_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
759
{
760 761
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
762
	unsigned long irqflags;
763

764 765 766
	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);

	I915_WRITE_FW(DVSCNTR(pipe), 0);
767
	/* Disable the scaler */
768 769 770 771
	I915_WRITE_FW(DVSSCALE(pipe), 0);

	I915_WRITE_FW(DVSSURF(pipe), 0);
	POSTING_READ_FW(DVSSURF(pipe));
772

773
	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
774 775 776
}

static int
777
intel_check_sprite_plane(struct intel_plane *plane,
778
			 struct intel_crtc_state *crtc_state,
779
			 struct intel_plane_state *state)
780
{
781 782
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
783
	struct drm_framebuffer *fb = state->base.fb;
784 785 786
	int crtc_x, crtc_y;
	unsigned int crtc_w, crtc_h;
	uint32_t src_x, src_y, src_w, src_h;
787 788
	struct drm_rect *src = &state->base.src;
	struct drm_rect *dst = &state->base.dst;
789
	const struct drm_rect *clip = &state->clip;
790 791
	int hscale, vscale;
	int max_scale, min_scale;
792
	bool can_scale;
793
	int ret;
794

795 796
	*src = drm_plane_state_src(&state->base);
	*dst = drm_plane_state_dest(&state->base);
797

798
	if (!fb) {
799
		state->base.visible = false;
800
		return 0;
801
	}
802

803
	/* Don't modify another pipe's plane */
804
	if (plane->pipe != crtc->pipe) {
805
		DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
806
		return -EINVAL;
807
	}
808

809 810 811
	/* FIXME check all gen limits */
	if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) {
		DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
812
		return -EINVAL;
813
	}
814

815
	/* setup can_scale, min_scale, max_scale */
816
	if (INTEL_GEN(dev_priv) >= 9) {
817
		/* use scaler when colorkey is not required */
818
		if (state->ckey.flags == I915_SET_COLORKEY_NONE) {
819 820
			can_scale = 1;
			min_scale = 1;
821
			max_scale = skl_max_scale(crtc, crtc_state);
822 823 824 825 826 827
		} else {
			can_scale = 0;
			min_scale = DRM_PLANE_HELPER_NO_SCALING;
			max_scale = DRM_PLANE_HELPER_NO_SCALING;
		}
	} else {
828 829 830
		can_scale = plane->can_scale;
		max_scale = plane->max_downscale << 16;
		min_scale = plane->can_scale ? 1 : (1 << 16);
831 832
	}

833 834 835 836 837
	/*
	 * 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.
	 */
838
	drm_rect_rotate(src, fb->width << 16, fb->height << 16,
839
			state->base.rotation);
840

841
	hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale);
842
	BUG_ON(hscale < 0);
843

844
	vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale);
845
	BUG_ON(vscale < 0);
846

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

849 850 851 852
	crtc_x = dst->x1;
	crtc_y = dst->y1;
	crtc_w = drm_rect_width(dst);
	crtc_h = drm_rect_height(dst);
853

854
	if (state->base.visible) {
855
		/* check again in case clipping clamped the results */
856
		hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
857 858
		if (hscale < 0) {
			DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
859 860
			drm_rect_debug_print("src: ", src, true);
			drm_rect_debug_print("dst: ", dst, false);
861 862 863 864

			return hscale;
		}

865
		vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
866 867
		if (vscale < 0) {
			DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
868 869
			drm_rect_debug_print("src: ", src, true);
			drm_rect_debug_print("dst: ", dst, false);
870 871 872 873

			return vscale;
		}

874
		/* Make the source viewport size an exact multiple of the scaling factors. */
875 876 877
		drm_rect_adjust_size(src,
				     drm_rect_width(dst) * hscale - drm_rect_width(src),
				     drm_rect_height(dst) * vscale - drm_rect_height(src));
878

879
		drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16,
880
				    state->base.rotation);
881

882
		/* sanity check to make sure the src viewport wasn't enlarged */
883 884 885 886
		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);
887 888 889 890 891 892 893

		/*
		 * 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.
		 */
894 895 896 897
		src_x = src->x1 >> 16;
		src_w = drm_rect_width(src) >> 16;
		src_y = src->y1 >> 16;
		src_h = drm_rect_height(src) >> 16;
898

V
Ville Syrjälä 已提交
899
		if (format_is_yuv(fb->format->format)) {
900 901 902 903 904 905 906
			src_x &= ~1;
			src_w &= ~1;

			/*
			 * Must keep src and dst the
			 * same if we can't scale.
			 */
907
			if (!can_scale)
908 909 910
				crtc_w &= ~1;

			if (crtc_w == 0)
911
				state->base.visible = false;
912 913 914 915
		}
	}

	/* Check size restrictions when scaling */
916
	if (state->base.visible && (src_w != crtc_w || src_h != crtc_h)) {
917
		unsigned int width_bytes;
918
		int cpp = fb->format->cpp[0];
919

920
		WARN_ON(!can_scale);
921 922 923 924

		/* FIXME interlacing min height is 6 */

		if (crtc_w < 3 || crtc_h < 3)
925
			state->base.visible = false;
926 927

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

930
		width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
931

932
		if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 ||
933
		    width_bytes > 4096 || fb->pitches[0] > 4096)) {
934 935 936 937 938
			DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
			return -EINVAL;
		}
	}

939
	if (state->base.visible) {
940 941 942 943
		src->x1 = src_x << 16;
		src->x2 = (src_x + src_w) << 16;
		src->y1 = src_y << 16;
		src->y2 = (src_y + src_h) << 16;
944 945 946 947 948 949 950
	}

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

951
	if (INTEL_GEN(dev_priv) >= 9) {
952 953 954
		ret = skl_check_plane_surface(state);
		if (ret)
			return ret;
955 956 957

		state->ctl = skl_plane_ctl(crtc_state, state);
	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
958 959 960 961
		ret = i9xx_check_plane_surface(state);
		if (ret)
			return ret;

962 963
		state->ctl = vlv_sprite_ctl(crtc_state, state);
	} else if (INTEL_GEN(dev_priv) >= 7) {
964 965 966 967
		ret = i9xx_check_plane_surface(state);
		if (ret)
			return ret;

968 969
		state->ctl = ivb_sprite_ctl(crtc_state, state);
	} else {
970 971 972 973
		ret = i9xx_check_plane_surface(state);
		if (ret)
			return ret;

974
		state->ctl = g4x_sprite_ctl(crtc_state, state);
975 976
	}

977 978 979
	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
		state->color_ctl = glk_plane_color_ctl(crtc_state, state);

980 981 982
	return 0;
}

983 984 985
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
			      struct drm_file *file_priv)
{
986
	struct drm_i915_private *dev_priv = to_i915(dev);
987 988
	struct drm_intel_sprite_colorkey *set = data;
	struct drm_plane *plane;
989 990 991
	struct drm_plane_state *plane_state;
	struct drm_atomic_state *state;
	struct drm_modeset_acquire_ctx ctx;
992 993 994 995 996 997
	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;

998
	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
999 1000 1001
	    set->flags & I915_SET_COLORKEY_DESTINATION)
		return -EINVAL;

1002
	plane = drm_plane_find(dev, file_priv, set->plane_id);
1003 1004
	if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
		return -ENOENT;
1005

1006
	drm_modeset_acquire_init(&ctx, 0);
1007

1008 1009 1010 1011
	state = drm_atomic_state_alloc(plane->dev);
	if (!state) {
		ret = -ENOMEM;
		goto out;
1012
	}
1013 1014 1015 1016 1017 1018 1019 1020 1021
	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);
		}
1022

1023 1024
		if (ret != -EDEADLK)
			break;
1025

1026 1027 1028
		drm_atomic_state_clear(state);
		drm_modeset_backoff(&ctx);
	}
1029

1030
	drm_atomic_state_put(state);
1031 1032 1033 1034
out:
	drm_modeset_drop_locks(&ctx);
	drm_modeset_acquire_fini(&ctx);
	return ret;
1035 1036
}

1037
static const uint32_t g4x_plane_formats[] = {
1038 1039 1040 1041 1042 1043 1044
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

1045 1046 1047 1048 1049 1050
static const uint64_t i9xx_plane_format_modifiers[] = {
	I915_FORMAT_MOD_X_TILED,
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
};

1051
static const uint32_t snb_plane_formats[] = {
1052 1053 1054 1055 1056 1057 1058 1059
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

1060
static const uint32_t vlv_plane_formats[] = {
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
	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,
};

1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
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,
};

1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
static const uint64_t skl_plane_format_modifiers[] = {
	I915_FORMAT_MOD_X_TILED,
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
};

static bool g4x_sprite_plane_format_mod_supported(struct drm_plane *plane,
						  uint32_t format,
						  uint64_t modifier)
{
	switch (format) {
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_YUYV:
	case DRM_FORMAT_YVYU:
	case DRM_FORMAT_UYVY:
	case DRM_FORMAT_VYUY:
		if (modifier == DRM_FORMAT_MOD_LINEAR ||
		    modifier == I915_FORMAT_MOD_X_TILED)
			return true;
		/* fall through */
	default:
		return false;
	}
}

static bool vlv_sprite_plane_format_mod_supported(struct drm_plane *plane,
						  uint32_t format,
						  uint64_t modifier)
{
	switch (format) {
	case DRM_FORMAT_YUYV:
	case DRM_FORMAT_YVYU:
	case DRM_FORMAT_UYVY:
	case DRM_FORMAT_VYUY:
	case DRM_FORMAT_RGB565:
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_ARGB8888:
	case DRM_FORMAT_XBGR2101010:
	case DRM_FORMAT_ABGR2101010:
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_ABGR8888:
		if (modifier == DRM_FORMAT_MOD_LINEAR ||
		    modifier == I915_FORMAT_MOD_X_TILED)
			return true;
		/* fall through */
	default:
		return false;
	}
}

static bool skl_sprite_plane_format_mod_supported(struct drm_plane *plane,
						  uint32_t format,
						  uint64_t modifier)
{
	/* This is the same as primary plane since SKL has universal planes */
	switch (format) {
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_ARGB8888:
	case DRM_FORMAT_ABGR8888:
	case DRM_FORMAT_RGB565:
	case DRM_FORMAT_XRGB2101010:
	case DRM_FORMAT_XBGR2101010:
	case DRM_FORMAT_YUYV:
	case DRM_FORMAT_YVYU:
	case DRM_FORMAT_UYVY:
	case DRM_FORMAT_VYUY:
		if (modifier == I915_FORMAT_MOD_Yf_TILED)
			return true;
		/* fall through */
	case DRM_FORMAT_C8:
		if (modifier == DRM_FORMAT_MOD_LINEAR ||
		    modifier == I915_FORMAT_MOD_X_TILED ||
		    modifier == I915_FORMAT_MOD_Y_TILED)
			return true;
		/* fall through */
	default:
		return false;
	}
}

static bool intel_sprite_plane_format_mod_supported(struct drm_plane *plane,
                                                    uint32_t format,
                                                    uint64_t modifier)
{
	struct drm_i915_private *dev_priv = to_i915(plane->dev);

	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
		return false;

	if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_INTEL &&
	    modifier != DRM_FORMAT_MOD_LINEAR)
		return false;

	if (INTEL_GEN(dev_priv) >= 9)
		return skl_sprite_plane_format_mod_supported(plane, format, modifier);
	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
		return vlv_sprite_plane_format_mod_supported(plane, format, modifier);
	else
		return g4x_sprite_plane_format_mod_supported(plane, format, modifier);

	unreachable();
}

1191
static const struct drm_plane_funcs intel_sprite_plane_funcs = {
1192 1193 1194 1195 1196 1197 1198 1199 1200 1201
        .update_plane = drm_atomic_helper_update_plane,
        .disable_plane = drm_atomic_helper_disable_plane,
        .destroy = intel_plane_destroy,
        .atomic_get_property = intel_plane_atomic_get_property,
        .atomic_set_property = intel_plane_atomic_set_property,
        .atomic_duplicate_state = intel_plane_duplicate_state,
        .atomic_destroy_state = intel_plane_destroy_state,
        .format_mod_supported = intel_sprite_plane_format_mod_supported,
};

1202
struct intel_plane *
1203 1204
intel_sprite_plane_create(struct drm_i915_private *dev_priv,
			  enum pipe pipe, int plane)
1205
{
1206 1207
	struct intel_plane *intel_plane = NULL;
	struct intel_plane_state *state = NULL;
1208
	unsigned long possible_crtcs;
1209
	const uint32_t *plane_formats;
1210
	const uint64_t *modifiers;
1211
	unsigned int supported_rotations;
1212
	int num_plane_formats;
1213 1214
	int ret;

1215
	intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
1216 1217 1218 1219
	if (!intel_plane) {
		ret = -ENOMEM;
		goto fail;
	}
1220

1221 1222
	state = intel_create_plane_state(&intel_plane->base);
	if (!state) {
1223 1224
		ret = -ENOMEM;
		goto fail;
1225
	}
1226
	intel_plane->base.state = &state->base;
1227

1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
	if (INTEL_GEN(dev_priv) >= 10) {
		intel_plane->can_scale = true;
		state->scaler_id = -1;

		intel_plane->update_plane = skl_update_plane;
		intel_plane->disable_plane = skl_disable_plane;

		plane_formats = skl_plane_formats;
		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
		modifiers = skl_plane_format_modifiers;
	} else if (INTEL_GEN(dev_priv) >= 9) {
1239
		intel_plane->can_scale = true;
V
Ville Syrjälä 已提交
1240
		state->scaler_id = -1;
1241

V
Ville Syrjälä 已提交
1242 1243 1244 1245 1246
		intel_plane->update_plane = skl_update_plane;
		intel_plane->disable_plane = skl_disable_plane;

		plane_formats = skl_plane_formats;
		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
1247
		modifiers = skl_plane_format_modifiers;
V
Ville Syrjälä 已提交
1248 1249 1250 1251 1252 1253
	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
		intel_plane->can_scale = false;
		intel_plane->max_downscale = 1;

		intel_plane->update_plane = vlv_update_plane;
		intel_plane->disable_plane = vlv_disable_plane;
1254

V
Ville Syrjälä 已提交
1255 1256
		plane_formats = vlv_plane_formats;
		num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
1257
		modifiers = i9xx_plane_format_modifiers;
V
Ville Syrjälä 已提交
1258
	} else if (INTEL_GEN(dev_priv) >= 7) {
1259
		if (IS_IVYBRIDGE(dev_priv)) {
1260
			intel_plane->can_scale = true;
1261 1262 1263 1264 1265
			intel_plane->max_downscale = 2;
		} else {
			intel_plane->can_scale = false;
			intel_plane->max_downscale = 1;
		}
1266

V
Ville Syrjälä 已提交
1267 1268
		intel_plane->update_plane = ivb_update_plane;
		intel_plane->disable_plane = ivb_disable_plane;
1269

V
Ville Syrjälä 已提交
1270 1271
		plane_formats = snb_plane_formats;
		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1272
		modifiers = i9xx_plane_format_modifiers;
V
Ville Syrjälä 已提交
1273 1274 1275 1276
	} else {
		intel_plane->can_scale = true;
		intel_plane->max_downscale = 16;

1277 1278
		intel_plane->update_plane = g4x_update_plane;
		intel_plane->disable_plane = g4x_disable_plane;
1279

1280
		modifiers = i9xx_plane_format_modifiers;
V
Ville Syrjälä 已提交
1281
		if (IS_GEN6(dev_priv)) {
1282 1283
			plane_formats = snb_plane_formats;
			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
V
Ville Syrjälä 已提交
1284
		} else {
1285 1286
			plane_formats = g4x_plane_formats;
			num_plane_formats = ARRAY_SIZE(g4x_plane_formats);
1287
		}
1288 1289
	}

1290
	if (INTEL_GEN(dev_priv) >= 9) {
1291
		supported_rotations =
1292 1293
			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
			DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
1294 1295
	} else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
		supported_rotations =
1296 1297
			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
			DRM_MODE_REFLECT_X;
1298 1299
	} else {
		supported_rotations =
1300
			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1301 1302
	}

1303
	intel_plane->pipe = pipe;
1304
	intel_plane->plane = plane;
1305
	intel_plane->id = PLANE_SPRITE0 + plane;
1306
	intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane);
1307
	intel_plane->check_plane = intel_check_sprite_plane;
1308

1309
	possible_crtcs = (1 << pipe);
1310

V
Ville Syrjälä 已提交
1311
	if (INTEL_GEN(dev_priv) >= 9)
1312
		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
1313
					       possible_crtcs, &intel_sprite_plane_funcs,
1314
					       plane_formats, num_plane_formats,
1315 1316
					       modifiers,
					       DRM_PLANE_TYPE_OVERLAY,
1317 1318
					       "plane %d%c", plane + 2, pipe_name(pipe));
	else
1319
		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
1320
					       possible_crtcs, &intel_sprite_plane_funcs,
1321
					       plane_formats, num_plane_formats,
1322 1323
					       modifiers,
					       DRM_PLANE_TYPE_OVERLAY,
1324
					       "sprite %c", sprite_name(pipe, plane));
1325 1326
	if (ret)
		goto fail;
1327

1328
	drm_plane_create_rotation_property(&intel_plane->base,
1329
					   DRM_MODE_ROTATE_0,
1330
					   supported_rotations);
1331

1332 1333
	drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);

1334
	return intel_plane;
1335 1336 1337 1338 1339

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

1340
	return ERR_PTR(ret);
1341
}