intel_sprite.c 44.6 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
bool intel_format_is_yuv(u32 format)
45 46 47 48 49 50 51 52 53 54 55 56
{
	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
/* 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
73
#define VBLANK_EVASION_TIME_US 100
74
#endif
75

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

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

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

109 110
	local_irq_disable();

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

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

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

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

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

146
	finish_wait(wq, &wait);
147

148
	drm_crtc_vblank_put(&crtc->base);
149

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
	/*
	 * 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);

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

172
	trace_i915_pipe_update_vblank_evaded(crtc);
173 174
}

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

192
	trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
193

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

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

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

208 209
	local_irq_enable();

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

213 214 215 216 217 218 219 220
	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);
221 222 223 224
	}
#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
	else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
		 VBLANK_EVASION_TIME_US)
225 226 227 228
		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);
229
#endif
230 231
}

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

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

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

265
	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
266
		I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id),
267
			      plane_state->color_ctl);
268

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 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
bool
skl_plane_get_hw_state(struct intel_plane *plane)
{
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum intel_display_power_domain power_domain;
	enum plane_id plane_id = plane->id;
	enum pipe pipe = plane->pipe;
	bool ret;

	power_domain = POWER_DOMAIN_PIPE(pipe);
	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
		return false;

	ret = I915_READ(PLANE_CTL(pipe, plane_id)) & PLANE_CTL_ENABLE;

	intel_display_power_put(dev_priv, power_domain);

	return ret;
}

348
static void
349
chv_update_csc(const struct intel_plane_state *plane_state)
350
{
351
	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
352
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
353
	const struct drm_framebuffer *fb = plane_state->base.fb;
354
	enum plane_id plane_id = plane->id;
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
	/*
	 * |r|   | c0 c1 c2 |   |cr|
	 * |g| = | c3 c4 c5 | x |y |
	 * |b|   | c6 c7 c8 |   |cb|
	 *
	 * Coefficients are s3.12.
	 *
	 * Cb and Cr apparently come in as signed already, and
	 * we always get full range data in on account of CLRC0/1.
	 */
	static const s16 csc_matrix[][9] = {
		/* BT.601 full range YCbCr -> full range RGB */
		[DRM_COLOR_YCBCR_BT601] = {
			 5743, 4096,     0,
			-2925, 4096, -1410,
			    0, 4096,  7258,
		},
		/* BT.709 full range YCbCr -> full range RGB */
		[DRM_COLOR_YCBCR_BT709] = {
			 6450, 4096,     0,
			-1917, 4096,  -767,
			    0, 4096,  7601,
		},
	};
	const s16 *csc = csc_matrix[plane_state->base.color_encoding];
380 381

	/* Seems RGB data bypasses the CSC always */
382
	if (!intel_format_is_yuv(fb->format->format))
383 384
		return;

385
	I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
386 387 388
	I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
	I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));

389 390 391 392 393
	I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
	I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
	I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
	I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
	I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8]));
394

395 396 397
	I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
	I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
	I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
398 399 400 401

	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));
402 403
}

404 405 406 407 408 409 410 411 412 413 414 415 416
#define SIN_0 0
#define COS_0 1

