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

#include <drm/drm_atomic.h>
34
#include <drm/drm_atomic_helper.h>
35
#include <drm/drm_color_mgmt.h>
36 37
#include <drm/drm_crtc.h>
#include <drm/drm_fourcc.h>
38
#include <drm/drm_plane_helper.h>
39
#include <drm/drm_rect.h>
40
#include <drm/i915_drm.h>
41

42
#include "i915_drv.h"
43
#include "intel_atomic_plane.h"
44 45
#include "intel_drv.h"
#include "intel_frontbuffer.h"
46
#include "intel_pm.h"
47
#include "intel_psr.h"
48
#include "intel_sprite.h"
49

50 51 52 53 54 55 56 57 58 59 60 61 62
bool is_planar_yuv_format(u32 pixelformat)
{
	switch (pixelformat) {
	case DRM_FORMAT_NV12:
	case DRM_FORMAT_P010:
	case DRM_FORMAT_P012:
	case DRM_FORMAT_P016:
		return true;
	default:
		return false;
	}
}

63 64
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
			     int usecs)
65 66
{
	/* paranoia */
67
	if (!adjusted_mode->crtc_htotal)
68 69
		return 1;

70 71
	return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
			    1000 * adjusted_mode->crtc_htotal);
72 73
}

74 75 76 77 78
/* 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
79
#define VBLANK_EVASION_TIME_US 100
80
#endif
81

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

107 108
	vblank_start = adjusted_mode->crtc_vblank_start;
	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
109 110 111
		vblank_start = DIV_ROUND_UP(vblank_start, 2);

	/* FIXME needs to be calibrated sensibly */
112 113
	min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
						      VBLANK_EVASION_TIME_US);
114 115 116
	max = vblank_start - 1;

	if (min <= 0 || max <= 0)
117
		goto irq_disable;
118

119
	if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
120 121 122 123 124 125 126
		goto irq_disable;

	/*
	 * Wait for psr to idle out after enabling the VBL interrupts
	 * VBL interrupts will start the PSR exit and prevent a PSR
	 * re-entry as well.
	 */
127 128 129
	if (intel_psr_wait_for_idle(new_crtc_state, &psr_status))
		DRM_ERROR("PSR idle timed out 0x%x, atomic update may fail\n",
			  psr_status);
130 131

	local_irq_disable();
132

133 134 135
	crtc->debug.min_vbl = min;
	crtc->debug.max_vbl = max;
	trace_i915_pipe_update_start(crtc);
136

137 138 139 140 141 142
	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.
		 */
143
		prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
144 145 146 147 148

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

149
		if (!timeout) {
150 151 152 153 154 155 156 157 158 159 160 161
			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();
	}

162
	finish_wait(wq, &wait);
163

164
	drm_crtc_vblank_put(&crtc->base);
165

166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
	/*
	 * 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);

184 185
	crtc->debug.scanline_start = scanline;
	crtc->debug.start_vbl_time = ktime_get();
186
	crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
187

188
	trace_i915_pipe_update_vblank_evaded(crtc);
189 190 191 192
	return;

irq_disable:
	local_irq_disable();
193 194
}

195 196
/**
 * intel_pipe_update_end() - end update of a set of display registers
197
 * @new_crtc_state: the new crtc state
198 199 200
 *
 * Mark the end of an update started with intel_pipe_update_start(). This
 * re-enables interrupts and verifies the update was actually completed
201
 * before a vblank.
202
 */
203
void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
204
{
205
	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
206
	enum pipe pipe = crtc->pipe;
207
	int scanline_end = intel_get_crtc_scanline(crtc);
208
	u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
209
	ktime_t end_vbl_time = ktime_get();
210
	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
211

212
	trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
213

214 215 216 217
	/* 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 ... */
218
	if (new_crtc_state->base.event) {
219 220 221
		WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);

		spin_lock(&crtc->base.dev->event_lock);
222
		drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event);
223 224
		spin_unlock(&crtc->base.dev->event_lock);

225
		new_crtc_state->base.event = NULL;
226 227
	}

228 229
	local_irq_enable();

230 231 232
	if (intel_vgpu_active(dev_priv))
		return;

233 234 235 236 237 238 239 240
	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);
241 242 243 244
	}
#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
	else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
		 VBLANK_EVASION_TIME_US)
245 246 247 248
		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);
249
#endif
250 251
}

252 253 254 255 256 257 258
int intel_plane_check_stride(const struct intel_plane_state *plane_state)
{
	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
	const struct drm_framebuffer *fb = plane_state->base.fb;
	unsigned int rotation = plane_state->base.rotation;
	u32 stride, max_stride;

259 260 261 262 263 264 265 266 267 268
	/*
	 * We ignore stride for all invisible planes that
	 * can be remapped. Otherwise we could end up
	 * with a false positive when the remapping didn't
	 * kick in due the plane being invisible.
	 */
	if (intel_plane_can_remap(plane_state) &&
	    !plane_state->base.visible)
		return 0;

269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
	/* FIXME other color planes? */
	stride = plane_state->color_plane[0].stride;
	max_stride = plane->max_stride(plane, fb->format->format,
				       fb->modifier, rotation);

	if (stride > max_stride) {
		DRM_DEBUG_KMS("[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n",
			      fb->base.id, stride,
			      plane->base.base.id, plane->base.name, max_stride);
		return -EINVAL;
	}

	return 0;
}

284 285 286 287
int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
{
	const struct drm_framebuffer *fb = plane_state->base.fb;
	struct drm_rect *src = &plane_state->base.src;
288 289
	u32 src_x, src_y, src_w, src_h, hsub, vsub;
	bool rotated = drm_rotation_90_or_270(plane_state->base.rotation);
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306

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

	src->x1 = src_x << 16;
	src->x2 = (src_x + src_w) << 16;
	src->y1 = src_y << 16;
	src->y2 = (src_y + src_h) << 16;

307 308 309 310 311 312 313 314 315 316 317 318 319 320
	if (!fb->format->is_yuv)
		return 0;

	/* YUV specific checks */
	if (!rotated) {
		hsub = fb->format->hsub;
		vsub = fb->format->vsub;
	} else {
		hsub = vsub = max(fb->format->hsub, fb->format->vsub);
	}

	if (src_x % hsub || src_w % hsub) {
		DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u for %sYUV planes\n",
			      src_x, src_w, hsub, rotated ? "rotated " : "");
321 322 323
		return -EINVAL;
	}

324 325 326
	if (src_y % vsub || src_h % vsub) {
		DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u for %sYUV planes\n",
			      src_y, src_h, vsub, rotated ? "rotated " : "");
327 328 329
		return -EINVAL;
	}

330 331 332
	return 0;
}

333
static unsigned int
334 335 336 337
skl_plane_max_stride(struct intel_plane *plane,
		     u32 pixel_format, u64 modifier,
		     unsigned int rotation)
{
338
	const struct drm_format_info *info = drm_format_info(pixel_format);
339
	int cpp = info->cpp[0];
340 341 342 343 344 345 346 347 348 349 350

	/*
	 * "The stride in bytes must not exceed the
	 * of the size of 8K pixels and 32K bytes."
	 */
	if (drm_rotation_90_or_270(rotation))
		return min(8192, 32768 / cpp);
	else
		return min(8192 * cpp, 32768);
}

351
static void
352
skl_program_scaler(struct intel_plane *plane,
353 354 355
		   const struct intel_crtc_state *crtc_state,
		   const struct intel_plane_state *plane_state)
{
356
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
357 358 359 360 361 362
	enum pipe pipe = plane->pipe;
	int scaler_id = plane_state->scaler_id;
	const struct intel_scaler *scaler =
		&crtc_state->scaler_state.scalers[scaler_id];
	int crtc_x = plane_state->base.dst.x1;
	int crtc_y = plane_state->base.dst.y1;
363 364
	u32 crtc_w = drm_rect_width(&plane_state->base.dst);
	u32 crtc_h = drm_rect_height(&plane_state->base.dst);
365 366
	u16 y_hphase, uv_rgb_hphase;
	u16 y_vphase, uv_rgb_vphase;
367 368 369 370 371 372 373 374
	int hscale, vscale;

	hscale = drm_rect_calc_hscale(&plane_state->base.src,
				      &plane_state->base.dst,
				      0, INT_MAX);
	vscale = drm_rect_calc_vscale(&plane_state->base.src,
				      &plane_state->base.dst,
				      0, INT_MAX);
375 376

	/* TODO: handle sub-pixel coordinates */
377
	if (is_planar_yuv_format(plane_state->base.fb->format->format) &&
378
	    !icl_is_hdr_plane(dev_priv, plane->id)) {
379 380
		y_hphase = skl_scaler_calc_phase(1, hscale, false);
		y_vphase = skl_scaler_calc_phase(1, vscale, false);
381 382

		/* MPEG2 chroma siting convention */
383 384
		uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
		uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
385 386 387 388 389
	} else {
		/* not used */
		y_hphase = 0;
		y_vphase = 0;

390 391
		uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
		uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
392 393 394
	}

	I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
395
		      PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode);
