intel_sprite.c 72.7 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 "i915_trace.h"
44
#include "intel_atomic_plane.h"
45 46
#include "intel_drv.h"
#include "intel_frontbuffer.h"
47
#include "intel_pm.h"
48
#include "intel_psr.h"
49
#include "intel_sprite.h"
50

51 52 53 54 55 56 57 58 59 60 61 62 63
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;
	}
}

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

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

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

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

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

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

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

120
	if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
121 122 123 124 125 126 127
		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.
	 */
128 129 130
	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);
131 132

	local_irq_disable();
133

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

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

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

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

163
	finish_wait(wq, &wait);
164

165
	drm_crtc_vblank_put(&crtc->base);
166

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

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

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

irq_disable:
	local_irq_disable();
194 195
}

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

213
	trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
214

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

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

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

229 230
	local_irq_enable();

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

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

253 254 255 256 257 258 259
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;

260 261 262 263 264 265 266 267 268 269
	/*
	 * 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;

270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
	/* 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;
}

285 286 287 288
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;
289 290
	u32 src_x, src_y, src_w, src_h, hsub, vsub;
	bool rotated = drm_rotation_90_or_270(plane_state->base.rotation);
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307

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

308 309 310 311 312 313 314 315 316 317 318 319 320 321
	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 " : "");
322 323 324
		return -EINVAL;
	}

325 326 327
	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 " : "");
328 329 330
		return -EINVAL;
	}

331 332 333
	return 0;
}

334 335 336 337 338 339
bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
{
	return INTEL_GEN(dev_priv) >= 11 &&
		icl_hdr_plane_mask() & BIT(plane_id);
}

340
static unsigned int
341 342 343 344
skl_plane_max_stride(struct intel_plane *plane,
		     u32 pixel_format, u64 modifier,
		     unsigned int rotation)
{
345
	const struct drm_format_info *info = drm_format_info(pixel_format);
346
	int cpp = info->cpp[0];
347 348 349 350 351 352 353 354 355 356 357

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

358
static void
359
skl_program_scaler(struct intel_plane *plane,
360 361 362
		   const struct intel_crtc_state *crtc_state,
		   const struct intel_plane_state *plane_state)
{
363
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
364 365 366 367 368 369
	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;
370 371
	u32 crtc_w = drm_rect_width(&plane_state->base.dst);
	u32 crtc_h = drm_rect_height(&plane_state->base.dst);
372 373
	u16 y_hphase, uv_rgb_hphase;
	u16 y_vphase, uv_rgb_vphase;
374 375 376 377 378 379 380 381
	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);
382 383

	/* TODO: handle sub-pixel coordinates */
384
	if (is_planar_yuv_format(plane_state->base.fb->format->format) &&
385
	    !icl_is_hdr_plane(dev_priv, plane->id)) {
386 387
		y_hphase = skl_scaler_calc_phase(1, hscale, false);
		y_vphase = skl_scaler_calc_phase(1, vscale, false);
388 389

		/* MPEG2 chroma siting convention */
390 391
		uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
		uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
392 393 394 395 396
	} else {
		/* not used */
		y_hphase = 0;
		y_vphase = 0;

397 398
		uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
		uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
399 400 401
	}

	I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
402
		      PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode);
403 404 405 406 407
	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);
408
	I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h);
409 410
}

411 412 413 414 415 416 417 418 419 420
/* 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
421 422 423
icl_program_input_csc(struct intel_plane *plane,
		      const struct intel_crtc_state *crtc_state,
		      const struct intel_plane_state *plane_state)
424
{
425 426
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
	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,
451
			0x9EF8, 0x7800, 0xAC00,
452 453
			0x0, 0x7800,  0x7ED8,
		},
454 455 456 457 458 459 460 461 462 463 464 465
		/*
		 * BT.2020 full range YCbCr -> full range RGB
		 * The matrix required is :
		 * [1.000, 0.000, 1.474,
		 *  1.000, -0.1645, -0.5713,
		 *  1.000, 1.8814, 0.0000]
		 */
		[DRM_COLOR_YCBCR_BT2020] = {
			0x7BC8, 0x7800, 0x0,
			0x8928, 0x7800, 0xAA88,
			0x0, 0x7800, 0x7F10,
		},
466 467 468 469 470 471 472
	};

	/* 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 :
473 474 475
		 * [1.164384, 0.000, 1.596027,
		 *  1.164384, -0.39175, -0.812813,
		 *  1.164384, 2.017232, 0.0000]
476 477 478
		 */
		[DRM_COLOR_YCBCR_BT601] = {
			0x7CC8, 0x7950, 0x0,
479 480
			0x8D00, 0x7950, 0x9C88,
			0x0, 0x7950, 0x6810,
481 482 483 484
		},
		/*
		 * BT.709 Limited range YCbCr -> full range RGB
		 * The matrix required is :
485 486 487
		 * [1.164384, 0.000, 1.792741,
		 *  1.164384, -0.213249, -0.532909,
		 *  1.164384, 2.112402, 0.0000]
488 489
		 */
		[DRM_COLOR_YCBCR_BT709] = {
490 491 492
			0x7E58, 0x7950, 0x0,
			0x8888, 0x7950, 0xADA8,
			0x0, 0x7950,  0x6870,
493
		},
494 495 496 497 498 499 500 501 502 503 504 505
		/*
		 * BT.2020 Limited range YCbCr -> full range RGB
		 * The matrix required is :
		 * [1.164, 0.000, 1.678,
		 *  1.164, -0.1873, -0.6504,
		 *  1.164, 2.1417, 0.0000]
		 */
		[DRM_COLOR_YCBCR_BT2020] = {
			0x7D70, 0x7950, 0x0,
			0x8A68, 0x7950, 0xAC00,
			0x0, 0x7950, 0x6890,
		},
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
	};
	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);
