cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

intel_sprite.c (51541B)


      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 <linux/string_helpers.h>
     34
     35#include <drm/drm_atomic.h>
     36#include <drm/drm_atomic_helper.h>
     37#include <drm/drm_color_mgmt.h>
     38#include <drm/drm_crtc.h>
     39#include <drm/drm_damage_helper.h>
     40#include <drm/drm_fourcc.h>
     41#include <drm/drm_plane_helper.h>
     42#include <drm/drm_rect.h>
     43
     44#include "i915_drv.h"
     45#include "i915_vgpu.h"
     46#include "i9xx_plane.h"
     47#include "intel_atomic_plane.h"
     48#include "intel_crtc.h"
     49#include "intel_de.h"
     50#include "intel_display_types.h"
     51#include "intel_fb.h"
     52#include "intel_frontbuffer.h"
     53#include "intel_sprite.h"
     54#include "intel_vrr.h"
     55
     56int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
     57{
     58	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
     59	const struct drm_framebuffer *fb = plane_state->hw.fb;
     60	struct drm_rect *src = &plane_state->uapi.src;
     61	u32 src_x, src_y, src_w, src_h, hsub, vsub;
     62	bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
     63
     64	/*
     65	 * FIXME hsub/vsub vs. block size is a mess. Pre-tgl CCS
     66	 * abuses hsub/vsub so we can't use them here. But as they
     67	 * are limited to 32bpp RGB formats we don't actually need
     68	 * to check anything.
     69	 */
     70	if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
     71	    fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)
     72		return 0;
     73
     74	/*
     75	 * Hardware doesn't handle subpixel coordinates.
     76	 * Adjust to (macro)pixel boundary, but be careful not to
     77	 * increase the source viewport size, because that could
     78	 * push the downscaling factor out of bounds.
     79	 */
     80	src_x = src->x1 >> 16;
     81	src_w = drm_rect_width(src) >> 16;
     82	src_y = src->y1 >> 16;
     83	src_h = drm_rect_height(src) >> 16;
     84
     85	drm_rect_init(src, src_x << 16, src_y << 16,
     86		      src_w << 16, src_h << 16);
     87
     88	if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
     89		hsub = 2;
     90		vsub = 2;
     91	} else {
     92		hsub = fb->format->hsub;
     93		vsub = fb->format->vsub;
     94	}
     95
     96	if (rotated)
     97		hsub = vsub = max(hsub, vsub);
     98
     99	if (src_x % hsub || src_w % hsub) {
    100		drm_dbg_kms(&i915->drm, "src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
    101			    src_x, src_w, hsub, str_yes_no(rotated));
    102		return -EINVAL;
    103	}
    104
    105	if (src_y % vsub || src_h % vsub) {
    106		drm_dbg_kms(&i915->drm, "src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
    107			    src_y, src_h, vsub, str_yes_no(rotated));
    108		return -EINVAL;
    109	}
    110
    111	return 0;
    112}
    113
    114static void i9xx_plane_linear_gamma(u16 gamma[8])
    115{
    116	/* The points are not evenly spaced. */
    117	static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
    118	int i;
    119
    120	for (i = 0; i < 8; i++)
    121		gamma[i] = (in[i] << 8) / 32;
    122}
    123
    124static void
    125chv_sprite_update_csc(const struct intel_plane_state *plane_state)
    126{
    127	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
    128	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    129	const struct drm_framebuffer *fb = plane_state->hw.fb;
    130	enum plane_id plane_id = plane->id;
    131	/*
    132	 * |r|   | c0 c1 c2 |   |cr|
    133	 * |g| = | c3 c4 c5 | x |y |
    134	 * |b|   | c6 c7 c8 |   |cb|
    135	 *
    136	 * Coefficients are s3.12.
    137	 *
    138	 * Cb and Cr apparently come in as signed already, and
    139	 * we always get full range data in on account of CLRC0/1.
    140	 */
    141	static const s16 csc_matrix[][9] = {
    142		/* BT.601 full range YCbCr -> full range RGB */
    143		[DRM_COLOR_YCBCR_BT601] = {
    144			 5743, 4096,     0,
    145			-2925, 4096, -1410,
    146			    0, 4096,  7258,
    147		},
    148		/* BT.709 full range YCbCr -> full range RGB */
    149		[DRM_COLOR_YCBCR_BT709] = {
    150			 6450, 4096,     0,
    151			-1917, 4096,  -767,
    152			    0, 4096,  7601,
    153		},
    154	};
    155	const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
    156
    157	/* Seems RGB data bypasses the CSC always */
    158	if (!fb->format->is_yuv)
    159		return;
    160
    161	intel_de_write_fw(dev_priv, SPCSCYGOFF(plane_id),
    162			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
    163	intel_de_write_fw(dev_priv, SPCSCCBOFF(plane_id),
    164			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
    165	intel_de_write_fw(dev_priv, SPCSCCROFF(plane_id),
    166			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
    167
    168	intel_de_write_fw(dev_priv, SPCSCC01(plane_id),
    169			  SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
    170	intel_de_write_fw(dev_priv, SPCSCC23(plane_id),
    171			  SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
    172	intel_de_write_fw(dev_priv, SPCSCC45(plane_id),
    173			  SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
    174	intel_de_write_fw(dev_priv, SPCSCC67(plane_id),
    175			  SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
    176	intel_de_write_fw(dev_priv, SPCSCC8(plane_id), SPCSC_C0(csc[8]));
    177
    178	intel_de_write_fw(dev_priv, SPCSCYGICLAMP(plane_id),
    179			  SPCSC_IMAX(1023) | SPCSC_IMIN(0));
    180	intel_de_write_fw(dev_priv, SPCSCCBICLAMP(plane_id),
    181			  SPCSC_IMAX(512) | SPCSC_IMIN(-512));
    182	intel_de_write_fw(dev_priv, SPCSCCRICLAMP(plane_id),
    183			  SPCSC_IMAX(512) | SPCSC_IMIN(-512));
    184
    185	intel_de_write_fw(dev_priv, SPCSCYGOCLAMP(plane_id),
    186			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
    187	intel_de_write_fw(dev_priv, SPCSCCBOCLAMP(plane_id),
    188			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
    189	intel_de_write_fw(dev_priv, SPCSCCROCLAMP(plane_id),
    190			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
    191}
    192
    193#define SIN_0 0
    194#define COS_0 1
    195
    196static void
    197vlv_sprite_update_clrc(const struct intel_plane_state *plane_state)
    198{
    199	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
    200	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    201	const struct drm_framebuffer *fb = plane_state->hw.fb;
    202	enum pipe pipe = plane->pipe;
    203	enum plane_id plane_id = plane->id;
    204	int contrast, brightness, sh_scale, sh_sin, sh_cos;
    205
    206	if (fb->format->is_yuv &&
    207	    plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
    208		/*
    209		 * Expand limited range to full range:
    210		 * Contrast is applied first and is used to expand Y range.
    211		 * Brightness is applied second and is used to remove the
    212		 * offset from Y. Saturation/hue is used to expand CbCr range.
    213		 */
    214		contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
    215		brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
    216		sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
    217		sh_sin = SIN_0 * sh_scale;
    218		sh_cos = COS_0 * sh_scale;
    219	} else {
    220		/* Pass-through everything. */
    221		contrast = 1 << 6;
    222		brightness = 0;
    223		sh_scale = 1 << 7;
    224		sh_sin = SIN_0 * sh_scale;
    225		sh_cos = COS_0 * sh_scale;
    226	}
    227
    228	/* FIXME these register are single buffered :( */
    229	intel_de_write_fw(dev_priv, SPCLRC0(pipe, plane_id),
    230			  SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
    231	intel_de_write_fw(dev_priv, SPCLRC1(pipe, plane_id),
    232			  SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
    233}
    234
    235static void
    236vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
    237		const struct intel_plane_state *plane_state,
    238		unsigned int *num, unsigned int *den)
    239{
    240	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
    241	const struct drm_framebuffer *fb = plane_state->hw.fb;
    242	unsigned int cpp = fb->format->cpp[0];
    243
    244	/*
    245	 * VLV bspec only considers cases where all three planes are
    246	 * enabled, and cases where the primary and one sprite is enabled.
    247	 * Let's assume the case with just two sprites enabled also
    248	 * maps to the latter case.
    249	 */
    250	if (hweight8(active_planes) == 3) {
    251		switch (cpp) {
    252		case 8:
    253			*num = 11;
    254			*den = 8;
    255			break;
    256		case 4:
    257			*num = 18;
    258			*den = 16;
    259			break;
    260		default:
    261			*num = 1;
    262			*den = 1;
    263			break;
    264		}
    265	} else if (hweight8(active_planes) == 2) {
    266		switch (cpp) {
    267		case 8:
    268			*num = 10;
    269			*den = 8;
    270			break;
    271		case 4:
    272			*num = 17;
    273			*den = 16;
    274			break;
    275		default:
    276			*num = 1;
    277			*den = 1;
    278			break;
    279		}
    280	} else {
    281		switch (cpp) {
    282		case 8:
    283			*num = 10;
    284			*den = 8;
    285			break;
    286		default:
    287			*num = 1;
    288			*den = 1;
    289			break;
    290		}
    291	}
    292}
    293
    294int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
    295			const struct intel_plane_state *plane_state)
    296{
    297	unsigned int pixel_rate;
    298	unsigned int num, den;
    299
    300	/*
    301	 * Note that crtc_state->pixel_rate accounts for both
    302	 * horizontal and vertical panel fitter downscaling factors.
    303	 * Pre-HSW bspec tells us to only consider the horizontal
    304	 * downscaling factor here. We ignore that and just consider
    305	 * both for simplicity.
    306	 */
    307	pixel_rate = crtc_state->pixel_rate;
    308
    309	vlv_plane_ratio(crtc_state, plane_state, &num, &den);
    310
    311	return DIV_ROUND_UP(pixel_rate * num, den);
    312}
    313
    314static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
    315{
    316	u32 sprctl = 0;
    317
    318	if (crtc_state->gamma_enable)
    319		sprctl |= SP_PIPE_GAMMA_ENABLE;
    320
    321	return sprctl;
    322}
    323
    324static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
    325			  const struct intel_plane_state *plane_state)
    326{
    327	const struct drm_framebuffer *fb = plane_state->hw.fb;
    328	unsigned int rotation = plane_state->hw.rotation;
    329	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
    330	u32 sprctl;
    331
    332	sprctl = SP_ENABLE;
    333
    334	switch (fb->format->format) {
    335	case DRM_FORMAT_YUYV:
    336		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
    337		break;
    338	case DRM_FORMAT_YVYU:
    339		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
    340		break;
    341	case DRM_FORMAT_UYVY:
    342		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
    343		break;
    344	case DRM_FORMAT_VYUY:
    345		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
    346		break;
    347	case DRM_FORMAT_C8:
    348		sprctl |= SP_FORMAT_8BPP;
    349		break;
    350	case DRM_FORMAT_RGB565:
    351		sprctl |= SP_FORMAT_BGR565;
    352		break;
    353	case DRM_FORMAT_XRGB8888:
    354		sprctl |= SP_FORMAT_BGRX8888;
    355		break;
    356	case DRM_FORMAT_ARGB8888:
    357		sprctl |= SP_FORMAT_BGRA8888;
    358		break;
    359	case DRM_FORMAT_XBGR2101010:
    360		sprctl |= SP_FORMAT_RGBX1010102;
    361		break;
    362	case DRM_FORMAT_ABGR2101010:
    363		sprctl |= SP_FORMAT_RGBA1010102;
    364		break;
    365	case DRM_FORMAT_XRGB2101010:
    366		sprctl |= SP_FORMAT_BGRX1010102;
    367		break;
    368	case DRM_FORMAT_ARGB2101010:
    369		sprctl |= SP_FORMAT_BGRA1010102;
    370		break;
    371	case DRM_FORMAT_XBGR8888:
    372		sprctl |= SP_FORMAT_RGBX8888;
    373		break;
    374	case DRM_FORMAT_ABGR8888:
    375		sprctl |= SP_FORMAT_RGBA8888;
    376		break;
    377	default:
    378		MISSING_CASE(fb->format->format);
    379		return 0;
    380	}
    381
    382	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
    383		sprctl |= SP_YUV_FORMAT_BT709;
    384
    385	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
    386		sprctl |= SP_TILED;
    387
    388	if (rotation & DRM_MODE_ROTATE_180)
    389		sprctl |= SP_ROTATE_180;
    390
    391	if (rotation & DRM_MODE_REFLECT_X)
    392		sprctl |= SP_MIRROR;
    393
    394	if (key->flags & I915_SET_COLORKEY_SOURCE)
    395		sprctl |= SP_SOURCE_KEY;
    396
    397	return sprctl;
    398}
    399
    400static void vlv_sprite_update_gamma(const struct intel_plane_state *plane_state)
    401{
    402	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
    403	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    404	const struct drm_framebuffer *fb = plane_state->hw.fb;
    405	enum pipe pipe = plane->pipe;
    406	enum plane_id plane_id = plane->id;
    407	u16 gamma[8];
    408	int i;
    409
    410	/* Seems RGB data bypasses the gamma always */
    411	if (!fb->format->is_yuv)
    412		return;
    413
    414	i9xx_plane_linear_gamma(gamma);
    415
    416	/* FIXME these register are single buffered :( */
    417	/* The two end points are implicit (0.0 and 1.0) */
    418	for (i = 1; i < 8 - 1; i++)
    419		intel_de_write_fw(dev_priv, SPGAMC(pipe, plane_id, i - 1),
    420				  gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
    421}
    422
    423static void
    424vlv_sprite_update_noarm(struct intel_plane *plane,
    425			const struct intel_crtc_state *crtc_state,
    426			const struct intel_plane_state *plane_state)
    427{
    428	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    429	enum pipe pipe = plane->pipe;
    430	enum plane_id plane_id = plane->id;
    431	int crtc_x = plane_state->uapi.dst.x1;
    432	int crtc_y = plane_state->uapi.dst.y1;
    433	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
    434	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
    435
    436	intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id),
    437			  plane_state->view.color_plane[0].mapping_stride);
    438	intel_de_write_fw(dev_priv, SPPOS(pipe, plane_id),
    439			  SP_POS_Y(crtc_y) | SP_POS_X(crtc_x));
    440	intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id),
    441			  SP_HEIGHT(crtc_h - 1) | SP_WIDTH(crtc_w - 1));
    442}
    443
    444static void
    445vlv_sprite_update_arm(struct intel_plane *plane,
    446		      const struct intel_crtc_state *crtc_state,
    447		      const struct intel_plane_state *plane_state)
    448{
    449	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    450	enum pipe pipe = plane->pipe;
    451	enum plane_id plane_id = plane->id;
    452	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
    453	u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
    454	u32 x = plane_state->view.color_plane[0].x;
    455	u32 y = plane_state->view.color_plane[0].y;
    456	u32 sprctl, linear_offset;
    457
    458	sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
    459
    460	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
    461
    462	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
    463		chv_sprite_update_csc(plane_state);
    464
    465	if (key->flags) {
    466		intel_de_write_fw(dev_priv, SPKEYMINVAL(pipe, plane_id),
    467				  key->min_value);
    468		intel_de_write_fw(dev_priv, SPKEYMSK(pipe, plane_id),
    469				  key->channel_mask);
    470		intel_de_write_fw(dev_priv, SPKEYMAXVAL(pipe, plane_id),
    471				  key->max_value);
    472	}
    473
    474	intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0);
    475
    476	intel_de_write_fw(dev_priv, SPLINOFF(pipe, plane_id), linear_offset);
    477	intel_de_write_fw(dev_priv, SPTILEOFF(pipe, plane_id),
    478			  SP_OFFSET_Y(y) | SP_OFFSET_X(x));
    479
    480	/*
    481	 * The control register self-arms if the plane was previously
    482	 * disabled. Try to make the plane enable atomic by writing
    483	 * the control register just before the surface register.
    484	 */
    485	intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), sprctl);
    486	intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id),
    487			  intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
    488
    489	vlv_sprite_update_clrc(plane_state);
    490	vlv_sprite_update_gamma(plane_state);
    491}
    492
    493static void
    494vlv_sprite_disable_arm(struct intel_plane *plane,
    495		       const struct intel_crtc_state *crtc_state)
    496{
    497	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    498	enum pipe pipe = plane->pipe;
    499	enum plane_id plane_id = plane->id;
    500
    501	intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0);
    502	intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0);
    503}
    504
    505static bool
    506vlv_sprite_get_hw_state(struct intel_plane *plane,
    507			enum pipe *pipe)
    508{
    509	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    510	enum intel_display_power_domain power_domain;
    511	enum plane_id plane_id = plane->id;
    512	intel_wakeref_t wakeref;
    513	bool ret;
    514
    515	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
    516	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
    517	if (!wakeref)
    518		return false;
    519
    520	ret = intel_de_read(dev_priv, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
    521
    522	*pipe = plane->pipe;
    523
    524	intel_display_power_put(dev_priv, power_domain, wakeref);
    525
    526	return ret;
    527}
    528
    529static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
    530			    const struct intel_plane_state *plane_state,
    531			    unsigned int *num, unsigned int *den)
    532{
    533	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
    534	const struct drm_framebuffer *fb = plane_state->hw.fb;
    535	unsigned int cpp = fb->format->cpp[0];
    536
    537	if (hweight8(active_planes) == 2) {
    538		switch (cpp) {
    539		case 8:
    540			*num = 10;
    541			*den = 8;
    542			break;
    543		case 4:
    544			*num = 17;
    545			*den = 16;
    546			break;
    547		default:
    548			*num = 1;
    549			*den = 1;
    550			break;
    551		}
    552	} else {
    553		switch (cpp) {
    554		case 8:
    555			*num = 9;
    556			*den = 8;
    557			break;
    558		default:
    559			*num = 1;
    560			*den = 1;
    561			break;
    562		}
    563	}
    564}
    565
    566static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
    567				    const struct intel_plane_state *plane_state,
    568				    unsigned int *num, unsigned int *den)
    569{
    570	const struct drm_framebuffer *fb = plane_state->hw.fb;
    571	unsigned int cpp = fb->format->cpp[0];
    572
    573	switch (cpp) {
    574	case 8:
    575		*num = 12;
    576		*den = 8;
    577		break;
    578	case 4:
    579		*num = 19;
    580		*den = 16;
    581		break;
    582	case 2:
    583		*num = 33;
    584		*den = 32;
    585		break;
    586	default:
    587		*num = 1;
    588		*den = 1;
    589		break;
    590	}
    591}
    592
    593int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
    594			const struct intel_plane_state *plane_state)
    595{
    596	unsigned int pixel_rate;
    597	unsigned int num, den;
    598
    599	/*
    600	 * Note that crtc_state->pixel_rate accounts for both
    601	 * horizontal and vertical panel fitter downscaling factors.
    602	 * Pre-HSW bspec tells us to only consider the horizontal
    603	 * downscaling factor here. We ignore that and just consider
    604	 * both for simplicity.
    605	 */
    606	pixel_rate = crtc_state->pixel_rate;
    607
    608	ivb_plane_ratio(crtc_state, plane_state, &num, &den);
    609
    610	return DIV_ROUND_UP(pixel_rate * num, den);
    611}
    612
    613static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
    614				const struct intel_plane_state *plane_state)
    615{
    616	unsigned int src_w, dst_w, pixel_rate;
    617	unsigned int num, den;
    618
    619	/*
    620	 * Note that crtc_state->pixel_rate accounts for both
    621	 * horizontal and vertical panel fitter downscaling factors.
    622	 * Pre-HSW bspec tells us to only consider the horizontal
    623	 * downscaling factor here. We ignore that and just consider
    624	 * both for simplicity.
    625	 */
    626	pixel_rate = crtc_state->pixel_rate;
    627
    628	src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
    629	dst_w = drm_rect_width(&plane_state->uapi.dst);
    630
    631	if (src_w != dst_w)
    632		ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
    633	else
    634		ivb_plane_ratio(crtc_state, plane_state, &num, &den);
    635
    636	/* Horizontal downscaling limits the maximum pixel rate */
    637	dst_w = min(src_w, dst_w);
    638
    639	return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
    640				den * dst_w);
    641}
    642
    643static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
    644			    const struct intel_plane_state *plane_state,
    645			    unsigned int *num, unsigned int *den)
    646{
    647	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
    648	const struct drm_framebuffer *fb = plane_state->hw.fb;
    649	unsigned int cpp = fb->format->cpp[0];
    650
    651	if (hweight8(active_planes) == 2) {
    652		switch (cpp) {
    653		case 8:
    654			*num = 10;
    655			*den = 8;
    656			break;
    657		default:
    658			*num = 1;
    659			*den = 1;
    660			break;
    661		}
    662	} else {
    663		switch (cpp) {
    664		case 8:
    665			*num = 9;
    666			*den = 8;
    667			break;
    668		default:
    669			*num = 1;
    670			*den = 1;
    671			break;
    672		}
    673	}
    674}
    675
    676int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
    677			const struct intel_plane_state *plane_state)
    678{
    679	unsigned int pixel_rate = crtc_state->pixel_rate;
    680	unsigned int num, den;
    681
    682	hsw_plane_ratio(crtc_state, plane_state, &num, &den);
    683
    684	return DIV_ROUND_UP(pixel_rate * num, den);
    685}
    686
    687static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
    688{
    689	u32 sprctl = 0;
    690
    691	if (crtc_state->gamma_enable)
    692		sprctl |= SPRITE_PIPE_GAMMA_ENABLE;
    693
    694	if (crtc_state->csc_enable)
    695		sprctl |= SPRITE_PIPE_CSC_ENABLE;
    696
    697	return sprctl;
    698}
    699
    700static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
    701{
    702	struct drm_i915_private *dev_priv =
    703		to_i915(plane_state->uapi.plane->dev);
    704	const struct drm_framebuffer *fb = plane_state->hw.fb;
    705
    706	return fb->format->cpp[0] == 8 &&
    707		(IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
    708}
    709
    710static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
    711			  const struct intel_plane_state *plane_state)
    712{
    713	struct drm_i915_private *dev_priv =
    714		to_i915(plane_state->uapi.plane->dev);
    715	const struct drm_framebuffer *fb = plane_state->hw.fb;
    716	unsigned int rotation = plane_state->hw.rotation;
    717	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
    718	u32 sprctl;
    719
    720	sprctl = SPRITE_ENABLE;
    721
    722	if (IS_IVYBRIDGE(dev_priv))
    723		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
    724
    725	switch (fb->format->format) {
    726	case DRM_FORMAT_XBGR8888:
    727		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
    728		break;
    729	case DRM_FORMAT_XRGB8888:
    730		sprctl |= SPRITE_FORMAT_RGBX888;
    731		break;
    732	case DRM_FORMAT_XBGR2101010:
    733		sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
    734		break;
    735	case DRM_FORMAT_XRGB2101010:
    736		sprctl |= SPRITE_FORMAT_RGBX101010;
    737		break;
    738	case DRM_FORMAT_XBGR16161616F:
    739		sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
    740		break;
    741	case DRM_FORMAT_XRGB16161616F:
    742		sprctl |= SPRITE_FORMAT_RGBX161616;
    743		break;
    744	case DRM_FORMAT_YUYV:
    745		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
    746		break;
    747	case DRM_FORMAT_YVYU:
    748		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
    749		break;
    750	case DRM_FORMAT_UYVY:
    751		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
    752		break;
    753	case DRM_FORMAT_VYUY:
    754		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
    755		break;
    756	default:
    757		MISSING_CASE(fb->format->format);
    758		return 0;
    759	}
    760
    761	if (!ivb_need_sprite_gamma(plane_state))
    762		sprctl |= SPRITE_PLANE_GAMMA_DISABLE;
    763
    764	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
    765		sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
    766
    767	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
    768		sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
    769
    770	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
    771		sprctl |= SPRITE_TILED;
    772
    773	if (rotation & DRM_MODE_ROTATE_180)
    774		sprctl |= SPRITE_ROTATE_180;
    775
    776	if (key->flags & I915_SET_COLORKEY_DESTINATION)
    777		sprctl |= SPRITE_DEST_KEY;
    778	else if (key->flags & I915_SET_COLORKEY_SOURCE)
    779		sprctl |= SPRITE_SOURCE_KEY;
    780
    781	return sprctl;
    782}
    783
    784static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
    785				    u16 gamma[18])
    786{
    787	int scale, i;
    788
    789	/*
    790	 * WaFP16GammaEnabling:ivb,hsw
    791	 * "Workaround : When using the 64-bit format, the sprite output
    792	 *  on each color channel has one quarter amplitude. It can be
    793	 *  brought up to full amplitude by using sprite internal gamma
    794	 *  correction, pipe gamma correction, or pipe color space
    795	 *  conversion to multiply the sprite output by four."
    796	 */
    797	scale = 4;
    798
    799	for (i = 0; i < 16; i++)
    800		gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
    801
    802	gamma[i] = min((scale * i << 10) / 16, 1 << 10);
    803	i++;
    804
    805	gamma[i] = 3 << 10;
    806	i++;
    807}
    808
    809static void ivb_sprite_update_gamma(const struct intel_plane_state *plane_state)
    810{
    811	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
    812	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    813	enum pipe pipe = plane->pipe;
    814	u16 gamma[18];
    815	int i;
    816
    817	if (!ivb_need_sprite_gamma(plane_state))
    818		return;
    819
    820	ivb_sprite_linear_gamma(plane_state, gamma);
    821
    822	/* FIXME these register are single buffered :( */
    823	for (i = 0; i < 16; i++)
    824		intel_de_write_fw(dev_priv, SPRGAMC(pipe, i),
    825				  gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
    826
    827	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 0), gamma[i]);
    828	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 1), gamma[i]);
    829	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 2), gamma[i]);
    830	i++;
    831
    832	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 0), gamma[i]);
    833	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 1), gamma[i]);
    834	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 2), gamma[i]);
    835	i++;
    836}
    837
    838static void
    839ivb_sprite_update_noarm(struct intel_plane *plane,
    840			const struct intel_crtc_state *crtc_state,
    841			const struct intel_plane_state *plane_state)
    842{
    843	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    844	enum pipe pipe = plane->pipe;
    845	int crtc_x = plane_state->uapi.dst.x1;
    846	int crtc_y = plane_state->uapi.dst.y1;
    847	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
    848	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
    849	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
    850	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
    851	u32 sprscale = 0;
    852
    853	if (crtc_w != src_w || crtc_h != src_h)
    854		sprscale = SPRITE_SCALE_ENABLE |
    855			SPRITE_SRC_WIDTH(src_w - 1) |
    856			SPRITE_SRC_HEIGHT(src_h - 1);
    857
    858	intel_de_write_fw(dev_priv, SPRSTRIDE(pipe),
    859			  plane_state->view.color_plane[0].mapping_stride);
    860	intel_de_write_fw(dev_priv, SPRPOS(pipe),
    861			  SPRITE_POS_Y(crtc_y) | SPRITE_POS_X(crtc_x));
    862	intel_de_write_fw(dev_priv, SPRSIZE(pipe),
    863			  SPRITE_HEIGHT(crtc_h - 1) | SPRITE_WIDTH(crtc_w - 1));
    864	if (IS_IVYBRIDGE(dev_priv))
    865		intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale);
    866}
    867
    868static void
    869ivb_sprite_update_arm(struct intel_plane *plane,
    870		      const struct intel_crtc_state *crtc_state,
    871		      const struct intel_plane_state *plane_state)
    872{
    873	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    874	enum pipe pipe = plane->pipe;
    875	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
    876	u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
    877	u32 x = plane_state->view.color_plane[0].x;
    878	u32 y = plane_state->view.color_plane[0].y;
    879	u32 sprctl, linear_offset;
    880
    881	sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
    882
    883	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
    884
    885	if (key->flags) {
    886		intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value);
    887		intel_de_write_fw(dev_priv, SPRKEYMSK(pipe),
    888				  key->channel_mask);
    889		intel_de_write_fw(dev_priv, SPRKEYMAX(pipe), key->max_value);
    890	}
    891
    892	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
    893	 * register */
    894	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
    895		intel_de_write_fw(dev_priv, SPROFFSET(pipe),
    896				  SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
    897	} else {
    898		intel_de_write_fw(dev_priv, SPRLINOFF(pipe), linear_offset);
    899		intel_de_write_fw(dev_priv, SPRTILEOFF(pipe),
    900				  SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
    901	}
    902
    903	/*
    904	 * The control register self-arms if the plane was previously
    905	 * disabled. Try to make the plane enable atomic by writing
    906	 * the control register just before the surface register.
    907	 */
    908	intel_de_write_fw(dev_priv, SPRCTL(pipe), sprctl);
    909	intel_de_write_fw(dev_priv, SPRSURF(pipe),
    910			  intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
    911
    912	ivb_sprite_update_gamma(plane_state);
    913}
    914
    915static void
    916ivb_sprite_disable_arm(struct intel_plane *plane,
    917		       const struct intel_crtc_state *crtc_state)
    918{
    919	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    920	enum pipe pipe = plane->pipe;
    921
    922	intel_de_write_fw(dev_priv, SPRCTL(pipe), 0);
    923	/* Disable the scaler */
    924	if (IS_IVYBRIDGE(dev_priv))
    925		intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0);
    926	intel_de_write_fw(dev_priv, SPRSURF(pipe), 0);
    927}
    928
    929static bool
    930ivb_sprite_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_PIPE_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_sprite_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_sprite_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_sprite_update_noarm(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	int crtc_x = plane_state->uapi.dst.x1;
   1173	int crtc_y = plane_state->uapi.dst.y1;
   1174	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
   1175	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
   1176	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
   1177	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
   1178	u32 dvsscale = 0;
   1179
   1180	if (crtc_w != src_w || crtc_h != src_h)
   1181		dvsscale = DVS_SCALE_ENABLE |
   1182			DVS_SRC_WIDTH(src_w - 1) |
   1183			DVS_SRC_HEIGHT(src_h - 1);
   1184
   1185	intel_de_write_fw(dev_priv, DVSSTRIDE(pipe),
   1186			  plane_state->view.color_plane[0].mapping_stride);
   1187	intel_de_write_fw(dev_priv, DVSPOS(pipe),
   1188			  DVS_POS_Y(crtc_y) | DVS_POS_X(crtc_x));
   1189	intel_de_write_fw(dev_priv, DVSSIZE(pipe),
   1190			  DVS_HEIGHT(crtc_h - 1) | DVS_WIDTH(crtc_w - 1));
   1191	intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale);
   1192}
   1193
   1194static void
   1195g4x_sprite_update_arm(struct intel_plane *plane,
   1196		      const struct intel_crtc_state *crtc_state,
   1197		      const struct intel_plane_state *plane_state)
   1198{
   1199	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
   1200	enum pipe pipe = plane->pipe;
   1201	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
   1202	u32 dvssurf_offset = plane_state->view.color_plane[0].offset;
   1203	u32 x = plane_state->view.color_plane[0].x;
   1204	u32 y = plane_state->view.color_plane[0].y;
   1205	u32 dvscntr, linear_offset;
   1206
   1207	dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
   1208
   1209	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
   1210
   1211	if (key->flags) {
   1212		intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value);
   1213		intel_de_write_fw(dev_priv, DVSKEYMSK(pipe),
   1214				  key->channel_mask);
   1215		intel_de_write_fw(dev_priv, DVSKEYMAX(pipe), key->max_value);
   1216	}
   1217
   1218	intel_de_write_fw(dev_priv, DVSLINOFF(pipe), linear_offset);
   1219	intel_de_write_fw(dev_priv, DVSTILEOFF(pipe), (y << 16) | x);
   1220
   1221	/*
   1222	 * The control register self-arms if the plane was previously
   1223	 * disabled. Try to make the plane enable atomic by writing
   1224	 * the control register just before the surface register.
   1225	 */
   1226	intel_de_write_fw(dev_priv, DVSCNTR(pipe), dvscntr);
   1227	intel_de_write_fw(dev_priv, DVSSURF(pipe),
   1228			  intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
   1229
   1230	if (IS_G4X(dev_priv))
   1231		g4x_sprite_update_gamma(plane_state);
   1232	else
   1233		ilk_sprite_update_gamma(plane_state);
   1234}
   1235
   1236static void
   1237g4x_sprite_disable_arm(struct intel_plane *plane,
   1238		       const struct intel_crtc_state *crtc_state)
   1239{
   1240	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
   1241	enum pipe pipe = plane->pipe;
   1242
   1243	intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0);
   1244	/* Disable the scaler */
   1245	intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0);
   1246	intel_de_write_fw(dev_priv, DVSSURF(pipe), 0);
   1247}
   1248
   1249static bool
   1250g4x_sprite_get_hw_state(struct intel_plane *plane,
   1251			enum pipe *pipe)
   1252{
   1253	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
   1254	enum intel_display_power_domain power_domain;
   1255	intel_wakeref_t wakeref;
   1256	bool ret;
   1257
   1258	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
   1259	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
   1260	if (!wakeref)
   1261		return false;
   1262
   1263	ret = intel_de_read(dev_priv, DVSCNTR(plane->pipe)) & DVS_ENABLE;
   1264
   1265	*pipe = plane->pipe;
   1266
   1267	intel_display_power_put(dev_priv, power_domain, wakeref);
   1268
   1269	return ret;
   1270}
   1271
   1272static bool g4x_fb_scalable(const struct drm_framebuffer *fb)
   1273{
   1274	if (!fb)
   1275		return false;
   1276
   1277	switch (fb->format->format) {
   1278	case DRM_FORMAT_C8:
   1279	case DRM_FORMAT_XRGB16161616F:
   1280	case DRM_FORMAT_ARGB16161616F:
   1281	case DRM_FORMAT_XBGR16161616F:
   1282	case DRM_FORMAT_ABGR16161616F:
   1283		return false;
   1284	default:
   1285		return true;
   1286	}
   1287}
   1288
   1289static int
   1290g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
   1291			 struct intel_plane_state *plane_state)
   1292{
   1293	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
   1294	const struct drm_framebuffer *fb = plane_state->hw.fb;
   1295	const struct drm_rect *src = &plane_state->uapi.src;
   1296	const struct drm_rect *dst = &plane_state->uapi.dst;
   1297	int src_x, src_w, src_h, crtc_w, crtc_h;
   1298	const struct drm_display_mode *adjusted_mode =
   1299		&crtc_state->hw.adjusted_mode;
   1300	unsigned int stride = plane_state->view.color_plane[0].mapping_stride;
   1301	unsigned int cpp = fb->format->cpp[0];
   1302	unsigned int width_bytes;
   1303	int min_width, min_height;
   1304
   1305	crtc_w = drm_rect_width(dst);
   1306	crtc_h = drm_rect_height(dst);
   1307
   1308	src_x = src->x1 >> 16;
   1309	src_w = drm_rect_width(src) >> 16;
   1310	src_h = drm_rect_height(src) >> 16;
   1311
   1312	if (src_w == crtc_w && src_h == crtc_h)
   1313		return 0;
   1314
   1315	min_width = 3;
   1316
   1317	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
   1318		if (src_h & 1) {
   1319			drm_dbg_kms(&i915->drm, "Source height must be even with interlaced modes\n");
   1320			return -EINVAL;
   1321		}
   1322		min_height = 6;
   1323	} else {
   1324		min_height = 3;
   1325	}
   1326
   1327	width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
   1328
   1329	if (src_w < min_width || src_h < min_height ||
   1330	    src_w > 2048 || src_h > 2048) {
   1331		drm_dbg_kms(&i915->drm, "Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
   1332			    src_w, src_h, min_width, min_height, 2048, 2048);
   1333		return -EINVAL;
   1334	}
   1335
   1336	if (width_bytes > 4096) {
   1337		drm_dbg_kms(&i915->drm, "Fetch width (%d) exceeds hardware max with scaling (%u)\n",
   1338			    width_bytes, 4096);
   1339		return -EINVAL;
   1340	}
   1341
   1342	if (stride > 4096) {
   1343		drm_dbg_kms(&i915->drm, "Stride (%u) exceeds hardware max with scaling (%u)\n",
   1344			    stride, 4096);
   1345		return -EINVAL;
   1346	}
   1347
   1348	return 0;
   1349}
   1350
   1351static int
   1352g4x_sprite_check(struct intel_crtc_state *crtc_state,
   1353		 struct intel_plane_state *plane_state)
   1354{
   1355	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
   1356	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
   1357	int min_scale = DRM_PLANE_HELPER_NO_SCALING;
   1358	int max_scale = DRM_PLANE_HELPER_NO_SCALING;
   1359	int ret;
   1360
   1361	if (g4x_fb_scalable(plane_state->hw.fb)) {
   1362		if (DISPLAY_VER(dev_priv) < 7) {
   1363			min_scale = 1;
   1364			max_scale = 16 << 16;
   1365		} else if (IS_IVYBRIDGE(dev_priv)) {
   1366			min_scale = 1;
   1367			max_scale = 2 << 16;
   1368		}
   1369	}
   1370
   1371	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
   1372						min_scale, max_scale, true);
   1373	if (ret)
   1374		return ret;
   1375
   1376	ret = i9xx_check_plane_surface(plane_state);
   1377	if (ret)
   1378		return ret;
   1379
   1380	if (!plane_state->uapi.visible)
   1381		return 0;
   1382
   1383	ret = intel_plane_check_src_coordinates(plane_state);
   1384	if (ret)
   1385		return ret;
   1386
   1387	ret = g4x_sprite_check_scaling(crtc_state, plane_state);
   1388	if (ret)
   1389		return ret;
   1390
   1391	if (DISPLAY_VER(dev_priv) >= 7)
   1392		plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
   1393	else
   1394		plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
   1395
   1396	return 0;
   1397}
   1398
   1399int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
   1400{
   1401	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
   1402	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
   1403	unsigned int rotation = plane_state->hw.rotation;
   1404
   1405	/* CHV ignores the mirror bit when the rotate bit is set :( */
   1406	if (IS_CHERRYVIEW(dev_priv) &&
   1407	    rotation & DRM_MODE_ROTATE_180 &&
   1408	    rotation & DRM_MODE_REFLECT_X) {
   1409		drm_dbg_kms(&dev_priv->drm,
   1410			    "Cannot rotate and reflect at the same time\n");
   1411		return -EINVAL;
   1412	}
   1413
   1414	return 0;
   1415}
   1416
   1417static int
   1418vlv_sprite_check(struct intel_crtc_state *crtc_state,
   1419		 struct intel_plane_state *plane_state)
   1420{
   1421	int ret;
   1422
   1423	ret = chv_plane_check_rotation(plane_state);
   1424	if (ret)
   1425		return ret;
   1426
   1427	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
   1428						DRM_PLANE_HELPER_NO_SCALING,
   1429						DRM_PLANE_HELPER_NO_SCALING,
   1430						true);
   1431	if (ret)
   1432		return ret;
   1433
   1434	ret = i9xx_check_plane_surface(plane_state);
   1435	if (ret)
   1436		return ret;
   1437
   1438	if (!plane_state->uapi.visible)
   1439		return 0;
   1440
   1441	ret = intel_plane_check_src_coordinates(plane_state);
   1442	if (ret)
   1443		return ret;
   1444
   1445	plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
   1446
   1447	return 0;
   1448}
   1449
   1450static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
   1451{
   1452	return DISPLAY_VER(dev_priv) >= 9;
   1453}
   1454
   1455static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
   1456				 const struct drm_intel_sprite_colorkey *set)
   1457{
   1458	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
   1459	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
   1460	struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
   1461
   1462	*key = *set;
   1463
   1464	/*
   1465	 * We want src key enabled on the
   1466	 * sprite and not on the primary.
   1467	 */
   1468	if (plane->id == PLANE_PRIMARY &&
   1469	    set->flags & I915_SET_COLORKEY_SOURCE)
   1470		key->flags = 0;
   1471
   1472	/*
   1473	 * On SKL+ we want dst key enabled on
   1474	 * the primary and not on the sprite.
   1475	 */
   1476	if (DISPLAY_VER(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
   1477	    set->flags & I915_SET_COLORKEY_DESTINATION)
   1478		key->flags = 0;
   1479}
   1480
   1481int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
   1482				    struct drm_file *file_priv)
   1483{
   1484	struct drm_i915_private *dev_priv = to_i915(dev);
   1485	struct drm_intel_sprite_colorkey *set = data;
   1486	struct drm_plane *plane;
   1487	struct drm_plane_state *plane_state;
   1488	struct drm_atomic_state *state;
   1489	struct drm_modeset_acquire_ctx ctx;
   1490	int ret = 0;
   1491
   1492	/* ignore the pointless "none" flag */
   1493	set->flags &= ~I915_SET_COLORKEY_NONE;
   1494
   1495	if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
   1496		return -EINVAL;
   1497
   1498	/* Make sure we don't try to enable both src & dest simultaneously */
   1499	if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
   1500		return -EINVAL;
   1501
   1502	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
   1503	    set->flags & I915_SET_COLORKEY_DESTINATION)
   1504		return -EINVAL;
   1505
   1506	plane = drm_plane_find(dev, file_priv, set->plane_id);
   1507	if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
   1508		return -ENOENT;
   1509
   1510	/*
   1511	 * SKL+ only plane 2 can do destination keying against plane 1.
   1512	 * Also multiple planes can't do destination keying on the same
   1513	 * pipe simultaneously.
   1514	 */
   1515	if (DISPLAY_VER(dev_priv) >= 9 &&
   1516	    to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
   1517	    set->flags & I915_SET_COLORKEY_DESTINATION)
   1518		return -EINVAL;
   1519
   1520	drm_modeset_acquire_init(&ctx, 0);
   1521
   1522	state = drm_atomic_state_alloc(plane->dev);
   1523	if (!state) {
   1524		ret = -ENOMEM;
   1525		goto out;
   1526	}
   1527	state->acquire_ctx = &ctx;
   1528
   1529	while (1) {
   1530		plane_state = drm_atomic_get_plane_state(state, plane);
   1531		ret = PTR_ERR_OR_ZERO(plane_state);
   1532		if (!ret)
   1533			intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
   1534
   1535		/*
   1536		 * On some platforms we have to configure
   1537		 * the dst colorkey on the primary plane.
   1538		 */
   1539		if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
   1540			struct intel_crtc *crtc =
   1541				intel_crtc_for_pipe(dev_priv,
   1542						    to_intel_plane(plane)->pipe);
   1543
   1544			plane_state = drm_atomic_get_plane_state(state,
   1545								 crtc->base.primary);
   1546			ret = PTR_ERR_OR_ZERO(plane_state);
   1547			if (!ret)
   1548				intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
   1549		}
   1550
   1551		if (!ret)
   1552			ret = drm_atomic_commit(state);
   1553
   1554		if (ret != -EDEADLK)
   1555			break;
   1556
   1557		drm_atomic_state_clear(state);
   1558		drm_modeset_backoff(&ctx);
   1559	}
   1560
   1561	drm_atomic_state_put(state);
   1562out:
   1563	drm_modeset_drop_locks(&ctx);
   1564	drm_modeset_acquire_fini(&ctx);
   1565	return ret;
   1566}
   1567
   1568static const u32 g4x_sprite_formats[] = {
   1569	DRM_FORMAT_XRGB8888,
   1570	DRM_FORMAT_YUYV,
   1571	DRM_FORMAT_YVYU,
   1572	DRM_FORMAT_UYVY,
   1573	DRM_FORMAT_VYUY,
   1574};
   1575
   1576static const u32 snb_sprite_formats[] = {
   1577	DRM_FORMAT_XRGB8888,
   1578	DRM_FORMAT_XBGR8888,
   1579	DRM_FORMAT_XRGB2101010,
   1580	DRM_FORMAT_XBGR2101010,
   1581	DRM_FORMAT_XRGB16161616F,
   1582	DRM_FORMAT_XBGR16161616F,
   1583	DRM_FORMAT_YUYV,
   1584	DRM_FORMAT_YVYU,
   1585	DRM_FORMAT_UYVY,
   1586	DRM_FORMAT_VYUY,
   1587};
   1588
   1589static const u32 vlv_sprite_formats[] = {
   1590	DRM_FORMAT_C8,
   1591	DRM_FORMAT_RGB565,
   1592	DRM_FORMAT_XRGB8888,
   1593	DRM_FORMAT_XBGR8888,
   1594	DRM_FORMAT_ARGB8888,
   1595	DRM_FORMAT_ABGR8888,
   1596	DRM_FORMAT_XBGR2101010,
   1597	DRM_FORMAT_ABGR2101010,
   1598	DRM_FORMAT_YUYV,
   1599	DRM_FORMAT_YVYU,
   1600	DRM_FORMAT_UYVY,
   1601	DRM_FORMAT_VYUY,
   1602};
   1603
   1604static const u32 chv_pipe_b_sprite_formats[] = {
   1605	DRM_FORMAT_C8,
   1606	DRM_FORMAT_RGB565,
   1607	DRM_FORMAT_XRGB8888,
   1608	DRM_FORMAT_XBGR8888,
   1609	DRM_FORMAT_ARGB8888,
   1610	DRM_FORMAT_ABGR8888,
   1611	DRM_FORMAT_XRGB2101010,
   1612	DRM_FORMAT_XBGR2101010,
   1613	DRM_FORMAT_ARGB2101010,
   1614	DRM_FORMAT_ABGR2101010,
   1615	DRM_FORMAT_YUYV,
   1616	DRM_FORMAT_YVYU,
   1617	DRM_FORMAT_UYVY,
   1618	DRM_FORMAT_VYUY,
   1619};
   1620
   1621static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
   1622					    u32 format, u64 modifier)
   1623{
   1624	if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
   1625		return false;
   1626
   1627	switch (format) {
   1628	case DRM_FORMAT_XRGB8888:
   1629	case DRM_FORMAT_YUYV:
   1630	case DRM_FORMAT_YVYU:
   1631	case DRM_FORMAT_UYVY:
   1632	case DRM_FORMAT_VYUY:
   1633		if (modifier == DRM_FORMAT_MOD_LINEAR ||
   1634		    modifier == I915_FORMAT_MOD_X_TILED)
   1635			return true;
   1636		fallthrough;
   1637	default:
   1638		return false;
   1639	}
   1640}
   1641
   1642static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
   1643					    u32 format, u64 modifier)
   1644{
   1645	if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
   1646		return false;
   1647
   1648	switch (format) {
   1649	case DRM_FORMAT_XRGB8888:
   1650	case DRM_FORMAT_XBGR8888:
   1651	case DRM_FORMAT_XRGB2101010:
   1652	case DRM_FORMAT_XBGR2101010:
   1653	case DRM_FORMAT_XRGB16161616F:
   1654	case DRM_FORMAT_XBGR16161616F:
   1655	case DRM_FORMAT_YUYV:
   1656	case DRM_FORMAT_YVYU:
   1657	case DRM_FORMAT_UYVY:
   1658	case DRM_FORMAT_VYUY:
   1659		if (modifier == DRM_FORMAT_MOD_LINEAR ||
   1660		    modifier == I915_FORMAT_MOD_X_TILED)
   1661			return true;
   1662		fallthrough;
   1663	default:
   1664		return false;
   1665	}
   1666}
   1667
   1668static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
   1669					    u32 format, u64 modifier)
   1670{
   1671	if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
   1672		return false;
   1673
   1674	switch (format) {
   1675	case DRM_FORMAT_C8:
   1676	case DRM_FORMAT_RGB565:
   1677	case DRM_FORMAT_ABGR8888:
   1678	case DRM_FORMAT_ARGB8888:
   1679	case DRM_FORMAT_XBGR8888:
   1680	case DRM_FORMAT_XRGB8888:
   1681	case DRM_FORMAT_XBGR2101010:
   1682	case DRM_FORMAT_ABGR2101010:
   1683	case DRM_FORMAT_XRGB2101010:
   1684	case DRM_FORMAT_ARGB2101010:
   1685	case DRM_FORMAT_YUYV:
   1686	case DRM_FORMAT_YVYU:
   1687	case DRM_FORMAT_UYVY:
   1688	case DRM_FORMAT_VYUY:
   1689		if (modifier == DRM_FORMAT_MOD_LINEAR ||
   1690		    modifier == I915_FORMAT_MOD_X_TILED)
   1691			return true;
   1692		fallthrough;
   1693	default:
   1694		return false;
   1695	}
   1696}
   1697
   1698static const struct drm_plane_funcs g4x_sprite_funcs = {
   1699	.update_plane = drm_atomic_helper_update_plane,
   1700	.disable_plane = drm_atomic_helper_disable_plane,
   1701	.destroy = intel_plane_destroy,
   1702	.atomic_duplicate_state = intel_plane_duplicate_state,
   1703	.atomic_destroy_state = intel_plane_destroy_state,
   1704	.format_mod_supported = g4x_sprite_format_mod_supported,
   1705};
   1706
   1707static const struct drm_plane_funcs snb_sprite_funcs = {
   1708	.update_plane = drm_atomic_helper_update_plane,
   1709	.disable_plane = drm_atomic_helper_disable_plane,
   1710	.destroy = intel_plane_destroy,
   1711	.atomic_duplicate_state = intel_plane_duplicate_state,
   1712	.atomic_destroy_state = intel_plane_destroy_state,
   1713	.format_mod_supported = snb_sprite_format_mod_supported,
   1714};
   1715
   1716static const struct drm_plane_funcs vlv_sprite_funcs = {
   1717	.update_plane = drm_atomic_helper_update_plane,
   1718	.disable_plane = drm_atomic_helper_disable_plane,
   1719	.destroy = intel_plane_destroy,
   1720	.atomic_duplicate_state = intel_plane_duplicate_state,
   1721	.atomic_destroy_state = intel_plane_destroy_state,
   1722	.format_mod_supported = vlv_sprite_format_mod_supported,
   1723};
   1724
   1725struct intel_plane *
   1726intel_sprite_plane_create(struct drm_i915_private *dev_priv,
   1727			  enum pipe pipe, int sprite)
   1728{
   1729	struct intel_plane *plane;
   1730	const struct drm_plane_funcs *plane_funcs;
   1731	unsigned int supported_rotations;
   1732	const u64 *modifiers;
   1733	const u32 *formats;
   1734	int num_formats;
   1735	int ret, zpos;
   1736
   1737	plane = intel_plane_alloc();
   1738	if (IS_ERR(plane))
   1739		return plane;
   1740
   1741	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
   1742		plane->update_noarm = vlv_sprite_update_noarm;
   1743		plane->update_arm = vlv_sprite_update_arm;
   1744		plane->disable_arm = vlv_sprite_disable_arm;
   1745		plane->get_hw_state = vlv_sprite_get_hw_state;
   1746		plane->check_plane = vlv_sprite_check;
   1747		plane->max_stride = i965_plane_max_stride;
   1748		plane->min_cdclk = vlv_plane_min_cdclk;
   1749
   1750		if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
   1751			formats = chv_pipe_b_sprite_formats;
   1752			num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
   1753		} else {
   1754			formats = vlv_sprite_formats;
   1755			num_formats = ARRAY_SIZE(vlv_sprite_formats);
   1756		}
   1757
   1758		plane_funcs = &vlv_sprite_funcs;
   1759	} else if (DISPLAY_VER(dev_priv) >= 7) {
   1760		plane->update_noarm = ivb_sprite_update_noarm;
   1761		plane->update_arm = ivb_sprite_update_arm;
   1762		plane->disable_arm = ivb_sprite_disable_arm;
   1763		plane->get_hw_state = ivb_sprite_get_hw_state;
   1764		plane->check_plane = g4x_sprite_check;
   1765
   1766		if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
   1767			plane->max_stride = hsw_sprite_max_stride;
   1768			plane->min_cdclk = hsw_plane_min_cdclk;
   1769		} else {
   1770			plane->max_stride = g4x_sprite_max_stride;
   1771			plane->min_cdclk = ivb_sprite_min_cdclk;
   1772		}
   1773
   1774		formats = snb_sprite_formats;
   1775		num_formats = ARRAY_SIZE(snb_sprite_formats);
   1776
   1777		plane_funcs = &snb_sprite_funcs;
   1778	} else {
   1779		plane->update_noarm = g4x_sprite_update_noarm;
   1780		plane->update_arm = g4x_sprite_update_arm;
   1781		plane->disable_arm = g4x_sprite_disable_arm;
   1782		plane->get_hw_state = g4x_sprite_get_hw_state;
   1783		plane->check_plane = g4x_sprite_check;
   1784		plane->max_stride = g4x_sprite_max_stride;
   1785		plane->min_cdclk = g4x_sprite_min_cdclk;
   1786
   1787		if (IS_SANDYBRIDGE(dev_priv)) {
   1788			formats = snb_sprite_formats;
   1789			num_formats = ARRAY_SIZE(snb_sprite_formats);
   1790
   1791			plane_funcs = &snb_sprite_funcs;
   1792		} else {
   1793			formats = g4x_sprite_formats;
   1794			num_formats = ARRAY_SIZE(g4x_sprite_formats);
   1795
   1796			plane_funcs = &g4x_sprite_funcs;
   1797		}
   1798	}
   1799
   1800	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
   1801		supported_rotations =
   1802			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
   1803			DRM_MODE_REFLECT_X;
   1804	} else {
   1805		supported_rotations =
   1806			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
   1807	}
   1808
   1809	plane->pipe = pipe;
   1810	plane->id = PLANE_SPRITE0 + sprite;
   1811	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
   1812
   1813	modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X);
   1814
   1815	ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
   1816				       0, plane_funcs,
   1817				       formats, num_formats, modifiers,
   1818				       DRM_PLANE_TYPE_OVERLAY,
   1819				       "sprite %c", sprite_name(pipe, sprite));
   1820	kfree(modifiers);
   1821
   1822	if (ret)
   1823		goto fail;
   1824
   1825	drm_plane_create_rotation_property(&plane->base,
   1826					   DRM_MODE_ROTATE_0,
   1827					   supported_rotations);
   1828
   1829	drm_plane_create_color_properties(&plane->base,
   1830					  BIT(DRM_COLOR_YCBCR_BT601) |
   1831					  BIT(DRM_COLOR_YCBCR_BT709),
   1832					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
   1833					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
   1834					  DRM_COLOR_YCBCR_BT709,
   1835					  DRM_COLOR_YCBCR_LIMITED_RANGE);
   1836
   1837	zpos = sprite + 1;
   1838	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
   1839
   1840	intel_plane_helper_add(plane);
   1841
   1842	return plane;
   1843
   1844fail:
   1845	intel_plane_free(plane);
   1846
   1847	return ERR_PTR(ret);
   1848}