396 397 398 399 400
	I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
		      PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
	I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
		      PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
	I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
401
	I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h);
402 403
}

404 405 406 407 408 409 410 411 412 413
/* Preoffset values for YUV to RGB Conversion */
#define PREOFF_YUV_TO_RGB_HI		0x1800
#define PREOFF_YUV_TO_RGB_ME		0x1F00
#define PREOFF_YUV_TO_RGB_LO		0x1800

#define  ROFF(x)          (((x) & 0xffff) << 16)
#define  GOFF(x)          (((x) & 0xffff) << 0)
#define  BOFF(x)          (((x) & 0xffff) << 16)

static void
414 415 416
icl_program_input_csc(struct intel_plane *plane,
		      const struct intel_crtc_state *crtc_state,
		      const struct intel_plane_state *plane_state)
417
{
418 419
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
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 445 446 447 448 449 450 451 452 453 454 455 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 490 491 492 493 494 495 496 497 498 499 500 501 502 503
	enum plane_id plane_id = plane->id;

	static const u16 input_csc_matrix[][9] = {
		/*
		 * BT.601 full range YCbCr -> full range RGB
		 * The matrix required is :
		 * [1.000, 0.000, 1.371,
		 *  1.000, -0.336, -0.698,
		 *  1.000, 1.732, 0.0000]
		 */
		[DRM_COLOR_YCBCR_BT601] = {
			0x7AF8, 0x7800, 0x0,
			0x8B28, 0x7800, 0x9AC0,
			0x0, 0x7800, 0x7DD8,
		},
		/*
		 * BT.709 full range YCbCr -> full range RGB
		 * The matrix required is :
		 * [1.000, 0.000, 1.574,
		 *  1.000, -0.187, -0.468,
		 *  1.000, 1.855, 0.0000]
		 */
		[DRM_COLOR_YCBCR_BT709] = {
			0x7C98, 0x7800, 0x0,
			0x9EF8, 0x7800, 0xABF8,
			0x0, 0x7800,  0x7ED8,
		},
	};

	/* Matrix for Limited Range to Full Range Conversion */
	static const u16 input_csc_matrix_lr[][9] = {
		/*
		 * BT.601 Limted range YCbCr -> full range RGB
		 * The matrix required is :
		 * [1.164384, 0.000, 1.596370,
		 *  1.138393, -0.382500, -0.794598,
		 *  1.138393, 1.971696, 0.0000]
		 */
		[DRM_COLOR_YCBCR_BT601] = {
			0x7CC8, 0x7950, 0x0,
			0x8CB8, 0x7918, 0x9C40,
			0x0, 0x7918, 0x7FC8,
		},
		/*
		 * BT.709 Limited range YCbCr -> full range RGB
		 * The matrix required is :
		 * [1.164, 0.000, 1.833671,
		 *  1.138393, -0.213249, -0.532909,
		 *  1.138393, 2.112402, 0.0000]
		 */
		[DRM_COLOR_YCBCR_BT709] = {
			0x7EA8, 0x7950, 0x0,
			0x8888, 0x7918, 0xADA8,
			0x0, 0x7918,  0x6870,
		},
	};
	const u16 *csc;

	if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
		csc = input_csc_matrix[plane_state->base.color_encoding];
	else
		csc = input_csc_matrix_lr[plane_state->base.color_encoding];

	I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0), ROFF(csc[0]) |
		      GOFF(csc[1]));
	I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1), BOFF(csc[2]));
	I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2), ROFF(csc[3]) |
		      GOFF(csc[4]));
	I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3), BOFF(csc[5]));
	I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4), ROFF(csc[6]) |
		      GOFF(csc[7]));
	I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5), BOFF(csc[8]));

	I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
		      PREOFF_YUV_TO_RGB_HI);
	I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
		      PREOFF_YUV_TO_RGB_ME);
	I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
		      PREOFF_YUV_TO_RGB_LO);
	I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
	I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
	I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
}

504
static void
505 506 507 508
skl_program_plane(struct intel_plane *plane,
		  const struct intel_crtc_state *crtc_state,
		  const struct intel_plane_state *plane_state,
		  int color_plane, bool slave, u32 plane_ctl)
509
{
510 511 512
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum plane_id plane_id = plane->id;
	enum pipe pipe = plane->pipe;
513
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
514 515
	u32 surf_addr = plane_state->color_plane[color_plane].offset;
	u32 stride = skl_plane_stride(plane_state, color_plane);
516
	u32 aux_stride = skl_plane_stride(plane_state, 1);
517 518
	int crtc_x = plane_state->base.dst.x1;
	int crtc_y = plane_state->base.dst.y1;
519 520 521 522
	u32 x = plane_state->color_plane[color_plane].x;
	u32 y = plane_state->color_plane[color_plane].y;
	u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
	u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
523
	struct intel_plane *linked = plane_state->linked_plane;
524
	const struct drm_framebuffer *fb = plane_state->base.fb;
525
	u8 alpha = plane_state->base.alpha >> 8;
526
	u32 plane_color_ctl = 0;
527
	unsigned long irqflags;
528
	u32 keymsk, keymax;
529

530 531 532 533 534 535
	plane_ctl |= skl_plane_ctl_crtc(crtc_state);

	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
		plane_color_ctl = plane_state->color_ctl |
			glk_plane_color_ctl_crtc(crtc_state);

536 537 538 539
	/* Sizes are 0 based */
	src_w--;
	src_h--;

540 541
	keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);

542
	keymsk = key->channel_mask & 0x7ffffff;
543 544 545
	if (alpha < 0xff)
		keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;

546 547 548 549 550 551
	/* The scaler will handle the output position */
	if (plane_state->scaler_id >= 0) {
		crtc_x = 0;
		crtc_y = 0;
	}

552 553 554
	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);

	I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
555
	I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
556
	I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
557
	I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
558
		      (plane_state->color_plane[1].offset - surf_addr) | aux_stride);
559

560
	if (icl_is_hdr_plane(dev_priv, plane_id)) {
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
		u32 cus_ctl = 0;

		if (linked) {
			/* Enable and use MPEG-2 chroma siting */
			cus_ctl = PLANE_CUS_ENABLE |
				PLANE_CUS_HPHASE_0 |
				PLANE_CUS_VPHASE_SIGN_NEGATIVE |
				PLANE_CUS_VPHASE_0_25;

			if (linked->id == PLANE_SPRITE5)
				cus_ctl |= PLANE_CUS_PLANE_7;
			else if (linked->id == PLANE_SPRITE4)
				cus_ctl |= PLANE_CUS_PLANE_6;
			else
				MISSING_CASE(linked->id);
		}

		I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), cus_ctl);
	}

581
	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
582
		I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
583

584
	if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
585
		icl_program_input_csc(plane, crtc_state, plane_state);
586

587 588
	skl_write_plane_wm(plane, crtc_state);

589 590 591 592 593 594 595 596 597 598
	I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
	I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), keymsk);
	I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), keymax);

	I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);

	if (INTEL_GEN(dev_priv) < 11)
		I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
			      (plane_state->color_plane[1].y << 16) |
			      plane_state->color_plane[1].x);
599

600 601 602 603 604
	/*
	 * The control register self-arms if the plane was previously
	 * disabled. Try to make the plane enable atomic by writing
	 * the control register just before the surface register.
	 */
605 606 607 608
	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);

609 610 611
	if (!slave && plane_state->scaler_id >= 0)
		skl_program_scaler(plane, crtc_state, plane_state);

612
	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
613 614
}

615
static void
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
skl_update_plane(struct intel_plane *plane,
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
	int color_plane = 0;

	if (plane_state->linked_plane) {
		/* Program the UV plane */
		color_plane = 1;
	}

	skl_program_plane(plane, crtc_state, plane_state,
			  color_plane, false, plane_state->ctl);
}