526 527 528 529 530
	if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
		I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1), 0);
	else
		I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
			      PREOFF_YUV_TO_RGB_ME);
531 532 533 534 535 536 537
	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);
}

538
static void
539 540 541 542
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)
543
{
544 545 546
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum plane_id plane_id = plane->id;
	enum pipe pipe = plane->pipe;
547
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
548 549
	u32 surf_addr = plane_state->color_plane[color_plane].offset;
	u32 stride = skl_plane_stride(plane_state, color_plane);
550
	u32 aux_stride = skl_plane_stride(plane_state, 1);
551 552
	int crtc_x = plane_state->base.dst.x1;
	int crtc_y = plane_state->base.dst.y1;
553 554 555 556
	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;
557
	struct intel_plane *linked = plane_state->linked_plane;
558
	const struct drm_framebuffer *fb = plane_state->base.fb;
559
	u8 alpha = plane_state->base.alpha >> 8;
560
	u32 plane_color_ctl = 0;
561
	unsigned long irqflags;
562
	u32 keymsk, keymax;
563

564 565 566 567 568 569
	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);

570 571 572 573
	/* Sizes are 0 based */
	src_w--;
	src_h--;

574 575
	keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);

576
	keymsk = key->channel_mask & 0x7ffffff;
577 578 579
	if (alpha < 0xff)
		keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;

580 581 582 583 584 585
	/* The scaler will handle the output position */
	if (plane_state->scaler_id >= 0) {
		crtc_x = 0;
		crtc_y = 0;
	}

586 587 588
	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);

	I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
589
	I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
590
	I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
591
	I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
592
		      (plane_state->color_plane[1].offset - surf_addr) | aux_stride);
593

594
	if (icl_is_hdr_plane(dev_priv, plane_id)) {
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
		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);
	}

615
	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
616
		I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
617

618
	if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
619
		icl_program_input_csc(plane, crtc_state, plane_state);
620

621 622
	skl_write_plane_wm(plane, crtc_state);

623 624 625 626 627 628 629 630 631 632
	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);
633

634 635 636 637 638
	/*
	 * 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.
	 */
639 640 641 642
	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);

643 644 645
	if (!slave && plane_state->scaler_id >= 0)
		skl_program_scaler(plane, crtc_state, plane_state);

646
	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
647 648
}

649
static void
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
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);
}

665
static void
666 667 668 669 670 671 672 673
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);
}

674
static void
675 676
skl_disable_plane(struct intel_plane *plane,
		  const struct intel_crtc_state *crtc_state)
677
{
678 679 680
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum plane_id plane_id = plane->id;
	enum pipe pipe = plane->pipe;
681 682 683
	unsigned long irqflags;

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

685 686 687
	if (icl_is_hdr_plane(dev_priv, plane_id))
		I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), 0);

688 689
	skl_write_plane_wm(plane, crtc_state);

690 691 692 693
	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);
694 695
}

696
static bool
697 698
skl_plane_get_hw_state(struct intel_plane *plane,
		       enum pipe *pipe)
699 700 701 702
{
	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;
703
	intel_wakeref_t wakeref;
704 705
	bool ret;

706
	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
707 708
	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
	if (!wakeref)
709 710
		return false;

711 712 713
	ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;

	*pipe = plane->pipe;
714

715
	intel_display_power_put(dev_priv, power_domain, wakeref);
716 717 718 719

	return ret;
}

720 721 722 723 724 725 726 727 728 729
static void i9xx_plane_linear_gamma(u16 gamma[8])
{
	/* The points are not evenly spaced. */
	static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
	int i;

	for (i = 0; i < 8; i++)
		gamma[i] = (in[i] << 8) / 32;
}

730
static void
731
chv_update_csc(const struct intel_plane_state *plane_state)
732
{
733
	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
734
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
735
	const struct drm_framebuffer *fb = plane_state->base.fb;
736
	enum plane_id plane_id = plane->id;
737
	/*
738 739 740
	 * |r|   | c0 c1 c2 |   |cr|
	 * |g| = | c3 c4 c5 | x |y |
	 * |b|   | c6 c7 c8 |   |cb|
741
	 *
742
	 * Coefficients are s3.12.
743
	 *
744 745
	 * Cb and Cr apparently come in as signed already, and
	 * we always get full range data in on account of CLRC0/1.
746
	 */
747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
	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];
762 763

	/* Seems RGB data bypasses the CSC always */
764
	if (!fb->format->is_yuv)
765 766
		return;

767
	I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
768 769 770
	I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
	I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));

771 772 773 774 775
	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]));
776

777 778 779
	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));
780 781 782 783

	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));
784 785
}

786 787 788 789 790 791 792 793 794 795 796 797 798
#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;

799
	if (fb->format->is_yuv &&
800
	    plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
		/*
		 * 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));
}

828 829
static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
{
830 831 832 833 834 835
	u32 sprctl = 0;

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

	return sprctl;
836 837
}

838 839
static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
			  const struct intel_plane_state *plane_state)
840
{
841
	const struct drm_framebuffer *fb = plane_state->base.fb;
842
	unsigned int rotation = plane_state->base.rotation;
843
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
844
	u32 sprctl;
845

846
	sprctl = SP_ENABLE;
847

V
Ville Syrjälä 已提交
848
	switch (fb->format->format) {
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882
	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:
883 884
		MISSING_CASE(fb->format->format);
		return 0;
885 886
	}

887 888 889
	if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
		sprctl |= SP_YUV_FORMAT_BT709;

V
Ville Syrjälä 已提交
890
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
891 892
		sprctl |= SP_TILED;

893
	if (rotation & DRM_MODE_ROTATE_180)
894 895
		sprctl |= SP_ROTATE_180;

896
	if (rotation & DRM_MODE_REFLECT_X)
897 898
		sprctl |= SP_MIRROR;

899 900 901
	if (key->flags & I915_SET_COLORKEY_SOURCE)
		sprctl |= SP_SOURCE_KEY;

902 903 904
	return sprctl;
}

905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929
static void vlv_update_gamma(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;
	u16 gamma[8];
	int i;

	/* Seems RGB data bypasses the gamma always */
	if (!fb->format->is_yuv)
		return;

	i9xx_plane_linear_gamma(gamma);

	/* FIXME these register are single buffered :( */
	/* The two end points are implicit (0.0 and 1.0) */
	for (i = 1; i < 8 - 1; i++)
		I915_WRITE_FW(SPGAMC(pipe, plane_id, i - 1),
			      gamma[i] << 16 |
			      gamma[i] << 8 |
			      gamma[i]);
}