static void
vlv_update_clrc(const struct intel_plane_state *plane_state)
{
	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
	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;
	int contrast, brightness, sh_scale, sh_sin, sh_cos;

417
	if (intel_format_is_yuv(fb->format->format)) {
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
		/*
		 * Expand limited range to full range:
		 * Contrast is applied first and is used to expand Y range.
		 * Brightness is applied second and is used to remove the
		 * offset from Y. Saturation/hue is used to expand CbCr range.
		 */
		contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
		brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
		sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
		sh_sin = SIN_0 * sh_scale;
		sh_cos = COS_0 * sh_scale;
	} else {
		/* Pass-through everything. */
		contrast = 1 << 6;
		brightness = 0;
		sh_scale = 1 << 7;
		sh_sin = SIN_0 * sh_scale;
		sh_cos = COS_0 * sh_scale;
	}

	/* FIXME these register are single buffered :( */
	I915_WRITE_FW(SPCLRC0(pipe, plane_id),
		      SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
	I915_WRITE_FW(SPCLRC1(pipe, plane_id),
		      SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
}

445 446
static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
			  const struct intel_plane_state *plane_state)
447
{
448
	const struct drm_framebuffer *fb = plane_state->base.fb;
449
	unsigned int rotation = plane_state->base.rotation;
450
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
451
	u32 sprctl;
452

453
	sprctl = SP_ENABLE | SP_GAMMA_ENABLE;
454

V
Ville Syrjälä 已提交
455
	switch (fb->format->format) {
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
	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:
490 491
		MISSING_CASE(fb->format->format);
		return 0;
492 493
	}

494 495 496
	if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
		sprctl |= SP_YUV_FORMAT_BT709;

V
Ville Syrjälä 已提交
497
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
498 499
		sprctl |= SP_TILED;

500
	if (rotation & DRM_MODE_ROTATE_180)
501 502
		sprctl |= SP_ROTATE_180;

503
	if (rotation & DRM_MODE_REFLECT_X)
504 505
		sprctl |= SP_MIRROR;

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

509 510 511 512
	return sprctl;
}

static void
513
vlv_update_plane(struct intel_plane *plane,
514 515 516
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
517 518 519 520
	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;
521
	u32 sprctl = plane_state->ctl;
522 523
	u32 sprsurf_offset = plane_state->main.offset;
	u32 linear_offset;
524 525 526 527 528
	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);
529 530
	uint32_t x = plane_state->main.x;
	uint32_t y = plane_state->main.y;
531 532
	unsigned long irqflags;

533 534 535 536
	/* Sizes are 0 based */
	crtc_w--;
	crtc_h--;

537
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
538

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

541 542
	vlv_update_clrc(plane_state);

543
	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
544
		chv_update_csc(plane_state);
545

546
	if (key->flags) {
547 548 549
		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);
550
	}
551 552
	I915_WRITE_FW(SPSTRIDE(pipe, plane_id), fb->pitches[0]);
	I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
553

V
Ville Syrjälä 已提交
554
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
555
		I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
556
	else
557
		I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
558

559
	I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
560

561 562 563 564 565 566 567
	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);
568 569 570
}

static void
571
vlv_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
572
{
573 574 575
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
	enum plane_id plane_id = plane->id;
576 577 578
	unsigned long irqflags;

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

580
	I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
581

582 583 584 585
	I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
	POSTING_READ_FW(SPSURF(pipe, plane_id));

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
586 587
}

588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
static bool
vlv_plane_get_hw_state(struct intel_plane *plane)
{
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum intel_display_power_domain power_domain;
	enum plane_id plane_id = plane->id;
	enum pipe pipe = plane->pipe;
	bool ret;

	power_domain = POWER_DOMAIN_PIPE(pipe);
	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
		return false;

	ret = I915_READ(SPCNTR(pipe, plane_id)) & SP_ENABLE;

	intel_display_power_put(dev_priv, power_domain);

	return ret;
}

608 609
static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
			  const struct intel_plane_state *plane_state)
610
{
611 612 613
	struct drm_i915_private *dev_priv =
		to_i915(plane_state->base.plane->dev);
	const struct drm_framebuffer *fb = plane_state->base.fb;
614
	unsigned int rotation = plane_state->base.rotation;
615
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
616 617 618
	u32 sprctl;

	sprctl = SPRITE_ENABLE | SPRITE_GAMMA_ENABLE;
619

620 621 622 623 624
	if (IS_IVYBRIDGE(dev_priv))
		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;

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

V
Ville Syrjälä 已提交
626
	switch (fb->format->format) {
627
	case DRM_FORMAT_XBGR8888:
628
		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
629 630
		break;
	case DRM_FORMAT_XRGB8888:
631
		sprctl |= SPRITE_FORMAT_RGBX888;
632 633 634 635 636 637 638 639 640 641 642 643 644 645
		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:
646 647
		MISSING_CASE(fb->format->format);
		return 0;
648 649
	}

650 651 652
	if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
		sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;

V
Ville Syrjälä 已提交
653
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
654 655
		sprctl |= SPRITE_TILED;

656
	if (rotation & DRM_MODE_ROTATE_180)
657 658
		sprctl |= SPRITE_ROTATE_180;

659 660 661 662 663
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
		sprctl |= SPRITE_DEST_KEY;
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
		sprctl |= SPRITE_SOURCE_KEY;

664 665 666 667
	return sprctl;
}