631
static void
632 633 634 635 636 637 638 639
icl_update_slave(struct intel_plane *plane,
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
	skl_program_plane(plane, crtc_state, plane_state, 0, true,
			  plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE);
}

640
static void
641 642
skl_disable_plane(struct intel_plane *plane,
		  const struct intel_crtc_state *crtc_state)
643
{
644 645 646
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum plane_id plane_id = plane->id;
	enum pipe pipe = plane->pipe;
647 648 649
	unsigned long irqflags;

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

651 652 653
	if (icl_is_hdr_plane(dev_priv, plane_id))
		I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), 0);

654 655
	skl_write_plane_wm(plane, crtc_state);

656 657 658 659
	I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
	I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
660 661
}

662
static bool
663 664
skl_plane_get_hw_state(struct intel_plane *plane,
		       enum pipe *pipe)
665 666 667 668
{
	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;
669
	intel_wakeref_t wakeref;
670 671
	bool ret;

672
	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
673 674
	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
	if (!wakeref)
675 676
		return false;

677 678 679
	ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;

	*pipe = plane->pipe;
680

681
	intel_display_power_put(dev_priv, power_domain, wakeref);
682 683 684 685

	return ret;
}

686
static void
687
chv_update_csc(const struct intel_plane_state *plane_state)
688
{
689
	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
690
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
691
	const struct drm_framebuffer *fb = plane_state->base.fb;
692
	enum plane_id plane_id = plane->id;
693
	/*
694 695 696
	 * |r|   | c0 c1 c2 |   |cr|
	 * |g| = | c3 c4 c5 | x |y |
	 * |b|   | c6 c7 c8 |   |cb|
697
	 *
698
	 * Coefficients are s3.12.
699
	 *
700 701
	 * Cb and Cr apparently come in as signed already, and
	 * we always get full range data in on account of CLRC0/1.
702
	 */
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
	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];
718 719

	/* Seems RGB data bypasses the CSC always */
720
	if (!fb->format->is_yuv)
721 722
		return;

723
	I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
724 725 726
	I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
	I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));

727 728 729 730 731
	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]));
732

733 734 735
	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));
736 737 738 739

	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));
740 741
}

742 743 744 745 746 747 748 749 750 751 752 753 754
#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;

755
	if (fb->format->is_yuv &&
756
	    plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
		/*
		 * 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));
}

784 785
static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
{
786 787 788 789 790 791
	u32 sprctl = 0;

	if (crtc_state->gamma_enable)
		sprctl |= SP_GAMMA_ENABLE;

	return sprctl;
792 793
}

794 795
static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
			  const struct intel_plane_state *plane_state)
796
{
797
	const struct drm_framebuffer *fb = plane_state->base.fb;
798
	unsigned int rotation = plane_state->base.rotation;
799
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
800
	u32 sprctl;
801

802
	sprctl = SP_ENABLE;
803

V
Ville Syrjälä 已提交
804
	switch (fb->format->format) {
805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838
	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:
839 840
		MISSING_CASE(fb->format->format);
		return 0;
841 842
	}

843 844 845
	if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
		sprctl |= SP_YUV_FORMAT_BT709;

V
Ville Syrjälä 已提交
846
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
847 848
		sprctl |= SP_TILED;

849
	if (rotation & DRM_MODE_ROTATE_180)
850 851
		sprctl |= SP_ROTATE_180;

852
	if (rotation & DRM_MODE_REFLECT_X)
853 854
		sprctl |= SP_MIRROR;

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

858 859 860 861
	return sprctl;
}

static void
862
vlv_update_plane(struct intel_plane *plane,
863 864 865
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
866 867 868
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
	enum plane_id plane_id = plane->id;
869
	u32 sprsurf_offset = plane_state->color_plane[0].offset;
870
	u32 linear_offset;
871 872 873
	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;
874 875 876 877
	u32 crtc_w = drm_rect_width(&plane_state->base.dst);
	u32 crtc_h = drm_rect_height(&plane_state->base.dst);
	u32 x = plane_state->color_plane[0].x;
	u32 y = plane_state->color_plane[0].y;
878
	unsigned long irqflags;
879 880 881
	u32 sprctl;

	sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
882

883 884 885 886
	/* Sizes are 0 based */
	crtc_w--;
	crtc_h--;

887
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
888

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

891 892 893 894 895 896
	I915_WRITE_FW(SPSTRIDE(pipe, plane_id),
		      plane_state->color_plane[0].stride);
	I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
	I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
	I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);

897
	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
898
		chv_update_csc(plane_state);
899

900
	if (key->flags) {
901 902
		I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
		I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
903
		I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
904
	}
905

906
	I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
907
	I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
908

909 910 911 912 913
	/*
	 * The control register self-arms if the plane was previously
	 * disabled. Try to make the plane enable atomic by writing
	 * the control register just before the surface register.
	 */
914 915 916 917
	I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
	I915_WRITE_FW(SPSURF(pipe, plane_id),
		      intel_plane_ggtt_offset(plane_state) + sprsurf_offset);

918 919
	vlv_update_clrc(plane_state);

920
	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
921 922 923
}

static void
924 925
vlv_disable_plane(struct intel_plane *plane,
		  const struct intel_crtc_state *crtc_state)
926
{
927 928 929
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
	enum plane_id plane_id = plane->id;
930 931 932
	unsigned long irqflags;

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

934 935 936 937
	I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
	I915_WRITE_FW(SPSURF(pipe, plane_id), 0);

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
938 939
}

940
static bool
941 942
vlv_plane_get_hw_state(struct intel_plane *plane,
		       enum pipe *pipe)
943 944 945 946
{
	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;
947
	intel_wakeref_t wakeref;
948 949
	bool ret;

950
	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
951 952
	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
	if (!wakeref)
953 954
		return false;

955 956 957
	ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;

	*pipe = plane->pipe;
958

959
	intel_display_power_put(dev_priv, power_domain, wakeref);
960 961 962 963

	return ret;
}

964 965 966 967
static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
{
	u32 sprctl = 0;

968 969
	if (crtc_state->gamma_enable)
		sprctl |= SPRITE_GAMMA_ENABLE;
970

971
	if (crtc_state->csc_enable)
972 973 974 975 976
		sprctl |= SPRITE_PIPE_CSC_ENABLE;

	return sprctl;
}

977 978
static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
			  const struct intel_plane_state *plane_state)
979
{
980 981 982
	struct drm_i915_private *dev_priv =
		to_i915(plane_state->base.plane->dev);
	const struct drm_framebuffer *fb = plane_state->base.fb;
983
	unsigned int rotation = plane_state->base.rotation;
984
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
985 986
	u32 sprctl;

987
	sprctl = SPRITE_ENABLE;
988

989 990 991
	if (IS_IVYBRIDGE(dev_priv))
		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;

V
Ville Syrjälä 已提交
992
	switch (fb->format->format) {
993
	case DRM_FORMAT_XBGR8888:
994
		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
995 996
		break;
	case DRM_FORMAT_XRGB8888:
997
		sprctl |= SPRITE_FORMAT_RGBX888;
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
		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:
1012 1013
		MISSING_CASE(fb->format->format);
		return 0;
1014 1015
	}

1016 1017 1018
	if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
		sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;

1019 1020 1021
	if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
		sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;

V
Ville Syrjälä 已提交
1022
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1023 1024
		sprctl |= SPRITE_TILED;

1025
	if (rotation & DRM_MODE_ROTATE_180)
1026 1027
		sprctl |= SPRITE_ROTATE_180;

1028 1029 1030 1031 1032
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
		sprctl |= SPRITE_DEST_KEY;
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
		sprctl |= SPRITE_SOURCE_KEY;

1033 1034 1035 1036
	return sprctl;
}

static void
1037
ivb_update_plane(struct intel_plane *plane,
1038 1039 1040
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
1041 1042
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
1043
	u32 sprsurf_offset = plane_state->color_plane[0].offset;
1044
	u32 linear_offset;
1045 1046 1047
	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;
1048 1049 1050 1051 1052 1053
	u32 crtc_w = drm_rect_width(&plane_state->base.dst);
	u32 crtc_h = drm_rect_height(&plane_state->base.dst);
	u32 x = plane_state->color_plane[0].x;
	u32 y = plane_state->color_plane[0].y;
	u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
	u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
1054
	u32 sprctl, sprscale = 0;
1055 1056
	unsigned long irqflags;

1057 1058
	sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);