930
static void
931
vlv_update_plane(struct intel_plane *plane,
932 933 934
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
935 936 937
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
	enum plane_id plane_id = plane->id;
938
	u32 sprsurf_offset = plane_state->color_plane[0].offset;
939
	u32 linear_offset;
940 941 942
	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;
943 944 945 946
	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;
947
	unsigned long irqflags;
948 949 950
	u32 sprctl;

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

952 953 954 955
	/* Sizes are 0 based */
	crtc_w--;
	crtc_h--;

956
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
957

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

960 961 962 963 964 965
	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);

966
	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
967
		chv_update_csc(plane_state);
968

969
	if (key->flags) {
970 971
		I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
		I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
972
		I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
973
	}
974

975
	I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
976
	I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
977

978 979 980 981 982
	/*
	 * 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.
	 */
983 984 985 986
	I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
	I915_WRITE_FW(SPSURF(pipe, plane_id),
		      intel_plane_ggtt_offset(plane_state) + sprsurf_offset);

987
	vlv_update_clrc(plane_state);
988
	vlv_update_gamma(plane_state);
989

990
	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
991 992 993
}

static void
994 995
vlv_disable_plane(struct intel_plane *plane,
		  const struct intel_crtc_state *crtc_state)
996
{
997 998 999
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
	enum plane_id plane_id = plane->id;
1000 1001 1002
	unsigned long irqflags;

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

1004 1005 1006 1007
	I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
	I915_WRITE_FW(SPSURF(pipe, plane_id), 0);

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1008 1009
}

1010
static bool
1011 1012
vlv_plane_get_hw_state(struct intel_plane *plane,
		       enum pipe *pipe)
1013 1014 1015 1016
{
	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;
1017
	intel_wakeref_t wakeref;
1018 1019
	bool ret;

1020
	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1021 1022
	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
	if (!wakeref)
1023 1024
		return false;

1025 1026 1027
	ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;

	*pipe = plane->pipe;
1028

1029
	intel_display_power_put(dev_priv, power_domain, wakeref);
1030 1031 1032 1033

	return ret;
}

1034 1035 1036 1037
static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
{
	u32 sprctl = 0;

1038 1039
	if (crtc_state->gamma_enable)
		sprctl |= SPRITE_GAMMA_ENABLE;
1040

1041
	if (crtc_state->csc_enable)
1042 1043 1044 1045 1046
		sprctl |= SPRITE_PIPE_CSC_ENABLE;

	return sprctl;
}

1047 1048
static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
			  const struct intel_plane_state *plane_state)
1049
{
1050 1051 1052
	struct drm_i915_private *dev_priv =
		to_i915(plane_state->base.plane->dev);
	const struct drm_framebuffer *fb = plane_state->base.fb;
1053
	unsigned int rotation = plane_state->base.rotation;
1054
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1055 1056
	u32 sprctl;

1057
	sprctl = SPRITE_ENABLE;
1058

1059 1060 1061
	if (IS_IVYBRIDGE(dev_priv))
		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;

V
Ville Syrjälä 已提交
1062
	switch (fb->format->format) {
1063
	case DRM_FORMAT_XBGR8888:
1064
		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
1065 1066
		break;
	case DRM_FORMAT_XRGB8888:
1067
		sprctl |= SPRITE_FORMAT_RGBX888;
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
		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:
1082 1083
		MISSING_CASE(fb->format->format);
		return 0;
1084 1085
	}

1086 1087
	sprctl |= SPRITE_INT_GAMMA_DISABLE;

1088 1089 1090
	if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
		sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;

1091 1092 1093
	if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
		sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;

V
Ville Syrjälä 已提交
1094
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1095 1096
		sprctl |= SPRITE_TILED;

1097
	if (rotation & DRM_MODE_ROTATE_180)
1098 1099
		sprctl |= SPRITE_ROTATE_180;

1100 1101 1102 1103 1104
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
		sprctl |= SPRITE_DEST_KEY;
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
		sprctl |= SPRITE_SOURCE_KEY;

1105 1106 1107
	return sprctl;
}

1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
static void ivb_sprite_linear_gamma(u16 gamma[18])
{
	int i;

	for (i = 0; i < 17; i++)
		gamma[i] = (i << 10) / 16;

	gamma[i] = 3 << 10;
	i++;
}

static void ivb_update_gamma(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);
	enum pipe pipe = plane->pipe;
	u16 gamma[18];
	int i;

	ivb_sprite_linear_gamma(gamma);

	/* FIXME these register are single buffered :( */
	for (i = 0; i < 16; i++)
		I915_WRITE_FW(SPRGAMC(pipe, i),
			      gamma[i] << 20 |
			      gamma[i] << 10 |
			      gamma[i]);

	I915_WRITE_FW(SPRGAMC16(pipe, 0), gamma[i]);
	I915_WRITE_FW(SPRGAMC16(pipe, 1), gamma[i]);
	I915_WRITE_FW(SPRGAMC16(pipe, 2), gamma[i]);
	i++;

	I915_WRITE_FW(SPRGAMC17(pipe, 0), gamma[i]);
	I915_WRITE_FW(SPRGAMC17(pipe, 1), gamma[i]);
	I915_WRITE_FW(SPRGAMC17(pipe, 2), gamma[i]);
	i++;
}