static void
668
ivb_update_plane(struct intel_plane *plane,
669 670 671
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
672 673 674
	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;
675
	u32 sprctl = plane_state->ctl, sprscale = 0;
676 677
	u32 sprsurf_offset = plane_state->main.offset;
	u32 linear_offset;
678 679 680 681 682
	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);
683 684
	uint32_t x = plane_state->main.x;
	uint32_t y = plane_state->main.y;
685 686 687 688
	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;

689 690 691 692 693 694
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

695
	if (crtc_w != src_w || crtc_h != src_h)
696 697
		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;

698
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
699

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

702
	if (key->flags) {
703 704 705
		I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
		I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
		I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
706 707
	}

708 709
	I915_WRITE_FW(SPRSTRIDE(pipe), fb->pitches[0]);
	I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
710

711 712
	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
	 * register */
713
	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
714
		I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
V
Ville Syrjälä 已提交
715
	else if (fb->modifier == I915_FORMAT_MOD_X_TILED)
716
		I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
717
	else
718
		I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
719

720
	I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
721
	if (plane->can_scale)
722 723 724 725 726 727 728
		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);
729 730 731
}

static void
732
ivb_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
733
{
734 735
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
736 737 738
	unsigned long irqflags;

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

740
	I915_WRITE_FW(SPRCTL(pipe), 0);
741
	/* Can't leave the scaler enabled... */
742
	if (plane->can_scale)
743
		I915_WRITE_FW(SPRSCALE(pipe), 0);
744

745 746 747 748
	I915_WRITE_FW(SPRSURF(pipe), 0);
	POSTING_READ_FW(SPRSURF(pipe));

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
749 750
}

751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
static bool
ivb_plane_get_hw_state(struct intel_plane *plane)
{
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum intel_display_power_domain power_domain;
	enum pipe pipe = plane->pipe;
	bool ret;

	power_domain = POWER_DOMAIN_PIPE(pipe);
	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
		return false;

	ret =  I915_READ(SPRCTL(pipe)) & SPRITE_ENABLE;

	intel_display_power_put(dev_priv, power_domain);

	return ret;
}

770
static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
771
			  const struct intel_plane_state *plane_state)
772
{
773 774 775
	struct drm_i915_private *dev_priv =
		to_i915(plane_state->base.plane->dev);
	const struct drm_framebuffer *fb = plane_state->base.fb;
776
	unsigned int rotation = plane_state->base.rotation;
777
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
778 779 780
	u32 dvscntr;

	dvscntr = DVS_ENABLE | DVS_GAMMA_ENABLE;
781

782 783
	if (IS_GEN6(dev_priv))
		dvscntr |= DVS_TRICKLE_FEED_DISABLE;
784

V
Ville Syrjälä 已提交
785
	switch (fb->format->format) {
786
	case DRM_FORMAT_XBGR8888:
787
		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
788 789
		break;
	case DRM_FORMAT_XRGB8888:
790
		dvscntr |= DVS_FORMAT_RGBX888;
791 792 793 794 795 796 797 798 799 800 801 802 803 804
		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:
805 806
		MISSING_CASE(fb->format->format);
		return 0;
807 808
	}

809 810 811
	if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
		dvscntr |= DVS_YUV_FORMAT_BT709;

V
Ville Syrjälä 已提交
812
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
813 814
		dvscntr |= DVS_TILED;

815
	if (rotation & DRM_MODE_ROTATE_180)
816 817
		dvscntr |= DVS_ROTATE_180;

818 819 820 821 822
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
		dvscntr |= DVS_DEST_KEY;
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
		dvscntr |= DVS_SOURCE_KEY;

823 824 825 826
	return dvscntr;
}