1059 1060 1061 1062 1063 1064
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

1065
	if (crtc_w != src_w || crtc_h != src_h)
1066 1067
		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;

1068
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1069

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

1072 1073 1074 1075 1076 1077
	I915_WRITE_FW(SPRSTRIDE(pipe), plane_state->color_plane[0].stride);
	I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
	I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
	if (IS_IVYBRIDGE(dev_priv))
		I915_WRITE_FW(SPRSCALE(pipe), sprscale);

1078
	if (key->flags) {
1079 1080
		I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
		I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
1081
		I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
1082 1083
	}

1084 1085
	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
	 * register */
1086
	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1087
		I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
1088
	} else {
1089
		I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
1090
		I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
1091
	}
1092

1093 1094 1095 1096 1097
	/*
	 * The control register self-arms if the plane was previously
	 * disabled. Try to make the plane enable atomic by writing
	 * the control register just before the surface register.
	 */
1098 1099 1100 1101 1102
	I915_WRITE_FW(SPRCTL(pipe), sprctl);
	I915_WRITE_FW(SPRSURF(pipe),
		      intel_plane_ggtt_offset(plane_state) + sprsurf_offset);

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1103 1104 1105
}

static void
1106 1107
ivb_disable_plane(struct intel_plane *plane,
		  const struct intel_crtc_state *crtc_state)
1108
{
1109 1110
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
1111 1112 1113
	unsigned long irqflags;

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

1115
	I915_WRITE_FW(SPRCTL(pipe), 0);
1116
	/* Disable the scaler */
1117
	if (IS_IVYBRIDGE(dev_priv))
1118 1119 1120 1121
		I915_WRITE_FW(SPRSCALE(pipe), 0);
	I915_WRITE_FW(SPRSURF(pipe), 0);

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1122 1123
}

1124
static bool
1125 1126
ivb_plane_get_hw_state(struct intel_plane *plane,
		       enum pipe *pipe)
1127 1128 1129
{
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum intel_display_power_domain power_domain;
1130
	intel_wakeref_t wakeref;
1131 1132
	bool ret;

1133
	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1134 1135
	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
	if (!wakeref)
1136 1137
		return false;

1138 1139 1140
	ret =  I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;

	*pipe = plane->pipe;
1141

1142
	intel_display_power_put(dev_priv, power_domain, wakeref);
1143 1144 1145 1146

	return ret;
}

1147 1148 1149 1150 1151 1152 1153 1154
static unsigned int
g4x_sprite_max_stride(struct intel_plane *plane,
		      u32 pixel_format, u64 modifier,
		      unsigned int rotation)
{
	return 16384;
}

1155 1156
static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
{
1157 1158 1159 1160 1161
	u32 dvscntr = 0;

	if (crtc_state->gamma_enable)
		dvscntr |= DVS_GAMMA_ENABLE;

1162 1163 1164
	if (crtc_state->csc_enable)
		dvscntr |= DVS_PIPE_CSC_ENABLE;

1165
	return dvscntr;
1166 1167
}

1168
static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1169
			  const struct intel_plane_state *plane_state)
1170
{
1171 1172 1173
	struct drm_i915_private *dev_priv =
		to_i915(plane_state->base.plane->dev);
	const struct drm_framebuffer *fb = plane_state->base.fb;
1174
	unsigned int rotation = plane_state->base.rotation;
1175
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1176 1177
	u32 dvscntr;

1178
	dvscntr = DVS_ENABLE;
1179

1180
	if (IS_GEN(dev_priv, 6))
1181
		dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1182

V
Ville Syrjälä 已提交
1183
	switch (fb->format->format) {
1184
	case DRM_FORMAT_XBGR8888:
1185
		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1186 1187
		break;
	case DRM_FORMAT_XRGB8888:
1188
		dvscntr |= DVS_FORMAT_RGBX888;
1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
		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:
1203 1204
		MISSING_CASE(fb->format->format);
		return 0;
1205 1206
	}

1207 1208 1209
	if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
		dvscntr |= DVS_YUV_FORMAT_BT709;

1210 1211 1212
	if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
		dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;

V
Ville Syrjälä 已提交
1213
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1214 1215
		dvscntr |= DVS_TILED;

1216
	if (rotation & DRM_MODE_ROTATE_180)
1217 1218
		dvscntr |= DVS_ROTATE_180;

1219 1220 1221 1222 1223
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
		dvscntr |= DVS_DEST_KEY;
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
		dvscntr |= DVS_SOURCE_KEY;

1224 1225 1226 1227
	return dvscntr;
}

static void
1228
g4x_update_plane(struct intel_plane *plane,
1229 1230 1231
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
1232 1233
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
1234
	u32 dvssurf_offset = plane_state->color_plane[0].offset;
1235
	u32 linear_offset;
1236 1237 1238
	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;
1239 1240 1241 1242 1243 1244
	u32 crtc_w = drm_rect_width(&plane_state->base.dst);
	u32 crtc_h = drm_rect_height(&plane_state->base.dst);
	u32 x = plane_state->color_plane[0].x;
	u32 y = plane_state->color_plane[0].y;
	u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
	u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
1245
	u32 dvscntr, dvsscale = 0;
1246 1247
	unsigned long irqflags;

1248 1249
	dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);

1250 1251 1252 1253 1254 1255
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

1256
	if (crtc_w != src_w || crtc_h != src_h)
1257 1258
		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;

1259
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1260

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

1263 1264 1265 1266 1267
	I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride);
	I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
	I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
	I915_WRITE_FW(DVSSCALE(pipe), dvsscale);

1268
	if (key->flags) {
1269 1270
		I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
		I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
1271
		I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
1272 1273
	}

1274
	I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
1275
	I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
1276

1277 1278 1279 1280 1281
	/*
	 * The control register self-arms if the plane was previously
	 * disabled. Try to make the plane enable atomic by writing
	 * the control register just before the surface register.
	 */
1282 1283 1284 1285 1286
	I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
	I915_WRITE_FW(DVSSURF(pipe),
		      intel_plane_ggtt_offset(plane_state) + dvssurf_offset);

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1287 1288 1289
}

static void
1290 1291
g4x_disable_plane(struct intel_plane *plane,
		  const struct intel_crtc_state *crtc_state)
1292
{
1293 1294
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
1295
	unsigned long irqflags;
1296

1297 1298 1299
	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);

	I915_WRITE_FW(DVSCNTR(pipe), 0);
1300
	/* Disable the scaler */
1301 1302
	I915_WRITE_FW(DVSSCALE(pipe), 0);
	I915_WRITE_FW(DVSSURF(pipe), 0);
1303

1304
	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1305 1306
}

1307
static bool
1308 1309
g4x_plane_get_hw_state(struct intel_plane *plane,
		       enum pipe *pipe)
1310 1311 1312
{
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum intel_display_power_domain power_domain;
1313
	intel_wakeref_t wakeref;
1314 1315
	bool ret;

1316
	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1317 1318
	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
	if (!wakeref)
1319 1320
		return false;

1321 1322 1323
	ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;

	*pipe = plane->pipe;
1324

1325
	intel_display_power_put(dev_priv, power_domain, wakeref);
1326 1327 1328 1329

	return ret;
}

1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342
static bool intel_fb_scalable(const struct drm_framebuffer *fb)
{
	if (!fb)
		return false;

	switch (fb->format->format) {
	case DRM_FORMAT_C8:
		return false;
	default:
		return true;
	}
}

1343
static int
1344 1345
g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
			 struct intel_plane_state *plane_state)
1346
{
1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
	const struct drm_framebuffer *fb = plane_state->base.fb;
	const struct drm_rect *src = &plane_state->base.src;
	const struct drm_rect *dst = &plane_state->base.dst;
	int src_x, src_y, src_w, src_h, crtc_w, crtc_h;
	const struct drm_display_mode *adjusted_mode =
		&crtc_state->base.adjusted_mode;
	unsigned int cpp = fb->format->cpp[0];
	unsigned int width_bytes;
	int min_width, min_height;

	crtc_w = drm_rect_width(dst);
	crtc_h = drm_rect_height(dst);

	src_x = src->x1 >> 16;
	src_y = src->y1 >> 16;
	src_w = drm_rect_width(src) >> 16;
	src_h = drm_rect_height(src) >> 16;

	if (src_w == crtc_w && src_h == crtc_h)
1366
		return 0;
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377

	min_width = 3;

	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
		if (src_h & 1) {
			DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
			return -EINVAL;
		}
		min_height = 6;
	} else {
		min_height = 3;
1378
	}