1147
static void
1148
ivb_update_plane(struct intel_plane *plane,
1149 1150 1151
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
1152 1153
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
1154
	u32 sprsurf_offset = plane_state->color_plane[0].offset;
1155
	u32 linear_offset;
1156 1157 1158
	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;
1159 1160 1161 1162 1163 1164
	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;
1165
	u32 sprctl, sprscale = 0;
1166 1167
	unsigned long irqflags;

1168 1169
	sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);

1170 1171 1172 1173 1174 1175
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

1176
	if (crtc_w != src_w || crtc_h != src_h)
1177 1178
		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;

1179
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1180

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

1183 1184 1185 1186 1187 1188
	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);

1189
	if (key->flags) {
1190 1191
		I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
		I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
1192
		I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
1193 1194
	}

1195 1196
	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
	 * register */
1197
	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1198
		I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
1199
	} else {
1200
		I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
1201
		I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
1202
	}
1203

1204 1205 1206 1207 1208
	/*
	 * 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.
	 */
1209 1210 1211 1212
	I915_WRITE_FW(SPRCTL(pipe), sprctl);
	I915_WRITE_FW(SPRSURF(pipe),
		      intel_plane_ggtt_offset(plane_state) + sprsurf_offset);

1213 1214
	ivb_update_gamma(plane_state);

1215
	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1216 1217 1218
}

static void
1219 1220
ivb_disable_plane(struct intel_plane *plane,
		  const struct intel_crtc_state *crtc_state)
1221
{
1222 1223
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
1224 1225 1226
	unsigned long irqflags;

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

1228
	I915_WRITE_FW(SPRCTL(pipe), 0);
1229
	/* Disable the scaler */
1230
	if (IS_IVYBRIDGE(dev_priv))
1231 1232 1233 1234
		I915_WRITE_FW(SPRSCALE(pipe), 0);
	I915_WRITE_FW(SPRSURF(pipe), 0);

	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1235 1236
}

1237
static bool
1238 1239
ivb_plane_get_hw_state(struct intel_plane *plane,
		       enum pipe *pipe)
1240 1241 1242
{
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum intel_display_power_domain power_domain;
1243
	intel_wakeref_t wakeref;
1244 1245
	bool ret;

1246
	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1247 1248
	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
	if (!wakeref)
1249 1250
		return false;

1251 1252 1253
	ret =  I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;

	*pipe = plane->pipe;
1254

1255
	intel_display_power_put(dev_priv, power_domain, wakeref);
1256 1257 1258 1259

	return ret;
}

1260 1261 1262 1263 1264 1265 1266 1267
static unsigned int
g4x_sprite_max_stride(struct intel_plane *plane,
		      u32 pixel_format, u64 modifier,
		      unsigned int rotation)
{
	return 16384;
}

1268 1269
static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
{
1270 1271 1272 1273 1274
	u32 dvscntr = 0;

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

1275 1276 1277
	if (crtc_state->csc_enable)
		dvscntr |= DVS_PIPE_CSC_ENABLE;

1278
	return dvscntr;
1279 1280
}

1281
static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1282
			  const struct intel_plane_state *plane_state)
1283
{
1284 1285 1286
	struct drm_i915_private *dev_priv =
		to_i915(plane_state->base.plane->dev);
	const struct drm_framebuffer *fb = plane_state->base.fb;
1287
	unsigned int rotation = plane_state->base.rotation;
1288
	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1289 1290
	u32 dvscntr;

1291
	dvscntr = DVS_ENABLE;
1292

1293
	if (IS_GEN(dev_priv, 6))
1294
		dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1295

V
Ville Syrjälä 已提交
1296
	switch (fb->format->format) {
1297
	case DRM_FORMAT_XBGR8888:
1298
		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1299 1300
		break;
	case DRM_FORMAT_XRGB8888:
1301
		dvscntr |= DVS_FORMAT_RGBX888;
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
		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:
1316 1317
		MISSING_CASE(fb->format->format);
		return 0;
1318 1319
	}

1320 1321 1322
	if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
		dvscntr |= DVS_YUV_FORMAT_BT709;

1323 1324 1325
	if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
		dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;

V
Ville Syrjälä 已提交
1326
	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1327 1328
		dvscntr |= DVS_TILED;

1329
	if (rotation & DRM_MODE_ROTATE_180)
1330 1331
		dvscntr |= DVS_ROTATE_180;

1332 1333 1334 1335 1336
	if (key->flags & I915_SET_COLORKEY_DESTINATION)
		dvscntr |= DVS_DEST_KEY;
	else if (key->flags & I915_SET_COLORKEY_SOURCE)
		dvscntr |= DVS_SOURCE_KEY;

1337 1338 1339
	return dvscntr;
}

1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399
static void g4x_update_gamma(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;
	u16 gamma[8];
	int i;

	/* Seems RGB data bypasses the gamma always */
	if (!fb->format->is_yuv)
		return;

	i9xx_plane_linear_gamma(gamma);

	/* FIXME these register are single buffered :( */
	/* The two end points are implicit (0.0 and 1.0) */
	for (i = 1; i < 8 - 1; i++)
		I915_WRITE_FW(DVSGAMC_G4X(pipe, i - 1),
			      gamma[i] << 16 |
			      gamma[i] << 8 |
			      gamma[i]);
}

static void ilk_sprite_linear_gamma(u16 gamma[17])
{
	int i;

	for (i = 0; i < 17; i++)
		gamma[i] = (i << 10) / 16;
}

static void ilk_update_gamma(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;
	u16 gamma[17];
	int i;

	/* Seems RGB data bypasses the gamma always */
	if (!fb->format->is_yuv)
		return;

	ilk_sprite_linear_gamma(gamma);

	/* FIXME these register are single buffered :( */
	for (i = 0; i < 16; i++)
		I915_WRITE_FW(DVSGAMC_ILK(pipe, i),
			      gamma[i] << 20 |
			      gamma[i] << 10 |
			      gamma[i]);

	I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
	I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
	I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
	i++;
}