static void
827
g4x_update_plane(struct intel_plane *plane,
828 829 830
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
831 832 833
	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;
834 835 836
	u32 dvscntr = plane_state->ctl, dvsscale = 0;
	u32 dvssurf_offset = plane_state->main.offset;
	u32 linear_offset;
837 838 839 840 841
	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);
842 843
	uint32_t x = plane_state->main.x;
	uint32_t y = plane_state->main.y;
844 845 846 847
	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;

848 849 850 851 852 853
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

854
	if (crtc_w != src_w || crtc_h != src_h)
855 856
		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;

857
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
858

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

861
	if (key->flags) {
862 863 864
		I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
		I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
		I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
865 866
	}

867 868
	I915_WRITE_FW(DVSSTRIDE(pipe), fb->pitches[0]);
	I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
869

V
Ville Syrjälä 已提交
870
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
871
		I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
872
	else
873 874 875 876 877 878 879 880 881 882
		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);
883 884 885
}

static void
886
g4x_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
887
{
888 889
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
890
	unsigned long irqflags;
891

892 893 894
	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);

	I915_WRITE_FW(DVSCNTR(pipe), 0);
895
	/* Disable the scaler */
896 897 898 899
	I915_WRITE_FW(DVSSCALE(pipe), 0);

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

901
	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
902 903
}

904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
static bool
g4x_plane_get_hw_state(struct intel_plane *plane)
{
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum intel_display_power_domain power_domain;
	enum pipe pipe = plane->pipe;
	bool ret;

	power_domain = POWER_DOMAIN_PIPE(pipe);
	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
		return false;

	ret = I915_READ(DVSCNTR(pipe)) & DVS_ENABLE;

	intel_display_power_put(dev_priv, power_domain);

	return ret;
}

923
static int
924
intel_check_sprite_plane(struct intel_plane *plane,
925
			 struct intel_crtc_state *crtc_state,
926
			 struct intel_plane_state *state)
927
{
928 929
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
930
	struct drm_framebuffer *fb = state->base.fb;
931 932 933
	int crtc_x, crtc_y;
	unsigned int crtc_w, crtc_h;
	uint32_t src_x, src_y, src_w, src_h;
934 935
	struct drm_rect *src = &state->base.src;
	struct drm_rect *dst = &state->base.dst;
936
	struct drm_rect clip = {};
937
	int max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384;
938 939
	int hscale, vscale;
	int max_scale, min_scale;
940
	bool can_scale;
941
	int ret;
942

943 944
	*src = drm_plane_state_src(&state->base);
	*dst = drm_plane_state_dest(&state->base);
945

946
	if (!fb) {
947
		state->base.visible = false;
948
		return 0;
949
	}
950

951
	/* Don't modify another pipe's plane */
952
	if (plane->pipe != crtc->pipe) {
953
		DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
954
		return -EINVAL;
955
	}
956

957
	/* FIXME check all gen limits */
958
	if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > max_stride) {
959
		DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
960
		return -EINVAL;
961
	}
962

963
	/* setup can_scale, min_scale, max_scale */
964
	if (INTEL_GEN(dev_priv) >= 9) {
965
		/* use scaler when colorkey is not required */
966
		if (!state->ckey.flags) {
967 968
			can_scale = 1;
			min_scale = 1;
969
			max_scale = skl_max_scale(crtc, crtc_state);
970 971 972 973 974 975
		} else {
			can_scale = 0;
			min_scale = DRM_PLANE_HELPER_NO_SCALING;
			max_scale = DRM_PLANE_HELPER_NO_SCALING;
		}
	} else {
976 977 978
		can_scale = plane->can_scale;
		max_scale = plane->max_downscale << 16;
		min_scale = plane->can_scale ? 1 : (1 << 16);
979 980
	}

981 982 983 984 985
	/*
	 * 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.
	 */