1379

1380 1381 1382 1383 1384 1385
	width_bytes = ((src_x * cpp) & 63) + src_w * cpp;

	if (src_w < min_width || src_h < min_height ||
	    src_w > 2048 || src_h > 2048) {
		DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
			      src_w, src_h, min_width, min_height, 2048, 2048);
1386
		return -EINVAL;
1387
	}
1388

1389 1390 1391
	if (width_bytes > 4096) {
		DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
			      width_bytes, 4096);
1392
		return -EINVAL;
1393
	}
1394

1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409
	if (width_bytes > 4096 || fb->pitches[0] > 4096) {
		DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
			      fb->pitches[0], 4096);
		return -EINVAL;
	}

	return 0;
}

static int
g4x_sprite_check(struct intel_crtc_state *crtc_state,
		 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);
1410 1411
	int min_scale = DRM_PLANE_HELPER_NO_SCALING;
	int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1412 1413
	int ret;

1414 1415 1416 1417 1418 1419 1420 1421
	if (intel_fb_scalable(plane_state->base.fb)) {
		if (INTEL_GEN(dev_priv) < 7) {
			min_scale = 1;
			max_scale = 16 << 16;
		} else if (IS_IVYBRIDGE(dev_priv)) {
			min_scale = 1;
			max_scale = 2 << 16;
		}
1422 1423
	}

1424
	ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1425 1426 1427 1428 1429
						  &crtc_state->base,
						  min_scale, max_scale,
						  true, true);
	if (ret)
		return ret;
1430

1431 1432 1433 1434
	ret = i9xx_check_plane_surface(plane_state);
	if (ret)
		return ret;

1435 1436
	if (!plane_state->base.visible)
		return 0;
1437

1438 1439 1440
	ret = intel_plane_check_src_coordinates(plane_state);
	if (ret)
		return ret;
1441

1442 1443 1444
	ret = g4x_sprite_check_scaling(crtc_state, plane_state);
	if (ret)
		return ret;
1445

1446 1447 1448 1449
	if (INTEL_GEN(dev_priv) >= 7)
		plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
	else
		plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1450

1451 1452
	return 0;
}
1453

1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470
int chv_plane_check_rotation(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);
	unsigned int rotation = plane_state->base.rotation;

	/* CHV ignores the mirror bit when the rotate bit is set :( */
	if (IS_CHERRYVIEW(dev_priv) &&
	    rotation & DRM_MODE_ROTATE_180 &&
	    rotation & DRM_MODE_REFLECT_X) {
		DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n");
		return -EINVAL;
	}

	return 0;
}

1471 1472 1473 1474 1475 1476
static int
vlv_sprite_check(struct intel_crtc_state *crtc_state,
		 struct intel_plane_state *plane_state)
{
	int ret;

1477 1478 1479 1480
	ret = chv_plane_check_rotation(plane_state);
	if (ret)
		return ret;

1481 1482 1483 1484 1485 1486 1487 1488
	ret = drm_atomic_helper_check_plane_state(&plane_state->base,
						  &crtc_state->base,
						  DRM_PLANE_HELPER_NO_SCALING,
						  DRM_PLANE_HELPER_NO_SCALING,
						  true, true);
	if (ret)
		return ret;

1489 1490 1491 1492
	ret = i9xx_check_plane_surface(plane_state);
	if (ret)
		return ret;

1493 1494 1495 1496 1497 1498 1499 1500
	if (!plane_state->base.visible)
		return 0;

	ret = intel_plane_check_src_coordinates(plane_state);
	if (ret)
		return ret;

	plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1501

1502 1503 1504
	return 0;
}

1505 1506 1507
static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
			      const struct intel_plane_state *plane_state)
{
1508 1509
	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1510 1511 1512 1513 1514 1515 1516 1517
	const struct drm_framebuffer *fb = plane_state->base.fb;
	unsigned int rotation = plane_state->base.rotation;
	struct drm_format_name_buf format_name;

	if (!fb)
		return 0;

	if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1518
	    is_ccs_modifier(fb->modifier)) {
1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537
		DRM_DEBUG_KMS("RC support only with 0/180 degree rotation (%x)\n",
			      rotation);
		return -EINVAL;
	}

	if (rotation & DRM_MODE_REFLECT_X &&
	    fb->modifier == DRM_FORMAT_MOD_LINEAR) {
		DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n");
		return -EINVAL;
	}

	if (drm_rotation_90_or_270(rotation)) {
		if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
		    fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
			DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
			return -EINVAL;
		}

		/*
1538 1539
		 * 90/270 is not allowed with RGB64 16:16:16:16 and
		 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
1540 1541 1542
		 */
		switch (fb->format->format) {
		case DRM_FORMAT_RGB565:
1543 1544 1545 1546
			if (INTEL_GEN(dev_priv) >= 11)
				break;
			/* fall through */
		case DRM_FORMAT_C8:
1547 1548 1549 1550
		case DRM_FORMAT_XRGB16161616F:
		case DRM_FORMAT_XBGR16161616F:
		case DRM_FORMAT_ARGB16161616F:
		case DRM_FORMAT_ABGR16161616F:
1551 1552 1553 1554 1555
		case DRM_FORMAT_Y210:
		case DRM_FORMAT_Y212:
		case DRM_FORMAT_Y216:
		case DRM_FORMAT_XVYU12_16161616:
		case DRM_FORMAT_XVYU16161616:
1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578
			DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
				      drm_get_format_name(fb->format->format,
							  &format_name));
			return -EINVAL;
		default:
			break;
		}
	}

	/* Y-tiling is not supported in IF-ID Interlace mode */
	if (crtc_state->base.enable &&
	    crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
	    (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
	     fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
	     fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
	     fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) {
		DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n");
		return -EINVAL;
	}

	return 0;
}

1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608
static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
					   const struct intel_plane_state *plane_state)
{
	struct drm_i915_private *dev_priv =
		to_i915(plane_state->base.plane->dev);
	int crtc_x = plane_state->base.dst.x1;
	int crtc_w = drm_rect_width(&plane_state->base.dst);
	int pipe_src_w = crtc_state->pipe_src_w;

	/*
	 * Display WA #1175: cnl,glk
	 * Planes other than the cursor may cause FIFO underflow and display
	 * corruption if starting less than 4 pixels from the right edge of
	 * the screen.
	 * Besides the above WA fix the similar problem, where planes other
	 * than the cursor ending less than 4 pixels from the left edge of the
	 * screen may cause FIFO underflow and display corruption.
	 */
	if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
	    (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
		DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n",
			      crtc_x + crtc_w < 4 ? "end" : "start",
			      crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
			      4, pipe_src_w - 4);
		return -ERANGE;
	}

	return 0;
}

1609 1610 1611 1612 1613 1614 1615
static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
{
	const struct drm_framebuffer *fb = plane_state->base.fb;
	unsigned int rotation = plane_state->base.rotation;
	int src_w = drm_rect_width(&plane_state->base.src) >> 16;

	/* Display WA #1106 */
1616
	if (is_planar_yuv_format(fb->format->format) && src_w & 3 &&
1617 1618
	    (rotation == DRM_MODE_ROTATE_270 ||
	     rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1619
		DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
1620 1621 1622 1623 1624 1625
		return -EINVAL;
	}

	return 0;
}

1626 1627
static int skl_plane_check(struct intel_crtc_state *crtc_state,
			   struct intel_plane_state *plane_state)
1628 1629 1630
{
	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1631 1632 1633
	const struct drm_framebuffer *fb = plane_state->base.fb;
	int min_scale = DRM_PLANE_HELPER_NO_SCALING;
	int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1634 1635
	int ret;

1636 1637 1638 1639
	ret = skl_plane_check_fb(crtc_state, plane_state);
	if (ret)
		return ret;

1640
	/* use scaler when colorkey is not required */
1641
	if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
1642
		min_scale = 1;
1643
		max_scale = skl_max_scale(crtc_state, fb->format->format);
1644 1645
	}

1646 1647 1648 1649 1650 1651 1652
	ret = drm_atomic_helper_check_plane_state(&plane_state->base,
						  &crtc_state->base,
						  min_scale, max_scale,
						  true, true);
	if (ret)
		return ret;

1653 1654 1655 1656
	ret = skl_check_plane_surface(plane_state);
	if (ret)
		return ret;

1657 1658 1659
	if (!plane_state->base.visible)
		return 0;

1660 1661 1662 1663
	ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
	if (ret)
		return ret;

1664 1665 1666 1667
	ret = intel_plane_check_src_coordinates(plane_state);
	if (ret)
		return ret;

1668 1669 1670 1671
	ret = skl_plane_check_nv12_rotation(plane_state);
	if (ret)
		return ret;

1672 1673 1674 1675
	/* HW only has 8 bits pixel precision, disable plane if invisible */
	if (!(plane_state->base.alpha >> 8))
		plane_state->base.visible = false;

1676 1677
	plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);