1400
static void
1401
g4x_update_plane(struct intel_plane *plane,
1402 1403 1404
		 const struct intel_crtc_state *crtc_state,
		 const struct intel_plane_state *plane_state)
{
1405 1406
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
1407
	u32 dvssurf_offset = plane_state->color_plane[0].offset;
1408
	u32 linear_offset;
1409 1410 1411
	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;
1412 1413 1414 1415 1416 1417
	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;
1418
	u32 dvscntr, dvsscale = 0;
1419 1420
	unsigned long irqflags;

1421 1422
	dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);

1423 1424 1425 1426 1427 1428
	/* Sizes are 0 based */
	src_w--;
	src_h--;
	crtc_w--;
	crtc_h--;

1429
	if (crtc_w != src_w || crtc_h != src_h)
1430 1431
		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;

1432
	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1433

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

1436 1437 1438 1439 1440
	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);

1441
	if (key->flags) {
1442 1443
		I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
		I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
1444
		I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
1445 1446
	}

1447
	I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
1448
	I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
1449

1450 1451 1452 1453 1454
	/*
	 * 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.
	 */
1455 1456 1457 1458
	I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
	I915_WRITE_FW(DVSSURF(pipe),
		      intel_plane_ggtt_offset(plane_state) + dvssurf_offset);

1459 1460 1461 1462 1463
	if (IS_G4X(dev_priv))
		g4x_update_gamma(plane_state);
	else
		ilk_update_gamma(plane_state);

1464
	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1465 1466 1467
}

static void
1468 1469
g4x_disable_plane(struct intel_plane *plane,
		  const struct intel_crtc_state *crtc_state)
1470
{
1471 1472
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
1473
	unsigned long irqflags;
1474

1475 1476 1477
	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);

	I915_WRITE_FW(DVSCNTR(pipe), 0);
1478
	/* Disable the scaler */
1479 1480
	I915_WRITE_FW(DVSSCALE(pipe), 0);
	I915_WRITE_FW(DVSSURF(pipe), 0);
1481

1482
	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1483 1484
}

1485
static bool
1486 1487
g4x_plane_get_hw_state(struct intel_plane *plane,
		       enum pipe *pipe)
1488 1489 1490
{
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum intel_display_power_domain power_domain;
1491
	intel_wakeref_t wakeref;
1492 1493
	bool ret;

1494
	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1495 1496
	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
	if (!wakeref)
1497 1498
		return false;

1499 1500 1501
	ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;

	*pipe = plane->pipe;
1502

1503
	intel_display_power_put(dev_priv, power_domain, wakeref);
1504 1505 1506 1507

	return ret;
}

1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520
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;
	}
}

1521
static int
1522 1523
g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
			 struct intel_plane_state *plane_state)
1524
{
1525 1526 1527
	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;
1528
	int src_x, src_w, src_h, crtc_w, crtc_h;
1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542
	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_w = drm_rect_width(src) >> 16;
	src_h = drm_rect_height(src) >> 16;

	if (src_w == crtc_w && src_h == crtc_h)
1543
		return 0;
1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554

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

1557 1558 1559 1560 1561 1562
	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);
1563
		return -EINVAL;
1564
	}
1565

1566 1567 1568
	if (width_bytes > 4096) {
		DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
			      width_bytes, 4096);
1569
		return -EINVAL;
1570
	}
1571

1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586
	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);
1587 1588
	int min_scale = DRM_PLANE_HELPER_NO_SCALING;
	int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1589 1590
	int ret;

1591 1592 1593 1594 1595 1596 1597 1598
	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;
		}
1599 1600
	}

1601
	ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1602 1603 1604 1605 1606
						  &crtc_state->base,
						  min_scale, max_scale,
						  true, true);
	if (ret)
		return ret;
1607

1608 1609 1610 1611
	ret = i9xx_check_plane_surface(plane_state);
	if (ret)
		return ret;

1612 1613
	if (!plane_state->base.visible)
		return 0;
1614

1615 1616 1617
	ret = intel_plane_check_src_coordinates(plane_state);
	if (ret)
		return ret;
1618

1619 1620 1621
	ret = g4x_sprite_check_scaling(crtc_state, plane_state);
	if (ret)
		return ret;
1622

1623 1624 1625 1626
	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);
1627

1628 1629
	return 0;
}
1630

1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647
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;
}

1648 1649 1650 1651 1652 1653
static int
vlv_sprite_check(struct intel_crtc_state *crtc_state,
		 struct intel_plane_state *plane_state)
{
	int ret;

1654 1655 1656 1657
	ret = chv_plane_check_rotation(plane_state);
	if (ret)
		return ret;

1658 1659 1660 1661 1662 1663 1664 1665
	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;

1666 1667 1668 1669
	ret = i9xx_check_plane_surface(plane_state);
	if (ret)
		return ret;

1670 1671 1672 1673 1674 1675 1676 1677
	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);
1678

1679 1680 1681
	return 0;
}

1682 1683 1684
static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
			      const struct intel_plane_state *plane_state)
{
1685 1686
	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1687 1688 1689 1690 1691 1692 1693 1694
	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) &&
1695
	    is_ccs_modifier(fb->modifier)) {
1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714
		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;
		}

		/*
1715 1716
		 * 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.
1717 1718 1719
		 */
		switch (fb->format->format) {
		case DRM_FORMAT_RGB565:
1720 1721 1722 1723
			if (INTEL_GEN(dev_priv) >= 11)
				break;
			/* fall through */
		case DRM_FORMAT_C8:
1724 1725 1726 1727
		case DRM_FORMAT_XRGB16161616F:
		case DRM_FORMAT_XBGR16161616F:
		case DRM_FORMAT_ARGB16161616F:
		case DRM_FORMAT_ABGR16161616F:
1728 1729 1730 1731 1732
		case DRM_FORMAT_Y210:
		case DRM_FORMAT_Y212:
		case DRM_FORMAT_Y216:
		case DRM_FORMAT_XVYU12_16161616:
		case DRM_FORMAT_XVYU16161616:
1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755
			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;
}

