Linux Audio

Check our new training course

Linux kernel drivers training

Mar 31-Apr 9, 2025, special US time zones
Register
Loading...
v5.14.15
   1/*
   2 * Copyright © 2011 Intel Corporation
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice (including the next
  12 * paragraph) shall be included in all copies or substantial portions of the
  13 * Software.
  14 *
  15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21 * SOFTWARE.
  22 *
  23 * Authors:
  24 *   Jesse Barnes <jbarnes@virtuousgeek.org>
  25 *
  26 * New plane/sprite handling.
  27 *
  28 * The older chips had a separate interface for programming plane related
  29 * registers; newer ones are much simpler and we can use the new DRM plane
  30 * support.
  31 */
  32
  33#include <drm/drm_atomic.h>
  34#include <drm/drm_atomic_helper.h>
  35#include <drm/drm_color_mgmt.h>
  36#include <drm/drm_crtc.h>
  37#include <drm/drm_damage_helper.h>
  38#include <drm/drm_fourcc.h>
  39#include <drm/drm_plane_helper.h>
  40#include <drm/drm_rect.h>
  41
  42#include "i915_drv.h"
  43#include "i915_trace.h"
  44#include "i915_vgpu.h"
  45#include "intel_atomic_plane.h"
  46#include "intel_de.h"
  47#include "intel_display_types.h"
  48#include "intel_frontbuffer.h"
 
 
  49#include "intel_sprite.h"
  50#include "i9xx_plane.h"
  51#include "intel_vrr.h"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  52
  53int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
  54{
  55	const struct drm_framebuffer *fb = plane_state->hw.fb;
  56	struct drm_rect *src = &plane_state->uapi.src;
  57	u32 src_x, src_y, src_w, src_h, hsub, vsub;
  58	bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
  59
  60	/*
  61	 * FIXME hsub/vsub vs. block size is a mess. Pre-tgl CCS
  62	 * abuses hsub/vsub so we can't use them here. But as they
  63	 * are limited to 32bpp RGB formats we don't actually need
  64	 * to check anything.
  65	 */
  66	if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
  67	    fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)
  68		return 0;
  69
  70	/*
  71	 * Hardware doesn't handle subpixel coordinates.
  72	 * Adjust to (macro)pixel boundary, but be careful not to
  73	 * increase the source viewport size, because that could
  74	 * push the downscaling factor out of bounds.
  75	 */
  76	src_x = src->x1 >> 16;
  77	src_w = drm_rect_width(src) >> 16;
  78	src_y = src->y1 >> 16;
  79	src_h = drm_rect_height(src) >> 16;
  80
  81	drm_rect_init(src, src_x << 16, src_y << 16,
  82		      src_w << 16, src_h << 16);
  83
  84	if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
  85		hsub = 2;
  86		vsub = 2;
  87	} else {
  88		hsub = fb->format->hsub;
  89		vsub = fb->format->vsub;
  90	}
  91
  92	if (rotated)
  93		hsub = vsub = max(hsub, vsub);
  94
  95	if (src_x % hsub || src_w % hsub) {
  96		DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
  97			      src_x, src_w, hsub, yesno(rotated));
  98		return -EINVAL;
  99	}
 100
 101	if (src_y % vsub || src_h % vsub) {
 102		DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
 103			      src_y, src_h, vsub, yesno(rotated));
 104		return -EINVAL;
 105	}
 106
 107	return 0;
 108}
 109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 110static void i9xx_plane_linear_gamma(u16 gamma[8])
 111{
 112	/* The points are not evenly spaced. */
 113	static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
 114	int i;
 115
 116	for (i = 0; i < 8; i++)
 117		gamma[i] = (in[i] << 8) / 32;
 118}
 119
 120static void
 121chv_update_csc(const struct intel_plane_state *plane_state)
 122{
 123	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 124	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 125	const struct drm_framebuffer *fb = plane_state->hw.fb;
 126	enum plane_id plane_id = plane->id;
 127	/*
 128	 * |r|   | c0 c1 c2 |   |cr|
 129	 * |g| = | c3 c4 c5 | x |y |
 130	 * |b|   | c6 c7 c8 |   |cb|
 131	 *
 132	 * Coefficients are s3.12.
 133	 *
 134	 * Cb and Cr apparently come in as signed already, and
 135	 * we always get full range data in on account of CLRC0/1.
 136	 */
 137	static const s16 csc_matrix[][9] = {
 138		/* BT.601 full range YCbCr -> full range RGB */
 139		[DRM_COLOR_YCBCR_BT601] = {
 140			 5743, 4096,     0,
 141			-2925, 4096, -1410,
 142			    0, 4096,  7258,
 143		},
 144		/* BT.709 full range YCbCr -> full range RGB */
 145		[DRM_COLOR_YCBCR_BT709] = {
 146			 6450, 4096,     0,
 147			-1917, 4096,  -767,
 148			    0, 4096,  7601,
 149		},
 150	};
 151	const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
 152
 153	/* Seems RGB data bypasses the CSC always */
 154	if (!fb->format->is_yuv)
 155		return;
 156
 157	intel_de_write_fw(dev_priv, SPCSCYGOFF(plane_id),
 158			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
 159	intel_de_write_fw(dev_priv, SPCSCCBOFF(plane_id),
 160			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
 161	intel_de_write_fw(dev_priv, SPCSCCROFF(plane_id),
 162			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
 163
 164	intel_de_write_fw(dev_priv, SPCSCC01(plane_id),
 165			  SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
 166	intel_de_write_fw(dev_priv, SPCSCC23(plane_id),
 167			  SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
 168	intel_de_write_fw(dev_priv, SPCSCC45(plane_id),
 169			  SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
 170	intel_de_write_fw(dev_priv, SPCSCC67(plane_id),
 171			  SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
 172	intel_de_write_fw(dev_priv, SPCSCC8(plane_id), SPCSC_C0(csc[8]));
 173
 174	intel_de_write_fw(dev_priv, SPCSCYGICLAMP(plane_id),
 175			  SPCSC_IMAX(1023) | SPCSC_IMIN(0));
 176	intel_de_write_fw(dev_priv, SPCSCCBICLAMP(plane_id),
 177			  SPCSC_IMAX(512) | SPCSC_IMIN(-512));
 178	intel_de_write_fw(dev_priv, SPCSCCRICLAMP(plane_id),
 179			  SPCSC_IMAX(512) | SPCSC_IMIN(-512));
 180
 181	intel_de_write_fw(dev_priv, SPCSCYGOCLAMP(plane_id),
 182			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 183	intel_de_write_fw(dev_priv, SPCSCCBOCLAMP(plane_id),
 184			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 185	intel_de_write_fw(dev_priv, SPCSCCROCLAMP(plane_id),
 186			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 187}
 188
 189#define SIN_0 0
 190#define COS_0 1
 191
 192static void
 193vlv_update_clrc(const struct intel_plane_state *plane_state)
 194{
 195	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 196	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 197	const struct drm_framebuffer *fb = plane_state->hw.fb;
 198	enum pipe pipe = plane->pipe;
 199	enum plane_id plane_id = plane->id;
 200	int contrast, brightness, sh_scale, sh_sin, sh_cos;
 201
 202	if (fb->format->is_yuv &&
 203	    plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
 204		/*
 205		 * Expand limited range to full range:
 206		 * Contrast is applied first and is used to expand Y range.
 207		 * Brightness is applied second and is used to remove the
 208		 * offset from Y. Saturation/hue is used to expand CbCr range.
 209		 */
 210		contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
 211		brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
 212		sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
 213		sh_sin = SIN_0 * sh_scale;
 214		sh_cos = COS_0 * sh_scale;
 215	} else {
 216		/* Pass-through everything. */
 217		contrast = 1 << 6;
 218		brightness = 0;
 219		sh_scale = 1 << 7;
 220		sh_sin = SIN_0 * sh_scale;
 221		sh_cos = COS_0 * sh_scale;
 222	}
 223
 224	/* FIXME these register are single buffered :( */
 225	intel_de_write_fw(dev_priv, SPCLRC0(pipe, plane_id),
 226			  SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
 227	intel_de_write_fw(dev_priv, SPCLRC1(pipe, plane_id),
 228			  SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
 229}
 230
 231static void
 232vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
 233		const struct intel_plane_state *plane_state,
 234		unsigned int *num, unsigned int *den)
 235{
 236	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
 237	const struct drm_framebuffer *fb = plane_state->hw.fb;
 238	unsigned int cpp = fb->format->cpp[0];
 239
 240	/*
 241	 * VLV bspec only considers cases where all three planes are
 242	 * enabled, and cases where the primary and one sprite is enabled.
 243	 * Let's assume the case with just two sprites enabled also
 244	 * maps to the latter case.
 245	 */
 246	if (hweight8(active_planes) == 3) {
 247		switch (cpp) {
 248		case 8:
 249			*num = 11;
 250			*den = 8;
 251			break;
 252		case 4:
 253			*num = 18;
 254			*den = 16;
 255			break;
 256		default:
 257			*num = 1;
 258			*den = 1;
 259			break;
 260		}
 261	} else if (hweight8(active_planes) == 2) {
 262		switch (cpp) {
 263		case 8:
 264			*num = 10;
 265			*den = 8;
 266			break;
 267		case 4:
 268			*num = 17;
 269			*den = 16;
 270			break;
 271		default:
 272			*num = 1;
 273			*den = 1;
 274			break;
 275		}
 276	} else {
 277		switch (cpp) {
 278		case 8:
 279			*num = 10;
 280			*den = 8;
 281			break;
 282		default:
 283			*num = 1;
 284			*den = 1;
 285			break;
 286		}
 287	}
 288}
 289
 290int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 291			const struct intel_plane_state *plane_state)
 292{
 293	unsigned int pixel_rate;
 294	unsigned int num, den;
 295
 296	/*
 297	 * Note that crtc_state->pixel_rate accounts for both
 298	 * horizontal and vertical panel fitter downscaling factors.
 299	 * Pre-HSW bspec tells us to only consider the horizontal
 300	 * downscaling factor here. We ignore that and just consider
 301	 * both for simplicity.
 302	 */
 303	pixel_rate = crtc_state->pixel_rate;
 304
 305	vlv_plane_ratio(crtc_state, plane_state, &num, &den);
 306
 307	return DIV_ROUND_UP(pixel_rate * num, den);
 308}
 309
 310static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
 311{
 312	u32 sprctl = 0;
 313
 314	if (crtc_state->gamma_enable)
 315		sprctl |= SP_GAMMA_ENABLE;
 316
 317	return sprctl;
 318}
 319
 320static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
 321			  const struct intel_plane_state *plane_state)
 322{
 323	const struct drm_framebuffer *fb = plane_state->hw.fb;
 324	unsigned int rotation = plane_state->hw.rotation;
 325	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 326	u32 sprctl;
 327
 328	sprctl = SP_ENABLE;
 329
 330	switch (fb->format->format) {
 331	case DRM_FORMAT_YUYV:
 332		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
 333		break;
 334	case DRM_FORMAT_YVYU:
 335		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
 336		break;
 337	case DRM_FORMAT_UYVY:
 338		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
 339		break;
 340	case DRM_FORMAT_VYUY:
 341		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
 342		break;
 343	case DRM_FORMAT_C8:
 344		sprctl |= SP_FORMAT_8BPP;
 345		break;
 346	case DRM_FORMAT_RGB565:
 347		sprctl |= SP_FORMAT_BGR565;
 348		break;
 349	case DRM_FORMAT_XRGB8888:
 350		sprctl |= SP_FORMAT_BGRX8888;
 351		break;
 352	case DRM_FORMAT_ARGB8888:
 353		sprctl |= SP_FORMAT_BGRA8888;
 354		break;
 355	case DRM_FORMAT_XBGR2101010:
 356		sprctl |= SP_FORMAT_RGBX1010102;
 357		break;
 358	case DRM_FORMAT_ABGR2101010:
 359		sprctl |= SP_FORMAT_RGBA1010102;
 360		break;
 361	case DRM_FORMAT_XRGB2101010:
 362		sprctl |= SP_FORMAT_BGRX1010102;
 363		break;
 364	case DRM_FORMAT_ARGB2101010:
 365		sprctl |= SP_FORMAT_BGRA1010102;
 366		break;
 367	case DRM_FORMAT_XBGR8888:
 368		sprctl |= SP_FORMAT_RGBX8888;
 369		break;
 370	case DRM_FORMAT_ABGR8888:
 371		sprctl |= SP_FORMAT_RGBA8888;
 372		break;
 373	default:
 374		MISSING_CASE(fb->format->format);
 375		return 0;
 376	}
 377
 378	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
 379		sprctl |= SP_YUV_FORMAT_BT709;
 380
 381	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 382		sprctl |= SP_TILED;
 383
 384	if (rotation & DRM_MODE_ROTATE_180)
 385		sprctl |= SP_ROTATE_180;
 386
 387	if (rotation & DRM_MODE_REFLECT_X)
 388		sprctl |= SP_MIRROR;
 389
 390	if (key->flags & I915_SET_COLORKEY_SOURCE)
 391		sprctl |= SP_SOURCE_KEY;
 392
 393	return sprctl;
 394}
 395
 396static void vlv_update_gamma(const struct intel_plane_state *plane_state)
 397{
 398	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 399	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 400	const struct drm_framebuffer *fb = plane_state->hw.fb;
 401	enum pipe pipe = plane->pipe;
 402	enum plane_id plane_id = plane->id;
 403	u16 gamma[8];
 404	int i;
 405
 406	/* Seems RGB data bypasses the gamma always */
 407	if (!fb->format->is_yuv)
 408		return;
 409
 410	i9xx_plane_linear_gamma(gamma);
 411
 412	/* FIXME these register are single buffered :( */
 413	/* The two end points are implicit (0.0 and 1.0) */
 414	for (i = 1; i < 8 - 1; i++)
 415		intel_de_write_fw(dev_priv, SPGAMC(pipe, plane_id, i - 1),
 416				  gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
 417}
 418
 419static void
 420vlv_update_plane(struct intel_plane *plane,
 421		 const struct intel_crtc_state *crtc_state,
 422		 const struct intel_plane_state *plane_state)
 423{
 424	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 425	enum pipe pipe = plane->pipe;
 426	enum plane_id plane_id = plane->id;
 427	u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
 428	u32 linear_offset;
 429	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 430	int crtc_x = plane_state->uapi.dst.x1;
 431	int crtc_y = plane_state->uapi.dst.y1;
 432	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
 433	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
 434	u32 x = plane_state->view.color_plane[0].x;
 435	u32 y = plane_state->view.color_plane[0].y;
 436	unsigned long irqflags;
 437	u32 sprctl;
 438
 439	sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
 440
 441	/* Sizes are 0 based */
 442	crtc_w--;
 443	crtc_h--;
 444
 445	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 446
 447	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 448
 449	intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id),
 450			  plane_state->view.color_plane[0].stride);
 451	intel_de_write_fw(dev_priv, SPPOS(pipe, plane_id),
 452			  (crtc_y << 16) | crtc_x);
 453	intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id),
 454			  (crtc_h << 16) | crtc_w);
 455	intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0);
 456
 457	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
 458		chv_update_csc(plane_state);
 459
 460	if (key->flags) {
 461		intel_de_write_fw(dev_priv, SPKEYMINVAL(pipe, plane_id),
 462				  key->min_value);
 463		intel_de_write_fw(dev_priv, SPKEYMSK(pipe, plane_id),
 464				  key->channel_mask);
 465		intel_de_write_fw(dev_priv, SPKEYMAXVAL(pipe, plane_id),
 466				  key->max_value);
 467	}
 468
 469	intel_de_write_fw(dev_priv, SPLINOFF(pipe, plane_id), linear_offset);
 470	intel_de_write_fw(dev_priv, SPTILEOFF(pipe, plane_id), (y << 16) | x);
 471
 472	/*
 473	 * The control register self-arms if the plane was previously
 474	 * disabled. Try to make the plane enable atomic by writing
 475	 * the control register just before the surface register.
 476	 */
 477	intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), sprctl);
 478	intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id),
 479			  intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
 480
 481	vlv_update_clrc(plane_state);
 482	vlv_update_gamma(plane_state);
 483
 484	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 485}
 486
 487static void
 488vlv_disable_plane(struct intel_plane *plane,
 489		  const struct intel_crtc_state *crtc_state)
 490{
 491	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 492	enum pipe pipe = plane->pipe;
 493	enum plane_id plane_id = plane->id;
 494	unsigned long irqflags;
 495
 496	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 497
 498	intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0);
 499	intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0);
 500
 501	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 502}
 503
 504static bool
 505vlv_plane_get_hw_state(struct intel_plane *plane,
 506		       enum pipe *pipe)
 507{
 508	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 509	enum intel_display_power_domain power_domain;
 510	enum plane_id plane_id = plane->id;
 511	intel_wakeref_t wakeref;
 512	bool ret;
 513
 514	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
 515	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
 516	if (!wakeref)
 517		return false;
 518
 519	ret = intel_de_read(dev_priv, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
 520
 521	*pipe = plane->pipe;
 522
 523	intel_display_power_put(dev_priv, power_domain, wakeref);
 524
 525	return ret;
 526}
 527
 528static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
 529			    const struct intel_plane_state *plane_state,
 530			    unsigned int *num, unsigned int *den)
 531{
 532	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
 533	const struct drm_framebuffer *fb = plane_state->hw.fb;
 534	unsigned int cpp = fb->format->cpp[0];
 535
 536	if (hweight8(active_planes) == 2) {
 537		switch (cpp) {
 538		case 8:
 539			*num = 10;
 540			*den = 8;
 541			break;
 542		case 4:
 543			*num = 17;
 544			*den = 16;
 545			break;
 546		default:
 547			*num = 1;
 548			*den = 1;
 549			break;
 550		}
 551	} else {
 552		switch (cpp) {
 553		case 8:
 554			*num = 9;
 555			*den = 8;
 556			break;
 557		default:
 558			*num = 1;
 559			*den = 1;
 560			break;
 561		}
 562	}
 563}
 564
 565static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
 566				    const struct intel_plane_state *plane_state,
 567				    unsigned int *num, unsigned int *den)
 568{
 569	const struct drm_framebuffer *fb = plane_state->hw.fb;
 570	unsigned int cpp = fb->format->cpp[0];
 571
 572	switch (cpp) {
 573	case 8:
 574		*num = 12;
 575		*den = 8;
 576		break;
 577	case 4:
 578		*num = 19;
 579		*den = 16;
 580		break;
 581	case 2:
 582		*num = 33;
 583		*den = 32;
 584		break;
 585	default:
 586		*num = 1;
 587		*den = 1;
 588		break;
 589	}
 590}
 591
 592int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 593			const struct intel_plane_state *plane_state)
 594{
 595	unsigned int pixel_rate;
 596	unsigned int num, den;
 597
 598	/*
 599	 * Note that crtc_state->pixel_rate accounts for both
 600	 * horizontal and vertical panel fitter downscaling factors.
 601	 * Pre-HSW bspec tells us to only consider the horizontal
 602	 * downscaling factor here. We ignore that and just consider
 603	 * both for simplicity.
 604	 */
 605	pixel_rate = crtc_state->pixel_rate;
 606
 607	ivb_plane_ratio(crtc_state, plane_state, &num, &den);
 608
 609	return DIV_ROUND_UP(pixel_rate * num, den);
 610}
 611
 612static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
 613				const struct intel_plane_state *plane_state)
 614{
 615	unsigned int src_w, dst_w, pixel_rate;
 616	unsigned int num, den;
 617
 618	/*
 619	 * Note that crtc_state->pixel_rate accounts for both
 620	 * horizontal and vertical panel fitter downscaling factors.
 621	 * Pre-HSW bspec tells us to only consider the horizontal
 622	 * downscaling factor here. We ignore that and just consider
 623	 * both for simplicity.
 624	 */
 625	pixel_rate = crtc_state->pixel_rate;
 626
 627	src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
 628	dst_w = drm_rect_width(&plane_state->uapi.dst);
 629
 630	if (src_w != dst_w)
 631		ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
 632	else
 633		ivb_plane_ratio(crtc_state, plane_state, &num, &den);
 634
 635	/* Horizontal downscaling limits the maximum pixel rate */
 636	dst_w = min(src_w, dst_w);
 637
 638	return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
 639				den * dst_w);
 640}
 641
 642static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
 643			    const struct intel_plane_state *plane_state,
 644			    unsigned int *num, unsigned int *den)
 645{
 646	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
 647	const struct drm_framebuffer *fb = plane_state->hw.fb;
 648	unsigned int cpp = fb->format->cpp[0];
 649
 650	if (hweight8(active_planes) == 2) {
 651		switch (cpp) {
 652		case 8:
 653			*num = 10;
 654			*den = 8;
 655			break;
 656		default:
 657			*num = 1;
 658			*den = 1;
 659			break;
 660		}
 661	} else {
 662		switch (cpp) {
 663		case 8:
 664			*num = 9;
 665			*den = 8;
 666			break;
 667		default:
 668			*num = 1;
 669			*den = 1;
 670			break;
 671		}
 672	}
 673}
 674
 675int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 676			const struct intel_plane_state *plane_state)
 677{
 678	unsigned int pixel_rate = crtc_state->pixel_rate;
 679	unsigned int num, den;
 680
 681	hsw_plane_ratio(crtc_state, plane_state, &num, &den);
 682
 683	return DIV_ROUND_UP(pixel_rate * num, den);
 684}
 685
 686static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
 687{
 688	u32 sprctl = 0;
 689
 690	if (crtc_state->gamma_enable)
 691		sprctl |= SPRITE_GAMMA_ENABLE;
 692
 693	if (crtc_state->csc_enable)
 694		sprctl |= SPRITE_PIPE_CSC_ENABLE;
 695
 696	return sprctl;
 697}
 698
 699static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
 700{
 701	struct drm_i915_private *dev_priv =
 702		to_i915(plane_state->uapi.plane->dev);
 703	const struct drm_framebuffer *fb = plane_state->hw.fb;
 704
 705	return fb->format->cpp[0] == 8 &&
 706		(IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
 707}
 708
 709static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
 710			  const struct intel_plane_state *plane_state)
 711{
 712	struct drm_i915_private *dev_priv =
 713		to_i915(plane_state->uapi.plane->dev);
 714	const struct drm_framebuffer *fb = plane_state->hw.fb;
 715	unsigned int rotation = plane_state->hw.rotation;
 716	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 717	u32 sprctl;
 718
 719	sprctl = SPRITE_ENABLE;
 720
 721	if (IS_IVYBRIDGE(dev_priv))
 722		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
 723
 724	switch (fb->format->format) {
 725	case DRM_FORMAT_XBGR8888:
 726		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
 727		break;
 728	case DRM_FORMAT_XRGB8888:
 729		sprctl |= SPRITE_FORMAT_RGBX888;
 730		break;
 731	case DRM_FORMAT_XBGR2101010:
 732		sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
 733		break;
 734	case DRM_FORMAT_XRGB2101010:
 735		sprctl |= SPRITE_FORMAT_RGBX101010;
 736		break;
 737	case DRM_FORMAT_XBGR16161616F:
 738		sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
 739		break;
 740	case DRM_FORMAT_XRGB16161616F:
 741		sprctl |= SPRITE_FORMAT_RGBX161616;
 742		break;
 743	case DRM_FORMAT_YUYV:
 744		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
 745		break;
 746	case DRM_FORMAT_YVYU:
 747		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
 748		break;
 749	case DRM_FORMAT_UYVY:
 750		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
 751		break;
 752	case DRM_FORMAT_VYUY:
 753		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
 754		break;
 755	default:
 756		MISSING_CASE(fb->format->format);
 757		return 0;
 758	}
 759
 760	if (!ivb_need_sprite_gamma(plane_state))
 761		sprctl |= SPRITE_INT_GAMMA_DISABLE;
 762
 763	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
 764		sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
 765
 766	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
 767		sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
 768
 769	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 770		sprctl |= SPRITE_TILED;
 771
 772	if (rotation & DRM_MODE_ROTATE_180)
 773		sprctl |= SPRITE_ROTATE_180;
 774
 775	if (key->flags & I915_SET_COLORKEY_DESTINATION)
 776		sprctl |= SPRITE_DEST_KEY;
 777	else if (key->flags & I915_SET_COLORKEY_SOURCE)
 778		sprctl |= SPRITE_SOURCE_KEY;
 779
 780	return sprctl;
 781}
 782
 783static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
 784				    u16 gamma[18])
 785{
 786	int scale, i;
 787
 788	/*
 789	 * WaFP16GammaEnabling:ivb,hsw
 790	 * "Workaround : When using the 64-bit format, the sprite output
 791	 *  on each color channel has one quarter amplitude. It can be
 792	 *  brought up to full amplitude by using sprite internal gamma
 793	 *  correction, pipe gamma correction, or pipe color space
 794	 *  conversion to multiply the sprite output by four."
 795	 */
 796	scale = 4;
 797
 798	for (i = 0; i < 16; i++)
 799		gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
 800
 801	gamma[i] = min((scale * i << 10) / 16, 1 << 10);
 802	i++;
 803
 804	gamma[i] = 3 << 10;
 805	i++;
 806}
 807
 808static void ivb_update_gamma(const struct intel_plane_state *plane_state)
 809{
 810	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 811	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 812	enum pipe pipe = plane->pipe;
 813	u16 gamma[18];
 814	int i;
 815
 816	if (!ivb_need_sprite_gamma(plane_state))
 817		return;
 818
 819	ivb_sprite_linear_gamma(plane_state, gamma);
 820
 821	/* FIXME these register are single buffered :( */
 822	for (i = 0; i < 16; i++)
 823		intel_de_write_fw(dev_priv, SPRGAMC(pipe, i),
 824				  gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
 825
 826	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 0), gamma[i]);
 827	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 1), gamma[i]);
 828	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 2), gamma[i]);
 829	i++;
 830
 831	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 0), gamma[i]);
 832	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 1), gamma[i]);
 833	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 2), gamma[i]);
 834	i++;
 835}
 836
 837static void
 838ivb_update_plane(struct intel_plane *plane,
 839		 const struct intel_crtc_state *crtc_state,
 840		 const struct intel_plane_state *plane_state)
 841{
 842	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 843	enum pipe pipe = plane->pipe;
 844	u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
 845	u32 linear_offset;
 846	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 847	int crtc_x = plane_state->uapi.dst.x1;
 848	int crtc_y = plane_state->uapi.dst.y1;
 849	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
 850	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
 851	u32 x = plane_state->view.color_plane[0].x;
 852	u32 y = plane_state->view.color_plane[0].y;
 853	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
 854	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
 855	u32 sprctl, sprscale = 0;
 856	unsigned long irqflags;
 857
 858	sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
 859
 860	/* Sizes are 0 based */
 861	src_w--;
 862	src_h--;
 863	crtc_w--;
 864	crtc_h--;
 865
 866	if (crtc_w != src_w || crtc_h != src_h)
 867		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
 868
 869	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 870
 871	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 872
 873	intel_de_write_fw(dev_priv, SPRSTRIDE(pipe),
 874			  plane_state->view.color_plane[0].stride);
 875	intel_de_write_fw(dev_priv, SPRPOS(pipe), (crtc_y << 16) | crtc_x);
 876	intel_de_write_fw(dev_priv, SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
 877	if (IS_IVYBRIDGE(dev_priv))
 878		intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale);
 879
 880	if (key->flags) {
 881		intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value);
 882		intel_de_write_fw(dev_priv, SPRKEYMSK(pipe),
 883				  key->channel_mask);
 884		intel_de_write_fw(dev_priv, SPRKEYMAX(pipe), key->max_value);
 885	}
 886
 887	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
 888	 * register */
 889	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 890		intel_de_write_fw(dev_priv, SPROFFSET(pipe), (y << 16) | x);
 891	} else {
 892		intel_de_write_fw(dev_priv, SPRLINOFF(pipe), linear_offset);
 893		intel_de_write_fw(dev_priv, SPRTILEOFF(pipe), (y << 16) | x);
 894	}
 895
 896	/*
 897	 * The control register self-arms if the plane was previously
 898	 * disabled. Try to make the plane enable atomic by writing
 899	 * the control register just before the surface register.
 900	 */
 901	intel_de_write_fw(dev_priv, SPRCTL(pipe), sprctl);
 902	intel_de_write_fw(dev_priv, SPRSURF(pipe),
 903			  intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
 904
 905	ivb_update_gamma(plane_state);
 906
 907	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 908}
 909
 910static void
 911ivb_disable_plane(struct intel_plane *plane,
 912		  const struct intel_crtc_state *crtc_state)
 913{
 914	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 915	enum pipe pipe = plane->pipe;
 916	unsigned long irqflags;
 917
 918	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 919
 920	intel_de_write_fw(dev_priv, SPRCTL(pipe), 0);
 921	/* Disable the scaler */
 922	if (IS_IVYBRIDGE(dev_priv))
 923		intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0);
 924	intel_de_write_fw(dev_priv, SPRSURF(pipe), 0);
 925
 926	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 927}
 928
 929static bool
 930ivb_plane_get_hw_state(struct intel_plane *plane,
 931		       enum pipe *pipe)
 932{
 933	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 934	enum intel_display_power_domain power_domain;
 935	intel_wakeref_t wakeref;
 936	bool ret;
 937
 938	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
 939	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
 940	if (!wakeref)
 941		return false;
 942
 943	ret =  intel_de_read(dev_priv, SPRCTL(plane->pipe)) & SPRITE_ENABLE;
 944
 945	*pipe = plane->pipe;
 946
 947	intel_display_power_put(dev_priv, power_domain, wakeref);
 948
 949	return ret;
 950}
 951
 952static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
 953				const struct intel_plane_state *plane_state)
 954{
 955	const struct drm_framebuffer *fb = plane_state->hw.fb;
 956	unsigned int hscale, pixel_rate;
 957	unsigned int limit, decimate;
 958
 959	/*
 960	 * Note that crtc_state->pixel_rate accounts for both
 961	 * horizontal and vertical panel fitter downscaling factors.
 962	 * Pre-HSW bspec tells us to only consider the horizontal
 963	 * downscaling factor here. We ignore that and just consider
 964	 * both for simplicity.
 965	 */
 966	pixel_rate = crtc_state->pixel_rate;
 967
 968	/* Horizontal downscaling limits the maximum pixel rate */
 969	hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
 970				      &plane_state->uapi.dst,
 971				      0, INT_MAX);
 972	hscale = max(hscale, 0x10000u);
 
 973
 974	/* Decimation steps at 2x,4x,8x,16x */
 975	decimate = ilog2(hscale >> 16);
 976	hscale >>= decimate;
 977
 978	/* Starting limit is 90% of cdclk */
 979	limit = 9;
 980
 981	/* -10% per decimation step */
 982	limit -= decimate;
 983
 984	/* -10% for RGB */
 985	if (!fb->format->is_yuv)
 986		limit--;
 987
 988	/*
 989	 * We should also do -10% if sprite scaling is enabled
 990	 * on the other pipe, but we can't really check for that,
 991	 * so we ignore it.
 992	 */
 993
 994	return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
 995				limit << 16);
 996}
 997
 998static unsigned int
 999g4x_sprite_max_stride(struct intel_plane *plane,
1000		      u32 pixel_format, u64 modifier,
1001		      unsigned int rotation)
1002{
1003	const struct drm_format_info *info = drm_format_info(pixel_format);
1004	int cpp = info->cpp[0];
1005
1006	/* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
1007	if (modifier == I915_FORMAT_MOD_X_TILED)
1008		return min(4096 * cpp, 16 * 1024);
1009	else
1010		return 16 * 1024;
1011}
1012
1013static unsigned int
1014hsw_sprite_max_stride(struct intel_plane *plane,
1015		      u32 pixel_format, u64 modifier,
1016		      unsigned int rotation)
1017{
1018	const struct drm_format_info *info = drm_format_info(pixel_format);
1019	int cpp = info->cpp[0];
1020
1021	/* Limit to 8k pixels to guarantee OFFSET.x doesn't get too big. */
1022	return min(8192 * cpp, 16 * 1024);
1023}
1024
1025static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1026{
1027	u32 dvscntr = 0;
1028
1029	if (crtc_state->gamma_enable)
1030		dvscntr |= DVS_GAMMA_ENABLE;
1031
1032	if (crtc_state->csc_enable)
1033		dvscntr |= DVS_PIPE_CSC_ENABLE;
1034
1035	return dvscntr;
1036}
1037
1038static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1039			  const struct intel_plane_state *plane_state)
1040{
1041	struct drm_i915_private *dev_priv =
1042		to_i915(plane_state->uapi.plane->dev);
1043	const struct drm_framebuffer *fb = plane_state->hw.fb;
1044	unsigned int rotation = plane_state->hw.rotation;
1045	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1046	u32 dvscntr;
1047
1048	dvscntr = DVS_ENABLE;
1049
1050	if (IS_SANDYBRIDGE(dev_priv))
1051		dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1052
1053	switch (fb->format->format) {
1054	case DRM_FORMAT_XBGR8888:
1055		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1056		break;
1057	case DRM_FORMAT_XRGB8888:
1058		dvscntr |= DVS_FORMAT_RGBX888;
1059		break;
1060	case DRM_FORMAT_XBGR2101010:
1061		dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
1062		break;
1063	case DRM_FORMAT_XRGB2101010:
1064		dvscntr |= DVS_FORMAT_RGBX101010;
1065		break;
1066	case DRM_FORMAT_XBGR16161616F:
1067		dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1068		break;
1069	case DRM_FORMAT_XRGB16161616F:
1070		dvscntr |= DVS_FORMAT_RGBX161616;
1071		break;
1072	case DRM_FORMAT_YUYV:
1073		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1074		break;
1075	case DRM_FORMAT_YVYU:
1076		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1077		break;
1078	case DRM_FORMAT_UYVY:
1079		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1080		break;
1081	case DRM_FORMAT_VYUY:
1082		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1083		break;
1084	default:
1085		MISSING_CASE(fb->format->format);
1086		return 0;
1087	}
1088
1089	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1090		dvscntr |= DVS_YUV_FORMAT_BT709;
1091
1092	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1093		dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1094
1095	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1096		dvscntr |= DVS_TILED;
1097
1098	if (rotation & DRM_MODE_ROTATE_180)
1099		dvscntr |= DVS_ROTATE_180;
1100
1101	if (key->flags & I915_SET_COLORKEY_DESTINATION)
1102		dvscntr |= DVS_DEST_KEY;
1103	else if (key->flags & I915_SET_COLORKEY_SOURCE)
1104		dvscntr |= DVS_SOURCE_KEY;
1105
1106	return dvscntr;
1107}
1108
1109static void g4x_update_gamma(const struct intel_plane_state *plane_state)
1110{
1111	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1112	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1113	const struct drm_framebuffer *fb = plane_state->hw.fb;
1114	enum pipe pipe = plane->pipe;
1115	u16 gamma[8];
1116	int i;
1117
1118	/* Seems RGB data bypasses the gamma always */
1119	if (!fb->format->is_yuv)
1120		return;
1121
1122	i9xx_plane_linear_gamma(gamma);
1123
1124	/* FIXME these register are single buffered :( */
1125	/* The two end points are implicit (0.0 and 1.0) */
1126	for (i = 1; i < 8 - 1; i++)
1127		intel_de_write_fw(dev_priv, DVSGAMC_G4X(pipe, i - 1),
1128				  gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
1129}
1130
1131static void ilk_sprite_linear_gamma(u16 gamma[17])
1132{
1133	int i;
1134
1135	for (i = 0; i < 17; i++)
1136		gamma[i] = (i << 10) / 16;
1137}
1138
1139static void ilk_update_gamma(const struct intel_plane_state *plane_state)
1140{
1141	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1142	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1143	const struct drm_framebuffer *fb = plane_state->hw.fb;
1144	enum pipe pipe = plane->pipe;
1145	u16 gamma[17];
1146	int i;
1147
1148	/* Seems RGB data bypasses the gamma always */
1149	if (!fb->format->is_yuv)
1150		return;
1151
1152	ilk_sprite_linear_gamma(gamma);
1153
1154	/* FIXME these register are single buffered :( */
1155	for (i = 0; i < 16; i++)
1156		intel_de_write_fw(dev_priv, DVSGAMC_ILK(pipe, i),
1157				  gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
1158
1159	intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1160	intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1161	intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1162	i++;
1163}
1164
1165static void
1166g4x_update_plane(struct intel_plane *plane,
1167		 const struct intel_crtc_state *crtc_state,
1168		 const struct intel_plane_state *plane_state)
1169{
1170	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1171	enum pipe pipe = plane->pipe;
1172	u32 dvssurf_offset = plane_state->view.color_plane[0].offset;
1173	u32 linear_offset;
1174	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1175	int crtc_x = plane_state->uapi.dst.x1;
1176	int crtc_y = plane_state->uapi.dst.y1;
1177	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1178	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1179	u32 x = plane_state->view.color_plane[0].x;
1180	u32 y = plane_state->view.color_plane[0].y;
1181	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1182	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1183	u32 dvscntr, dvsscale = 0;
1184	unsigned long irqflags;
1185
1186	dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1187
1188	/* Sizes are 0 based */
1189	src_w--;
1190	src_h--;
1191	crtc_w--;
1192	crtc_h--;
1193
1194	if (crtc_w != src_w || crtc_h != src_h)
1195		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
1196
1197	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1198
1199	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1200
1201	intel_de_write_fw(dev_priv, DVSSTRIDE(pipe),
1202			  plane_state->view.color_plane[0].stride);
1203	intel_de_write_fw(dev_priv, DVSPOS(pipe), (crtc_y << 16) | crtc_x);
1204	intel_de_write_fw(dev_priv, DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
1205	intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale);
1206
1207	if (key->flags) {
1208		intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value);
1209		intel_de_write_fw(dev_priv, DVSKEYMSK(pipe),
1210				  key->channel_mask);
1211		intel_de_write_fw(dev_priv, DVSKEYMAX(pipe), key->max_value);
1212	}
1213
1214	intel_de_write_fw(dev_priv, DVSLINOFF(pipe), linear_offset);
1215	intel_de_write_fw(dev_priv, DVSTILEOFF(pipe), (y << 16) | x);
1216
1217	/*
1218	 * The control register self-arms if the plane was previously
1219	 * disabled. Try to make the plane enable atomic by writing
1220	 * the control register just before the surface register.
1221	 */
1222	intel_de_write_fw(dev_priv, DVSCNTR(pipe), dvscntr);
1223	intel_de_write_fw(dev_priv, DVSSURF(pipe),
1224			  intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1225
1226	if (IS_G4X(dev_priv))
1227		g4x_update_gamma(plane_state);
1228	else
1229		ilk_update_gamma(plane_state);
1230
1231	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1232}
1233
1234static void
1235g4x_disable_plane(struct intel_plane *plane,
1236		  const struct intel_crtc_state *crtc_state)
1237{
1238	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1239	enum pipe pipe = plane->pipe;
1240	unsigned long irqflags;
1241
1242	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1243
1244	intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0);
1245	/* Disable the scaler */
1246	intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0);
1247	intel_de_write_fw(dev_priv, DVSSURF(pipe), 0);
1248
1249	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1250}
1251
1252static bool
1253g4x_plane_get_hw_state(struct intel_plane *plane,
1254		       enum pipe *pipe)
1255{
1256	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1257	enum intel_display_power_domain power_domain;
1258	intel_wakeref_t wakeref;
1259	bool ret;
1260
1261	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1262	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1263	if (!wakeref)
1264		return false;
1265
1266	ret = intel_de_read(dev_priv, DVSCNTR(plane->pipe)) & DVS_ENABLE;
1267
1268	*pipe = plane->pipe;
1269
1270	intel_display_power_put(dev_priv, power_domain, wakeref);
1271
1272	return ret;
1273}
1274
1275static bool g4x_fb_scalable(const struct drm_framebuffer *fb)
1276{
1277	if (!fb)
1278		return false;
1279
1280	switch (fb->format->format) {
1281	case DRM_FORMAT_C8:
 
1282	case DRM_FORMAT_XRGB16161616F:
1283	case DRM_FORMAT_ARGB16161616F:
1284	case DRM_FORMAT_XBGR16161616F:
1285	case DRM_FORMAT_ABGR16161616F:
1286		return false;
1287	default:
1288		return true;
1289	}
1290}
1291
1292static int
1293g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1294			 struct intel_plane_state *plane_state)
1295{
1296	const struct drm_framebuffer *fb = plane_state->hw.fb;
1297	const struct drm_rect *src = &plane_state->uapi.src;
1298	const struct drm_rect *dst = &plane_state->uapi.dst;
1299	int src_x, src_w, src_h, crtc_w, crtc_h;
1300	const struct drm_display_mode *adjusted_mode =
1301		&crtc_state->hw.adjusted_mode;
1302	unsigned int stride = plane_state->view.color_plane[0].stride;
1303	unsigned int cpp = fb->format->cpp[0];
1304	unsigned int width_bytes;
1305	int min_width, min_height;
1306
1307	crtc_w = drm_rect_width(dst);
1308	crtc_h = drm_rect_height(dst);
1309
1310	src_x = src->x1 >> 16;
1311	src_w = drm_rect_width(src) >> 16;
1312	src_h = drm_rect_height(src) >> 16;
1313
1314	if (src_w == crtc_w && src_h == crtc_h)
1315		return 0;
1316
1317	min_width = 3;
1318
1319	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1320		if (src_h & 1) {
1321			DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
1322			return -EINVAL;
1323		}
1324		min_height = 6;
1325	} else {
1326		min_height = 3;
1327	}
1328
1329	width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1330
1331	if (src_w < min_width || src_h < min_height ||
1332	    src_w > 2048 || src_h > 2048) {
1333		DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1334			      src_w, src_h, min_width, min_height, 2048, 2048);
1335		return -EINVAL;
1336	}
1337
1338	if (width_bytes > 4096) {
1339		DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1340			      width_bytes, 4096);
1341		return -EINVAL;
1342	}
1343
1344	if (stride > 4096) {
1345		DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
1346			      stride, 4096);
1347		return -EINVAL;
1348	}
1349
1350	return 0;
1351}
1352
1353static int
1354g4x_sprite_check(struct intel_crtc_state *crtc_state,
1355		 struct intel_plane_state *plane_state)
1356{
1357	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1358	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1359	int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1360	int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1361	int ret;
1362
1363	if (g4x_fb_scalable(plane_state->hw.fb)) {
1364		if (DISPLAY_VER(dev_priv) < 7) {
1365			min_scale = 1;
1366			max_scale = 16 << 16;
1367		} else if (IS_IVYBRIDGE(dev_priv)) {
1368			min_scale = 1;
1369			max_scale = 2 << 16;
1370		}
1371	}
1372
1373	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1374						min_scale, max_scale, true);
 
 
1375	if (ret)
1376		return ret;
1377
1378	ret = i9xx_check_plane_surface(plane_state);
1379	if (ret)
1380		return ret;
1381
1382	if (!plane_state->uapi.visible)
1383		return 0;
1384
1385	ret = intel_plane_check_src_coordinates(plane_state);
1386	if (ret)
1387		return ret;
1388
1389	ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1390	if (ret)
1391		return ret;
1392
1393	if (DISPLAY_VER(dev_priv) >= 7)
1394		plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1395	else
1396		plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1397
1398	return 0;
1399}
1400
1401int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1402{
1403	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1404	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1405	unsigned int rotation = plane_state->hw.rotation;
1406
1407	/* CHV ignores the mirror bit when the rotate bit is set :( */
1408	if (IS_CHERRYVIEW(dev_priv) &&
1409	    rotation & DRM_MODE_ROTATE_180 &&
1410	    rotation & DRM_MODE_REFLECT_X) {
1411		drm_dbg_kms(&dev_priv->drm,
1412			    "Cannot rotate and reflect at the same time\n");
1413		return -EINVAL;
1414	}
1415
1416	return 0;
1417}
1418
1419static int
1420vlv_sprite_check(struct intel_crtc_state *crtc_state,
1421		 struct intel_plane_state *plane_state)
1422{
1423	int ret;
1424
1425	ret = chv_plane_check_rotation(plane_state);
1426	if (ret)
1427		return ret;
1428
1429	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1430						DRM_PLANE_HELPER_NO_SCALING,
1431						DRM_PLANE_HELPER_NO_SCALING,
1432						true);
 