1678
	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1679 1680
		plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
							     plane_state);
1681

1682 1683 1684
	return 0;
}

1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715
static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
{
	return INTEL_GEN(dev_priv) >= 9;
}

static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
				 const struct drm_intel_sprite_colorkey *set)
{
	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	struct drm_intel_sprite_colorkey *key = &plane_state->ckey;

	*key = *set;

	/*
	 * We want src key enabled on the
	 * sprite and not on the primary.
	 */
	if (plane->id == PLANE_PRIMARY &&
	    set->flags & I915_SET_COLORKEY_SOURCE)
		key->flags = 0;

	/*
	 * On SKL+ we want dst key enabled on
	 * the primary and not on the sprite.
	 */
	if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
	    set->flags & I915_SET_COLORKEY_DESTINATION)
		key->flags = 0;
}

1716 1717
int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
				    struct drm_file *file_priv)
1718
{
1719
	struct drm_i915_private *dev_priv = to_i915(dev);
1720 1721
	struct drm_intel_sprite_colorkey *set = data;
	struct drm_plane *plane;
1722 1723 1724
	struct drm_plane_state *plane_state;
	struct drm_atomic_state *state;
	struct drm_modeset_acquire_ctx ctx;
1725 1726
	int ret = 0;

1727 1728 1729
	/* ignore the pointless "none" flag */
	set->flags &= ~I915_SET_COLORKEY_NONE;

1730 1731 1732
	if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
		return -EINVAL;

1733 1734 1735 1736
	/* 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;

1737
	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1738 1739 1740
	    set->flags & I915_SET_COLORKEY_DESTINATION)
		return -EINVAL;

1741
	plane = drm_plane_find(dev, file_priv, set->plane_id);
1742 1743
	if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
		return -ENOENT;
1744

1745 1746 1747 1748 1749 1750 1751 1752 1753 1754
	/*
	 * SKL+ only plane 2 can do destination keying against plane 1.
	 * Also multiple planes can't do destination keying on the same
	 * pipe simultaneously.
	 */
	if (INTEL_GEN(dev_priv) >= 9 &&
	    to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
	    set->flags & I915_SET_COLORKEY_DESTINATION)
		return -EINVAL;

1755
	drm_modeset_acquire_init(&ctx, 0);
1756

1757 1758 1759 1760
	state = drm_atomic_state_alloc(plane->dev);
	if (!state) {
		ret = -ENOMEM;
		goto out;
1761
	}
1762 1763 1764 1765 1766
	state->acquire_ctx = &ctx;

	while (1) {
		plane_state = drm_atomic_get_plane_state(state, plane);
		ret = PTR_ERR_OR_ZERO(plane_state);
1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783
		if (!ret)
			intel_plane_set_ckey(to_intel_plane_state(plane_state), set);

		/*
		 * On some platforms we have to configure
		 * the dst colorkey on the primary plane.
		 */
		if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
			struct intel_crtc *crtc =
				intel_get_crtc_for_pipe(dev_priv,
							to_intel_plane(plane)->pipe);

			plane_state = drm_atomic_get_plane_state(state,
								 crtc->base.primary);
			ret = PTR_ERR_OR_ZERO(plane_state);
			if (!ret)
				intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1784
		}
1785

1786 1787 1788
		if (!ret)
			ret = drm_atomic_commit(state);

1789 1790
		if (ret != -EDEADLK)
			break;
1791

1792 1793 1794
		drm_atomic_state_clear(state);
		drm_modeset_backoff(&ctx);
	}
1795

1796
	drm_atomic_state_put(state);
1797 1798 1799 1800
out:
	drm_modeset_drop_locks(&ctx);
	drm_modeset_acquire_fini(&ctx);
	return ret;
1801 1802
}

1803
static const u32 g4x_plane_formats[] = {
1804 1805 1806 1807 1808 1809 1810
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

1811
static const u64 i9xx_plane_format_modifiers[] = {
1812 1813 1814 1815 1816
	I915_FORMAT_MOD_X_TILED,
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
};

1817
static const u32 snb_plane_formats[] = {
1818 1819 1820 1821 1822 1823 1824 1825
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

1826
static const u32 vlv_plane_formats[] = {
1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839
	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,
};

1840
static const u32 skl_plane_formats[] = {
1841
	DRM_FORMAT_C8,
1842 1843
	DRM_FORMAT_RGB565,
	DRM_FORMAT_XRGB8888,
1844 1845 1846 1847 1848
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XRGB2101010,
	DRM_FORMAT_XBGR2101010,
1849 1850 1851 1852 1853 1854
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

1855
static const u32 icl_plane_formats[] = {
1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870
	DRM_FORMAT_C8,
	DRM_FORMAT_RGB565,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XRGB2101010,
	DRM_FORMAT_XBGR2101010,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
	DRM_FORMAT_Y210,
	DRM_FORMAT_Y212,
	DRM_FORMAT_Y216,
1871 1872 1873
	DRM_FORMAT_XVYU2101010,
	DRM_FORMAT_XVYU12_16161616,
	DRM_FORMAT_XVYU16161616,
1874 1875
};

1876
static const u32 icl_hdr_plane_formats[] = {
1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895
	DRM_FORMAT_C8,
	DRM_FORMAT_RGB565,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XRGB2101010,
	DRM_FORMAT_XBGR2101010,
	DRM_FORMAT_XRGB16161616F,
	DRM_FORMAT_XBGR16161616F,
	DRM_FORMAT_ARGB16161616F,
	DRM_FORMAT_ABGR16161616F,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
	DRM_FORMAT_Y210,
	DRM_FORMAT_Y212,
	DRM_FORMAT_Y216,
1896 1897 1898
	DRM_FORMAT_XVYU2101010,
	DRM_FORMAT_XVYU12_16161616,
	DRM_FORMAT_XVYU16161616,
1899 1900
};

1901
static const u32 skl_planar_formats[] = {
1902
	DRM_FORMAT_C8,
1903 1904
	DRM_FORMAT_RGB565,
	DRM_FORMAT_XRGB8888,
1905 1906 1907 1908 1909
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XRGB2101010,
	DRM_FORMAT_XBGR2101010,
1910 1911 1912 1913 1914 1915 1916
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
	DRM_FORMAT_NV12,
};

1917
static const u32 glk_planar_formats[] = {
1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935
	DRM_FORMAT_C8,
	DRM_FORMAT_RGB565,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XRGB2101010,
	DRM_FORMAT_XBGR2101010,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
	DRM_FORMAT_NV12,
	DRM_FORMAT_P010,
	DRM_FORMAT_P012,
	DRM_FORMAT_P016,
};

1936
static const u32 icl_planar_formats[] = {
1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955
	DRM_FORMAT_C8,
	DRM_FORMAT_RGB565,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XRGB2101010,
	DRM_FORMAT_XBGR2101010,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
	DRM_FORMAT_NV12,
	DRM_FORMAT_P010,
	DRM_FORMAT_P012,
	DRM_FORMAT_P016,
	DRM_FORMAT_Y210,
	DRM_FORMAT_Y212,
	DRM_FORMAT_Y216,
1956 1957 1958
	DRM_FORMAT_XVYU2101010,
	DRM_FORMAT_XVYU12_16161616,
	DRM_FORMAT_XVYU16161616,
1959 1960
};

1961
static const u32 icl_hdr_planar_formats[] = {
1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984
	DRM_FORMAT_C8,
	DRM_FORMAT_RGB565,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XRGB2101010,
	DRM_FORMAT_XBGR2101010,
	DRM_FORMAT_XRGB16161616F,
	DRM_FORMAT_XBGR16161616F,
	DRM_FORMAT_ARGB16161616F,
	DRM_FORMAT_ABGR16161616F,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
	DRM_FORMAT_NV12,
	DRM_FORMAT_P010,
	DRM_FORMAT_P012,
	DRM_FORMAT_P016,
	DRM_FORMAT_Y210,
	DRM_FORMAT_Y212,
	DRM_FORMAT_Y216,
1985 1986 1987
	DRM_FORMAT_XVYU2101010,
	DRM_FORMAT_XVYU12_16161616,
	DRM_FORMAT_XVYU16161616,
1988 1989
};

1990
static const u64 skl_plane_format_modifiers_noccs[] = {
1991 1992 1993 1994 1995 1996 1997
	I915_FORMAT_MOD_Yf_TILED,
	I915_FORMAT_MOD_Y_TILED,
	I915_FORMAT_MOD_X_TILED,
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
};

1998
static const u64 skl_plane_format_modifiers_ccs[] = {
1999 2000
	I915_FORMAT_MOD_Yf_TILED_CCS,
	I915_FORMAT_MOD_Y_TILED_CCS,
2001 2002
	I915_FORMAT_MOD_Yf_TILED,
	I915_FORMAT_MOD_Y_TILED,
2003 2004 2005 2006 2007
	I915_FORMAT_MOD_X_TILED,
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
};

2008 2009
static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
					    u32 format, u64 modifier)
2010
{
2011 2012 2013 2014 2015 2016 2017 2018
	switch (modifier) {
	case DRM_FORMAT_MOD_LINEAR:
	case I915_FORMAT_MOD_X_TILED:
		break;
	default:
		return false;
	}

2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033
	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;
	}
}

2034 2035
static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
					    u32 format, u64 modifier)