1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785
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;
}

1786 1787 1788 1789 1790 1791 1792
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 */
1793
	if (is_planar_yuv_format(fb->format->format) && src_w & 3 &&
1794 1795
	    (rotation == DRM_MODE_ROTATE_270 ||
	     rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1796
		DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
1797 1798 1799 1800 1801 1802
		return -EINVAL;
	}

	return 0;
}

1803 1804
static int skl_plane_check(struct intel_crtc_state *crtc_state,
			   struct intel_plane_state *plane_state)
1805 1806 1807
{
	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1808 1809 1810
	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;
1811 1812
	int ret;

1813 1814 1815 1816
	ret = skl_plane_check_fb(crtc_state, plane_state);
	if (ret)
		return ret;

1817
	/* use scaler when colorkey is not required */
1818
	if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
1819
		min_scale = 1;
1820
		max_scale = skl_max_scale(crtc_state, fb->format->format);
1821 1822
	}

1823 1824 1825 1826 1827 1828 1829
	ret = drm_atomic_helper_check_plane_state(&plane_state->base,
						  &crtc_state->base,
						  min_scale, max_scale,
						  true, true);
	if (ret)
		return ret;

1830 1831 1832 1833
	ret = skl_check_plane_surface(plane_state);
	if (ret)
		return ret;

1834 1835 1836
	if (!plane_state->base.visible)
		return 0;

1837 1838 1839 1840
	ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
	if (ret)
		return ret;

1841 1842 1843 1844
	ret = intel_plane_check_src_coordinates(plane_state);
	if (ret)
		return ret;

1845 1846 1847 1848
	ret = skl_plane_check_nv12_rotation(plane_state);
	if (ret)
		return ret;

1849 1850 1851 1852
	/* HW only has 8 bits pixel precision, disable plane if invisible */
	if (!(plane_state->base.alpha >> 8))
		plane_state->base.visible = false;

1853 1854
	plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);

1855
	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1856 1857
		plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
							     plane_state);
1858

1859 1860 1861
	return 0;
}

1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892
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;
}

1893 1894
int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
				    struct drm_file *file_priv)
1895
{
1896
	struct drm_i915_private *dev_priv = to_i915(dev);
1897 1898
	struct drm_intel_sprite_colorkey *set = data;
	struct drm_plane *plane;
1899 1900 1901
	struct drm_plane_state *plane_state;
	struct drm_atomic_state *state;
	struct drm_modeset_acquire_ctx ctx;
1902 1903
	int ret = 0;

1904 1905 1906
	/* ignore the pointless "none" flag */
	set->flags &= ~I915_SET_COLORKEY_NONE;

1907 1908 1909
	if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
		return -EINVAL;

1910 1911 1912 1913
	/* 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;

1914
	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1915 1916 1917
	    set->flags & I915_SET_COLORKEY_DESTINATION)
		return -EINVAL;

1918
	plane = drm_plane_find(dev, file_priv, set->plane_id);
1919 1920
	if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
		return -ENOENT;
1921

1922 1923 1924 1925 1926 1927 1928 1929 1930 1931
	/*
	 * 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;

1932
	drm_modeset_acquire_init(&ctx, 0);
1933

1934 1935 1936 1937
	state = drm_atomic_state_alloc(plane->dev);
	if (!state) {
		ret = -ENOMEM;
		goto out;
1938
	}
1939 1940 1941 1942 1943
	state->acquire_ctx = &ctx;

	while (1) {
		plane_state = drm_atomic_get_plane_state(state, plane);
		ret = PTR_ERR_OR_ZERO(plane_state);
1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960
		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);
1961
		}
1962

1963 1964 1965
		if (!ret)
			ret = drm_atomic_commit(state);

1966 1967
		if (ret != -EDEADLK)
			break;
1968

1969 1970 1971
		drm_atomic_state_clear(state);
		drm_modeset_backoff(&ctx);
	}
1972

1973
	drm_atomic_state_put(state);
1974 1975 1976 1977
out:
	drm_modeset_drop_locks(&ctx);
	drm_modeset_acquire_fini(&ctx);
	return ret;
1978 1979
}

1980
static const u32 g4x_plane_formats[] = {
1981 1982 1983 1984 1985 1986 1987
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

1988
static const u64 i9xx_plane_format_modifiers[] = {
1989 1990 1991 1992 1993
	I915_FORMAT_MOD_X_TILED,
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
};

1994
static const u32 snb_plane_formats[] = {
1995 1996 1997 1998 1999 2000 2001 2002
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

2003
static const u32 vlv_plane_formats[] = {
2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
	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,
};

2017
static const u32 skl_plane_formats[] = {
2018
	DRM_FORMAT_C8,
2019 2020
	DRM_FORMAT_RGB565,
	DRM_FORMAT_XRGB8888,
2021 2022 2023 2024 2025
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XRGB2101010,
	DRM_FORMAT_XBGR2101010,
2026 2027 2028 2029 2030 2031
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
};

2032
static const u32 skl_planar_formats[] = {
2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044
	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,
2045
	DRM_FORMAT_NV12,
2046 2047
};

2048
static const u32 glk_planar_formats[] = {
2049
	DRM_FORMAT_C8,
2050 2051
	DRM_FORMAT_RGB565,
	DRM_FORMAT_XRGB8888,
2052 2053 2054 2055 2056
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XRGB2101010,
	DRM_FORMAT_XBGR2101010,
2057 2058 2059 2060 2061
	DRM_FORMAT_YUYV,
	DRM_FORMAT_YVYU,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_VYUY,
	DRM_FORMAT_NV12,
2062 2063 2064
	DRM_FORMAT_P010,
	DRM_FORMAT_P012,
	DRM_FORMAT_P016,
2065 2066
};

2067
static const u32 icl_sdr_y_plane_formats[] = {
2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079
	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,
2080 2081 2082 2083 2084 2085
	DRM_FORMAT_Y210,
	DRM_FORMAT_Y212,
	DRM_FORMAT_Y216,
	DRM_FORMAT_XVYU2101010,
	DRM_FORMAT_XVYU12_16161616,
	DRM_FORMAT_XVYU16161616,
2086 2087
};

2088
static const u32 icl_sdr_uv_plane_formats[] = {
2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107
	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,
2108 2109 2110
	DRM_FORMAT_XVYU2101010,
	DRM_FORMAT_XVYU12_16161616,
	DRM_FORMAT_XVYU16161616,
2111 2112
};

2113
static const u32 icl_hdr_plane_formats[] = {
2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136
	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,
2137 2138 2139
	DRM_FORMAT_XVYU2101010,
	DRM_FORMAT_XVYU12_16161616,
	DRM_FORMAT_XVYU16161616,
2140 2141
};

2142
static const u64 skl_plane_format_modifiers_noccs[] = {
2143 2144 2145 2146 2147 2148 2149
	I915_FORMAT_MOD_Yf_TILED,
	I915_FORMAT_MOD_Y_TILED,
	I915_FORMAT_MOD_X_TILED,
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
};

2150
static const u64 skl_plane_format_modifiers_ccs[] = {
2151 2152
	I915_FORMAT_MOD_Yf_TILED_CCS,
	I915_FORMAT_MOD_Y_TILED_CCS,
2153 2154
	I915_FORMAT_MOD_Yf_TILED,
	I915_FORMAT_MOD_Y_TILED,
2155 2156 2157 2158 2159
	I915_FORMAT_MOD_X_TILED,
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
};

2160 2161
static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
					    u32 format, u64 modifier)
2162
{
2163 2164 2165 2166 2167 2168 2169 2170
	switch (modifier) {
	case DRM_FORMAT_MOD_LINEAR:
	case I915_FORMAT_MOD_X_TILED:
		break;
	default:
		return false;
	}

2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185
	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;
	}
}

2186 2187
static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
					    u32 format, u64 modifier)
2188
{
2189 2190 2191 2192 2193 2194 2195 2196
	switch (modifier) {
	case DRM_FORMAT_MOD_LINEAR:
	case I915_FORMAT_MOD_X_TILED:
		break;
	default:
		return false;
	}

2197
	switch (format) {
2198 2199
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_XBGR8888:
2200 2201 2202 2203
	case DRM_FORMAT_YUYV:
	case DRM_FORMAT_YVYU:
	case DRM_FORMAT_UYVY:
	case DRM_FORMAT_VYUY:
2204 2205 2206 2207 2208 2209 2210 2211 2212
		if (modifier == DRM_FORMAT_MOD_LINEAR ||
		    modifier == I915_FORMAT_MOD_X_TILED)
			return true;
		/* fall through */
	default:
		return false;
	}
}