1433	if (ret)
1434		return ret;
1435
1436	ret = i9xx_check_plane_surface(plane_state);
1437	if (ret)
1438		return ret;
1439
1440	if (!plane_state->uapi.visible)
1441		return 0;
1442
1443	ret = intel_plane_check_src_coordinates(plane_state);
1444	if (ret)
1445		return ret;
1446
1447	plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1448
1449	return 0;
1450}
1451
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1452static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1453{
1454	return DISPLAY_VER(dev_priv) >= 9;
1455}
1456
1457static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1458				 const struct drm_intel_sprite_colorkey *set)
1459{
1460	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1461	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1462	struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1463
1464	*key = *set;
1465
1466	/*
1467	 * We want src key enabled on the
1468	 * sprite and not on the primary.
1469	 */
1470	if (plane->id == PLANE_PRIMARY &&
1471	    set->flags & I915_SET_COLORKEY_SOURCE)
1472		key->flags = 0;
1473
1474	/*
1475	 * On SKL+ we want dst key enabled on
1476	 * the primary and not on the sprite.
1477	 */
1478	if (DISPLAY_VER(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1479	    set->flags & I915_SET_COLORKEY_DESTINATION)
1480		key->flags = 0;
1481}
1482
1483int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1484				    struct drm_file *file_priv)
1485{
1486	struct drm_i915_private *dev_priv = to_i915(dev);
1487	struct drm_intel_sprite_colorkey *set = data;
1488	struct drm_plane *plane;
1489	struct drm_plane_state *plane_state;
1490	struct drm_atomic_state *state;
1491	struct drm_modeset_acquire_ctx ctx;
1492	int ret = 0;
1493
1494	/* ignore the pointless "none" flag */
1495	set->flags &= ~I915_SET_COLORKEY_NONE;
1496
1497	if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1498		return -EINVAL;
1499
1500	/* Make sure we don't try to enable both src & dest simultaneously */
1501	if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1502		return -EINVAL;
1503
1504	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1505	    set->flags & I915_SET_COLORKEY_DESTINATION)
1506		return -EINVAL;
1507
1508	plane = drm_plane_find(dev, file_priv, set->plane_id);
1509	if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1510		return -ENOENT;
1511
1512	/*
1513	 * SKL+ only plane 2 can do destination keying against plane 1.
1514	 * Also multiple planes can't do destination keying on the same
1515	 * pipe simultaneously.
1516	 */
1517	if (DISPLAY_VER(dev_priv) >= 9 &&
1518	    to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1519	    set->flags & I915_SET_COLORKEY_DESTINATION)
1520		return -EINVAL;
1521
1522	drm_modeset_acquire_init(&ctx, 0);
1523
1524	state = drm_atomic_state_alloc(plane->dev);
1525	if (!state) {
1526		ret = -ENOMEM;
1527		goto out;
1528	}
1529	state->acquire_ctx = &ctx;
1530
1531	while (1) {
1532		plane_state = drm_atomic_get_plane_state(state, plane);
1533		ret = PTR_ERR_OR_ZERO(plane_state);
1534		if (!ret)
1535			intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1536
1537		/*
1538		 * On some platforms we have to configure
1539		 * the dst colorkey on the primary plane.
1540		 */
1541		if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1542			struct intel_crtc *crtc =
1543				intel_get_crtc_for_pipe(dev_priv,
1544							to_intel_plane(plane)->pipe);
1545
1546			plane_state = drm_atomic_get_plane_state(state,
1547								 crtc->base.primary);
1548			ret = PTR_ERR_OR_ZERO(plane_state);
1549			if (!ret)
1550				intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1551		}
1552
1553		if (!ret)
1554			ret = drm_atomic_commit(state);
1555
1556		if (ret != -EDEADLK)
1557			break;
1558
1559		drm_atomic_state_clear(state);
1560		drm_modeset_backoff(&ctx);
1561	}
1562
1563	drm_atomic_state_put(state);
1564out:
1565	drm_modeset_drop_locks(&ctx);
1566	drm_modeset_acquire_fini(&ctx);
1567	return ret;
1568}
1569
1570static const u32 g4x_plane_formats[] = {
1571	DRM_FORMAT_XRGB8888,
1572	DRM_FORMAT_YUYV,
1573	DRM_FORMAT_YVYU,
1574	DRM_FORMAT_UYVY,
1575	DRM_FORMAT_VYUY,
1576};
1577
1578static const u64 i9xx_plane_format_modifiers[] = {
1579	I915_FORMAT_MOD_X_TILED,
1580	DRM_FORMAT_MOD_LINEAR,
1581	DRM_FORMAT_MOD_INVALID
1582};
1583
1584static const u32 snb_plane_formats[] = {
1585	DRM_FORMAT_XRGB8888,
1586	DRM_FORMAT_XBGR8888,
1587	DRM_FORMAT_XRGB2101010,
1588	DRM_FORMAT_XBGR2101010,
1589	DRM_FORMAT_XRGB16161616F,
1590	DRM_FORMAT_XBGR16161616F,
1591	DRM_FORMAT_YUYV,
1592	DRM_FORMAT_YVYU,
1593	DRM_FORMAT_UYVY,
1594	DRM_FORMAT_VYUY,
1595};
1596
1597static const u32 vlv_plane_formats[] = {
1598	DRM_FORMAT_C8,
1599	DRM_FORMAT_RGB565,
1600	DRM_FORMAT_XRGB8888,
1601	DRM_FORMAT_XBGR8888,
1602	DRM_FORMAT_ARGB8888,
1603	DRM_FORMAT_ABGR8888,
1604	DRM_FORMAT_XBGR2101010,
1605	DRM_FORMAT_ABGR2101010,
1606	DRM_FORMAT_YUYV,
1607	DRM_FORMAT_YVYU,
1608	DRM_FORMAT_UYVY,
1609	DRM_FORMAT_VYUY,
1610};
1611
1612static const u32 chv_pipe_b_sprite_formats[] = {
1613	DRM_FORMAT_C8,
1614	DRM_FORMAT_RGB565,
1615	DRM_FORMAT_XRGB8888,
1616	DRM_FORMAT_XBGR8888,
1617	DRM_FORMAT_ARGB8888,
1618	DRM_FORMAT_ABGR8888,
1619	DRM_FORMAT_XRGB2101010,
1620	DRM_FORMAT_XBGR2101010,
1621	DRM_FORMAT_ARGB2101010,
1622	DRM_FORMAT_ABGR2101010,
1623	DRM_FORMAT_YUYV,
1624	DRM_FORMAT_YVYU,
1625	DRM_FORMAT_UYVY,
1626	DRM_FORMAT_VYUY,
1627};
1628
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1629static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1630					    u32 format, u64 modifier)
1631{
1632	switch (modifier) {
1633	case DRM_FORMAT_MOD_LINEAR:
1634	case I915_FORMAT_MOD_X_TILED:
1635		break;
1636	default:
1637		return false;
1638	}
1639
1640	switch (format) {
1641	case DRM_FORMAT_XRGB8888:
1642	case DRM_FORMAT_YUYV:
1643	case DRM_FORMAT_YVYU:
1644	case DRM_FORMAT_UYVY:
1645	case DRM_FORMAT_VYUY:
1646		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1647		    modifier == I915_FORMAT_MOD_X_TILED)
1648			return true;
1649		fallthrough;
1650	default:
1651		return false;
1652	}
1653}
1654
1655static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1656					    u32 format, u64 modifier)
1657{
1658	switch (modifier) {
1659	case DRM_FORMAT_MOD_LINEAR:
1660	case I915_FORMAT_MOD_X_TILED:
1661		break;
1662	default:
1663		return false;
1664	}
1665
1666	switch (format) {
1667	case DRM_FORMAT_XRGB8888:
1668	case DRM_FORMAT_XBGR8888:
1669	case DRM_FORMAT_XRGB2101010:
1670	case DRM_FORMAT_XBGR2101010:
1671	case DRM_FORMAT_XRGB16161616F:
1672	case DRM_FORMAT_XBGR16161616F:
1673	case DRM_FORMAT_YUYV:
1674	case DRM_FORMAT_YVYU:
1675	case DRM_FORMAT_UYVY:
1676	case DRM_FORMAT_VYUY:
1677		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1678		    modifier == I915_FORMAT_MOD_X_TILED)
1679			return true;
1680		fallthrough;
1681	default:
1682		return false;
1683	}
1684}
1685
1686static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1687					    u32 format, u64 modifier)
1688{
1689	switch (modifier) {
1690	case DRM_FORMAT_MOD_LINEAR:
1691	case I915_FORMAT_MOD_X_TILED:
1692		break;
1693	default:
1694		return false;
1695	}
1696
1697	switch (format) {
1698	case DRM_FORMAT_C8:
1699	case DRM_FORMAT_RGB565:
1700	case DRM_FORMAT_ABGR8888:
1701	case DRM_FORMAT_ARGB8888:
1702	case DRM_FORMAT_XBGR8888:
1703	case DRM_FORMAT_XRGB8888:
1704	case DRM_FORMAT_XBGR2101010:
1705	case DRM_FORMAT_ABGR2101010:
1706	case DRM_FORMAT_XRGB2101010:
1707	case DRM_FORMAT_ARGB2101010:
1708	case DRM_FORMAT_YUYV:
1709	case DRM_FORMAT_YVYU:
1710	case DRM_FORMAT_UYVY:
1711	case DRM_FORMAT_VYUY:
1712		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1713		    modifier == I915_FORMAT_MOD_X_TILED)
1714			return true;
1715		fallthrough;
1716	default:
1717		return false;
1718	}
1719}
1720
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1721static const struct drm_plane_funcs g4x_sprite_funcs = {
1722	.update_plane = drm_atomic_helper_update_plane,
1723	.disable_plane = drm_atomic_helper_disable_plane,
1724	.destroy = intel_plane_destroy,
1725	.atomic_duplicate_state = intel_plane_duplicate_state,
1726	.atomic_destroy_state = intel_plane_destroy_state,
1727	.format_mod_supported = g4x_sprite_format_mod_supported,
1728};
1729
1730static const struct drm_plane_funcs snb_sprite_funcs = {
1731	.update_plane = drm_atomic_helper_update_plane,
1732	.disable_plane = drm_atomic_helper_disable_plane,
1733	.destroy = intel_plane_destroy,
1734	.atomic_duplicate_state = intel_plane_duplicate_state,
1735	.atomic_destroy_state = intel_plane_destroy_state,
1736	.format_mod_supported = snb_sprite_format_mod_supported,
1737};
1738
1739static const struct drm_plane_funcs vlv_sprite_funcs = {
1740	.update_plane = drm_atomic_helper_update_plane,
1741	.disable_plane = drm_atomic_helper_disable_plane,
1742	.destroy = intel_plane_destroy,
1743	.atomic_duplicate_state = intel_plane_duplicate_state,
1744	.atomic_destroy_state = intel_plane_destroy_state,
1745	.format_mod_supported = vlv_sprite_format_mod_supported,
1746};
1747
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1748struct intel_plane *
1749intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1750			  enum pipe pipe, int sprite)
1751{
1752	struct intel_plane *plane;
1753	const struct drm_plane_funcs *plane_funcs;
1754	unsigned int supported_rotations;
1755	const u64 *modifiers;
1756	const u32 *formats;
1757	int num_formats;
1758	int ret, zpos;
1759
 
 
 
 
1760	plane = intel_plane_alloc();
1761	if (IS_ERR(plane))
1762		return plane;
1763
1764	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 
1765		plane->update_plane = vlv_update_plane;
1766		plane->disable_plane = vlv_disable_plane;
1767		plane->get_hw_state = vlv_plane_get_hw_state;
1768		plane->check_plane = vlv_sprite_check;
1769		plane->max_stride = i965_plane_max_stride;
1770		plane->min_cdclk = vlv_plane_min_cdclk;
1771
1772		if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1773			formats = chv_pipe_b_sprite_formats;
1774			num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
1775		} else {
1776			formats = vlv_plane_formats;
1777			num_formats = ARRAY_SIZE(vlv_plane_formats);
1778		}
1779		modifiers = i9xx_plane_format_modifiers;
1780
1781		plane_funcs = &vlv_sprite_funcs;
1782	} else if (DISPLAY_VER(dev_priv) >= 7) {
 
1783		plane->update_plane = ivb_update_plane;
1784		plane->disable_plane = ivb_disable_plane;
1785		plane->get_hw_state = ivb_plane_get_hw_state;
1786		plane->check_plane = g4x_sprite_check;
1787
1788		if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
1789			plane->max_stride = hsw_sprite_max_stride;
1790			plane->min_cdclk = hsw_plane_min_cdclk;
1791		} else {
1792			plane->max_stride = g4x_sprite_max_stride;
1793			plane->min_cdclk = ivb_sprite_min_cdclk;
1794		}
1795
1796		formats = snb_plane_formats;
1797		num_formats = ARRAY_SIZE(snb_plane_formats);
1798		modifiers = i9xx_plane_format_modifiers;
1799
1800		plane_funcs = &snb_sprite_funcs;
1801	} else {
 
1802		plane->update_plane = g4x_update_plane;
1803		plane->disable_plane = g4x_disable_plane;
1804		plane->get_hw_state = g4x_plane_get_hw_state;
1805		plane->check_plane = g4x_sprite_check;
1806		plane->max_stride = g4x_sprite_max_stride;
1807		plane->min_cdclk = g4x_sprite_min_cdclk;
1808
1809		modifiers = i9xx_plane_format_modifiers;
1810		if (IS_SANDYBRIDGE(dev_priv)) {
1811			formats = snb_plane_formats;
1812			num_formats = ARRAY_SIZE(snb_plane_formats);
1813
1814			plane_funcs = &snb_sprite_funcs;
1815		} else {
1816			formats = g4x_plane_formats;
1817			num_formats = ARRAY_SIZE(g4x_plane_formats);
1818
1819			plane_funcs = &g4x_sprite_funcs;
1820		}
1821	}
1822
1823	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1824		supported_rotations =
1825			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1826			DRM_MODE_REFLECT_X;
1827	} else {
1828		supported_rotations =
1829			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1830	}
1831
1832	plane->pipe = pipe;
1833	plane->id = PLANE_SPRITE0 + sprite;
1834	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
1835
1836	ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
1837				       0, plane_funcs,
1838				       formats, num_formats, modifiers,
1839				       DRM_PLANE_TYPE_OVERLAY,
1840				       "sprite %c", sprite_name(pipe, sprite));
1841	if (ret)
1842		goto fail;
1843
1844	drm_plane_create_rotation_property(&plane->base,
1845					   DRM_MODE_ROTATE_0,
1846					   supported_rotations);
1847
1848	drm_plane_create_color_properties(&plane->base,
1849					  BIT(DRM_COLOR_YCBCR_BT601) |
1850					  BIT(DRM_COLOR_YCBCR_BT709),
1851					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1852					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1853					  DRM_COLOR_YCBCR_BT709,
1854					  DRM_COLOR_YCBCR_LIMITED_RANGE);
1855
1856	zpos = sprite + 1;
1857	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
1858
1859	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
1860
1861	return plane;
1862
1863fail:
1864	intel_plane_free(plane);
1865
1866	return ERR_PTR(ret);
1867}
v5.9
   1/*
   2 * Copyright © 2011 Intel Corporation
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice (including the next
  12 * paragraph) shall be included in all copies or substantial portions of the
  13 * Software.
  14 *
  15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21 * SOFTWARE.
  22 *
  23 * Authors:
  24 *   Jesse Barnes <jbarnes@virtuousgeek.org>
  25 *
  26 * New plane/sprite handling.
  27 *
  28 * The older chips had a separate interface for programming plane related
  29 * registers; newer ones are much simpler and we can use the new DRM plane
  30 * support.
  31 */
  32
  33#include <drm/drm_atomic.h>
  34#include <drm/drm_atomic_helper.h>
  35#include <drm/drm_color_mgmt.h>
  36#include <drm/drm_crtc.h>
  37#include <drm/drm_damage_helper.h>
  38#include <drm/drm_fourcc.h>
  39#include <drm/drm_plane_helper.h>
  40#include <drm/drm_rect.h>
  41
  42#include "i915_drv.h"
  43#include "i915_trace.h"
  44#include "i915_vgpu.h"
  45#include "intel_atomic_plane.h"
 
  46#include "intel_display_types.h"
  47#include "intel_frontbuffer.h"
  48#include "intel_pm.h"
  49#include "intel_psr.h"
  50#include "intel_sprite.h"
  51
  52int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
  53			     int usecs)
  54{
  55	/* paranoia */
  56	if (!adjusted_mode->crtc_htotal)
  57		return 1;
  58
  59	return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
  60			    1000 * adjusted_mode->crtc_htotal);
  61}
  62
  63/* FIXME: We should instead only take spinlocks once for the entire update
  64 * instead of once per mmio. */
  65#if IS_ENABLED(CONFIG_PROVE_LOCKING)
  66#define VBLANK_EVASION_TIME_US 250
  67#else
  68#define VBLANK_EVASION_TIME_US 100
  69#endif
  70
  71/**
  72 * intel_pipe_update_start() - start update of a set of display registers
  73 * @new_crtc_state: the new crtc state
  74 *
  75 * Mark the start of an update to pipe registers that should be updated
  76 * atomically regarding vblank. If the next vblank will happens within
  77 * the next 100 us, this function waits until the vblank passes.
  78 *
  79 * After a successful call to this function, interrupts will be disabled
  80 * until a subsequent call to intel_pipe_update_end(). That is done to
  81 * avoid random delays.
  82 */
  83void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
  84{
  85	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
  86	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
  87	const struct drm_display_mode *adjusted_mode = &new_crtc_state->hw.adjusted_mode;
  88	long timeout = msecs_to_jiffies_timeout(1);
  89	int scanline, min, max, vblank_start;
  90	wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
  91	bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
  92		intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
  93	DEFINE_WAIT(wait);
  94	u32 psr_status;
  95
  96	vblank_start = adjusted_mode->crtc_vblank_start;
  97	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
  98		vblank_start = DIV_ROUND_UP(vblank_start, 2);
  99
 100	/* FIXME needs to be calibrated sensibly */
 101	min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
 102						      VBLANK_EVASION_TIME_US);
 103	max = vblank_start - 1;
 104
 105	if (min <= 0 || max <= 0)
 106		goto irq_disable;
 107
 108	if (drm_WARN_ON(&dev_priv->drm, drm_crtc_vblank_get(&crtc->base)))
 109		goto irq_disable;
 110
 111	/*
 112	 * Wait for psr to idle out after enabling the VBL interrupts
 113	 * VBL interrupts will start the PSR exit and prevent a PSR
 114	 * re-entry as well.
 115	 */
 116	if (intel_psr_wait_for_idle(new_crtc_state, &psr_status))
 117		drm_err(&dev_priv->drm,
 118			"PSR idle timed out 0x%x, atomic update may fail\n",
 119			psr_status);
 120
 121	local_irq_disable();
 122
 123	crtc->debug.min_vbl = min;
 124	crtc->debug.max_vbl = max;
 125	trace_intel_pipe_update_start(crtc);
 126
 127	for (;;) {
 128		/*
 129		 * prepare_to_wait() has a memory barrier, which guarantees
 130		 * other CPUs can see the task state update by the time we
 131		 * read the scanline.
 132		 */
 133		prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
 134
 135		scanline = intel_get_crtc_scanline(crtc);
 136		if (scanline < min || scanline > max)
 137			break;
 138
 139		if (!timeout) {
 140			drm_err(&dev_priv->drm,
 141				"Potential atomic update failure on pipe %c\n",
 142				pipe_name(crtc->pipe));
 143			break;
 144		}
 145
 146		local_irq_enable();
 147
 148		timeout = schedule_timeout(timeout);
 149
 150		local_irq_disable();
 151	}
 152
 153	finish_wait(wq, &wait);
 154
 155	drm_crtc_vblank_put(&crtc->base);
 156
 157	/*
 158	 * On VLV/CHV DSI the scanline counter would appear to
 159	 * increment approx. 1/3 of a scanline before start of vblank.
 160	 * The registers still get latched at start of vblank however.
 161	 * This means we must not write any registers on the first
 162	 * line of vblank (since not the whole line is actually in
 163	 * vblank). And unfortunately we can't use the interrupt to
 164	 * wait here since it will fire too soon. We could use the
 165	 * frame start interrupt instead since it will fire after the
 166	 * critical scanline, but that would require more changes
 167	 * in the interrupt code. So for now we'll just do the nasty
 168	 * thing and poll for the bad scanline to pass us by.
 169	 *
 170	 * FIXME figure out if BXT+ DSI suffers from this as well
 171	 */
 172	while (need_vlv_dsi_wa && scanline == vblank_start)
 173		scanline = intel_get_crtc_scanline(crtc);
 174
 175	crtc->debug.scanline_start = scanline;
 176	crtc->debug.start_vbl_time = ktime_get();
 177	crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
 178
 179	trace_intel_pipe_update_vblank_evaded(crtc);
 180	return;
 181
 182irq_disable:
 183	local_irq_disable();
 184}
 185
 186/**
 187 * intel_pipe_update_end() - end update of a set of display registers
 188 * @new_crtc_state: the new crtc state
 189 *
 190 * Mark the end of an update started with intel_pipe_update_start(). This
 191 * re-enables interrupts and verifies the update was actually completed
 192 * before a vblank.
 193 */
 194void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
 195{
 196	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
 197	enum pipe pipe = crtc->pipe;
 198	int scanline_end = intel_get_crtc_scanline(crtc);
 199	u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
 200	ktime_t end_vbl_time = ktime_get();
 201	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 202
 203	trace_intel_pipe_update_end(crtc, end_vbl_count, scanline_end);
 204
 205	/* We're still in the vblank-evade critical section, this can't race.
 206	 * Would be slightly nice to just grab the vblank count and arm the
 207	 * event outside of the critical section - the spinlock might spin for a
 208	 * while ... */
 209	if (new_crtc_state->uapi.event) {
 210		drm_WARN_ON(&dev_priv->drm,
 211			    drm_crtc_vblank_get(&crtc->base) != 0);
 212
 213		spin_lock(&crtc->base.dev->event_lock);
 214		drm_crtc_arm_vblank_event(&crtc->base,
 215				          new_crtc_state->uapi.event);
 216		spin_unlock(&crtc->base.dev->event_lock);
 217
 218		new_crtc_state->uapi.event = NULL;
 219	}
 220
 221	local_irq_enable();
 222
 223	if (intel_vgpu_active(dev_priv))
 224		return;
 225
 226	if (crtc->debug.start_vbl_count &&
 227	    crtc->debug.start_vbl_count != end_vbl_count) {
 228		drm_err(&dev_priv->drm,
 229			"Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n",
 230			pipe_name(pipe), crtc->debug.start_vbl_count,
 231			end_vbl_count,
 232			ktime_us_delta(end_vbl_time,
 233				       crtc->debug.start_vbl_time),
 234			crtc->debug.min_vbl, crtc->debug.max_vbl,
 235			crtc->debug.scanline_start, scanline_end);
 236	}
 237#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
 238	else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
 239		 VBLANK_EVASION_TIME_US)
 240		drm_warn(&dev_priv->drm,
 241			 "Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
 242			 pipe_name(pipe),
 243			 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
 244			 VBLANK_EVASION_TIME_US);
 245#endif
 246}
 247
 248int intel_plane_check_stride(const struct intel_plane_state *plane_state)
 249{
 250	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 251	const struct drm_framebuffer *fb = plane_state->hw.fb;
 252	unsigned int rotation = plane_state->hw.rotation;
 253	u32 stride, max_stride;
 254
 255	/*
 256	 * We ignore stride for all invisible planes that
 257	 * can be remapped. Otherwise we could end up
 258	 * with a false positive when the remapping didn't
 259	 * kick in due the plane being invisible.
 260	 */
 261	if (intel_plane_can_remap(plane_state) &&
 262	    !plane_state->uapi.visible)
 263		return 0;
 264
 265	/* FIXME other color planes? */
 266	stride = plane_state->color_plane[0].stride;
 267	max_stride = plane->max_stride(plane, fb->format->format,
 268				       fb->modifier, rotation);
 269
 270	if (stride > max_stride) {
 271		DRM_DEBUG_KMS("[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n",
 272			      fb->base.id, stride,
 273			      plane->base.base.id, plane->base.name, max_stride);
 274		return -EINVAL;
 275	}
 276
 277	return 0;
 278}
 279
 280int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
 281{
 282	const struct drm_framebuffer *fb = plane_state->hw.fb;
 283	struct drm_rect *src = &plane_state->uapi.src;
 284	u32 src_x, src_y, src_w, src_h, hsub, vsub;
 285	bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
 286
 287	/*
 288	 * FIXME hsub/vsub vs. block size is a mess. Pre-tgl CCS
 289	 * abuses hsub/vsub so we can't use them here. But as they
 290	 * are limited to 32bpp RGB formats we don't actually need
 291	 * to check anything.
 292	 */
 293	if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
 294	    fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)
 295		return 0;
 296
 297	/*
 298	 * Hardware doesn't handle subpixel coordinates.
 299	 * Adjust to (macro)pixel boundary, but be careful not to
 300	 * increase the source viewport size, because that could
 301	 * push the downscaling factor out of bounds.
 302	 */
 303	src_x = src->x1 >> 16;
 304	src_w = drm_rect_width(src) >> 16;
 305	src_y = src->y1 >> 16;
 306	src_h = drm_rect_height(src) >> 16;
 307
 308	drm_rect_init(src, src_x << 16, src_y << 16,
 309		      src_w << 16, src_h << 16);
 310
 311	if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
 312		hsub = 2;
 313		vsub = 2;
 314	} else {
 315		hsub = fb->format->hsub;
 316		vsub = fb->format->vsub;
 317	}
 318
 319	if (rotated)
 320		hsub = vsub = max(hsub, vsub);
 321
 322	if (src_x % hsub || src_w % hsub) {
 323		DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
 324			      src_x, src_w, hsub, yesno(rotated));
 325		return -EINVAL;
 326	}
 327
 328	if (src_y % vsub || src_h % vsub) {
 329		DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
 330			      src_y, src_h, vsub, yesno(rotated));
 331		return -EINVAL;
 332	}
 333
 334	return 0;
 335}
 336
 337static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
 338{
 339	if (IS_ROCKETLAKE(i915))
 340		return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3);
 341	else
 342		return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5);
 343}
 344
 345bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
 346			 enum plane_id plane_id)
 347{
 348	return INTEL_GEN(dev_priv) >= 11 &&
 349		icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
 350}
 351
 352bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
 353{
 354	return INTEL_GEN(dev_priv) >= 11 &&
 355		icl_hdr_plane_mask() & BIT(plane_id);
 356}
 357
 358static void
 359skl_plane_ratio(const struct intel_crtc_state *crtc_state,
 360		const struct intel_plane_state *plane_state,
 361		unsigned int *num, unsigned int *den)
 362{
 363	struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
 364	const struct drm_framebuffer *fb = plane_state->hw.fb;
 365
 366	if (fb->format->cpp[0] == 8) {
 367		if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
 368			*num = 10;
 369			*den = 8;
 370		} else {
 371			*num = 9;
 372			*den = 8;
 373		}
 374	} else {
 375		*num = 1;
 376		*den = 1;
 377	}
 378}
 379
 380static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 381			       const struct intel_plane_state *plane_state)
 382{
 383	struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
 384	unsigned int num, den;
 385	unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
 386
 387	skl_plane_ratio(crtc_state, plane_state, &num, &den);
 388
 389	/* two pixels per clock on glk+ */
 390	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
 391		den *= 2;
 392
 393	return DIV_ROUND_UP(pixel_rate * num, den);
 394}
 395
 396static unsigned int
 397skl_plane_max_stride(struct intel_plane *plane,
 398		     u32 pixel_format, u64 modifier,
 399		     unsigned int rotation)
 400{
 401	const struct drm_format_info *info = drm_format_info(pixel_format);
 402	int cpp = info->cpp[0];
 403
 404	/*
 405	 * "The stride in bytes must not exceed the
 406	 * of the size of 8K pixels and 32K bytes."
 407	 */
 408	if (drm_rotation_90_or_270(rotation))
 409		return min(8192, 32768 / cpp);
 410	else
 411		return min(8192 * cpp, 32768);
 412}
 413
 414static void
 415skl_program_scaler(struct intel_plane *plane,
 416		   const struct intel_crtc_state *crtc_state,
 417		   const struct intel_plane_state *plane_state)
 418{
 419	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 420	const struct drm_framebuffer *fb = plane_state->hw.fb;
 421	enum pipe pipe = plane->pipe;
 422	int scaler_id = plane_state->scaler_id;
 423	const struct intel_scaler *scaler =
 424		&crtc_state->scaler_state.scalers[scaler_id];
 425	int crtc_x = plane_state->uapi.dst.x1;
 426	int crtc_y = plane_state->uapi.dst.y1;
 427	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
 428	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
 429	u16 y_hphase, uv_rgb_hphase;
 430	u16 y_vphase, uv_rgb_vphase;
 431	int hscale, vscale;
 432
 433	hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
 434				      &plane_state->uapi.dst,
 435				      0, INT_MAX);
 436	vscale = drm_rect_calc_vscale(&plane_state->uapi.src,
 437				      &plane_state->uapi.dst,
 438				      0, INT_MAX);
 439
 440	/* TODO: handle sub-pixel coordinates */
 441	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
 442	    !icl_is_hdr_plane(dev_priv, plane->id)) {
 443		y_hphase = skl_scaler_calc_phase(1, hscale, false);
 444		y_vphase = skl_scaler_calc_phase(1, vscale, false);
 445
 446		/* MPEG2 chroma siting convention */
 447		uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
 448		uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
 449	} else {
 450		/* not used */
 451		y_hphase = 0;
 452		y_vphase = 0;
 453
 454		uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
 455		uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
 456	}
 457
 458	intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, scaler_id),
 459			  PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode);
 460	intel_de_write_fw(dev_priv, SKL_PS_VPHASE(pipe, scaler_id),
 461			  PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
 462	intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, scaler_id),
 463			  PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
 464	intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(pipe, scaler_id),
 465			  (crtc_x << 16) | crtc_y);
 466	intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(pipe, scaler_id),
 467			  (crtc_w << 16) | crtc_h);
 468}
 469
 470/* Preoffset values for YUV to RGB Conversion */
 471#define PREOFF_YUV_TO_RGB_HI		0x1800
 472#define PREOFF_YUV_TO_RGB_ME		0x1F00
 473#define PREOFF_YUV_TO_RGB_LO		0x1800
 474
 475#define  ROFF(x)          (((x) & 0xffff) << 16)
 476#define  GOFF(x)          (((x) & 0xffff) << 0)
 477#define  BOFF(x)          (((x) & 0xffff) << 16)
 478
 479static void
 480icl_program_input_csc(struct intel_plane *plane,
 481		      const struct intel_crtc_state *crtc_state,
 482		      const struct intel_plane_state *plane_state)
 483{
 484	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 485	enum pipe pipe = plane->pipe;
 486	enum plane_id plane_id = plane->id;
 487
 488	static const u16 input_csc_matrix[][9] = {
 489		/*
 490		 * BT.601 full range YCbCr -> full range RGB
 491		 * The matrix required is :
 492		 * [1.000, 0.000, 1.371,
 493		 *  1.000, -0.336, -0.698,
 494		 *  1.000, 1.732, 0.0000]
 495		 */
 496		[DRM_COLOR_YCBCR_BT601] = {
 497			0x7AF8, 0x7800, 0x0,
 498			0x8B28, 0x7800, 0x9AC0,
 499			0x0, 0x7800, 0x7DD8,
 500		},
 501		/*
 502		 * BT.709 full range YCbCr -> full range RGB
 503		 * The matrix required is :
 504		 * [1.000, 0.000, 1.574,
 505		 *  1.000, -0.187, -0.468,
 506		 *  1.000, 1.855, 0.0000]
 507		 */
 508		[DRM_COLOR_YCBCR_BT709] = {
 509			0x7C98, 0x7800, 0x0,
 510			0x9EF8, 0x7800, 0xAC00,
 511			0x0, 0x7800,  0x7ED8,
 512		},
 513		/*
 514		 * BT.2020 full range YCbCr -> full range RGB
 515		 * The matrix required is :
 516		 * [1.000, 0.000, 1.474,
 517		 *  1.000, -0.1645, -0.5713,
 518		 *  1.000, 1.8814, 0.0000]
 519		 */
 520		[DRM_COLOR_YCBCR_BT2020] = {
 521			0x7BC8, 0x7800, 0x0,
 522			0x8928, 0x7800, 0xAA88,
 523			0x0, 0x7800, 0x7F10,
 524		},
 525	};
 526
 527	/* Matrix for Limited Range to Full Range Conversion */
 528	static const u16 input_csc_matrix_lr[][9] = {
 529		/*
 530		 * BT.601 Limted range YCbCr -> full range RGB
 531		 * The matrix required is :
 532		 * [1.164384, 0.000, 1.596027,
 533		 *  1.164384, -0.39175, -0.812813,
 534		 *  1.164384, 2.017232, 0.0000]
 535		 */
 536		[DRM_COLOR_YCBCR_BT601] = {
 537			0x7CC8, 0x7950, 0x0,
 538			0x8D00, 0x7950, 0x9C88,
 539			0x0, 0x7950, 0x6810,
 540		},
 541		/*
 542		 * BT.709 Limited range YCbCr -> full range RGB
 543		 * The matrix required is :
 544		 * [1.164384, 0.000, 1.792741,
 545		 *  1.164384, -0.213249, -0.532909,
 546		 *  1.164384, 2.112402, 0.0000]
 547		 */
 548		[DRM_COLOR_YCBCR_BT709] = {
 549			0x7E58, 0x7950, 0x0,
 550			0x8888, 0x7950, 0xADA8,
 551			0x0, 0x7950,  0x6870,
 552		},
 553		/*
 554		 * BT.2020 Limited range YCbCr -> full range RGB
 555		 * The matrix required is :
 556		 * [1.164, 0.000, 1.678,
 557		 *  1.164, -0.1873, -0.6504,
 558		 *  1.164, 2.1417, 0.0000]
 559		 */
 560		[DRM_COLOR_YCBCR_BT2020] = {
 561			0x7D70, 0x7950, 0x0,
 562			0x8A68, 0x7950, 0xAC00,
 563			0x0, 0x7950, 0x6890,
 564		},
 565	};
 566	const u16 *csc;
 567
 568	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
 569		csc = input_csc_matrix[plane_state->hw.color_encoding];
 570	else
 571		csc = input_csc_matrix_lr[plane_state->hw.color_encoding];
 572
 573	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
 574			  ROFF(csc[0]) | GOFF(csc[1]));
 575	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
 576			  BOFF(csc[2]));
 577	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
 578			  ROFF(csc[3]) | GOFF(csc[4]));
 579	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
 580			  BOFF(csc[5]));
 581	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
 582			  ROFF(csc[6]) | GOFF(csc[7]));
 583	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
 584			  BOFF(csc[8]));
 585
 586	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
 587			  PREOFF_YUV_TO_RGB_HI);
 588	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
 589		intel_de_write_fw(dev_priv,
 590				  PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
 591				  0);
 592	else
 593		intel_de_write_fw(dev_priv,
 594				  PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
 595				  PREOFF_YUV_TO_RGB_ME);
 596	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
 597			  PREOFF_YUV_TO_RGB_LO);
 598	intel_de_write_fw(dev_priv,
 599			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
 600	intel_de_write_fw(dev_priv,
 601			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
 602	intel_de_write_fw(dev_priv,
 603			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
 604}
 605
 606static void
 607skl_program_plane(struct intel_plane *plane,
 608		  const struct intel_crtc_state *crtc_state,
 609		  const struct intel_plane_state *plane_state,
 610		  int color_plane)
 611{
 612	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 613	enum plane_id plane_id = plane->id;
 614	enum pipe pipe = plane->pipe;
 615	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 616	u32 surf_addr = plane_state->color_plane[color_plane].offset;
 617	u32 stride = skl_plane_stride(plane_state, color_plane);
 618	const struct drm_framebuffer *fb = plane_state->hw.fb;
 619	int aux_plane = intel_main_to_aux_plane(fb, color_plane);
 620	u32 aux_dist = plane_state->color_plane[aux_plane].offset - surf_addr;
 621	u32 aux_stride = skl_plane_stride(plane_state, aux_plane);
 622	int crtc_x = plane_state->uapi.dst.x1;
 623	int crtc_y = plane_state->uapi.dst.y1;
 624	u32 x = plane_state->color_plane[color_plane].x;
 625	u32 y = plane_state->color_plane[color_plane].y;
 626	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
 627	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
 628	u8 alpha = plane_state->hw.alpha >> 8;
 629	u32 plane_color_ctl = 0;
 630	unsigned long irqflags;
 631	u32 keymsk, keymax;
 632	u32 plane_ctl = plane_state->ctl;
 633
 634	plane_ctl |= skl_plane_ctl_crtc(crtc_state);
 635
 636	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
 637		plane_color_ctl = plane_state->color_ctl |
 638			glk_plane_color_ctl_crtc(crtc_state);
 639
 640	/* Sizes are 0 based */
 641	src_w--;
 642	src_h--;
 643
 644	keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
 645
 646	keymsk = key->channel_mask & 0x7ffffff;
 647	if (alpha < 0xff)
 648		keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
 649
 650	/* The scaler will handle the output position */
 651	if (plane_state->scaler_id >= 0) {
 652		crtc_x = 0;
 653		crtc_y = 0;
 654	}
 655
 656	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 657
 658	intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride);
 659	intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
 660			  (crtc_y << 16) | crtc_x);
 661	intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
 662			  (src_h << 16) | src_w);
 663
 664	if (INTEL_GEN(dev_priv) < 12)
 665		aux_dist |= aux_stride;
 666	intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist);
 667
 668	if (icl_is_hdr_plane(dev_priv, plane_id))
 669		intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
 670				  plane_state->cus_ctl);
 671
 672	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
 673		intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id),
 674				  plane_color_ctl);
 675
 676	if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
 677		icl_program_input_csc(plane, crtc_state, plane_state);
 678
 679	skl_write_plane_wm(plane, crtc_state);
 680
 681	intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id),
 682			  key->min_value);
 683	intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), keymsk);
 684	intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), keymax);
 685
 686	intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
 687			  (y << 16) | x);
 688
 689	if (INTEL_GEN(dev_priv) < 11)
 690		intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
 691				  (plane_state->color_plane[1].y << 16) | plane_state->color_plane[1].x);
 692
 693	/*
 694	 * The control register self-arms if the plane was previously
 695	 * disabled. Try to make the plane enable atomic by writing
 696	 * the control register just before the surface register.
 697	 */
 698	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
 699	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
 700			  intel_plane_ggtt_offset(plane_state) + surf_addr);
 701
 702	if (plane_state->scaler_id >= 0)
 703		skl_program_scaler(plane, crtc_state, plane_state);
 704
 705	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 706}
 707
 708static void
 709skl_update_plane(struct intel_plane *plane,
 710		 const struct intel_crtc_state *crtc_state,
 711		 const struct intel_plane_state *plane_state)
 712{
 713	int color_plane = 0;
 714
 715	if (plane_state->planar_linked_plane && !plane_state->planar_slave)
 716		/* Program the UV plane on planar master */
 717		color_plane = 1;
 718
 719	skl_program_plane(plane, crtc_state, plane_state, color_plane);
 720}
 721static void
 722skl_disable_plane(struct intel_plane *plane,
 723		  const struct intel_crtc_state *crtc_state)
 724{
 725	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 726	enum plane_id plane_id = plane->id;
 727	enum pipe pipe = plane->pipe;
 728	unsigned long irqflags;
 729
 730	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 731
 732	if (icl_is_hdr_plane(dev_priv, plane_id))
 733		intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
 734
 735	skl_write_plane_wm(plane, crtc_state);
 736
 737	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
 738	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
 739
 740	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 741}
 742
 743static bool
 744skl_plane_get_hw_state(struct intel_plane *plane,
 745		       enum pipe *pipe)
 746{
 747	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 748	enum intel_display_power_domain power_domain;
 749	enum plane_id plane_id = plane->id;
 750	intel_wakeref_t wakeref;
 751	bool ret;
 752
 753	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
 754	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
 755	if (!wakeref)
 756		return false;
 757
 758	ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
 759
 760	*pipe = plane->pipe;
 761
 762	intel_display_power_put(dev_priv, power_domain, wakeref);
 763
 764	return ret;
 765}
 766
 767static void i9xx_plane_linear_gamma(u16 gamma[8])
 768{
 769	/* The points are not evenly spaced. */
 770	static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
 771	int i;
 772
 773	for (i = 0; i < 8; i++)
 774		gamma[i] = (in[i] << 8) / 32;
 775}
 776
 777static void
 778chv_update_csc(const struct intel_plane_state *plane_state)
 779{
 780	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 781	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 782	const struct drm_framebuffer *fb = plane_state->hw.fb;
 783	enum plane_id plane_id = plane->id;
 784	/*
 785	 * |r|   | c0 c1 c2 |   |cr|
 786	 * |g| = | c3 c4 c5 | x |y |
 787	 * |b|   | c6 c7 c8 |   |cb|
 788	 *
 789	 * Coefficients are s3.12.
 790	 *
 791	 * Cb and Cr apparently come in as signed already, and
 792	 * we always get full range data in on account of CLRC0/1.
 793	 */
 794	static const s16 csc_matrix[][9] = {
 795		/* BT.601 full range YCbCr -> full range RGB */
 796		[DRM_COLOR_YCBCR_BT601] = {
 797			 5743, 4096,     0,
 798			-2925, 4096, -1410,
 799			    0, 4096,  7258,
 800		},
 801		/* BT.709 full range YCbCr -> full range RGB */
 802		[DRM_COLOR_YCBCR_BT709] = {
 803			 6450, 4096,     0,
 804			-1917, 4096,  -767,
 805			    0, 4096,  7601,
 806		},
 807	};
 808	const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
 809
 810	/* Seems RGB data bypasses the CSC always */
 811	if (!fb->format->is_yuv)
 812		return;
 813
 814	intel_de_write_fw(dev_priv, SPCSCYGOFF(plane_id),
 815			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
 816	intel_de_write_fw(dev_priv, SPCSCCBOFF(plane_id),
 817			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
 818	intel_de_write_fw(dev_priv, SPCSCCROFF(plane_id),
 819			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
 820
 821	intel_de_write_fw(dev_priv, SPCSCC01(plane_id),
 822			  SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
 823	intel_de_write_fw(dev_priv, SPCSCC23(plane_id),
 824			  SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
 825	intel_de_write_fw(dev_priv, SPCSCC45(plane_id),
 826			  SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
 827	intel_de_write_fw(dev_priv, SPCSCC67(plane_id),
 828			  SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
 829	intel_de_write_fw(dev_priv, SPCSCC8(plane_id), SPCSC_C0(csc[8]));
 830
 831	intel_de_write_fw(dev_priv, SPCSCYGICLAMP(plane_id),
 832			  SPCSC_IMAX(1023) | SPCSC_IMIN(0));
 833	intel_de_write_fw(dev_priv, SPCSCCBICLAMP(plane_id),
 834			  SPCSC_IMAX(512) | SPCSC_IMIN(-512));
 835	intel_de_write_fw(dev_priv, SPCSCCRICLAMP(plane_id),
 836			  SPCSC_IMAX(512) | SPCSC_IMIN(-512));
 837
 838	intel_de_write_fw(dev_priv, SPCSCYGOCLAMP(plane_id),
 839			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 840	intel_de_write_fw(dev_priv, SPCSCCBOCLAMP(plane_id),
 841			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 842	intel_de_write_fw(dev_priv, SPCSCCROCLAMP(plane_id),
 843			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 844}
 845
 846#define SIN_0 0
 847#define COS_0 1
 848
 849static void
 850vlv_update_clrc(const struct intel_plane_state *plane_state)
 851{
 852	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 853	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 854	const struct drm_framebuffer *fb = plane_state->hw.fb;
 855	enum pipe pipe = plane->pipe;
 856	enum plane_id plane_id = plane->id;
 857	int contrast, brightness, sh_scale, sh_sin, sh_cos;
 858
 859	if (fb->format->is_yuv &&
 860	    plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
 861		/*
 862		 * Expand limited range to full range:
 863		 * Contrast is applied first and is used to expand Y range.
 864		 * Brightness is applied second and is used to remove the
 865		 * offset from Y. Saturation/hue is used to expand CbCr range.
 866		 */
 867		contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
 868		brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
 869		sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
 870		sh_sin = SIN_0 * sh_scale;
 871		sh_cos = COS_0 * sh_scale;
 872	} else {
 873		/* Pass-through everything. */
 874		contrast = 1 << 6;
 875		brightness = 0;
 876		sh_scale = 1 << 7;
 877		sh_sin = SIN_0 * sh_scale;
 878		sh_cos = COS_0 * sh_scale;
 879	}
 880
 881	/* FIXME these register are single buffered :( */
 882	intel_de_write_fw(dev_priv, SPCLRC0(pipe, plane_id),
 883			  SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
 884	intel_de_write_fw(dev_priv, SPCLRC1(pipe, plane_id),
 885			  SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
 886}
 887
 888static void
 889vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
 890		const struct intel_plane_state *plane_state,
 891		unsigned int *num, unsigned int *den)
 892{
 893	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
 894	const struct drm_framebuffer *fb = plane_state->hw.fb;
 895	unsigned int cpp = fb->format->cpp[0];
 896
 897	/*
 898	 * VLV bspec only considers cases where all three planes are
 899	 * enabled, and cases where the primary and one sprite is enabled.
 900	 * Let's assume the case with just two sprites enabled also
 901	 * maps to the latter case.
 902	 */
 903	if (hweight8(active_planes) == 3) {
 904		switch (cpp) {
 905		case 8:
 906			*num = 11;
 907			*den = 8;
 908			break;
 909		case 4:
 910			*num = 18;
 911			*den = 16;
 912			break;
 913		default:
 914			*num = 1;
 915			*den = 1;
 916			break;
 917		}
 918	} else if (hweight8(active_planes) == 2) {
 919		switch (cpp) {
 920		case 8:
 921			*num = 10;
 922			*den = 8;
 923			break;
 924		case 4:
 925			*num = 17;
 926			*den = 16;
 927			break;
 928		default:
 929			*num = 1;
 930			*den = 1;
 931			break;
 932		}
 933	} else {
 934		switch (cpp) {
 935		case 8:
 936			*num = 10;
 937			*den = 8;
 938			break;
 939		default:
 940			*num = 1;
 941			*den = 1;
 942			break;
 943		}
 944	}
 945}
 946
 947int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 948			const struct intel_plane_state *plane_state)
 949{
 950	unsigned int pixel_rate;
 951	unsigned int num, den;
 952
 953	/*
 954	 * Note that crtc_state->pixel_rate accounts for both
 955	 * horizontal and vertical panel fitter downscaling factors.
 956	 * Pre-HSW bspec tells us to only consider the horizontal
 957	 * downscaling factor here. We ignore that and just consider
 958	 * both for simplicity.
 959	 */
 960	pixel_rate = crtc_state->pixel_rate;
 961
 962	vlv_plane_ratio(crtc_state, plane_state, &num, &den);
 963
 964	return DIV_ROUND_UP(pixel_rate * num, den);
 965}
 966
 967static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
 968{
 969	u32 sprctl = 0;
 970
 971	if (crtc_state->gamma_enable)
 972		sprctl |= SP_GAMMA_ENABLE;
 973
 974	return sprctl;
 975}
 976
 977static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
 978			  const struct intel_plane_state *plane_state)
 979{
 980	const struct drm_framebuffer *fb = plane_state->hw.fb;
 981	unsigned int rotation = plane_state->hw.rotation;
 982	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 983	u32 sprctl;
 984
 985	sprctl = SP_ENABLE;
 986
 987	switch (fb->format->format) {
 988	case DRM_FORMAT_YUYV:
 989		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
 990		break;
 991	case DRM_FORMAT_YVYU:
 992		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
 993		break;
 994	case DRM_FORMAT_UYVY:
 995		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
 996		break;
 997	case DRM_FORMAT_VYUY:
 998		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
 999		break;
1000	case DRM_FORMAT_C8:
1001		sprctl |= SP_FORMAT_8BPP;
1002		break;
1003	case DRM_FORMAT_RGB565:
1004		sprctl |= SP_FORMAT_BGR565;
1005		break;
1006	case DRM_FORMAT_XRGB8888:
1007		sprctl |= SP_FORMAT_BGRX8888;
1008		break;
1009	case DRM_FORMAT_ARGB8888:
1010		sprctl |= SP_FORMAT_BGRA8888;
1011		break;
1012	case DRM_FORMAT_XBGR2101010:
1013		sprctl |= SP_FORMAT_RGBX1010102;
1014		break;
1015	case DRM_FORMAT_ABGR2101010:
1016		sprctl |= SP_FORMAT_RGBA1010102;
1017		break;
1018	case DRM_FORMAT_XRGB2101010:
1019		sprctl |= SP_FORMAT_BGRX1010102;
1020		break;
1021	case DRM_FORMAT_ARGB2101010:
1022		sprctl |= SP_FORMAT_BGRA1010102;
1023		break;
1024	case DRM_FORMAT_XBGR8888:
1025		sprctl |= SP_FORMAT_RGBX8888;
1026		break;
1027	case DRM_FORMAT_ABGR8888:
1028		sprctl |= SP_FORMAT_RGBA8888;
1029		break;
1030	default:
1031		MISSING_CASE(fb->format->format);
1032		return 0;
1033	}
1034
1035	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1036		sprctl |= SP_YUV_FORMAT_BT709;
1037
1038	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1039		sprctl |= SP_TILED;
1040
1041	if (rotation & DRM_MODE_ROTATE_180)
1042		sprctl |= SP_ROTATE_180;
1043
1044	if (rotation & DRM_MODE_REFLECT_X)
1045		sprctl |= SP_MIRROR;
1046
1047	if (key->flags & I915_SET_COLORKEY_SOURCE)
1048		sprctl |= SP_SOURCE_KEY;
1049
1050	return sprctl;
1051}
1052
1053static void vlv_update_gamma(const struct intel_plane_state *plane_state)
1054{
1055	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1056	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1057	const struct drm_framebuffer *fb = plane_state->hw.fb;
1058	enum pipe pipe = plane->pipe;
1059	enum plane_id plane_id = plane->id;
1060	u16 gamma[8];
1061	int i;
1062
1063	/* Seems RGB data bypasses the gamma always */
1064	if (!fb->format->is_yuv)
1065		return;
1066
1067	i9xx_plane_linear_gamma(gamma);
1068
1069	/* FIXME these register are single buffered :( */
1070	/* The two end points are implicit (0.0 and 1.0) */
1071	for (i = 1; i < 8 - 1; i++)
1072		intel_de_write_fw(dev_priv, SPGAMC(pipe, plane_id, i - 1),
1073				  gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
1074}
1075
1076static void
1077vlv_update_plane(struct intel_plane *plane,
1078		 const struct intel_crtc_state *crtc_state,
1079		 const struct intel_plane_state *plane_state)
1080{
1081	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1082	enum pipe pipe = plane->pipe;
1083	enum plane_id plane_id = plane->id;
1084	u32 sprsurf_offset = plane_state->color_plane[0].offset;
1085	u32 linear_offset;
1086	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1087	int crtc_x = plane_state->uapi.dst.x1;
1088	int crtc_y = plane_state->uapi.dst.y1;
1089	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1090	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1091	u32 x = plane_state->color_plane[0].x;
1092	u32 y = plane_state->color_plane[0].y;
1093	unsigned long irqflags;
1094	u32 sprctl;
1095
1096	sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
1097
1098	/* Sizes are 0 based */
1099	crtc_w--;
1100	crtc_h--;
1101
1102	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1103
1104	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1105
1106	intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id),
1107			  plane_state->color_plane[0].stride);
1108	intel_de_write_fw(dev_priv, SPPOS(pipe, plane_id),
1109			  (crtc_y << 16) | crtc_x);
1110	intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id),
1111			  (crtc_h << 16) | crtc_w);
1112	intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0);
1113
1114	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
1115		chv_update_csc(plane_state);
1116
1117	if (key->flags) {
1118		intel_de_write_fw(dev_priv, SPKEYMINVAL(pipe, plane_id),
1119				  key->min_value);
1120		intel_de_write_fw(dev_priv, SPKEYMSK(pipe, plane_id),
1121				  key->channel_mask);
1122		intel_de_write_fw(dev_priv, SPKEYMAXVAL(pipe, plane_id),
1123				  key->max_value);
1124	}
1125
1126	intel_de_write_fw(dev_priv, SPLINOFF(pipe, plane_id), linear_offset);
1127	intel_de_write_fw(dev_priv, SPTILEOFF(pipe, plane_id), (y << 16) | x);
1128
1129	/*
1130	 * The control register self-arms if the plane was previously
1131	 * disabled. Try to make the plane enable atomic by writing
1132	 * the control register just before the surface register.
1133	 */
1134	intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), sprctl);
1135	intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id),
1136			  intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1137
1138	vlv_update_clrc(plane_state);
1139	vlv_update_gamma(plane_state);
1140
1141	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1142}
1143
1144static void
1145vlv_disable_plane(struct intel_plane *plane,
1146		  const struct intel_crtc_state *crtc_state)
1147{
1148	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1149	enum pipe pipe = plane->pipe;
1150	enum plane_id plane_id = plane->id;
1151	unsigned long irqflags;
1152
1153	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1154
1155	intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0);
1156	intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0);
1157
1158	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1159}
1160
1161static bool
1162vlv_plane_get_hw_state(struct intel_plane *plane,
1163		       enum pipe *pipe)
1164{
1165	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1166	enum intel_display_power_domain power_domain;
1167	enum plane_id plane_id = plane->id;
1168	intel_wakeref_t wakeref;
1169	bool ret;
1170
1171	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1172	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1173	if (!wakeref)
1174		return false;
1175
1176	ret = intel_de_read(dev_priv, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
1177
1178	*pipe = plane->pipe;
1179
1180	intel_display_power_put(dev_priv, power_domain, wakeref);
1181
1182	return ret;
1183}
1184
1185static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
1186			    const struct intel_plane_state *plane_state,
1187			    unsigned int *num, unsigned int *den)
1188{
1189	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
1190	const struct drm_framebuffer *fb = plane_state->hw.fb;
1191	unsigned int cpp = fb->format->cpp[0];
1192
1193	if (hweight8(active_planes) == 2) {
1194		switch (cpp) {
1195		case 8:
1196			*num = 10;
1197			*den = 8;
1198			break;
1199		case 4:
1200			*num = 17;
1201			*den = 16;
1202			break;
1203		default:
1204			*num = 1;
1205			*den = 1;
1206			break;
1207		}
1208	} else {
1209		switch (cpp) {
1210		case 8:
1211			*num = 9;
1212			*den = 8;
1213			break;
1214		default:
1215			*num = 1;
1216			*den = 1;
1217			break;
1218		}
1219	}
1220}
1221
1222static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
1223				    const struct intel_plane_state *plane_state,
1224				    unsigned int *num, unsigned int *den)
1225{
1226	const struct drm_framebuffer *fb = plane_state->hw.fb;
1227	unsigned int cpp = fb->format->cpp[0];
1228
1229	switch (cpp) {
1230	case 8:
1231		*num = 12;
1232		*den = 8;
1233		break;
1234	case 4:
1235		*num = 19;
1236		*den = 16;
1237		break;
1238	case 2:
1239		*num = 33;
1240		*den = 32;
1241		break;
1242	default:
1243		*num = 1;
1244		*den = 1;
1245		break;
1246	}
1247}
1248
1249int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
1250			const struct intel_plane_state *plane_state)
1251{
1252	unsigned int pixel_rate;
1253	unsigned int num, den;
1254
1255	/*
1256	 * Note that crtc_state->pixel_rate accounts for both
1257	 * horizontal and vertical panel fitter downscaling factors.
1258	 * Pre-HSW bspec tells us to only consider the horizontal
1259	 * downscaling factor here. We ignore that and just consider
1260	 * both for simplicity.
1261	 */
1262	pixel_rate = crtc_state->pixel_rate;
1263
1264	ivb_plane_ratio(crtc_state, plane_state, &num, &den);
1265
1266	return DIV_ROUND_UP(pixel_rate * num, den);
1267}
1268
1269static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
1270				const struct intel_plane_state *plane_state)
1271{
1272	unsigned int src_w, dst_w, pixel_rate;
1273	unsigned int num, den;
1274
1275	/*
1276	 * Note that crtc_state->pixel_rate accounts for both
1277	 * horizontal and vertical panel fitter downscaling factors.
1278	 * Pre-HSW bspec tells us to only consider the horizontal
1279	 * downscaling factor here. We ignore that and just consider
1280	 * both for simplicity.
1281	 */
1282	pixel_rate = crtc_state->pixel_rate;
1283
1284	src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1285	dst_w = drm_rect_width(&plane_state->uapi.dst);
1286
1287	if (src_w != dst_w)
1288		ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
1289	else
1290		ivb_plane_ratio(crtc_state, plane_state, &num, &den);
1291
1292	/* Horizontal downscaling limits the maximum pixel rate */
1293	dst_w = min(src_w, dst_w);
1294
1295	return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
1296				den * dst_w);
1297}
1298
1299static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
1300			    const struct intel_plane_state *plane_state,
1301			    unsigned int *num, unsigned int *den)
1302{
1303	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
1304	const struct drm_framebuffer *fb = plane_state->hw.fb;
1305	unsigned int cpp = fb->format->cpp[0];
1306
1307	if (hweight8(active_planes) == 2) {
1308		switch (cpp) {
1309		case 8:
1310			*num = 10;
1311			*den = 8;
1312			break;
1313		default:
1314			*num = 1;
1315			*den = 1;
1316			break;
1317		}
1318	} else {
1319		switch (cpp) {
1320		case 8:
1321			*num = 9;
1322			*den = 8;
1323			break;
1324		default:
1325			*num = 1;
1326			*den = 1;
1327			break;
1328		}
1329	}
1330}
1331
1332int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
1333			const struct intel_plane_state *plane_state)
1334{
1335	unsigned int pixel_rate = crtc_state->pixel_rate;
1336	unsigned int num, den;
1337
1338	hsw_plane_ratio(crtc_state, plane_state, &num, &den);
1339
1340	return DIV_ROUND_UP(pixel_rate * num, den);
1341}
1342
1343static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1344{
1345	u32 sprctl = 0;
1346
1347	if (crtc_state->gamma_enable)
1348		sprctl |= SPRITE_GAMMA_ENABLE;
1349
1350	if (crtc_state->csc_enable)
1351		sprctl |= SPRITE_PIPE_CSC_ENABLE;
1352
1353	return sprctl;
1354}
1355
1356static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
1357{
1358	struct drm_i915_private *dev_priv =
1359		to_i915(plane_state->uapi.plane->dev);
1360	const struct drm_framebuffer *fb = plane_state->hw.fb;
1361
1362	return fb->format->cpp[0] == 8 &&
1363		(IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
1364}
1365
1366static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
1367			  const struct intel_plane_state *plane_state)
1368{
1369	struct drm_i915_private *dev_priv =
1370		to_i915(plane_state->uapi.plane->dev);
1371	const struct drm_framebuffer *fb = plane_state->hw.fb;
1372	unsigned int rotation = plane_state->hw.rotation;
1373	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1374	u32 sprctl;
1375
1376	sprctl = SPRITE_ENABLE;
1377
1378	if (IS_IVYBRIDGE(dev_priv))
1379		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
1380
1381	switch (fb->format->format) {
1382	case DRM_FORMAT_XBGR8888:
1383		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
1384		break;
1385	case DRM_FORMAT_XRGB8888:
1386		sprctl |= SPRITE_FORMAT_RGBX888;
1387		break;
1388	case DRM_FORMAT_XBGR2101010:
1389		sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
1390		break;
1391	case DRM_FORMAT_XRGB2101010:
1392		sprctl |= SPRITE_FORMAT_RGBX101010;
1393		break;
1394	case DRM_FORMAT_XBGR16161616F:
1395		sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
1396		break;
1397	case DRM_FORMAT_XRGB16161616F:
1398		sprctl |= SPRITE_FORMAT_RGBX161616;
1399		break;
1400	case DRM_FORMAT_YUYV:
1401		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
1402		break;
1403	case DRM_FORMAT_YVYU:
1404		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
1405		break;
1406	case DRM_FORMAT_UYVY:
1407		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
1408		break;
1409	case DRM_FORMAT_VYUY:
1410		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
1411		break;
1412	default:
1413		MISSING_CASE(fb->format->format);
1414		return 0;
1415	}
1416
1417	if (!ivb_need_sprite_gamma(plane_state))
1418		sprctl |= SPRITE_INT_GAMMA_DISABLE;
1419
1420	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1421		sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
1422
1423	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1424		sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
1425
1426	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1427		sprctl |= SPRITE_TILED;
1428
1429	if (rotation & DRM_MODE_ROTATE_180)
1430		sprctl |= SPRITE_ROTATE_180;
1431
1432	if (key->flags & I915_SET_COLORKEY_DESTINATION)
1433		sprctl |= SPRITE_DEST_KEY;
1434	else if (key->flags & I915_SET_COLORKEY_SOURCE)
1435		sprctl |= SPRITE_SOURCE_KEY;
1436
1437	return sprctl;
1438}
1439
1440static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
1441				    u16 gamma[18])
1442{
1443	int scale, i;
1444
1445	/*
1446	 * WaFP16GammaEnabling:ivb,hsw
1447	 * "Workaround : When using the 64-bit format, the sprite output
1448	 *  on each color channel has one quarter amplitude. It can be
1449	 *  brought up to full amplitude by using sprite internal gamma
1450	 *  correction, pipe gamma correction, or pipe color space
1451	 *  conversion to multiply the sprite output by four."
1452	 */
1453	scale = 4;
1454
1455	for (i = 0; i < 16; i++)
1456		gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
1457
1458	gamma[i] = min((scale * i << 10) / 16, 1 << 10);
1459	i++;
1460
1461	gamma[i] = 3 << 10;
1462	i++;
1463}
1464
1465static void ivb_update_gamma(const struct intel_plane_state *plane_state)
1466{
1467	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1468	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1469	enum pipe pipe = plane->pipe;
1470	u16 gamma[18];
1471	int i;
1472
1473	if (!ivb_need_sprite_gamma(plane_state))
1474		return;
1475
1476	ivb_sprite_linear_gamma(plane_state, gamma);
1477
1478	/* FIXME these register are single buffered :( */
1479	for (i = 0; i < 16; i++)
1480		intel_de_write_fw(dev_priv, SPRGAMC(pipe, i),
1481				  gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
1482
1483	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 0), gamma[i]);
1484	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 1), gamma[i]);
1485	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 2), gamma[i]);
1486	i++;
1487
1488	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 0), gamma[i]);
1489	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 1), gamma[i]);
1490	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 2), gamma[i]);
1491	i++;
1492}
1493
1494static void
1495ivb_update_plane(struct intel_plane *plane,
1496		 const struct intel_crtc_state *crtc_state,
1497		 const struct intel_plane_state *plane_state)
1498{
1499	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1500	enum pipe pipe = plane->pipe;
1501	u32 sprsurf_offset = plane_state->color_plane[0].offset;
1502	u32 linear_offset;
1503	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1504	int crtc_x = plane_state->uapi.dst.x1;
1505	int crtc_y = plane_state->uapi.dst.y1;
1506	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1507	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1508	u32 x = plane_state->color_plane[0].x;
1509	u32 y = plane_state->color_plane[0].y;
1510	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1511	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1512	u32 sprctl, sprscale = 0;
1513	unsigned long irqflags;
1514
1515	sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
1516
1517	/* Sizes are 0 based */
1518	src_w--;
1519	src_h--;
1520	crtc_w--;
1521	crtc_h--;
1522
1523	if (crtc_w != src_w || crtc_h != src_h)
1524		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
1525
1526	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1527
1528	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1529
1530	intel_de_write_fw(dev_priv, SPRSTRIDE(pipe),
1531			  plane_state->color_plane[0].stride);
1532	intel_de_write_fw(dev_priv, SPRPOS(pipe), (crtc_y << 16) | crtc_x);
1533	intel_de_write_fw(dev_priv, SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
1534	if (IS_IVYBRIDGE(dev_priv))
1535		intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale);
1536
1537	if (key->flags) {
1538		intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value);
1539		intel_de_write_fw(dev_priv, SPRKEYMSK(pipe),
1540				  key->channel_mask);
1541		intel_de_write_fw(dev_priv, SPRKEYMAX(pipe), key->max_value);
1542	}
1543
1544	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
1545	 * register */
1546	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1547		intel_de_write_fw(dev_priv, SPROFFSET(pipe), (y << 16) | x);
1548	} else {
1549		intel_de_write_fw(dev_priv, SPRLINOFF(pipe), linear_offset);
1550		intel_de_write_fw(dev_priv, SPRTILEOFF(pipe), (y << 16) | x);
1551	}
1552
1553	/*
1554	 * The control register self-arms if the plane was previously
1555	 * disabled. Try to make the plane enable atomic by writing
1556	 * the control register just before the surface register.
1557	 */
1558	intel_de_write_fw(dev_priv, SPRCTL(pipe), sprctl);
1559	intel_de_write_fw(dev_priv, SPRSURF(pipe),
1560			  intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1561
1562	ivb_update_gamma(plane_state);
1563
1564	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1565}
1566
1567static void
1568ivb_disable_plane(struct intel_plane *plane,
1569		  const struct intel_crtc_state *crtc_state)
1570{
1571	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1572	enum pipe pipe = plane->pipe;
1573	unsigned long irqflags;
1574
1575	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1576
1577	intel_de_write_fw(dev_priv, SPRCTL(pipe), 0);
1578	/* Disable the scaler */
1579	if (IS_IVYBRIDGE(dev_priv))
1580		intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0);
1581	intel_de_write_fw(dev_priv, SPRSURF(pipe), 0);
1582
1583	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1584}
1585
1586static bool
1587ivb_plane_get_hw_state(struct intel_plane *plane,
1588		       enum pipe *pipe)
1589{
1590	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1591	enum intel_display_power_domain power_domain;
1592	intel_wakeref_t wakeref;
1593	bool ret;
1594
1595	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1596	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1597	if (!wakeref)
1598		return false;
1599
1600	ret =  intel_de_read(dev_priv, SPRCTL(plane->pipe)) & SPRITE_ENABLE;
1601
1602	*pipe = plane->pipe;
1603
1604	intel_display_power_put(dev_priv, power_domain, wakeref);
1605
1606	return ret;
1607}
1608
1609static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
1610				const struct intel_plane_state *plane_state)
1611{
1612	const struct drm_framebuffer *fb = plane_state->hw.fb;
1613	unsigned int hscale, pixel_rate;
1614	unsigned int limit, decimate;
1615
1616	/*
1617	 * Note that crtc_state->pixel_rate accounts for both
1618	 * horizontal and vertical panel fitter downscaling factors.
1619	 * Pre-HSW bspec tells us to only consider the horizontal
1620	 * downscaling factor here. We ignore that and just consider
1621	 * both for simplicity.
1622	 */
1623	pixel_rate = crtc_state->pixel_rate;
1624
1625	/* Horizontal downscaling limits the maximum pixel rate */
1626	hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
1627				      &plane_state->uapi.dst,
1628				      0, INT_MAX);
1629	if (hscale < 0x10000)
1630		return pixel_rate;
1631
1632	/* Decimation steps at 2x,4x,8x,16x */
1633	decimate = ilog2(hscale >> 16);
1634	hscale >>= decimate;
1635
1636	/* Starting limit is 90% of cdclk */
1637	limit = 9;
1638
1639	/* -10% per decimation step */
1640	limit -= decimate;
1641
1642	/* -10% for RGB */
1643	if (fb->format->cpp[0] >= 4)
1644		limit--; /* -10% for RGB */
1645
1646	/*
1647	 * We should also do -10% if sprite scaling is enabled
1648	 * on the other pipe, but we can't really check for that,
1649	 * so we ignore it.
1650	 */
1651
1652	return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
1653				limit << 16);
1654}
1655
1656static unsigned int
1657g4x_sprite_max_stride(struct intel_plane *plane,
1658		      u32 pixel_format, u64 modifier,
1659		      unsigned int rotation)
1660{
1661	return 16384;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1662}
1663
1664static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1665{
1666	u32 dvscntr = 0;
1667
1668	if (crtc_state->gamma_enable)
1669		dvscntr |= DVS_GAMMA_ENABLE;
1670
1671	if (crtc_state->csc_enable)
1672		dvscntr |= DVS_PIPE_CSC_ENABLE;
1673
1674	return dvscntr;
1675}
1676
1677static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1678			  const struct intel_plane_state *plane_state)
1679{
1680	struct drm_i915_private *dev_priv =
1681		to_i915(plane_state->uapi.plane->dev);
1682	const struct drm_framebuffer *fb = plane_state->hw.fb;
1683	unsigned int rotation = plane_state->hw.rotation;
1684	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1685	u32 dvscntr;
1686
1687	dvscntr = DVS_ENABLE;
1688
1689	if (IS_GEN(dev_priv, 6))
1690		dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1691
1692	switch (fb->format->format) {
1693	case DRM_FORMAT_XBGR8888:
1694		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1695		break;
1696	case DRM_FORMAT_XRGB8888:
1697		dvscntr |= DVS_FORMAT_RGBX888;
1698		break;
1699	case DRM_FORMAT_XBGR2101010:
1700		dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
1701		break;
1702	case DRM_FORMAT_XRGB2101010:
1703		dvscntr |= DVS_FORMAT_RGBX101010;
1704		break;
1705	case DRM_FORMAT_XBGR16161616F:
1706		dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1707		break;
1708	case DRM_FORMAT_XRGB16161616F:
1709		dvscntr |= DVS_FORMAT_RGBX161616;
1710		break;
1711	case DRM_FORMAT_YUYV:
1712		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1713		break;
1714	case DRM_FORMAT_YVYU:
1715		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1716		break;
1717	case DRM_FORMAT_UYVY:
1718		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1719		break;
1720	case DRM_FORMAT_VYUY:
1721		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1722		break;
1723	default:
1724		MISSING_CASE(fb->format->format);
1725		return 0;
1726	}
1727
1728	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1729		dvscntr |= DVS_YUV_FORMAT_BT709;
1730
1731	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1732		dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1733
1734	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1735		dvscntr |= DVS_TILED;
1736
1737	if (rotation & DRM_MODE_ROTATE_180)
1738		dvscntr |= DVS_ROTATE_180;
1739
1740	if (key->flags & I915_SET_COLORKEY_DESTINATION)
1741		dvscntr |= DVS_DEST_KEY;
1742	else if (key->flags & I915_SET_COLORKEY_SOURCE)
1743		dvscntr |= DVS_SOURCE_KEY;
1744
1745	return dvscntr;
1746}
1747
1748static void g4x_update_gamma(const struct intel_plane_state *plane_state)
1749{
1750	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1751	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1752	const struct drm_framebuffer *fb = plane_state->hw.fb;
1753	enum pipe pipe = plane->pipe;
1754	u16 gamma[8];
1755	int i;
1756
1757	/* Seems RGB data bypasses the gamma always */
1758	if (!fb->format->is_yuv)
1759		return;
1760
1761	i9xx_plane_linear_gamma(gamma);
1762
1763	/* FIXME these register are single buffered :( */
1764	/* The two end points are implicit (0.0 and 1.0) */
1765	for (i = 1; i < 8 - 1; i++)
1766		intel_de_write_fw(dev_priv, DVSGAMC_G4X(pipe, i - 1),
1767				  gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
1768}
1769
1770static void ilk_sprite_linear_gamma(u16 gamma[17])
1771{
1772	int i;
1773
1774	for (i = 0; i < 17; i++)
1775		gamma[i] = (i << 10) / 16;
1776}
1777
1778static void ilk_update_gamma(const struct intel_plane_state *plane_state)
1779{
1780	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1781	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1782	const struct drm_framebuffer *fb = plane_state->hw.fb;
1783	enum pipe pipe = plane->pipe;
1784	u16 gamma[17];
1785	int i;
1786
1787	/* Seems RGB data bypasses the gamma always */
1788	if (!fb->format->is_yuv)
1789		return;
1790
1791	ilk_sprite_linear_gamma(gamma);
1792
1793	/* FIXME these register are single buffered :( */
1794	for (i = 0; i < 16; i++)
1795		intel_de_write_fw(dev_priv, DVSGAMC_ILK(pipe, i),
1796				  gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
1797
1798	intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1799	intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1800	intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1801	i++;
1802}
1803
1804static void
1805g4x_update_plane(struct intel_plane *plane,
1806		 const struct intel_crtc_state *crtc_state,
1807		 const struct intel_plane_state *plane_state)
1808{
1809	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1810	enum pipe pipe = plane->pipe;
1811	u32 dvssurf_offset = plane_state->color_plane[0].offset;
1812	u32 linear_offset;
1813	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1814	int crtc_x = plane_state->uapi.dst.x1;
1815	int crtc_y = plane_state->uapi.dst.y1;
1816	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1817	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1818	u32 x = plane_state->color_plane[0].x;
1819	u32 y = plane_state->color_plane[0].y;
1820	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1821	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1822	u32 dvscntr, dvsscale = 0;
1823	unsigned long irqflags;
1824
1825	dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1826
1827	/* Sizes are 0 based */
1828	src_w--;
1829	src_h--;
1830	crtc_w--;
1831	crtc_h--;
1832
1833	if (crtc_w != src_w || crtc_h != src_h)
1834		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
1835
1836	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1837
1838	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1839
1840	intel_de_write_fw(dev_priv, DVSSTRIDE(pipe),
1841			  plane_state->color_plane[0].stride);
1842	intel_de_write_fw(dev_priv, DVSPOS(pipe), (crtc_y << 16) | crtc_x);
1843	intel_de_write_fw(dev_priv, DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
1844	intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale);
1845
1846	if (key->flags) {
1847		intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value);
1848		intel_de_write_fw(dev_priv, DVSKEYMSK(pipe),
1849				  key->channel_mask);
1850		intel_de_write_fw(dev_priv, DVSKEYMAX(pipe), key->max_value);
1851	}
1852
1853	intel_de_write_fw(dev_priv, DVSLINOFF(pipe), linear_offset);
1854	intel_de_write_fw(dev_priv, DVSTILEOFF(pipe), (y << 16) | x);
1855
1856	/*
1857	 * The control register self-arms if the plane was previously
1858	 * disabled. Try to make the plane enable atomic by writing
1859	 * the control register just before the surface register.
1860	 */
1861	intel_de_write_fw(dev_priv, DVSCNTR(pipe), dvscntr);
1862	intel_de_write_fw(dev_priv, DVSSURF(pipe),
1863			  intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1864
1865	if (IS_G4X(dev_priv))
1866		g4x_update_gamma(plane_state);
1867	else
1868		ilk_update_gamma(plane_state);
1869
1870	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1871}
1872
1873static void
1874g4x_disable_plane(struct intel_plane *plane,
1875		  const struct intel_crtc_state *crtc_state)
1876{
1877	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1878	enum pipe pipe = plane->pipe;
1879	unsigned long irqflags;
1880
1881	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1882
1883	intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0);
1884	/* Disable the scaler */
1885	intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0);
1886	intel_de_write_fw(dev_priv, DVSSURF(pipe), 0);
1887
1888	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1889}
1890
1891static bool
1892g4x_plane_get_hw_state(struct intel_plane *plane,
1893		       enum pipe *pipe)
1894{
1895	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1896	enum intel_display_power_domain power_domain;
1897	intel_wakeref_t wakeref;
1898	bool ret;
1899
1900	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1901	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1902	if (!wakeref)
1903		return false;
1904
1905	ret = intel_de_read(dev_priv, DVSCNTR(plane->pipe)) & DVS_ENABLE;
1906
1907	*pipe = plane->pipe;
1908
1909	intel_display_power_put(dev_priv, power_domain, wakeref);
1910
1911	return ret;
1912}
1913
1914static bool intel_fb_scalable(const struct drm_framebuffer *fb)
1915{
1916	if (!fb)
1917		return false;
1918
1919	switch (fb->format->format) {
1920	case DRM_FORMAT_C8:
1921		return false;
1922	case DRM_FORMAT_XRGB16161616F:
1923	case DRM_FORMAT_ARGB16161616F:
1924	case DRM_FORMAT_XBGR16161616F:
1925	case DRM_FORMAT_ABGR16161616F:
1926		return INTEL_GEN(to_i915(fb->dev)) >= 11;
1927	default:
1928		return true;
1929	}
1930}
1931
1932static int
1933g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1934			 struct intel_plane_state *plane_state)
1935{
1936	const struct drm_framebuffer *fb = plane_state->hw.fb;
1937	const struct drm_rect *src = &plane_state->uapi.src;
1938	const struct drm_rect *dst = &plane_state->uapi.dst;
1939	int src_x, src_w, src_h, crtc_w, crtc_h;
1940	const struct drm_display_mode *adjusted_mode =
1941		&crtc_state->hw.adjusted_mode;
1942	unsigned int stride = plane_state->color_plane[0].stride;
1943	unsigned int cpp = fb->format->cpp[0];
1944	unsigned int width_bytes;
1945	int min_width, min_height;
1946
1947	crtc_w = drm_rect_width(dst);
1948	crtc_h = drm_rect_height(dst);
1949
1950	src_x = src->x1 >> 16;
1951	src_w = drm_rect_width(src) >> 16;
1952	src_h = drm_rect_height(src) >> 16;
1953
1954	if (src_w == crtc_w && src_h == crtc_h)
1955		return 0;
1956
1957	min_width = 3;
1958
1959	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1960		if (src_h & 1) {
1961			DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
1962			return -EINVAL;
1963		}
1964		min_height = 6;
1965	} else {
1966		min_height = 3;
1967	}
1968
1969	width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1970
1971	if (src_w < min_width || src_h < min_height ||
1972	    src_w > 2048 || src_h > 2048) {
1973		DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1974			      src_w, src_h, min_width, min_height, 2048, 2048);
1975		return -EINVAL;
1976	}
1977
1978	if (width_bytes > 4096) {
1979		DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1980			      width_bytes, 4096);
1981		return -EINVAL;
1982	}
1983
1984	if (stride > 4096) {
1985		DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
1986			      stride, 4096);
1987		return -EINVAL;
1988	}
1989
1990	return 0;
1991}
1992
1993static int
1994g4x_sprite_check(struct intel_crtc_state *crtc_state,
1995		 struct intel_plane_state *plane_state)
1996{
1997	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1998	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1999	int min_scale = DRM_PLANE_HELPER_NO_SCALING;
2000	int max_scale = DRM_PLANE_HELPER_NO_SCALING;
2001	int ret;
2002
2003	if (intel_fb_scalable(plane_state->hw.fb)) {
2004		if (INTEL_GEN(dev_priv) < 7) {
2005			min_scale = 1;
2006			max_scale = 16 << 16;
2007		} else if (IS_IVYBRIDGE(dev_priv)) {
2008			min_scale = 1;
2009			max_scale = 2 << 16;
2010		}
2011	}
2012
2013	ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
2014						  &crtc_state->uapi,
2015						  min_scale, max_scale,
2016						  true, true);
2017	if (ret)
2018		return ret;
2019
2020	ret = i9xx_check_plane_surface(plane_state);
2021	if (ret)
2022		return ret;
2023
2024	if (!plane_state->uapi.visible)
2025		return 0;
2026
2027	ret = intel_plane_check_src_coordinates(plane_state);
2028	if (ret)
2029		return ret;
2030
2031	ret = g4x_sprite_check_scaling(crtc_state, plane_state);
2032	if (ret)
2033		return ret;
2034
2035	if (INTEL_GEN(dev_priv) >= 7)
2036		plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
2037	else
2038		plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
2039
2040	return 0;
2041}
2042
2043int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
2044{
2045	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2046	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2047	unsigned int rotation = plane_state->hw.rotation;
2048
2049	/* CHV ignores the mirror bit when the rotate bit is set :( */
2050	if (IS_CHERRYVIEW(dev_priv) &&
2051	    rotation & DRM_MODE_ROTATE_180 &&
2052	    rotation & DRM_MODE_REFLECT_X) {
2053		drm_dbg_kms(&dev_priv->drm,
2054			    "Cannot rotate and reflect at the same time\n");
2055		return -EINVAL;
2056	}
2057
2058	return 0;
2059}
2060
2061static int
2062vlv_sprite_check(struct intel_crtc_state *crtc_state,
2063		 struct intel_plane_state *plane_state)
2064{
2065	int ret;
2066
2067	ret = chv_plane_check_rotation(plane_state);
2068	if (ret)
2069		return ret;
2070
2071	ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
2072						  &crtc_state->uapi,
2073						  DRM_PLANE_HELPER_NO_SCALING,
2074						  DRM_PLANE_HELPER_NO_SCALING,
2075						  true, true);
2076	if (ret)
2077		return ret;
2078
2079	ret = i9xx_check_plane_surface(plane_state);
2080	if (ret)
2081		return ret;
2082
2083	if (!plane_state->uapi.visible)
2084		return 0;
2085
2086	ret = intel_plane_check_src_coordinates(plane_state);
2087	if (ret)
2088		return ret;
2089
2090	plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
2091
2092	return 0;
2093}
2094
2095static bool intel_format_is_p01x(u32 format)
2096{
2097	switch (format) {
2098	case DRM_FORMAT_P010:
2099	case DRM_FORMAT_P012:
2100	case DRM_FORMAT_P016:
2101		return true;
2102	default:
2103		return false;
2104	}
2105}
2106
2107static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
2108			      const struct intel_plane_state *plane_state)
2109{
2110	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2111	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2112	const struct drm_framebuffer *fb = plane_state->hw.fb;
2113	unsigned int rotation = plane_state->hw.rotation;
2114	struct drm_format_name_buf format_name;
2115
2116	if (!fb)
2117		return 0;
2118
2119	if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
2120	    is_ccs_modifier(fb->modifier)) {
2121		drm_dbg_kms(&dev_priv->drm,
2122			    "RC support only with 0/180 degree rotation (%x)\n",
2123			    rotation);
2124		return -EINVAL;
2125	}
2126
2127	if (rotation & DRM_MODE_REFLECT_X &&
2128	    fb->modifier == DRM_FORMAT_MOD_LINEAR) {
2129		drm_dbg_kms(&dev_priv->drm,
2130			    "horizontal flip is not supported with linear surface formats\n");
2131		return -EINVAL;
2132	}
2133
2134	if (drm_rotation_90_or_270(rotation)) {
2135		if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
2136		    fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
2137			drm_dbg_kms(&dev_priv->drm,
2138				    "Y/Yf tiling required for 90/270!\n");
2139			return -EINVAL;
2140		}
2141
2142		/*
2143		 * 90/270 is not allowed with RGB64 16:16:16:16 and
2144		 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
2145		 */
2146		switch (fb->format->format) {
2147		case DRM_FORMAT_RGB565:
2148			if (INTEL_GEN(dev_priv) >= 11)
2149				break;
2150			fallthrough;
2151		case DRM_FORMAT_C8:
2152		case DRM_FORMAT_XRGB16161616F:
2153		case DRM_FORMAT_XBGR16161616F:
2154		case DRM_FORMAT_ARGB16161616F:
2155		case DRM_FORMAT_ABGR16161616F:
2156		case DRM_FORMAT_Y210:
2157		case DRM_FORMAT_Y212:
2158		case DRM_FORMAT_Y216:
2159		case DRM_FORMAT_XVYU12_16161616:
2160		case DRM_FORMAT_XVYU16161616:
2161			drm_dbg_kms(&dev_priv->drm,
2162				    "Unsupported pixel format %s for 90/270!\n",
2163				    drm_get_format_name(fb->format->format,
2164							&format_name));
2165			return -EINVAL;
2166		default:
2167			break;
2168		}
2169	}
2170
2171	/* Y-tiling is not supported in IF-ID Interlace mode */
2172	if (crtc_state->hw.enable &&
2173	    crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
2174	    (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
2175	     fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
2176	     fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
2177	     fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
2178	     fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
2179	     fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)) {
2180		drm_dbg_kms(&dev_priv->drm,
2181			    "Y/Yf tiling not supported in IF-ID mode\n");
2182		return -EINVAL;
2183	}
2184
2185	/* Wa_1606054188:tgl */
2186	if (IS_TIGERLAKE(dev_priv) &&
2187	    plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
2188	    intel_format_is_p01x(fb->format->format)) {
2189		drm_dbg_kms(&dev_priv->drm,
2190			    "Source color keying not supported with P01x formats\n");
2191		return -EINVAL;
2192	}
2193
2194	return 0;
2195}
2196
2197static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
2198					   const struct intel_plane_state *plane_state)
2199{
2200	struct drm_i915_private *dev_priv =
2201		to_i915(plane_state->uapi.plane->dev);
2202	int crtc_x = plane_state->uapi.dst.x1;
2203	int crtc_w = drm_rect_width(&plane_state->uapi.dst);
2204	int pipe_src_w = crtc_state->pipe_src_w;
2205
2206	/*
2207	 * Display WA #1175: cnl,glk
2208	 * Planes other than the cursor may cause FIFO underflow and display
2209	 * corruption if starting less than 4 pixels from the right edge of
2210	 * the screen.
2211	 * Besides the above WA fix the similar problem, where planes other
2212	 * than the cursor ending less than 4 pixels from the left edge of the
2213	 * screen may cause FIFO underflow and display corruption.
2214	 */
2215	if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
2216	    (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
2217		drm_dbg_kms(&dev_priv->drm,
2218			    "requested plane X %s position %d invalid (valid range %d-%d)\n",
2219			    crtc_x + crtc_w < 4 ? "end" : "start",
2220			    crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
2221			    4, pipe_src_w - 4);
2222		return -ERANGE;
2223	}
2224
2225	return 0;
2226}
2227
2228static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
2229{
2230	const struct drm_framebuffer *fb = plane_state->hw.fb;
2231	unsigned int rotation = plane_state->hw.rotation;
2232	int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
2233
2234	/* Display WA #1106 */
2235	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
2236	    src_w & 3 &&
2237	    (rotation == DRM_MODE_ROTATE_270 ||
2238	     rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
2239		DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
2240		return -EINVAL;
2241	}
2242
2243	return 0;
2244}
2245
2246static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
2247			       const struct drm_framebuffer *fb)
2248{
2249	/*
2250	 * We don't yet know the final source width nor
2251	 * whether we can use the HQ scaler mode. Assume
2252	 * the best case.
2253	 * FIXME need to properly check this later.
2254	 */
2255	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
2256	    !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
2257		return 0x30000 - 1;
2258	else
2259		return 0x20000 - 1;
2260}
2261
2262static int skl_plane_check(struct intel_crtc_state *crtc_state,
2263			   struct intel_plane_state *plane_state)
2264{
2265	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2266	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2267	const struct drm_framebuffer *fb = plane_state->hw.fb;
2268	int min_scale = DRM_PLANE_HELPER_NO_SCALING;
2269	int max_scale = DRM_PLANE_HELPER_NO_SCALING;
2270	int ret;
2271
2272	ret = skl_plane_check_fb(crtc_state, plane_state);
2273	if (ret)
2274		return ret;
2275
2276	/* use scaler when colorkey is not required */
2277	if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
2278		min_scale = 1;
2279		max_scale = skl_plane_max_scale(dev_priv, fb);
2280	}
2281
2282	ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
2283						  &crtc_state->uapi,
2284						  min_scale, max_scale,
2285						  true, true);
2286	if (ret)
2287		return ret;
2288
2289	ret = skl_check_plane_surface(plane_state);
2290	if (ret)
2291		return ret;
2292
2293	if (!plane_state->uapi.visible)
2294		return 0;
2295
2296	ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
2297	if (ret)
2298		return ret;
2299
2300	ret = intel_plane_check_src_coordinates(plane_state);
2301	if (ret)
2302		return ret;
2303
2304	ret = skl_plane_check_nv12_rotation(plane_state);
2305	if (ret)
2306		return ret;
2307
2308	/* HW only has 8 bits pixel precision, disable plane if invisible */
2309	if (!(plane_state->hw.alpha >> 8))
2310		plane_state->uapi.visible = false;
2311
2312	plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
2313
2314	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
2315		plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
2316							     plane_state);
2317
2318	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
2319	    icl_is_hdr_plane(dev_priv, plane->id))
2320		/* Enable and use MPEG-2 chroma siting */
2321		plane_state->cus_ctl = PLANE_CUS_ENABLE |
2322			PLANE_CUS_HPHASE_0 |
2323			PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
2324	else
2325		plane_state->cus_ctl = 0;
2326
2327	return 0;
2328}
2329
2330static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
2331{
2332	return INTEL_GEN(dev_priv) >= 9;
2333}
2334
2335static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
2336				 const struct drm_intel_sprite_colorkey *set)
2337{
2338	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2339	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2340	struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
2341
2342	*key = *set;
2343
2344	/*
2345	 * We want src key enabled on the
2346	 * sprite and not on the primary.
2347	 */
2348	if (plane->id == PLANE_PRIMARY &&
2349	    set->flags & I915_SET_COLORKEY_SOURCE)
2350		key->flags = 0;
2351
2352	/*
2353	 * On SKL+ we want dst key enabled on
2354	 * the primary and not on the sprite.
2355	 */
2356	if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
2357	    set->flags & I915_SET_COLORKEY_DESTINATION)
2358		key->flags = 0;
2359}
2360
2361int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
2362				    struct drm_file *file_priv)
2363{
2364	struct drm_i915_private *dev_priv = to_i915(dev);
2365	struct drm_intel_sprite_colorkey *set = data;
2366	struct drm_plane *plane;
2367	struct drm_plane_state *plane_state;
2368	struct drm_atomic_state *state;
2369	struct drm_modeset_acquire_ctx ctx;
2370	int ret = 0;
2371
2372	/* ignore the pointless "none" flag */
2373	set->flags &= ~I915_SET_COLORKEY_NONE;
2374
2375	if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
2376		return -EINVAL;
2377
2378	/* Make sure we don't try to enable both src & dest simultaneously */
2379	if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
2380		return -EINVAL;
2381
2382	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
2383	    set->flags & I915_SET_COLORKEY_DESTINATION)
2384		return -EINVAL;
2385
2386	plane = drm_plane_find(dev, file_priv, set->plane_id);
2387	if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
2388		return -ENOENT;
2389
2390	/*
2391	 * SKL+ only plane 2 can do destination keying against plane 1.
2392	 * Also multiple planes can't do destination keying on the same
2393	 * pipe simultaneously.
2394	 */
2395	if (INTEL_GEN(dev_priv) >= 9 &&
2396	    to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
2397	    set->flags & I915_SET_COLORKEY_DESTINATION)
2398		return -EINVAL;
2399
2400	drm_modeset_acquire_init(&ctx, 0);
2401
2402	state = drm_atomic_state_alloc(plane->dev);
2403	if (!state) {
2404		ret = -ENOMEM;
2405		goto out;
2406	}
2407	state->acquire_ctx = &ctx;
2408
2409	while (1) {
2410		plane_state = drm_atomic_get_plane_state(state, plane);
2411		ret = PTR_ERR_OR_ZERO(plane_state);
2412		if (!ret)
2413			intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
2414
2415		/*
2416		 * On some platforms we have to configure
2417		 * the dst colorkey on the primary plane.
2418		 */
2419		if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
2420			struct intel_crtc *crtc =
2421				intel_get_crtc_for_pipe(dev_priv,
2422							to_intel_plane(plane)->pipe);
2423
2424			plane_state = drm_atomic_get_plane_state(state,
2425								 crtc->base.primary);
2426			ret = PTR_ERR_OR_ZERO(plane_state);
2427			if (!ret)
2428				intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
2429		}
2430
2431		if (!ret)
2432			ret = drm_atomic_commit(state);
2433
2434		if (ret != -EDEADLK)
2435			break;
2436
2437		drm_atomic_state_clear(state);
2438		drm_modeset_backoff(&ctx);
2439	}
2440
2441	drm_atomic_state_put(state);
2442out:
2443	drm_modeset_drop_locks(&ctx);
2444	drm_modeset_acquire_fini(&ctx);
2445	return ret;
2446}
2447
2448static const u32 g4x_plane_formats[] = {
2449	DRM_FORMAT_XRGB8888,
2450	DRM_FORMAT_YUYV,
2451	DRM_FORMAT_YVYU,
2452	DRM_FORMAT_UYVY,
2453	DRM_FORMAT_VYUY,
2454};
2455
2456static const u64 i9xx_plane_format_modifiers[] = {
2457	I915_FORMAT_MOD_X_TILED,
2458	DRM_FORMAT_MOD_LINEAR,
2459	DRM_FORMAT_MOD_INVALID
2460};
2461
2462static const u32 snb_plane_formats[] = {
2463	DRM_FORMAT_XRGB8888,
2464	DRM_FORMAT_XBGR8888,
2465	DRM_FORMAT_XRGB2101010,
2466	DRM_FORMAT_XBGR2101010,
2467	DRM_FORMAT_XRGB16161616F,
2468	DRM_FORMAT_XBGR16161616F,
2469	DRM_FORMAT_YUYV,
2470	DRM_FORMAT_YVYU,
2471	DRM_FORMAT_UYVY,
2472	DRM_FORMAT_VYUY,
2473};
2474
2475static const u32 vlv_plane_formats[] = {
2476	DRM_FORMAT_C8,
2477	DRM_FORMAT_RGB565,
2478	DRM_FORMAT_XRGB8888,
2479	DRM_FORMAT_XBGR8888,
2480	DRM_FORMAT_ARGB8888,
2481	DRM_FORMAT_ABGR8888,
2482	DRM_FORMAT_XBGR2101010,
2483	DRM_FORMAT_ABGR2101010,
2484	DRM_FORMAT_YUYV,
2485	DRM_FORMAT_YVYU,
2486	DRM_FORMAT_UYVY,
2487	DRM_FORMAT_VYUY,
2488};
2489
2490static const u32 chv_pipe_b_sprite_formats[] = {
2491	DRM_FORMAT_C8,
2492	DRM_FORMAT_RGB565,
2493	DRM_FORMAT_XRGB8888,
2494	DRM_FORMAT_XBGR8888,
2495	DRM_FORMAT_ARGB8888,
2496	DRM_FORMAT_ABGR8888,
2497	DRM_FORMAT_XRGB2101010,
2498	DRM_FORMAT_XBGR2101010,
2499	DRM_FORMAT_ARGB2101010,
2500	DRM_FORMAT_ABGR2101010,
2501	DRM_FORMAT_YUYV,
2502	DRM_FORMAT_YVYU,
2503	DRM_FORMAT_UYVY,
2504	DRM_FORMAT_VYUY,
2505};
2506
2507static const u32 skl_plane_formats[] = {
2508	DRM_FORMAT_C8,
2509	DRM_FORMAT_RGB565,
2510	DRM_FORMAT_XRGB8888,
2511	DRM_FORMAT_XBGR8888,
2512	DRM_FORMAT_ARGB8888,
2513	DRM_FORMAT_ABGR8888,
2514	DRM_FORMAT_XRGB2101010,
2515	DRM_FORMAT_XBGR2101010,
2516	DRM_FORMAT_XRGB16161616F,
2517	DRM_FORMAT_XBGR16161616F,
2518	DRM_FORMAT_YUYV,
2519	DRM_FORMAT_YVYU,
2520	DRM_FORMAT_UYVY,
2521	DRM_FORMAT_VYUY,
2522	DRM_FORMAT_XYUV8888,
2523};
2524
2525static const u32 skl_planar_formats[] = {
2526	DRM_FORMAT_C8,
2527	DRM_FORMAT_RGB565,
2528	DRM_FORMAT_XRGB8888,
2529	DRM_FORMAT_XBGR8888,
2530	DRM_FORMAT_ARGB8888,
2531	DRM_FORMAT_ABGR8888,
2532	DRM_FORMAT_XRGB2101010,
2533	DRM_FORMAT_XBGR2101010,
2534	DRM_FORMAT_XRGB16161616F,
2535	DRM_FORMAT_XBGR16161616F,
2536	DRM_FORMAT_YUYV,
2537	DRM_FORMAT_YVYU,
2538	DRM_FORMAT_UYVY,
2539	DRM_FORMAT_VYUY,
2540	DRM_FORMAT_NV12,
2541	DRM_FORMAT_XYUV8888,
2542};
2543
2544static const u32 glk_planar_formats[] = {
2545	DRM_FORMAT_C8,
2546	DRM_FORMAT_RGB565,
2547	DRM_FORMAT_XRGB8888,
2548	DRM_FORMAT_XBGR8888,
2549	DRM_FORMAT_ARGB8888,
2550	DRM_FORMAT_ABGR8888,
2551	DRM_FORMAT_XRGB2101010,
2552	DRM_FORMAT_XBGR2101010,
2553	DRM_FORMAT_XRGB16161616F,
2554	DRM_FORMAT_XBGR16161616F,
2555	DRM_FORMAT_YUYV,
2556	DRM_FORMAT_YVYU,
2557	DRM_FORMAT_UYVY,
2558	DRM_FORMAT_VYUY,
2559	DRM_FORMAT_NV12,
2560	DRM_FORMAT_XYUV8888,
2561	DRM_FORMAT_P010,
2562	DRM_FORMAT_P012,
2563	DRM_FORMAT_P016,
2564};
2565
2566static const u32 icl_sdr_y_plane_formats[] = {
2567	DRM_FORMAT_C8,
2568	DRM_FORMAT_RGB565,
2569	DRM_FORMAT_XRGB8888,
2570	DRM_FORMAT_XBGR8888,
2571	DRM_FORMAT_ARGB8888,
2572	DRM_FORMAT_ABGR8888,
2573	DRM_FORMAT_XRGB2101010,
2574	DRM_FORMAT_XBGR2101010,
2575	DRM_FORMAT_ARGB2101010,
2576	DRM_FORMAT_ABGR2101010,
2577	DRM_FORMAT_YUYV,
2578	DRM_FORMAT_YVYU,
2579	DRM_FORMAT_UYVY,
2580	DRM_FORMAT_VYUY,
2581	DRM_FORMAT_Y210,
2582	DRM_FORMAT_Y212,
2583	DRM_FORMAT_Y216,
2584	DRM_FORMAT_XYUV8888,
2585	DRM_FORMAT_XVYU2101010,
2586	DRM_FORMAT_XVYU12_16161616,
2587	DRM_FORMAT_XVYU16161616,
2588};
2589
2590static const u32 icl_sdr_uv_plane_formats[] = {
2591	DRM_FORMAT_C8,
2592	DRM_FORMAT_RGB565,
2593	DRM_FORMAT_XRGB8888,
2594	DRM_FORMAT_XBGR8888,
2595	DRM_FORMAT_ARGB8888,
2596	DRM_FORMAT_ABGR8888,
2597	DRM_FORMAT_XRGB2101010,
2598	DRM_FORMAT_XBGR2101010,
2599	DRM_FORMAT_ARGB2101010,
2600	DRM_FORMAT_ABGR2101010,
2601	DRM_FORMAT_YUYV,
2602	DRM_FORMAT_YVYU,
2603	DRM_FORMAT_UYVY,
2604	DRM_FORMAT_VYUY,
2605	DRM_FORMAT_NV12,
2606	DRM_FORMAT_P010,
2607	DRM_FORMAT_P012,
2608	DRM_FORMAT_P016,
2609	DRM_FORMAT_Y210,
2610	DRM_FORMAT_Y212,
2611	DRM_FORMAT_Y216,
2612	DRM_FORMAT_XYUV8888,
2613	DRM_FORMAT_XVYU2101010,
2614	DRM_FORMAT_XVYU12_16161616,
2615	DRM_FORMAT_XVYU16161616,
2616};
2617
2618static const u32 icl_hdr_plane_formats[] = {
2619	DRM_FORMAT_C8,
2620	DRM_FORMAT_RGB565,
2621	DRM_FORMAT_XRGB8888,
2622	DRM_FORMAT_XBGR8888,
2623	DRM_FORMAT_ARGB8888,
2624	DRM_FORMAT_ABGR8888,
2625	DRM_FORMAT_XRGB2101010,
2626	DRM_FORMAT_XBGR2101010,
2627	DRM_FORMAT_ARGB2101010,
2628	DRM_FORMAT_ABGR2101010,
2629	DRM_FORMAT_XRGB16161616F,
2630	DRM_FORMAT_XBGR16161616F,
2631	DRM_FORMAT_ARGB16161616F,
2632	DRM_FORMAT_ABGR16161616F,
2633	DRM_FORMAT_YUYV,
2634	DRM_FORMAT_YVYU,
2635	DRM_FORMAT_UYVY,
2636	DRM_FORMAT_VYUY,
2637	DRM_FORMAT_NV12,
2638	DRM_FORMAT_P010,
2639	DRM_FORMAT_P012,
2640	DRM_FORMAT_P016,
2641	DRM_FORMAT_Y210,
2642	DRM_FORMAT_Y212,
2643	DRM_FORMAT_Y216,
2644	DRM_FORMAT_XYUV8888,
2645	DRM_FORMAT_XVYU2101010,
2646	DRM_FORMAT_XVYU12_16161616,
2647	DRM_FORMAT_XVYU16161616,
2648};
2649
2650static const u64 skl_plane_format_modifiers_noccs[] = {
2651	I915_FORMAT_MOD_Yf_TILED,
2652	I915_FORMAT_MOD_Y_TILED,
2653	I915_FORMAT_MOD_X_TILED,
2654	DRM_FORMAT_MOD_LINEAR,
2655	DRM_FORMAT_MOD_INVALID
2656};
2657
2658static const u64 skl_plane_format_modifiers_ccs[] = {
2659	I915_FORMAT_MOD_Yf_TILED_CCS,
2660	I915_FORMAT_MOD_Y_TILED_CCS,
2661	I915_FORMAT_MOD_Yf_TILED,
2662	I915_FORMAT_MOD_Y_TILED,
2663	I915_FORMAT_MOD_X_TILED,
2664	DRM_FORMAT_MOD_LINEAR,
2665	DRM_FORMAT_MOD_INVALID
2666};
2667
2668static const u64 gen12_plane_format_modifiers_mc_ccs[] = {
2669	I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
2670	I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
2671	I915_FORMAT_MOD_Y_TILED,
2672	I915_FORMAT_MOD_X_TILED,
2673	DRM_FORMAT_MOD_LINEAR,
2674	DRM_FORMAT_MOD_INVALID
2675};
2676
2677static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
2678	I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
2679	I915_FORMAT_MOD_Y_TILED,
2680	I915_FORMAT_MOD_X_TILED,
2681	DRM_FORMAT_MOD_LINEAR,
2682	DRM_FORMAT_MOD_INVALID
2683};
2684
2685static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
2686					    u32 format, u64 modifier)
2687{
2688	switch (modifier) {
2689	case DRM_FORMAT_MOD_LINEAR:
2690	case I915_FORMAT_MOD_X_TILED:
2691		break;
2692	default:
2693		return false;
2694	}
2695
2696	switch (format) {
2697	case DRM_FORMAT_XRGB8888:
2698	case DRM_FORMAT_YUYV:
2699	case DRM_FORMAT_YVYU:
2700	case DRM_FORMAT_UYVY:
2701	case DRM_FORMAT_VYUY:
2702		if (modifier == DRM_FORMAT_MOD_LINEAR ||
2703		    modifier == I915_FORMAT_MOD_X_TILED)
2704			return true;
2705		fallthrough;
2706	default:
2707		return false;
2708	}
2709}
2710
2711static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
2712					    u32 format, u64 modifier)
2713{
2714	switch (modifier) {
2715	case DRM_FORMAT_MOD_LINEAR:
2716	case I915_FORMAT_MOD_X_TILED:
2717		break;
2718	default:
2719		return false;
2720	}
2721
2722	switch (format) {
2723	case DRM_FORMAT_XRGB8888:
2724	case DRM_FORMAT_XBGR8888:
2725	case DRM_FORMAT_XRGB2101010:
2726	case DRM_FORMAT_XBGR2101010:
2727	case DRM_FORMAT_XRGB16161616F:
2728	case DRM_FORMAT_XBGR16161616F:
2729	case DRM_FORMAT_YUYV:
2730	case DRM_FORMAT_YVYU:
2731	case DRM_FORMAT_UYVY:
2732	case DRM_FORMAT_VYUY:
2733		if (modifier == DRM_FORMAT_MOD_LINEAR ||
2734		    modifier == I915_FORMAT_MOD_X_TILED)
2735			return true;
2736		fallthrough;
2737	default:
2738		return false;
2739	}
2740}
2741
2742static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
2743					    u32 format, u64 modifier)
2744{
2745	switch (modifier) {
2746	case DRM_FORMAT_MOD_LINEAR:
2747	case I915_FORMAT_MOD_X_TILED:
2748		break;
2749	default:
2750		return false;
2751	}
2752
2753	switch (format) {
2754	case DRM_FORMAT_C8:
2755	case DRM_FORMAT_RGB565:
2756	case DRM_FORMAT_ABGR8888:
2757	case DRM_FORMAT_ARGB8888:
2758	case DRM_FORMAT_XBGR8888:
2759	case DRM_FORMAT_XRGB8888:
2760	case DRM_FORMAT_XBGR2101010:
2761	case DRM_FORMAT_ABGR2101010:
2762	case DRM_FORMAT_XRGB2101010:
2763	case DRM_FORMAT_ARGB2101010:
2764	case DRM_FORMAT_YUYV:
2765	case DRM_FORMAT_YVYU:
2766	case DRM_FORMAT_UYVY:
2767	case DRM_FORMAT_VYUY:
2768		if (modifier == DRM_FORMAT_MOD_LINEAR ||
2769		    modifier == I915_FORMAT_MOD_X_TILED)
2770			return true;
2771		fallthrough;
2772	default:
2773		return false;
2774	}
2775}
2776
2777static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2778					   u32 format, u64 modifier)
2779{
2780	struct intel_plane *plane = to_intel_plane(_plane);
2781
2782	switch (modifier) {
2783	case DRM_FORMAT_MOD_LINEAR:
2784	case I915_FORMAT_MOD_X_TILED:
2785	case I915_FORMAT_MOD_Y_TILED:
2786	case I915_FORMAT_MOD_Yf_TILED:
2787		break;
2788	case I915_FORMAT_MOD_Y_TILED_CCS:
2789	case I915_FORMAT_MOD_Yf_TILED_CCS:
2790		if (!plane->has_ccs)
2791			return false;
2792		break;
2793	default:
2794		return false;
2795	}
2796
2797	switch (format) {
2798	case DRM_FORMAT_XRGB8888:
2799	case DRM_FORMAT_XBGR8888:
2800	case DRM_FORMAT_ARGB8888:
2801	case DRM_FORMAT_ABGR8888:
2802		if (is_ccs_modifier(modifier))
2803			return true;
2804		fallthrough;
2805	case DRM_FORMAT_RGB565:
2806	case DRM_FORMAT_XRGB2101010:
2807	case DRM_FORMAT_XBGR2101010:
2808	case DRM_FORMAT_ARGB2101010:
2809	case DRM_FORMAT_ABGR2101010:
2810	case DRM_FORMAT_YUYV:
2811	case DRM_FORMAT_YVYU:
2812	case DRM_FORMAT_UYVY:
2813	case DRM_FORMAT_VYUY:
2814	case DRM_FORMAT_NV12:
2815	case DRM_FORMAT_XYUV8888:
2816	case DRM_FORMAT_P010:
2817	case DRM_FORMAT_P012:
2818	case DRM_FORMAT_P016:
2819	case DRM_FORMAT_XVYU2101010:
2820		if (modifier == I915_FORMAT_MOD_Yf_TILED)
2821			return true;
2822		fallthrough;
2823	case DRM_FORMAT_C8:
2824	case DRM_FORMAT_XBGR16161616F:
2825	case DRM_FORMAT_ABGR16161616F:
2826	case DRM_FORMAT_XRGB16161616F:
2827	case DRM_FORMAT_ARGB16161616F:
2828	case DRM_FORMAT_Y210:
2829	case DRM_FORMAT_Y212:
2830	case DRM_FORMAT_Y216:
2831	case DRM_FORMAT_XVYU12_16161616:
2832	case DRM_FORMAT_XVYU16161616:
2833		if (modifier == DRM_FORMAT_MOD_LINEAR ||
2834		    modifier == I915_FORMAT_MOD_X_TILED ||
2835		    modifier == I915_FORMAT_MOD_Y_TILED)
2836			return true;
2837		fallthrough;
2838	default:
2839		return false;
2840	}
2841}
2842
2843static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
2844					enum plane_id plane_id)
2845{
2846	/* Wa_14010477008:tgl[a0..c0] */
2847	if (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_C0))
2848		return false;
2849
2850	return plane_id < PLANE_SPRITE4;
2851}
2852
2853static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
2854					     u32 format, u64 modifier)
2855{
2856	struct drm_i915_private *dev_priv = to_i915(_plane->dev);
2857	struct intel_plane *plane = to_intel_plane(_plane);
2858
2859	switch (modifier) {
2860	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
2861		if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
2862			return false;
2863		fallthrough;
2864	case DRM_FORMAT_MOD_LINEAR:
2865	case I915_FORMAT_MOD_X_TILED:
2866	case I915_FORMAT_MOD_Y_TILED:
2867	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
2868		break;
2869	default:
2870		return false;
2871	}
2872
2873	switch (format) {
2874	case DRM_FORMAT_XRGB8888:
2875	case DRM_FORMAT_XBGR8888:
2876	case DRM_FORMAT_ARGB8888:
2877	case DRM_FORMAT_ABGR8888:
2878		if (is_ccs_modifier(modifier))
2879			return true;
2880		fallthrough;
2881	case DRM_FORMAT_YUYV:
2882	case DRM_FORMAT_YVYU:
2883	case DRM_FORMAT_UYVY:
2884	case DRM_FORMAT_VYUY:
2885	case DRM_FORMAT_NV12:
2886	case DRM_FORMAT_XYUV8888:
2887	case DRM_FORMAT_P010:
2888	case DRM_FORMAT_P012:
2889	case DRM_FORMAT_P016:
2890		if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
2891			return true;
2892		fallthrough;
2893	case DRM_FORMAT_RGB565:
2894	case DRM_FORMAT_XRGB2101010:
2895	case DRM_FORMAT_XBGR2101010:
2896	case DRM_FORMAT_ARGB2101010:
2897	case DRM_FORMAT_ABGR2101010:
2898	case DRM_FORMAT_XVYU2101010:
2899	case DRM_FORMAT_C8:
2900	case DRM_FORMAT_XBGR16161616F:
2901	case DRM_FORMAT_ABGR16161616F:
2902	case DRM_FORMAT_XRGB16161616F:
2903	case DRM_FORMAT_ARGB16161616F:
2904	case DRM_FORMAT_Y210:
2905	case DRM_FORMAT_Y212:
2906	case DRM_FORMAT_Y216:
2907	case DRM_FORMAT_XVYU12_16161616:
2908	case DRM_FORMAT_XVYU16161616:
2909		if (modifier == DRM_FORMAT_MOD_LINEAR ||
2910		    modifier == I915_FORMAT_MOD_X_TILED ||
2911		    modifier == I915_FORMAT_MOD_Y_TILED)
2912			return true;
2913		fallthrough;
2914	default:
2915		return false;
2916	}
2917}
2918
2919static const struct drm_plane_funcs g4x_sprite_funcs = {
2920	.update_plane = drm_atomic_helper_update_plane,
2921	.disable_plane = drm_atomic_helper_disable_plane,
2922	.destroy = intel_plane_destroy,
2923	.atomic_duplicate_state = intel_plane_duplicate_state,
2924	.atomic_destroy_state = intel_plane_destroy_state,
2925	.format_mod_supported = g4x_sprite_format_mod_supported,
2926};
2927
2928static const struct drm_plane_funcs snb_sprite_funcs = {
2929	.update_plane = drm_atomic_helper_update_plane,
2930	.disable_plane = drm_atomic_helper_disable_plane,
2931	.destroy = intel_plane_destroy,
2932	.atomic_duplicate_state = intel_plane_duplicate_state,
2933	.atomic_destroy_state = intel_plane_destroy_state,
2934	.format_mod_supported = snb_sprite_format_mod_supported,
2935};
2936
2937static const struct drm_plane_funcs vlv_sprite_funcs = {
2938	.update_plane = drm_atomic_helper_update_plane,
2939	.disable_plane = drm_atomic_helper_disable_plane,
2940	.destroy = intel_plane_destroy,
2941	.atomic_duplicate_state = intel_plane_duplicate_state,
2942	.atomic_destroy_state = intel_plane_destroy_state,
2943	.format_mod_supported = vlv_sprite_format_mod_supported,
2944};
2945
2946static const struct drm_plane_funcs skl_plane_funcs = {
2947	.update_plane = drm_atomic_helper_update_plane,
2948	.disable_plane = drm_atomic_helper_disable_plane,
2949	.destroy = intel_plane_destroy,
2950	.atomic_duplicate_state = intel_plane_duplicate_state,
2951	.atomic_destroy_state = intel_plane_destroy_state,
2952	.format_mod_supported = skl_plane_format_mod_supported,
2953};
2954
2955static const struct drm_plane_funcs gen12_plane_funcs = {
2956	.update_plane = drm_atomic_helper_update_plane,
2957	.disable_plane = drm_atomic_helper_disable_plane,
2958	.destroy = intel_plane_destroy,
2959	.atomic_duplicate_state = intel_plane_duplicate_state,
2960	.atomic_destroy_state = intel_plane_destroy_state,
2961	.format_mod_supported = gen12_plane_format_mod_supported,
2962};
2963
2964static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
2965			      enum pipe pipe, enum plane_id plane_id)
2966{
2967	if (!HAS_FBC(dev_priv))
2968		return false;
2969
2970	return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
2971}
2972
2973static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
2974				 enum pipe pipe, enum plane_id plane_id)
2975{
2976	/* Display WA #0870: skl, bxt */
2977	if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
2978		return false;
2979
2980	if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
2981		return false;
2982
2983	if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
2984		return false;
2985
2986	return true;
2987}
2988
2989static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
2990					enum pipe pipe, enum plane_id plane_id,
2991					int *num_formats)
2992{
2993	if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2994		*num_formats = ARRAY_SIZE(skl_planar_formats);
2995		return skl_planar_formats;
2996	} else {
2997		*num_formats = ARRAY_SIZE(skl_plane_formats);
2998		return skl_plane_formats;
2999	}
3000}
3001
3002static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
3003					enum pipe pipe, enum plane_id plane_id,
3004					int *num_formats)
3005{
3006	if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
3007		*num_formats = ARRAY_SIZE(glk_planar_formats);
3008		return glk_planar_formats;
3009	} else {
3010		*num_formats = ARRAY_SIZE(skl_plane_formats);
3011		return skl_plane_formats;
3012	}
3013}
3014
3015static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
3016					enum pipe pipe, enum plane_id plane_id,
3017					int *num_formats)
3018{
3019	if (icl_is_hdr_plane(dev_priv, plane_id)) {
3020		*num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
3021		return icl_hdr_plane_formats;
3022	} else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
3023		*num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
3024		return icl_sdr_y_plane_formats;
3025	} else {
3026		*num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
3027		return icl_sdr_uv_plane_formats;
3028	}
3029}
3030
3031static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
3032					    enum plane_id plane_id)
3033{
3034	if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
3035		return gen12_plane_format_modifiers_mc_ccs;
3036	else
3037		return gen12_plane_format_modifiers_rc_ccs;
3038}
3039
3040static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
3041			      enum pipe pipe, enum plane_id plane_id)
3042{
3043	if (plane_id == PLANE_CURSOR)
3044		return false;
3045
3046	if (INTEL_GEN(dev_priv) >= 10)
3047		return true;
3048
3049	if (IS_GEMINILAKE(dev_priv))
3050		return pipe != PIPE_C;
3051
3052	return pipe != PIPE_C &&
3053		(plane_id == PLANE_PRIMARY ||
3054		 plane_id == PLANE_SPRITE0);
3055}
3056
3057struct intel_plane *
3058skl_universal_plane_create(struct drm_i915_private *dev_priv,
3059			   enum pipe pipe, enum plane_id plane_id)
3060{
3061	const struct drm_plane_funcs *plane_funcs;
3062	struct intel_plane *plane;
3063	enum drm_plane_type plane_type;
3064	unsigned int supported_rotations;
3065	unsigned int supported_csc;
3066	const u64 *modifiers;
3067	const u32 *formats;
3068	int num_formats;
3069	int ret;
3070
3071	plane = intel_plane_alloc();
3072	if (IS_ERR(plane))
3073		return plane;
3074
3075	plane->pipe = pipe;
3076	plane->id = plane_id;
3077	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
3078
3079	plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
3080	if (plane->has_fbc) {
3081		struct intel_fbc *fbc = &dev_priv->fbc;
3082
3083		fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
3084	}
3085
3086	plane->max_stride = skl_plane_max_stride;
3087	plane->update_plane = skl_update_plane;
3088	plane->disable_plane = skl_disable_plane;
3089	plane->get_hw_state = skl_plane_get_hw_state;
3090	plane->check_plane = skl_plane_check;
3091	plane->min_cdclk = skl_plane_min_cdclk;
3092
3093	if (INTEL_GEN(dev_priv) >= 11)
3094		formats = icl_get_plane_formats(dev_priv, pipe,
3095						plane_id, &num_formats);
3096	else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
3097		formats = glk_get_plane_formats(dev_priv, pipe,
3098						plane_id, &num_formats);
3099	else
3100		formats = skl_get_plane_formats(dev_priv, pipe,
3101						plane_id, &num_formats);
3102
3103	plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
3104	if (INTEL_GEN(dev_priv) >= 12) {
3105		modifiers = gen12_get_plane_modifiers(dev_priv, plane_id);
3106		plane_funcs = &gen12_plane_funcs;
3107	} else {
3108		if (plane->has_ccs)
3109			modifiers = skl_plane_format_modifiers_ccs;
3110		else
3111			modifiers = skl_plane_format_modifiers_noccs;
3112		plane_funcs = &skl_plane_funcs;
3113	}
3114
3115	if (plane_id == PLANE_PRIMARY)
3116		plane_type = DRM_PLANE_TYPE_PRIMARY;
3117	else
3118		plane_type = DRM_PLANE_TYPE_OVERLAY;
3119
3120	ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
3121				       0, plane_funcs,
3122				       formats, num_formats, modifiers,
3123				       plane_type,
3124				       "plane %d%c", plane_id + 1,
3125				       pipe_name(pipe));
3126	if (ret)
3127		goto fail;
3128
3129	supported_rotations =
3130		DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
3131		DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
3132
3133	if (INTEL_GEN(dev_priv) >= 10)
3134		supported_rotations |= DRM_MODE_REFLECT_X;
3135
3136	drm_plane_create_rotation_property(&plane->base,
3137					   DRM_MODE_ROTATE_0,
3138					   supported_rotations);
3139
3140	supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
3141
3142	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
3143		supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
3144
3145	drm_plane_create_color_properties(&plane->base,
3146					  supported_csc,
3147					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
3148					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
3149					  DRM_COLOR_YCBCR_BT709,
3150					  DRM_COLOR_YCBCR_LIMITED_RANGE);
3151
3152	drm_plane_create_alpha_property(&plane->base);
3153	drm_plane_create_blend_mode_property(&plane->base,
3154					     BIT(DRM_MODE_BLEND_PIXEL_NONE) |
3155					     BIT(DRM_MODE_BLEND_PREMULTI) |
3156					     BIT(DRM_MODE_BLEND_COVERAGE));
3157
3158	drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
3159
3160	if (INTEL_GEN(dev_priv) >= 12)
3161		drm_plane_enable_fb_damage_clips(&plane->base);
3162
3163	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
3164
3165	return plane;
3166
3167fail:
3168	intel_plane_free(plane);
3169
3170	return ERR_PTR(ret);
3171}
3172
3173struct intel_plane *
3174intel_sprite_plane_create(struct drm_i915_private *dev_priv,
3175			  enum pipe pipe, int sprite)
3176{
3177	struct intel_plane *plane;
3178	const struct drm_plane_funcs *plane_funcs;
3179	unsigned int supported_rotations;
3180	const u64 *modifiers;
3181	const u32 *formats;
3182	int num_formats;
3183	int ret, zpos;
3184
3185	if (INTEL_GEN(dev_priv) >= 9)
3186		return skl_universal_plane_create(dev_priv, pipe,
3187						  PLANE_SPRITE0 + sprite);
3188
3189	plane = intel_plane_alloc();
3190	if (IS_ERR(plane))
3191		return plane;
3192
3193	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
3194		plane->max_stride = i9xx_plane_max_stride;
3195		plane->update_plane = vlv_update_plane;
3196		plane->disable_plane = vlv_disable_plane;
3197		plane->get_hw_state = vlv_plane_get_hw_state;
3198		plane->check_plane = vlv_sprite_check;
 
3199		plane->min_cdclk = vlv_plane_min_cdclk;
3200
3201		if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
3202			formats = chv_pipe_b_sprite_formats;
3203			num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
3204		} else {
3205			formats = vlv_plane_formats;
3206			num_formats = ARRAY_SIZE(vlv_plane_formats);
3207		}
3208		modifiers = i9xx_plane_format_modifiers;
3209
3210		plane_funcs = &vlv_sprite_funcs;
3211	} else if (INTEL_GEN(dev_priv) >= 7) {
3212		plane->max_stride = g4x_sprite_max_stride;
3213		plane->update_plane = ivb_update_plane;
3214		plane->disable_plane = ivb_disable_plane;
3215		plane->get_hw_state = ivb_plane_get_hw_state;
3216		plane->check_plane = g4x_sprite_check;
3217
3218		if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
 
3219			plane->min_cdclk = hsw_plane_min_cdclk;
3220		else
 
3221			plane->min_cdclk = ivb_sprite_min_cdclk;
 
3222
3223		formats = snb_plane_formats;
3224		num_formats = ARRAY_SIZE(snb_plane_formats);
3225		modifiers = i9xx_plane_format_modifiers;
3226
3227		plane_funcs = &snb_sprite_funcs;
3228	} else {
3229		plane->max_stride = g4x_sprite_max_stride;
3230		plane->update_plane = g4x_update_plane;
3231		plane->disable_plane = g4x_disable_plane;
3232		plane->get_hw_state = g4x_plane_get_hw_state;
3233		plane->check_plane = g4x_sprite_check;
 
3234		plane->min_cdclk = g4x_sprite_min_cdclk;
3235
3236		modifiers = i9xx_plane_format_modifiers;
3237		if (IS_GEN(dev_priv, 6)) {
3238			formats = snb_plane_formats;
3239			num_formats = ARRAY_SIZE(snb_plane_formats);
3240
3241			plane_funcs = &snb_sprite_funcs;
3242		} else {
3243			formats = g4x_plane_formats;
3244			num_formats = ARRAY_SIZE(g4x_plane_formats);
3245
3246			plane_funcs = &g4x_sprite_funcs;
3247		}
3248	}
3249
3250	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
3251		supported_rotations =
3252			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
3253			DRM_MODE_REFLECT_X;
3254	} else {
3255		supported_rotations =
3256			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
3257	}
3258
3259	plane->pipe = pipe;
3260	plane->id = PLANE_SPRITE0 + sprite;
3261	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
3262
3263	ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
3264				       0, plane_funcs,
3265				       formats, num_formats, modifiers,
3266				       DRM_PLANE_TYPE_OVERLAY,
3267				       "sprite %c", sprite_name(pipe, sprite));
3268	if (ret)
3269		goto fail;
3270
3271	drm_plane_create_rotation_property(&plane->base,
3272					   DRM_MODE_ROTATE_0,
3273					   supported_rotations);
3274
3275	drm_plane_create_color_properties(&plane->base,
3276					  BIT(DRM_COLOR_YCBCR_BT601) |
3277					  BIT(DRM_COLOR_YCBCR_BT709),
3278					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
3279					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
3280					  DRM_COLOR_YCBCR_BT709,
3281					  DRM_COLOR_YCBCR_LIMITED_RANGE);
3282
3283	zpos = sprite + 1;
3284	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
3285
3286	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
3287
3288	return plane;
3289
3290fail:
3291	intel_plane_free(plane);
3292
3293	return ERR_PTR(ret);
3294}