2036
{
2037 2038 2039 2040 2041 2042 2043 2044
	switch (modifier) {
	case DRM_FORMAT_MOD_LINEAR:
	case I915_FORMAT_MOD_X_TILED:
		break;
	default:
		return false;
	}

2045
	switch (format) {
2046 2047
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_XBGR8888:
2048 2049 2050 2051
	case DRM_FORMAT_YUYV:
	case DRM_FORMAT_YVYU:
	case DRM_FORMAT_UYVY:
	case DRM_FORMAT_VYUY:
2052 2053 2054 2055 2056 2057 2058 2059 2060
		if (modifier == DRM_FORMAT_MOD_LINEAR ||
		    modifier == I915_FORMAT_MOD_X_TILED)
			return true;
		/* fall through */
	default:
		return false;
	}
}

2061 2062
static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
					    u32 format, u64 modifier)
2063
{
2064 2065 2066 2067 2068 2069 2070 2071
	switch (modifier) {
	case DRM_FORMAT_MOD_LINEAR:
	case I915_FORMAT_MOD_X_TILED:
		break;
	default:
		return false;
	}

2072
	switch (format) {
2073
	case DRM_FORMAT_RGB565:
2074
	case DRM_FORMAT_ABGR8888:
2075
	case DRM_FORMAT_ARGB8888:
2076 2077
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_XRGB8888:
2078 2079
	case DRM_FORMAT_XBGR2101010:
	case DRM_FORMAT_ABGR2101010:
2080 2081 2082 2083
	case DRM_FORMAT_YUYV:
	case DRM_FORMAT_YVYU:
	case DRM_FORMAT_UYVY:
	case DRM_FORMAT_VYUY:
2084 2085 2086 2087 2088 2089 2090 2091 2092
		if (modifier == DRM_FORMAT_MOD_LINEAR ||
		    modifier == I915_FORMAT_MOD_X_TILED)
			return true;
		/* fall through */
	default:
		return false;
	}
}

2093 2094
static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
					   u32 format, u64 modifier)
2095
{
2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112
	struct intel_plane *plane = to_intel_plane(_plane);

	switch (modifier) {
	case DRM_FORMAT_MOD_LINEAR:
	case I915_FORMAT_MOD_X_TILED:
	case I915_FORMAT_MOD_Y_TILED:
	case I915_FORMAT_MOD_Yf_TILED:
		break;
	case I915_FORMAT_MOD_Y_TILED_CCS:
	case I915_FORMAT_MOD_Yf_TILED_CCS:
		if (!plane->has_ccs)
			return false;
		break;
	default:
		return false;
	}

2113 2114 2115 2116 2117
	switch (format) {
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_ARGB8888:
	case DRM_FORMAT_ABGR8888:
2118
		if (is_ccs_modifier(modifier))
2119 2120
			return true;
		/* fall through */
2121 2122 2123 2124 2125 2126 2127
	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:
2128
	case DRM_FORMAT_NV12:
2129 2130 2131
	case DRM_FORMAT_P010:
	case DRM_FORMAT_P012:
	case DRM_FORMAT_P016:
2132
	case DRM_FORMAT_XVYU2101010:
2133 2134 2135 2136
		if (modifier == I915_FORMAT_MOD_Yf_TILED)
			return true;
		/* fall through */
	case DRM_FORMAT_C8:
2137 2138 2139 2140
	case DRM_FORMAT_XBGR16161616F:
	case DRM_FORMAT_ABGR16161616F:
	case DRM_FORMAT_XRGB16161616F:
	case DRM_FORMAT_ARGB16161616F:
2141 2142 2143 2144 2145
	case DRM_FORMAT_Y210:
	case DRM_FORMAT_Y212:
	case DRM_FORMAT_Y216:
	case DRM_FORMAT_XVYU12_16161616:
	case DRM_FORMAT_XVYU16161616:
2146 2147 2148 2149 2150 2151 2152 2153 2154 2155
		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;
	}
}

2156 2157 2158 2159 2160 2161 2162 2163
static const struct drm_plane_funcs g4x_sprite_funcs = {
	.update_plane = drm_atomic_helper_update_plane,
	.disable_plane = drm_atomic_helper_disable_plane,
	.destroy = intel_plane_destroy,
	.atomic_duplicate_state = intel_plane_duplicate_state,
	.atomic_destroy_state = intel_plane_destroy_state,
	.format_mod_supported = g4x_sprite_format_mod_supported,
};
2164

2165 2166 2167 2168 2169 2170 2171 2172
static const struct drm_plane_funcs snb_sprite_funcs = {
	.update_plane = drm_atomic_helper_update_plane,
	.disable_plane = drm_atomic_helper_disable_plane,
	.destroy = intel_plane_destroy,
	.atomic_duplicate_state = intel_plane_duplicate_state,
	.atomic_destroy_state = intel_plane_destroy_state,
	.format_mod_supported = snb_sprite_format_mod_supported,
};
2173

2174 2175 2176 2177 2178 2179 2180 2181
static const struct drm_plane_funcs vlv_sprite_funcs = {
	.update_plane = drm_atomic_helper_update_plane,
	.disable_plane = drm_atomic_helper_disable_plane,
	.destroy = intel_plane_destroy,
	.atomic_duplicate_state = intel_plane_duplicate_state,
	.atomic_destroy_state = intel_plane_destroy_state,
	.format_mod_supported = vlv_sprite_format_mod_supported,
};
2182

2183
static const struct drm_plane_funcs skl_plane_funcs = {
2184 2185 2186 2187 2188
	.update_plane = drm_atomic_helper_update_plane,
	.disable_plane = drm_atomic_helper_disable_plane,
	.destroy = intel_plane_destroy,
	.atomic_duplicate_state = intel_plane_duplicate_state,
	.atomic_destroy_state = intel_plane_destroy_state,
2189
	.format_mod_supported = skl_plane_format_mod_supported,
2190 2191
};

2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204
static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
			      enum pipe pipe, enum plane_id plane_id)
{
	if (!HAS_FBC(dev_priv))
		return false;

	return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
}

static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
				 enum pipe pipe, enum plane_id plane_id)
{
	if (INTEL_GEN(dev_priv) >= 11)
2205
		return plane_id <= PLANE_SPRITE3;
2206

2207
	/* Display WA #0870: skl, bxt */
2208 2209 2210
	if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
		return false;

2211
	if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
2212 2213 2214 2215 2216 2217 2218 2219 2220 2221
		return false;

	if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
		return false;

	return true;
}

static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
			      enum pipe pipe, enum plane_id plane_id)
2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236
{
	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);
}