986
	drm_rect_rotate(src, fb->width << 16, fb->height << 16,
987
			state->base.rotation);
988

989
	hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale);
990
	BUG_ON(hscale < 0);
991

992
	vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale);
993
	BUG_ON(vscale < 0);
994

995 996 997 998 999
	if (crtc_state->base.enable)
		drm_mode_get_hv_timing(&crtc_state->base.mode,
				       &clip.x2, &clip.y2);

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

1001 1002 1003 1004
	crtc_x = dst->x1;
	crtc_y = dst->y1;
	crtc_w = drm_rect_width(dst);
	crtc_h = drm_rect_height(dst);
1005

1006
	if (state->base.visible) {
1007
		/* check again in case clipping clamped the results */
1008
		hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
1009 1010
		if (hscale < 0) {
			DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
1011 1012
			drm_rect_debug_print("src: ", src, true);
			drm_rect_debug_print("dst: ", dst, false);
1013 1014 1015 1016

			return hscale;
		}

1017
		vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
1018 1019
		if (vscale < 0) {
			DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
1020 1021
			drm_rect_debug_print("src: ", src, true);
			drm_rect_debug_print("dst: ", dst, false);
1022 1023 1024 1025

			return vscale;
		}

1026
		/* Make the source viewport size an exact multiple of the scaling factors. */
1027 1028 1029
		drm_rect_adjust_size(src,
				     drm_rect_width(dst) * hscale - drm_rect_width(src),
				     drm_rect_height(dst) * vscale - drm_rect_height(src));
1030

1031
		drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16,
1032
				    state->base.rotation);
1033

1034
		/* sanity check to make sure the src viewport wasn't enlarged */
1035 1036 1037 1038
		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);
1039 1040 1041 1042 1043 1044 1045

		/*
		 * 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.
		 */
1046 1047 1048 1049
		src_x = src->x1 >> 16;
		src_w = drm_rect_width(src) >> 16;
		src_y = src->y1 >> 16;
		src_h = drm_rect_height(src) >> 16;
1050

1051
		if (intel_format_is_yuv(fb->format->format)) {
1052 1053 1054 1055 1056 1057 1058
			src_x &= ~1;
			src_w &= ~1;

			/*
			 * Must keep src and dst the
			 * same if we can't scale.
			 */
1059
			if (!can_scale)
1060 1061 1062
				crtc_w &= ~1;

			if (crtc_w == 0)
1063
				state->base.visible = false;
1064 1065 1066 1067
		}
	}

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

1072
		WARN_ON(!can_scale);
1073 1074 1075 1076

		/* FIXME interlacing min height is 6 */

		if (crtc_w < 3 || crtc_h < 3)
1077
			state->base.visible = false;
1078 1079

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

1082
		width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1083

1084
		if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 ||
1085
		    width_bytes > 4096 || fb->pitches[0] > 4096)) {
1086 1087 1088 1089 1090
			DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
			return -EINVAL;
		}
	}

1091
	if (state->base.visible) {
1092 1093 1094 1095
		src->x1 = src_x << 16;
		src->x2 = (src_x + src_w) << 16;
		src->y1 = src_y << 16;
		src->y2 = (src_y + src_h) << 16;
1096 1097 1098 1099 1100 1101 1102
	}

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

1103
	if (INTEL_GEN(dev_priv) >= 9) {
1104
		ret = skl_check_plane_surface(crtc_state, state);
1105 1106
		if (ret)
			return ret;
1107 1108 1109

		state->ctl = skl_plane_ctl(crtc_state, state);
	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1110 1111 1112 1113
		ret = i9xx_check_plane_surface(state);
		if (ret)
			return ret;

1114 1115
		state->ctl = vlv_sprite_ctl(crtc_state, state);
	} else if (INTEL_GEN(dev_priv) >= 7) {
1116 1117 1118 1119
		ret = i9xx_check_plane_surface(state);
		if (ret)
			return ret;

1120 1121
		state->ctl = ivb_sprite_ctl(crtc_state, state);
	} else {
1122 1123 1124 1125
		ret = i9xx_check_plane_surface(state);
		if (ret)
			return ret;

1126
		state->ctl = g4x_sprite_ctl(crtc_state, state);
1127 1128
	}