2213 2214
static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
					    u32 format, u64 modifier)
2215
{
2216 2217 2218 2219 2220 2221 2222 2223
	switch (modifier) {
	case DRM_FORMAT_MOD_LINEAR:
	case I915_FORMAT_MOD_X_TILED:
		break;
	default:
		return false;
	}

2224
	switch (format) {
2225
	case DRM_FORMAT_RGB565:
2226
	case DRM_FORMAT_ABGR8888:
2227
	case DRM_FORMAT_ARGB8888:
2228 2229
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_XRGB8888:
2230 2231
	case DRM_FORMAT_XBGR2101010:
	case DRM_FORMAT_ABGR2101010:
2232 2233 2234 2235
	case DRM_FORMAT_YUYV:
	case DRM_FORMAT_YVYU:
	case DRM_FORMAT_UYVY:
	case DRM_FORMAT_VYUY:
2236 2237 2238 2239 2240 2241 2242 2243 2244
		if (modifier == DRM_FORMAT_MOD_LINEAR ||
		    modifier == I915_FORMAT_MOD_X_TILED)
			return true;
		/* fall through */
	default:
		return false;
	}
}

2245 2246
static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
					   u32 format, u64 modifier)
2247
{
2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264
	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;
	}

2265 2266 2267 2268 2269
	switch (format) {
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_ARGB8888:
	case DRM_FORMAT_ABGR8888:
2270
		if (is_ccs_modifier(modifier))
2271 2272
			return true;
		/* fall through */
2273 2274 2275 2276 2277 2278 2279
	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:
2280
	case DRM_FORMAT_NV12:
2281 2282 2283
	case DRM_FORMAT_P010:
	case DRM_FORMAT_P012:
	case DRM_FORMAT_P016:
2284
	case DRM_FORMAT_XVYU2101010:
2285 2286 2287 2288
		if (modifier == I915_FORMAT_MOD_Yf_TILED)
			return true;
		/* fall through */
	case DRM_FORMAT_C8:
2289 2290 2291 2292
	case DRM_FORMAT_XBGR16161616F:
	case DRM_FORMAT_ABGR16161616F:
	case DRM_FORMAT_XRGB16161616F:
	case DRM_FORMAT_ARGB16161616F:
2293 2294 2295 2296 2297
	case DRM_FORMAT_Y210:
	case DRM_FORMAT_Y212:
	case DRM_FORMAT_Y216:
	case DRM_FORMAT_XVYU12_16161616:
	case DRM_FORMAT_XVYU16161616:
2298 2299 2300 2301 2302 2303 2304 2305 2306 2307
		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;
	}
}

2308 2309 2310 2311 2312 2313 2314 2315
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,
};
2316