2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269
struct intel_plane *
skl_universal_plane_create(struct drm_i915_private *dev_priv,
			   enum pipe pipe, enum plane_id plane_id)
{
	struct intel_plane *plane;
	enum drm_plane_type plane_type;
	unsigned int supported_rotations;
	unsigned int possible_crtcs;
	const u64 *modifiers;
	const u32 *formats;
	int num_formats;
	int ret;

	plane = intel_plane_alloc();
	if (IS_ERR(plane))
		return plane;

	plane->pipe = pipe;
	plane->id = plane_id;
	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);

	plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
	if (plane->has_fbc) {
		struct intel_fbc *fbc = &dev_priv->fbc;

		fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
	}

	plane->max_stride = skl_plane_max_stride;
	plane->update_plane = skl_update_plane;
	plane->disable_plane = skl_disable_plane;
	plane->get_hw_state = skl_plane_get_hw_state;
	plane->check_plane = skl_plane_check;
2270 2271
	if (icl_is_nv12_y_plane(plane_id))
		plane->update_slave = icl_update_slave;
2272 2273

	if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2274 2275 2276 2277
		if (icl_is_hdr_plane(dev_priv, plane_id)) {
			formats = icl_hdr_planar_formats;
			num_formats = ARRAY_SIZE(icl_hdr_planar_formats);
		} else if (INTEL_GEN(dev_priv) >= 11) {
2278 2279 2280
			formats = icl_planar_formats;
			num_formats = ARRAY_SIZE(icl_planar_formats);
		} else if (INTEL_GEN(dev_priv) == 10 || IS_GEMINILAKE(dev_priv)) {
2281 2282 2283 2284 2285 2286
			formats = glk_planar_formats;
			num_formats = ARRAY_SIZE(glk_planar_formats);
		} else {
			formats = skl_planar_formats;
			num_formats = ARRAY_SIZE(skl_planar_formats);
		}
2287 2288 2289
	} else if (icl_is_hdr_plane(dev_priv, plane_id)) {
		formats = icl_hdr_plane_formats;
		num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
2290 2291 2292
	} else if (INTEL_GEN(dev_priv) >= 11) {
		formats = icl_plane_formats;
		num_formats = ARRAY_SIZE(icl_plane_formats);
2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354
	} else {
		formats = skl_plane_formats;
		num_formats = ARRAY_SIZE(skl_plane_formats);
	}

	plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
	if (plane->has_ccs)
		modifiers = skl_plane_format_modifiers_ccs;
	else
		modifiers = skl_plane_format_modifiers_noccs;

	if (plane_id == PLANE_PRIMARY)
		plane_type = DRM_PLANE_TYPE_PRIMARY;
	else
		plane_type = DRM_PLANE_TYPE_OVERLAY;

	possible_crtcs = BIT(pipe);

	ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
				       possible_crtcs, &skl_plane_funcs,
				       formats, num_formats, modifiers,
				       plane_type,
				       "plane %d%c", plane_id + 1,
				       pipe_name(pipe));
	if (ret)
		goto fail;

	supported_rotations =
		DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
		DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;

	if (INTEL_GEN(dev_priv) >= 10)
		supported_rotations |= DRM_MODE_REFLECT_X;

	drm_plane_create_rotation_property(&plane->base,
					   DRM_MODE_ROTATE_0,
					   supported_rotations);

	drm_plane_create_color_properties(&plane->base,
					  BIT(DRM_COLOR_YCBCR_BT601) |
					  BIT(DRM_COLOR_YCBCR_BT709),
					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
					  DRM_COLOR_YCBCR_BT709,
					  DRM_COLOR_YCBCR_LIMITED_RANGE);

	drm_plane_create_alpha_property(&plane->base);
	drm_plane_create_blend_mode_property(&plane->base,
					     BIT(DRM_MODE_BLEND_PIXEL_NONE) |
					     BIT(DRM_MODE_BLEND_PREMULTI) |
					     BIT(DRM_MODE_BLEND_COVERAGE));

	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);

	return plane;

fail:
	intel_plane_free(plane);

	return ERR_PTR(ret);
}

2355
struct intel_plane *
2356
intel_sprite_plane_create(struct drm_i915_private *dev_priv,
2357
			  enum pipe pipe, int sprite)
2358
{
2359
	struct intel_plane *plane;
2360
	const struct drm_plane_funcs *plane_funcs;
2361
	unsigned long possible_crtcs;
2362
	unsigned int supported_rotations;
2363 2364 2365
	const u64 *modifiers;
	const u32 *formats;
	int num_formats;
2366 2367
	int ret;

2368 2369
	if (INTEL_GEN(dev_priv) >= 9)
		return skl_universal_plane_create(dev_priv, pipe,
2370
						  PLANE_SPRITE0 + sprite);
2371

2372 2373 2374
	plane = intel_plane_alloc();
	if (IS_ERR(plane))
		return plane;
2375

2376
	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
2377 2378 2379 2380 2381 2382 2383 2384
		plane->max_stride = i9xx_plane_max_stride;
		plane->update_plane = vlv_update_plane;
		plane->disable_plane = vlv_disable_plane;
		plane->get_hw_state = vlv_plane_get_hw_state;
		plane->check_plane = vlv_sprite_check;

		formats = vlv_plane_formats;
		num_formats = ARRAY_SIZE(vlv_plane_formats);
2385
		modifiers = i9xx_plane_format_modifiers;
2386 2387

		plane_funcs = &vlv_sprite_funcs;
V
Ville Syrjälä 已提交
2388
	} else if (INTEL_GEN(dev_priv) >= 7) {
2389 2390 2391 2392 2393 2394 2395 2396
		plane->max_stride = g4x_sprite_max_stride;
		plane->update_plane = ivb_update_plane;
		plane->disable_plane = ivb_disable_plane;
		plane->get_hw_state = ivb_plane_get_hw_state;
		plane->check_plane = g4x_sprite_check;

		formats = snb_plane_formats;
		num_formats = ARRAY_SIZE(snb_plane_formats);
2397
		modifiers = i9xx_plane_format_modifiers;
2398 2399

		plane_funcs = &snb_sprite_funcs;
V
Ville Syrjälä 已提交
2400
	} else {
2401 2402 2403 2404 2405
		plane->max_stride = g4x_sprite_max_stride;
		plane->update_plane = g4x_update_plane;
		plane->disable_plane = g4x_disable_plane;
		plane->get_hw_state = g4x_plane_get_hw_state;
		plane->check_plane = g4x_sprite_check;
2406

2407
		modifiers = i9xx_plane_format_modifiers;
2408
		if (IS_GEN(dev_priv, 6)) {
2409 2410
			formats = snb_plane_formats;
			num_formats = ARRAY_SIZE(snb_plane_formats);
2411 2412

			plane_funcs = &snb_sprite_funcs;
V
Ville Syrjälä 已提交
2413
		} else {
2414 2415
			formats = g4x_plane_formats;
			num_formats = ARRAY_SIZE(g4x_plane_formats);
2416 2417

			plane_funcs = &g4x_sprite_funcs;
2418
		}
2419 2420
	}

2421
	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
2422
		supported_rotations =
2423 2424
			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
			DRM_MODE_REFLECT_X;
2425 2426
	} else {
		supported_rotations =
2427
			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
2428 2429
	}

2430 2431 2432
	plane->pipe = pipe;
	plane->id = PLANE_SPRITE0 + sprite;
	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
2433

2434
	possible_crtcs = BIT(pipe);
2435

2436
	ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2437
				       possible_crtcs, plane_funcs,
2438
				       formats, num_formats, modifiers,
2439
				       DRM_PLANE_TYPE_OVERLAY,
2440
				       "sprite %c", sprite_name(pipe, sprite));
2441 2442
	if (ret)
		goto fail;
2443

2444
	drm_plane_create_rotation_property(&plane->base,
2445
					   DRM_MODE_ROTATE_0,
2446
					   supported_rotations);
2447

2448
	drm_plane_create_color_properties(&plane->base,
2449 2450
					  BIT(DRM_COLOR_YCBCR_BT601) |
					  BIT(DRM_COLOR_YCBCR_BT709),
2451 2452
					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2453
					  DRM_COLOR_YCBCR_BT709,
2454 2455
					  DRM_COLOR_YCBCR_LIMITED_RANGE);

2456
	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
2457

2458
	return plane;
2459 2460

fail:
2461
	intel_plane_free(plane);
2462

2463
	return ERR_PTR(ret);
2464
}