1129 1130 1131
	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
		state->color_ctl = glk_plane_color_ctl(crtc_state, state);

1132 1133 1134
	return 0;
}

1135 1136 1137
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
			      struct drm_file *file_priv)
{
1138
	struct drm_i915_private *dev_priv = to_i915(dev);
1139 1140
	struct drm_intel_sprite_colorkey *set = data;
	struct drm_plane *plane;
1141 1142 1143
	struct drm_plane_state *plane_state;
	struct drm_atomic_state *state;
	struct drm_modeset_acquire_ctx ctx;
1144 1145
	int ret = 0;

1146 1147 1148
	/* ignore the pointless "none" flag */
	set->flags &= ~I915_SET_COLORKEY_NONE;

1149 1150 1151 1152
	/* 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;

1153
	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1154 1155 1156
	    set->flags & I915_SET_COLORKEY_DESTINATION)
		return -EINVAL;

1157
	plane = drm_plane_find(dev, file_priv, set->plane_id);
1158 1159
	if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
		return -ENOENT;
1160

1161
	drm_modeset_acquire_init(&ctx, 0);
1162

1163 1164 1165 1166
	state = drm_atomic_state_alloc(plane->dev);
	if (!state) {
		ret = -ENOMEM;
		goto out;
1167
	}
1168 1169 1170 1171 1172 1173 1174 1175 1176
	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);
		}
1177

1178 1179
		if (ret != -EDEADLK)
			break;
1180

1181 1182 1183
		drm_atomic_state_clear(state);
		drm_modeset_backoff(&ctx);
	}
1184

1185
	drm_atomic_state_put(state);
1186 1187 1188 1189
out:
	drm_modeset_drop_locks(&ctx);
	drm_modeset_acquire_fini(&ctx);
	return ret;
1190 1191
}

1192
static const uint32_t g4x_plane_formats[] = {
1193 1194 1195 1196 1197 1198 1199
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

1200 1201 1202 1203 1204 1205
static const uint64_t i9xx_plane_format_modifiers[] = {
	I915_FORMAT_MOD_X_TILED,
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
};

1206
static const uint32_t snb_plane_formats[] = {
1207 1208 1209 1210 1211 1212 1213 1214
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

1215
static const uint32_t vlv_plane_formats[] = {
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228
	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,
};

1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240
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,
};

1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
static const uint64_t skl_plane_format_modifiers_noccs[] = {
	I915_FORMAT_MOD_Yf_TILED,
	I915_FORMAT_MOD_Y_TILED,
	I915_FORMAT_MOD_X_TILED,
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
};

static const uint64_t skl_plane_format_modifiers_ccs[] = {
	I915_FORMAT_MOD_Yf_TILED_CCS,
	I915_FORMAT_MOD_Y_TILED_CCS,
1252 1253
	I915_FORMAT_MOD_Yf_TILED,
	I915_FORMAT_MOD_Y_TILED,
1254 1255 1256 1257 1258
	I915_FORMAT_MOD_X_TILED,
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
};

1259
static bool g4x_mod_supported(uint32_t format, uint64_t modifier)
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275
{
	switch (format) {
	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;
	}
}

1276
static bool snb_mod_supported(uint32_t format, uint64_t modifier)
1277 1278
{
	switch (format) {
1279 1280
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_XBGR8888:
1281 1282 1283 1284
	case DRM_FORMAT_YUYV:
	case DRM_FORMAT_YVYU:
	case DRM_FORMAT_UYVY:
	case DRM_FORMAT_VYUY:
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296
		if (modifier == DRM_FORMAT_MOD_LINEAR ||
		    modifier == I915_FORMAT_MOD_X_TILED)
			return true;
		/* fall through */
	default:
		return false;
	}
}