2317 2318 2319 2320 2321 2322 2323 2324
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,
};
2325

2326 2327 2328 2329 2330 2331 2332 2333
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,
};
2334

2335
static const struct drm_plane_funcs skl_plane_funcs = {
2336 2337 2338 2339 2340
	.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,
2341
	.format_mod_supported = skl_plane_format_mod_supported,
2342 2343
};

2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355
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)
{
2356
	/* Display WA #0870: skl, bxt */
2357 2358 2359
	if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
		return false;

2360
	if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
2361 2362 2363 2364 2365 2366 2367 2368
		return false;

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

	return true;
}

2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410
static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
					enum pipe pipe, enum plane_id plane_id,
					int *num_formats)
{
	if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
		*num_formats = ARRAY_SIZE(skl_planar_formats);
		return skl_planar_formats;
	} else {
		*num_formats = ARRAY_SIZE(skl_plane_formats);
		return skl_plane_formats;
	}
}

static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
					enum pipe pipe, enum plane_id plane_id,
					int *num_formats)
{
	if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
		*num_formats = ARRAY_SIZE(glk_planar_formats);
		return glk_planar_formats;
	} else {
		*num_formats = ARRAY_SIZE(skl_plane_formats);
		return skl_plane_formats;
	}
}

static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
					enum pipe pipe, enum plane_id plane_id,
					int *num_formats)
{
	if (icl_is_hdr_plane(dev_priv, plane_id)) {
		*num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
		return icl_hdr_plane_formats;
	} else if (icl_is_nv12_y_plane(plane_id)) {
		*num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
		return icl_sdr_y_plane_formats;
	} else {
		*num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
		return icl_sdr_uv_plane_formats;
	}
}

2411 2412
static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
			      enum pipe pipe, enum plane_id plane_id)
2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427
{
	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);
}

2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460
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;
2461 2462
	if (icl_is_nv12_y_plane(plane_id))
		plane->update_slave = icl_update_slave;
2463

2464 2465 2466 2467 2468 2469 2470 2471 2472
	if (INTEL_GEN(dev_priv) >= 11)
		formats = icl_get_plane_formats(dev_priv, pipe,
						plane_id, &num_formats);
	else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
		formats = glk_get_plane_formats(dev_priv, pipe,
						plane_id, &num_formats);
	else
		formats = skl_get_plane_formats(dev_priv, pipe,
						plane_id, &num_formats);
2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530

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

2531
struct intel_plane *
2532
intel_sprite_plane_create(struct drm_i915_private *dev_priv,
2533
			  enum pipe pipe, int sprite)
2534
{
2535
	struct intel_plane *plane;
2536
	const struct drm_plane_funcs *plane_funcs;
2537
	unsigned long possible_crtcs;
2538
	unsigned int supported_rotations;
2539 2540 2541
	const u64 *modifiers;
	const u32 *formats;
	int num_formats;
2542 2543
	int ret;

2544 2545
	if (INTEL_GEN(dev_priv) >= 9)
		return skl_universal_plane_create(dev_priv, pipe,
2546
						  PLANE_SPRITE0 + sprite);
2547

2548 2549 2550
	plane = intel_plane_alloc();
	if (IS_ERR(plane))
		return plane;
2551

2552
	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
2553 2554 2555 2556 2557 2558 2559 2560
		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);
2561
		modifiers = i9xx_plane_format_modifiers;
2562 2563

		plane_funcs = &vlv_sprite_funcs;
V
Ville Syrjälä 已提交
2564
	} else if (INTEL_GEN(dev_priv) >= 7) {
2565 2566 2567 2568 2569 2570 2571 2572
		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);
2573
		modifiers = i9xx_plane_format_modifiers;
2574 2575

		plane_funcs = &snb_sprite_funcs;
V
Ville Syrjälä 已提交
2576
	} else {
2577 2578 2579 2580 2581
		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;
2582

2583
		modifiers = i9xx_plane_format_modifiers;
2584
		if (IS_GEN(dev_priv, 6)) {
2585 2586
			formats = snb_plane_formats;
			num_formats = ARRAY_SIZE(snb_plane_formats);
2587 2588

			plane_funcs = &snb_sprite_funcs;
V
Ville Syrjälä 已提交
2589
		} else {
2590 2591
			formats = g4x_plane_formats;
			num_formats = ARRAY_SIZE(g4x_plane_formats);
2592 2593

			plane_funcs = &g4x_sprite_funcs;
2594
		}
2595 2596
	}

2597
	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
2598
		supported_rotations =
2599 2600
			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
			DRM_MODE_REFLECT_X;
2601 2602
	} else {
		supported_rotations =
2603
			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
2604 2605
	}

2606 2607 2608
	plane->pipe = pipe;
	plane->id = PLANE_SPRITE0 + sprite;
	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
2609

2610
	possible_crtcs = BIT(pipe);
2611

2612
	ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2613
				       possible_crtcs, plane_funcs,
2614
				       formats, num_formats, modifiers,
2615
				       DRM_PLANE_TYPE_OVERLAY,
2616
				       "sprite %c", sprite_name(pipe, sprite));
2617 2618
	if (ret)
		goto fail;
2619

2620
	drm_plane_create_rotation_property(&plane->base,
2621
					   DRM_MODE_ROTATE_0,
2622
					   supported_rotations);
2623

2624
	drm_plane_create_color_properties(&plane->base,
2625 2626
					  BIT(DRM_COLOR_YCBCR_BT601) |
					  BIT(DRM_COLOR_YCBCR_BT709),
2627 2628
					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2629
					  DRM_COLOR_YCBCR_BT709,
2630 2631
					  DRM_COLOR_YCBCR_LIMITED_RANGE);

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

2634
	return plane;
2635 2636

fail:
2637
	intel_plane_free(plane);
2638

2639
	return ERR_PTR(ret);
2640
}