static bool vlv_mod_supported(uint32_t format, uint64_t modifier)
{
	switch (format) {
1297
	case DRM_FORMAT_RGB565:
1298
	case DRM_FORMAT_ABGR8888:
1299
	case DRM_FORMAT_ARGB8888:
1300 1301
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_XRGB8888:
1302 1303
	case DRM_FORMAT_XBGR2101010:
	case DRM_FORMAT_ABGR2101010:
1304 1305 1306 1307
	case DRM_FORMAT_YUYV:
	case DRM_FORMAT_YVYU:
	case DRM_FORMAT_UYVY:
	case DRM_FORMAT_VYUY:
1308 1309 1310 1311 1312 1313 1314 1315 1316
		if (modifier == DRM_FORMAT_MOD_LINEAR ||
		    modifier == I915_FORMAT_MOD_X_TILED)
			return true;
		/* fall through */
	default:
		return false;
	}
}

1317
static bool skl_mod_supported(uint32_t format, uint64_t modifier)
1318 1319 1320 1321 1322 1323
{
	switch (format) {
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_ARGB8888:
	case DRM_FORMAT_ABGR8888:
1324 1325 1326 1327
		if (modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
		    modifier == I915_FORMAT_MOD_Y_TILED_CCS)
			return true;
		/* fall through */
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362
	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)
1363
		return skl_mod_supported(format, modifier);
1364
	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
1365 1366 1367
		return vlv_mod_supported(format, modifier);
	else if (INTEL_GEN(dev_priv) >= 6)
		return snb_mod_supported(format, modifier);
1368
	else
1369
		return g4x_mod_supported(format, modifier);
1370 1371
}

1372
static const struct drm_plane_funcs intel_sprite_plane_funcs = {
1373 1374 1375 1376 1377 1378 1379 1380 1381 1382
        .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,
};

1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399
bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
		       enum pipe pipe, enum plane_id plane_id)
{
	if (plane_id == PLANE_CURSOR)
		return false;

	if (INTEL_GEN(dev_priv) >= 10)
		return true;

	if (IS_GEMINILAKE(dev_priv))
		return pipe != PIPE_C;

	return pipe != PIPE_C &&
		(plane_id == PLANE_PRIMARY ||
		 plane_id == PLANE_SPRITE0);
}

1400
struct intel_plane *
1401 1402
intel_sprite_plane_create(struct drm_i915_private *dev_priv,
			  enum pipe pipe, int plane)
1403
{
1404 1405
	struct intel_plane *intel_plane = NULL;
	struct intel_plane_state *state = NULL;
1406
	unsigned long possible_crtcs;
1407
	const uint32_t *plane_formats;
1408
	const uint64_t *modifiers;
1409
	unsigned int supported_rotations;
1410
	int num_plane_formats;
1411 1412
	int ret;

1413
	intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
1414 1415 1416 1417
	if (!intel_plane) {
		ret = -ENOMEM;
		goto fail;
	}
1418

1419 1420
	state = intel_create_plane_state(&intel_plane->base);
	if (!state) {
1421 1422
		ret = -ENOMEM;
		goto fail;
1423
	}
1424
	intel_plane->base.state = &state->base;
1425

1426
	if (INTEL_GEN(dev_priv) >= 9) {
1427 1428 1429 1430 1431
		intel_plane->can_scale = true;
		state->scaler_id = -1;

		intel_plane->update_plane = skl_update_plane;
		intel_plane->disable_plane = skl_disable_plane;
1432
		intel_plane->get_hw_state = skl_plane_get_hw_state;
1433 1434 1435

		plane_formats = skl_plane_formats;
		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
1436

1437 1438 1439 1440
		if (skl_plane_has_ccs(dev_priv, pipe, PLANE_SPRITE0 + plane))
			modifiers = skl_plane_format_modifiers_ccs;
		else
			modifiers = skl_plane_format_modifiers_noccs;
V
Ville Syrjälä 已提交
1441 1442 1443 1444 1445 1446
	} 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;
1447
		intel_plane->get_hw_state = vlv_plane_get_hw_state;
1448

V
Ville Syrjälä 已提交
1449 1450
		plane_formats = vlv_plane_formats;
		num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
1451
		modifiers = i9xx_plane_format_modifiers;
V
Ville Syrjälä 已提交
1452
	} else if (INTEL_GEN(dev_priv) >= 7) {
1453
		if (IS_IVYBRIDGE(dev_priv)) {
1454
			intel_plane->can_scale = true;
1455 1456 1457 1458 1459
			intel_plane->max_downscale = 2;
		} else {
			intel_plane->can_scale = false;
			intel_plane->max_downscale = 1;
		}
1460

V
Ville Syrjälä 已提交
1461 1462
		intel_plane->update_plane = ivb_update_plane;
		intel_plane->disable_plane = ivb_disable_plane;
1463
		intel_plane->get_hw_state = ivb_plane_get_hw_state;
1464

V
Ville Syrjälä 已提交
1465 1466
		plane_formats = snb_plane_formats;
		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1467
		modifiers = i9xx_plane_format_modifiers;
V
Ville Syrjälä 已提交
1468 1469 1470 1471
	} else {
		intel_plane->can_scale = true;
		intel_plane->max_downscale = 16;

1472 1473
		intel_plane->update_plane = g4x_update_plane;
		intel_plane->disable_plane = g4x_disable_plane;
1474
		intel_plane->get_hw_state = g4x_plane_get_hw_state;
1475

1476
		modifiers = i9xx_plane_format_modifiers;
V
Ville Syrjälä 已提交
1477
		if (IS_GEN6(dev_priv)) {
1478 1479
			plane_formats = snb_plane_formats;
			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
V
Ville Syrjälä 已提交
1480
		} else {
1481 1482
			plane_formats = g4x_plane_formats;
			num_plane_formats = ARRAY_SIZE(g4x_plane_formats);
1483
		}
1484 1485
	}

1486
	if (INTEL_GEN(dev_priv) >= 9) {
1487
		supported_rotations =
1488 1489
			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
			DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
1490 1491
	} else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
		supported_rotations =
1492 1493
			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
			DRM_MODE_REFLECT_X;
1494 1495
	} else {
		supported_rotations =
1496
			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1497 1498
	}

1499
	intel_plane->pipe = pipe;
1500
	intel_plane->i9xx_plane = plane;
1501
	intel_plane->id = PLANE_SPRITE0 + plane;
1502
	intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id);
1503
	intel_plane->check_plane = intel_check_sprite_plane;
1504

1505
	possible_crtcs = (1 << pipe);
1506

V
Ville Syrjälä 已提交
1507
	if (INTEL_GEN(dev_priv) >= 9)
1508
		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
1509
					       possible_crtcs, &intel_sprite_plane_funcs,
1510
					       plane_formats, num_plane_formats,
1511 1512
					       modifiers,
					       DRM_PLANE_TYPE_OVERLAY,
1513 1514
					       "plane %d%c", plane + 2, pipe_name(pipe));
	else
1515
		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
1516
					       possible_crtcs, &intel_sprite_plane_funcs,
1517
					       plane_formats, num_plane_formats,
1518 1519
					       modifiers,
					       DRM_PLANE_TYPE_OVERLAY,
1520
					       "sprite %c", sprite_name(pipe, plane));
1521 1522
	if (ret)
		goto fail;
1523

1524
	drm_plane_create_rotation_property(&intel_plane->base,
1525
					   DRM_MODE_ROTATE_0,
1526
					   supported_rotations);
1527

1528 1529 1530 1531
	drm_plane_create_color_properties(&intel_plane->base,
					  BIT(DRM_COLOR_YCBCR_BT601) |
					  BIT(DRM_COLOR_YCBCR_BT709),
					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
1532
					  DRM_COLOR_YCBCR_BT709,
1533 1534
					  DRM_COLOR_YCBCR_LIMITED_RANGE);

1535 1536
	drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);

1537
	return intel_plane;
1538 1539 1540 1541 1542

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

1543
	return ERR_PTR(ret);
1544
}