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

i9xx_plane.c (30415B)


      1// SPDX-License-Identifier: MIT
      2/*
      3 * Copyright © 2020 Intel Corporation
      4 */
      5#include <linux/kernel.h>
      6
      7#include <drm/drm_atomic_helper.h>
      8#include <drm/drm_fourcc.h>
      9#include <drm/drm_plane_helper.h>
     10
     11#include "intel_atomic.h"
     12#include "intel_atomic_plane.h"
     13#include "intel_de.h"
     14#include "intel_display_types.h"
     15#include "intel_fb.h"
     16#include "intel_fbc.h"
     17#include "intel_sprite.h"
     18#include "i9xx_plane.h"
     19
     20/* Primary plane formats for gen <= 3 */
     21static const u32 i8xx_primary_formats[] = {
     22	DRM_FORMAT_C8,
     23	DRM_FORMAT_XRGB1555,
     24	DRM_FORMAT_RGB565,
     25	DRM_FORMAT_XRGB8888,
     26};
     27
     28/* Primary plane formats for ivb (no fp16 due to hw issue) */
     29static const u32 ivb_primary_formats[] = {
     30	DRM_FORMAT_C8,
     31	DRM_FORMAT_RGB565,
     32	DRM_FORMAT_XRGB8888,
     33	DRM_FORMAT_XBGR8888,
     34	DRM_FORMAT_XRGB2101010,
     35	DRM_FORMAT_XBGR2101010,
     36};
     37
     38/* Primary plane formats for gen >= 4, except ivb */
     39static const u32 i965_primary_formats[] = {
     40	DRM_FORMAT_C8,
     41	DRM_FORMAT_RGB565,
     42	DRM_FORMAT_XRGB8888,
     43	DRM_FORMAT_XBGR8888,
     44	DRM_FORMAT_XRGB2101010,
     45	DRM_FORMAT_XBGR2101010,
     46	DRM_FORMAT_XBGR16161616F,
     47};
     48
     49/* Primary plane formats for vlv/chv */
     50static const u32 vlv_primary_formats[] = {
     51	DRM_FORMAT_C8,
     52	DRM_FORMAT_RGB565,
     53	DRM_FORMAT_XRGB8888,
     54	DRM_FORMAT_XBGR8888,
     55	DRM_FORMAT_ARGB8888,
     56	DRM_FORMAT_ABGR8888,
     57	DRM_FORMAT_XRGB2101010,
     58	DRM_FORMAT_XBGR2101010,
     59	DRM_FORMAT_ARGB2101010,
     60	DRM_FORMAT_ABGR2101010,
     61	DRM_FORMAT_XBGR16161616F,
     62};
     63
     64static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
     65					    u32 format, u64 modifier)
     66{
     67	if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
     68		return false;
     69
     70	switch (format) {
     71	case DRM_FORMAT_C8:
     72	case DRM_FORMAT_RGB565:
     73	case DRM_FORMAT_XRGB1555:
     74	case DRM_FORMAT_XRGB8888:
     75		return modifier == DRM_FORMAT_MOD_LINEAR ||
     76			modifier == I915_FORMAT_MOD_X_TILED;
     77	default:
     78		return false;
     79	}
     80}
     81
     82static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
     83					    u32 format, u64 modifier)
     84{
     85	if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
     86		return false;
     87
     88	switch (format) {
     89	case DRM_FORMAT_C8:
     90	case DRM_FORMAT_RGB565:
     91	case DRM_FORMAT_XRGB8888:
     92	case DRM_FORMAT_XBGR8888:
     93	case DRM_FORMAT_ARGB8888:
     94	case DRM_FORMAT_ABGR8888:
     95	case DRM_FORMAT_XRGB2101010:
     96	case DRM_FORMAT_XBGR2101010:
     97	case DRM_FORMAT_ARGB2101010:
     98	case DRM_FORMAT_ABGR2101010:
     99	case DRM_FORMAT_XBGR16161616F:
    100		return modifier == DRM_FORMAT_MOD_LINEAR ||
    101			modifier == I915_FORMAT_MOD_X_TILED;
    102	default:
    103		return false;
    104	}
    105}
    106
    107static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
    108			       enum i9xx_plane_id i9xx_plane)
    109{
    110	if (!HAS_FBC(dev_priv))
    111		return false;
    112
    113	if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
    114		return i9xx_plane == PLANE_A; /* tied to pipe A */
    115	else if (IS_IVYBRIDGE(dev_priv))
    116		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
    117			i9xx_plane == PLANE_C;
    118	else if (DISPLAY_VER(dev_priv) >= 4)
    119		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
    120	else
    121		return i9xx_plane == PLANE_A;
    122}
    123
    124static struct intel_fbc *i9xx_plane_fbc(struct drm_i915_private *dev_priv,
    125					enum i9xx_plane_id i9xx_plane)
    126{
    127	if (i9xx_plane_has_fbc(dev_priv, i9xx_plane))
    128		return dev_priv->fbc[INTEL_FBC_A];
    129	else
    130		return NULL;
    131}
    132
    133static bool i9xx_plane_has_windowing(struct intel_plane *plane)
    134{
    135	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    136	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
    137
    138	if (IS_CHERRYVIEW(dev_priv))
    139		return i9xx_plane == PLANE_B;
    140	else if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
    141		return false;
    142	else if (DISPLAY_VER(dev_priv) == 4)
    143		return i9xx_plane == PLANE_C;
    144	else
    145		return i9xx_plane == PLANE_B ||
    146			i9xx_plane == PLANE_C;
    147}
    148
    149static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
    150			  const struct intel_plane_state *plane_state)
    151{
    152	struct drm_i915_private *dev_priv =
    153		to_i915(plane_state->uapi.plane->dev);
    154	const struct drm_framebuffer *fb = plane_state->hw.fb;
    155	unsigned int rotation = plane_state->hw.rotation;
    156	u32 dspcntr;
    157
    158	dspcntr = DISP_ENABLE;
    159
    160	if (IS_G4X(dev_priv) || IS_IRONLAKE(dev_priv) ||
    161	    IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv))
    162		dspcntr |= DISP_TRICKLE_FEED_DISABLE;
    163
    164	switch (fb->format->format) {
    165	case DRM_FORMAT_C8:
    166		dspcntr |= DISP_FORMAT_8BPP;
    167		break;
    168	case DRM_FORMAT_XRGB1555:
    169		dspcntr |= DISP_FORMAT_BGRX555;
    170		break;
    171	case DRM_FORMAT_ARGB1555:
    172		dspcntr |= DISP_FORMAT_BGRA555;
    173		break;
    174	case DRM_FORMAT_RGB565:
    175		dspcntr |= DISP_FORMAT_BGRX565;
    176		break;
    177	case DRM_FORMAT_XRGB8888:
    178		dspcntr |= DISP_FORMAT_BGRX888;
    179		break;
    180	case DRM_FORMAT_XBGR8888:
    181		dspcntr |= DISP_FORMAT_RGBX888;
    182		break;
    183	case DRM_FORMAT_ARGB8888:
    184		dspcntr |= DISP_FORMAT_BGRA888;
    185		break;
    186	case DRM_FORMAT_ABGR8888:
    187		dspcntr |= DISP_FORMAT_RGBA888;
    188		break;
    189	case DRM_FORMAT_XRGB2101010:
    190		dspcntr |= DISP_FORMAT_BGRX101010;
    191		break;
    192	case DRM_FORMAT_XBGR2101010:
    193		dspcntr |= DISP_FORMAT_RGBX101010;
    194		break;
    195	case DRM_FORMAT_ARGB2101010:
    196		dspcntr |= DISP_FORMAT_BGRA101010;
    197		break;
    198	case DRM_FORMAT_ABGR2101010:
    199		dspcntr |= DISP_FORMAT_RGBA101010;
    200		break;
    201	case DRM_FORMAT_XBGR16161616F:
    202		dspcntr |= DISP_FORMAT_RGBX161616;
    203		break;
    204	default:
    205		MISSING_CASE(fb->format->format);
    206		return 0;
    207	}
    208
    209	if (DISPLAY_VER(dev_priv) >= 4 &&
    210	    fb->modifier == I915_FORMAT_MOD_X_TILED)
    211		dspcntr |= DISP_TILED;
    212
    213	if (rotation & DRM_MODE_ROTATE_180)
    214		dspcntr |= DISP_ROTATE_180;
    215
    216	if (rotation & DRM_MODE_REFLECT_X)
    217		dspcntr |= DISP_MIRROR;
    218
    219	return dspcntr;
    220}
    221
    222int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
    223{
    224	struct drm_i915_private *dev_priv =
    225		to_i915(plane_state->uapi.plane->dev);
    226	const struct drm_framebuffer *fb = plane_state->hw.fb;
    227	int src_x, src_y, src_w;
    228	u32 offset;
    229	int ret;
    230
    231	ret = intel_plane_compute_gtt(plane_state);
    232	if (ret)
    233		return ret;
    234
    235	if (!plane_state->uapi.visible)
    236		return 0;
    237
    238	src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
    239	src_x = plane_state->uapi.src.x1 >> 16;
    240	src_y = plane_state->uapi.src.y1 >> 16;
    241
    242	/* Undocumented hardware limit on i965/g4x/vlv/chv */
    243	if (HAS_GMCH(dev_priv) && fb->format->cpp[0] == 8 && src_w > 2048)
    244		return -EINVAL;
    245
    246	intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
    247
    248	if (DISPLAY_VER(dev_priv) >= 4)
    249		offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
    250							    plane_state, 0);
    251	else
    252		offset = 0;
    253
    254	/*
    255	 * When using an X-tiled surface the plane starts to
    256	 * misbehave if the x offset + width exceeds the stride.
    257	 * hsw/bdw: underrun galore
    258	 * ilk/snb/ivb: wrap to the next tile row mid scanout
    259	 * i965/g4x: so far appear immune to this
    260	 * vlv/chv: TODO check
    261	 *
    262	 * Linear surfaces seem to work just fine, even on hsw/bdw
    263	 * despite them not using the linear offset anymore.
    264	 */
    265	if (DISPLAY_VER(dev_priv) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) {
    266		u32 alignment = intel_surf_alignment(fb, 0);
    267		int cpp = fb->format->cpp[0];
    268
    269		while ((src_x + src_w) * cpp > plane_state->view.color_plane[0].mapping_stride) {
    270			if (offset == 0) {
    271				drm_dbg_kms(&dev_priv->drm,
    272					    "Unable to find suitable display surface offset due to X-tiling\n");
    273				return -EINVAL;
    274			}
    275
    276			offset = intel_plane_adjust_aligned_offset(&src_x, &src_y, plane_state, 0,
    277								   offset, offset - alignment);
    278		}
    279	}
    280
    281	/*
    282	 * Put the final coordinates back so that the src
    283	 * coordinate checks will see the right values.
    284	 */
    285	drm_rect_translate_to(&plane_state->uapi.src,
    286			      src_x << 16, src_y << 16);
    287
    288	/* HSW/BDW do this automagically in hardware */
    289	if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) {
    290		unsigned int rotation = plane_state->hw.rotation;
    291		int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
    292		int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
    293
    294		if (rotation & DRM_MODE_ROTATE_180) {
    295			src_x += src_w - 1;
    296			src_y += src_h - 1;
    297		} else if (rotation & DRM_MODE_REFLECT_X) {
    298			src_x += src_w - 1;
    299		}
    300	}
    301
    302	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
    303		drm_WARN_ON(&dev_priv->drm, src_x > 8191 || src_y > 4095);
    304	} else if (DISPLAY_VER(dev_priv) >= 4 &&
    305		   fb->modifier == I915_FORMAT_MOD_X_TILED) {
    306		drm_WARN_ON(&dev_priv->drm, src_x > 4095 || src_y > 4095);
    307	}
    308
    309	plane_state->view.color_plane[0].offset = offset;
    310	plane_state->view.color_plane[0].x = src_x;
    311	plane_state->view.color_plane[0].y = src_y;
    312
    313	return 0;
    314}
    315
    316static int
    317i9xx_plane_check(struct intel_crtc_state *crtc_state,
    318		 struct intel_plane_state *plane_state)
    319{
    320	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
    321	int ret;
    322
    323	ret = chv_plane_check_rotation(plane_state);
    324	if (ret)
    325		return ret;
    326
    327	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
    328						DRM_PLANE_HELPER_NO_SCALING,
    329						DRM_PLANE_HELPER_NO_SCALING,
    330						i9xx_plane_has_windowing(plane));
    331	if (ret)
    332		return ret;
    333
    334	ret = i9xx_check_plane_surface(plane_state);
    335	if (ret)
    336		return ret;
    337
    338	if (!plane_state->uapi.visible)
    339		return 0;
    340
    341	ret = intel_plane_check_src_coordinates(plane_state);
    342	if (ret)
    343		return ret;
    344
    345	plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
    346
    347	return 0;
    348}
    349
    350static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
    351{
    352	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
    353	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
    354	u32 dspcntr = 0;
    355
    356	if (crtc_state->gamma_enable)
    357		dspcntr |= DISP_PIPE_GAMMA_ENABLE;
    358
    359	if (crtc_state->csc_enable)
    360		dspcntr |= DISP_PIPE_CSC_ENABLE;
    361
    362	if (DISPLAY_VER(dev_priv) < 5)
    363		dspcntr |= DISP_PIPE_SEL(crtc->pipe);
    364
    365	return dspcntr;
    366}
    367
    368static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,
    369			     const struct intel_plane_state *plane_state,
    370			     unsigned int *num, unsigned int *den)
    371{
    372	const struct drm_framebuffer *fb = plane_state->hw.fb;
    373	unsigned int cpp = fb->format->cpp[0];
    374
    375	/*
    376	 * g4x bspec says 64bpp pixel rate can't exceed 80%
    377	 * of cdclk when the sprite plane is enabled on the
    378	 * same pipe. ilk/snb bspec says 64bpp pixel rate is
    379	 * never allowed to exceed 80% of cdclk. Let's just go
    380	 * with the ilk/snb limit always.
    381	 */
    382	if (cpp == 8) {
    383		*num = 10;
    384		*den = 8;
    385	} else {
    386		*num = 1;
    387		*den = 1;
    388	}
    389}
    390
    391static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
    392				const struct intel_plane_state *plane_state)
    393{
    394	unsigned int pixel_rate;
    395	unsigned int num, den;
    396
    397	/*
    398	 * Note that crtc_state->pixel_rate accounts for both
    399	 * horizontal and vertical panel fitter downscaling factors.
    400	 * Pre-HSW bspec tells us to only consider the horizontal
    401	 * downscaling factor here. We ignore that and just consider
    402	 * both for simplicity.
    403	 */
    404	pixel_rate = crtc_state->pixel_rate;
    405
    406	i9xx_plane_ratio(crtc_state, plane_state, &num, &den);
    407
    408	/* two pixels per clock with double wide pipe */
    409	if (crtc_state->double_wide)
    410		den *= 2;
    411
    412	return DIV_ROUND_UP(pixel_rate * num, den);
    413}
    414
    415static void i9xx_plane_update_noarm(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	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
    421
    422	intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
    423			  plane_state->view.color_plane[0].mapping_stride);
    424
    425	if (DISPLAY_VER(dev_priv) < 4) {
    426		int crtc_x = plane_state->uapi.dst.x1;
    427		int crtc_y = plane_state->uapi.dst.y1;
    428		int crtc_w = drm_rect_width(&plane_state->uapi.dst);
    429		int crtc_h = drm_rect_height(&plane_state->uapi.dst);
    430
    431		/*
    432		 * PLANE_A doesn't actually have a full window
    433		 * generator but let's assume we still need to
    434		 * program whatever is there.
    435		 */
    436		intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane),
    437				  DISP_POS_Y(crtc_y) | DISP_POS_X(crtc_x));
    438		intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
    439				  DISP_HEIGHT(crtc_h - 1) | DISP_WIDTH(crtc_w - 1));
    440	}
    441}
    442
    443static void i9xx_plane_update_arm(struct intel_plane *plane,
    444				  const struct intel_crtc_state *crtc_state,
    445				  const struct intel_plane_state *plane_state)
    446{
    447	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    448	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
    449	int x = plane_state->view.color_plane[0].x;
    450	int y = plane_state->view.color_plane[0].y;
    451	u32 dspcntr, dspaddr_offset, linear_offset;
    452
    453	dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
    454
    455	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
    456
    457	if (DISPLAY_VER(dev_priv) >= 4)
    458		dspaddr_offset = plane_state->view.color_plane[0].offset;
    459	else
    460		dspaddr_offset = linear_offset;
    461
    462	if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
    463		int crtc_x = plane_state->uapi.dst.x1;
    464		int crtc_y = plane_state->uapi.dst.y1;
    465		int crtc_w = drm_rect_width(&plane_state->uapi.dst);
    466		int crtc_h = drm_rect_height(&plane_state->uapi.dst);
    467
    468		intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane),
    469				  PRIM_POS_Y(crtc_y) | PRIM_POS_X(crtc_x));
    470		intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane),
    471				  PRIM_HEIGHT(crtc_h - 1) | PRIM_WIDTH(crtc_w - 1));
    472		intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0);
    473	}
    474
    475	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
    476		intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane),
    477				  DISP_OFFSET_Y(y) | DISP_OFFSET_X(x));
    478	} else if (DISPLAY_VER(dev_priv) >= 4) {
    479		intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane),
    480				  linear_offset);
    481		intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane),
    482				  DISP_OFFSET_Y(y) | DISP_OFFSET_X(x));
    483	}
    484
    485	/*
    486	 * The control register self-arms if the plane was previously
    487	 * disabled. Try to make the plane enable atomic by writing
    488	 * the control register just before the surface register.
    489	 */
    490	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
    491
    492	if (DISPLAY_VER(dev_priv) >= 4)
    493		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
    494				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
    495	else
    496		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
    497				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
    498}
    499
    500static void i830_plane_update_arm(struct intel_plane *plane,
    501				  const struct intel_crtc_state *crtc_state,
    502				  const struct intel_plane_state *plane_state)
    503{
    504	/*
    505	 * On i830/i845 all registers are self-arming [ALM040].
    506	 *
    507	 * Additional breakage on i830 causes register reads to return
    508	 * the last latched value instead of the last written value [ALM026].
    509	 */
    510	i9xx_plane_update_noarm(plane, crtc_state, plane_state);
    511	i9xx_plane_update_arm(plane, crtc_state, plane_state);
    512}
    513
    514static void i9xx_plane_disable_arm(struct intel_plane *plane,
    515				   const struct intel_crtc_state *crtc_state)
    516{
    517	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    518	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
    519	u32 dspcntr;
    520
    521	/*
    522	 * DSPCNTR pipe gamma enable on g4x+ and pipe csc
    523	 * enable on ilk+ affect the pipe bottom color as
    524	 * well, so we must configure them even if the plane
    525	 * is disabled.
    526	 *
    527	 * On pre-g4x there is no way to gamma correct the
    528	 * pipe bottom color but we'll keep on doing this
    529	 * anyway so that the crtc state readout works correctly.
    530	 */
    531	dspcntr = i9xx_plane_ctl_crtc(crtc_state);
    532
    533	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
    534
    535	if (DISPLAY_VER(dev_priv) >= 4)
    536		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
    537	else
    538		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
    539}
    540
    541static void
    542g4x_primary_async_flip(struct intel_plane *plane,
    543		       const struct intel_crtc_state *crtc_state,
    544		       const struct intel_plane_state *plane_state,
    545		       bool async_flip)
    546{
    547	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    548	u32 dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
    549	u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
    550	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
    551
    552	if (async_flip)
    553		dspcntr |= DISP_ASYNC_FLIP;
    554
    555	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
    556
    557	intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
    558			  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
    559}
    560
    561static void
    562vlv_primary_async_flip(struct intel_plane *plane,
    563		       const struct intel_crtc_state *crtc_state,
    564		       const struct intel_plane_state *plane_state,
    565		       bool async_flip)
    566{
    567	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    568	u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
    569	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
    570
    571	intel_de_write_fw(dev_priv, DSPADDR_VLV(i9xx_plane),
    572			  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
    573}
    574
    575static void
    576bdw_primary_enable_flip_done(struct intel_plane *plane)
    577{
    578	struct drm_i915_private *i915 = to_i915(plane->base.dev);
    579	enum pipe pipe = plane->pipe;
    580
    581	spin_lock_irq(&i915->irq_lock);
    582	bdw_enable_pipe_irq(i915, pipe, GEN8_PIPE_PRIMARY_FLIP_DONE);
    583	spin_unlock_irq(&i915->irq_lock);
    584}
    585
    586static void
    587bdw_primary_disable_flip_done(struct intel_plane *plane)
    588{
    589	struct drm_i915_private *i915 = to_i915(plane->base.dev);
    590	enum pipe pipe = plane->pipe;
    591
    592	spin_lock_irq(&i915->irq_lock);
    593	bdw_disable_pipe_irq(i915, pipe, GEN8_PIPE_PRIMARY_FLIP_DONE);
    594	spin_unlock_irq(&i915->irq_lock);
    595}
    596
    597static void
    598ivb_primary_enable_flip_done(struct intel_plane *plane)
    599{
    600	struct drm_i915_private *i915 = to_i915(plane->base.dev);
    601
    602	spin_lock_irq(&i915->irq_lock);
    603	ilk_enable_display_irq(i915, DE_PLANE_FLIP_DONE_IVB(plane->i9xx_plane));
    604	spin_unlock_irq(&i915->irq_lock);
    605}
    606
    607static void
    608ivb_primary_disable_flip_done(struct intel_plane *plane)
    609{
    610	struct drm_i915_private *i915 = to_i915(plane->base.dev);
    611
    612	spin_lock_irq(&i915->irq_lock);
    613	ilk_disable_display_irq(i915, DE_PLANE_FLIP_DONE_IVB(plane->i9xx_plane));
    614	spin_unlock_irq(&i915->irq_lock);
    615}
    616
    617static void
    618ilk_primary_enable_flip_done(struct intel_plane *plane)
    619{
    620	struct drm_i915_private *i915 = to_i915(plane->base.dev);
    621
    622	spin_lock_irq(&i915->irq_lock);
    623	ilk_enable_display_irq(i915, DE_PLANE_FLIP_DONE(plane->i9xx_plane));
    624	spin_unlock_irq(&i915->irq_lock);
    625}
    626
    627static void
    628ilk_primary_disable_flip_done(struct intel_plane *plane)
    629{
    630	struct drm_i915_private *i915 = to_i915(plane->base.dev);
    631
    632	spin_lock_irq(&i915->irq_lock);
    633	ilk_disable_display_irq(i915, DE_PLANE_FLIP_DONE(plane->i9xx_plane));
    634	spin_unlock_irq(&i915->irq_lock);
    635}
    636
    637static void
    638vlv_primary_enable_flip_done(struct intel_plane *plane)
    639{
    640	struct drm_i915_private *i915 = to_i915(plane->base.dev);
    641	enum pipe pipe = plane->pipe;
    642
    643	spin_lock_irq(&i915->irq_lock);
    644	i915_enable_pipestat(i915, pipe, PLANE_FLIP_DONE_INT_STATUS_VLV);
    645	spin_unlock_irq(&i915->irq_lock);
    646}
    647
    648static void
    649vlv_primary_disable_flip_done(struct intel_plane *plane)
    650{
    651	struct drm_i915_private *i915 = to_i915(plane->base.dev);
    652	enum pipe pipe = plane->pipe;
    653
    654	spin_lock_irq(&i915->irq_lock);
    655	i915_disable_pipestat(i915, pipe, PLANE_FLIP_DONE_INT_STATUS_VLV);
    656	spin_unlock_irq(&i915->irq_lock);
    657}
    658
    659static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
    660				    enum pipe *pipe)
    661{
    662	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    663	enum intel_display_power_domain power_domain;
    664	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
    665	intel_wakeref_t wakeref;
    666	bool ret;
    667	u32 val;
    668
    669	/*
    670	 * Not 100% correct for planes that can move between pipes,
    671	 * but that's only the case for gen2-4 which don't have any
    672	 * display power wells.
    673	 */
    674	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
    675	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
    676	if (!wakeref)
    677		return false;
    678
    679	val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
    680
    681	ret = val & DISP_ENABLE;
    682
    683	if (DISPLAY_VER(dev_priv) >= 5)
    684		*pipe = plane->pipe;
    685	else
    686		*pipe = REG_FIELD_GET(DISP_PIPE_SEL_MASK, val);
    687
    688	intel_display_power_put(dev_priv, power_domain, wakeref);
    689
    690	return ret;
    691}
    692
    693static unsigned int
    694hsw_primary_max_stride(struct intel_plane *plane,
    695		       u32 pixel_format, u64 modifier,
    696		       unsigned int rotation)
    697{
    698	const struct drm_format_info *info = drm_format_info(pixel_format);
    699	int cpp = info->cpp[0];
    700
    701	/* Limit to 8k pixels to guarantee OFFSET.x doesn't get too big. */
    702	return min(8192 * cpp, 32 * 1024);
    703}
    704
    705static unsigned int
    706ilk_primary_max_stride(struct intel_plane *plane,
    707		       u32 pixel_format, u64 modifier,
    708		       unsigned int rotation)
    709{
    710	const struct drm_format_info *info = drm_format_info(pixel_format);
    711	int cpp = info->cpp[0];
    712
    713	/* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
    714	if (modifier == I915_FORMAT_MOD_X_TILED)
    715		return min(4096 * cpp, 32 * 1024);
    716	else
    717		return 32 * 1024;
    718}
    719
    720unsigned int
    721i965_plane_max_stride(struct intel_plane *plane,
    722		      u32 pixel_format, u64 modifier,
    723		      unsigned int rotation)
    724{
    725	const struct drm_format_info *info = drm_format_info(pixel_format);
    726	int cpp = info->cpp[0];
    727
    728	/* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
    729	if (modifier == I915_FORMAT_MOD_X_TILED)
    730		return min(4096 * cpp, 16 * 1024);
    731	else
    732		return 32 * 1024;
    733}
    734
    735static unsigned int
    736i9xx_plane_max_stride(struct intel_plane *plane,
    737		      u32 pixel_format, u64 modifier,
    738		      unsigned int rotation)
    739{
    740	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
    741
    742	if (DISPLAY_VER(dev_priv) >= 3) {
    743		if (modifier == I915_FORMAT_MOD_X_TILED)
    744			return 8*1024;
    745		else
    746			return 16*1024;
    747	} else {
    748		if (plane->i9xx_plane == PLANE_C)
    749			return 4*1024;
    750		else
    751			return 8*1024;
    752	}
    753}
    754
    755static const struct drm_plane_funcs i965_plane_funcs = {
    756	.update_plane = drm_atomic_helper_update_plane,
    757	.disable_plane = drm_atomic_helper_disable_plane,
    758	.destroy = intel_plane_destroy,
    759	.atomic_duplicate_state = intel_plane_duplicate_state,
    760	.atomic_destroy_state = intel_plane_destroy_state,
    761	.format_mod_supported = i965_plane_format_mod_supported,
    762};
    763
    764static const struct drm_plane_funcs i8xx_plane_funcs = {
    765	.update_plane = drm_atomic_helper_update_plane,
    766	.disable_plane = drm_atomic_helper_disable_plane,
    767	.destroy = intel_plane_destroy,
    768	.atomic_duplicate_state = intel_plane_duplicate_state,
    769	.atomic_destroy_state = intel_plane_destroy_state,
    770	.format_mod_supported = i8xx_plane_format_mod_supported,
    771};
    772
    773struct intel_plane *
    774intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
    775{
    776	struct intel_plane *plane;
    777	const struct drm_plane_funcs *plane_funcs;
    778	unsigned int supported_rotations;
    779	const u64 *modifiers;
    780	const u32 *formats;
    781	int num_formats;
    782	int ret, zpos;
    783
    784	plane = intel_plane_alloc();
    785	if (IS_ERR(plane))
    786		return plane;
    787
    788	plane->pipe = pipe;
    789	/*
    790	 * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
    791	 * port is hooked to pipe B. Hence we want plane A feeding pipe B.
    792	 */
    793	if (HAS_FBC(dev_priv) && DISPLAY_VER(dev_priv) < 4 &&
    794	    INTEL_NUM_PIPES(dev_priv) == 2)
    795		plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
    796	else
    797		plane->i9xx_plane = (enum i9xx_plane_id) pipe;
    798	plane->id = PLANE_PRIMARY;
    799	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
    800
    801	intel_fbc_add_plane(i9xx_plane_fbc(dev_priv, plane->i9xx_plane), plane);
    802
    803	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
    804		formats = vlv_primary_formats;
    805		num_formats = ARRAY_SIZE(vlv_primary_formats);
    806	} else if (DISPLAY_VER(dev_priv) >= 4) {
    807		/*
    808		 * WaFP16GammaEnabling:ivb
    809		 * "Workaround : When using the 64-bit format, the plane
    810		 *  output on each color channel has one quarter amplitude.
    811		 *  It can be brought up to full amplitude by using pipe
    812		 *  gamma correction or pipe color space conversion to
    813		 *  multiply the plane output by four."
    814		 *
    815		 * There is no dedicated plane gamma for the primary plane,
    816		 * and using the pipe gamma/csc could conflict with other
    817		 * planes, so we choose not to expose fp16 on IVB primary
    818		 * planes. HSW primary planes no longer have this problem.
    819		 */
    820		if (IS_IVYBRIDGE(dev_priv)) {
    821			formats = ivb_primary_formats;
    822			num_formats = ARRAY_SIZE(ivb_primary_formats);
    823		} else {
    824			formats = i965_primary_formats;
    825			num_formats = ARRAY_SIZE(i965_primary_formats);
    826		}
    827	} else {
    828		formats = i8xx_primary_formats;
    829		num_formats = ARRAY_SIZE(i8xx_primary_formats);
    830	}
    831
    832	if (DISPLAY_VER(dev_priv) >= 4)
    833		plane_funcs = &i965_plane_funcs;
    834	else
    835		plane_funcs = &i8xx_plane_funcs;
    836
    837	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
    838		plane->min_cdclk = vlv_plane_min_cdclk;
    839	else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
    840		plane->min_cdclk = hsw_plane_min_cdclk;
    841	else if (IS_IVYBRIDGE(dev_priv))
    842		plane->min_cdclk = ivb_plane_min_cdclk;
    843	else
    844		plane->min_cdclk = i9xx_plane_min_cdclk;
    845
    846	if (HAS_GMCH(dev_priv)) {
    847		if (DISPLAY_VER(dev_priv) >= 4)
    848			plane->max_stride = i965_plane_max_stride;
    849		else
    850			plane->max_stride = i9xx_plane_max_stride;
    851	} else {
    852		if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
    853			plane->max_stride = hsw_primary_max_stride;
    854		else
    855			plane->max_stride = ilk_primary_max_stride;
    856	}
    857
    858	if (IS_I830(dev_priv) || IS_I845G(dev_priv)) {
    859		plane->update_arm = i830_plane_update_arm;
    860	} else {
    861		plane->update_noarm = i9xx_plane_update_noarm;
    862		plane->update_arm = i9xx_plane_update_arm;
    863	}
    864	plane->disable_arm = i9xx_plane_disable_arm;
    865	plane->get_hw_state = i9xx_plane_get_hw_state;
    866	plane->check_plane = i9xx_plane_check;
    867
    868	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
    869		plane->async_flip = vlv_primary_async_flip;
    870		plane->enable_flip_done = vlv_primary_enable_flip_done;
    871		plane->disable_flip_done = vlv_primary_disable_flip_done;
    872	} else if (IS_BROADWELL(dev_priv)) {
    873		plane->need_async_flip_disable_wa = true;
    874		plane->async_flip = g4x_primary_async_flip;
    875		plane->enable_flip_done = bdw_primary_enable_flip_done;
    876		plane->disable_flip_done = bdw_primary_disable_flip_done;
    877	} else if (DISPLAY_VER(dev_priv) >= 7) {
    878		plane->async_flip = g4x_primary_async_flip;
    879		plane->enable_flip_done = ivb_primary_enable_flip_done;
    880		plane->disable_flip_done = ivb_primary_disable_flip_done;
    881	} else if (DISPLAY_VER(dev_priv) >= 5) {
    882		plane->async_flip = g4x_primary_async_flip;
    883		plane->enable_flip_done = ilk_primary_enable_flip_done;
    884		plane->disable_flip_done = ilk_primary_disable_flip_done;
    885	}
    886
    887	modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X);
    888
    889	if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
    890		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
    891					       0, plane_funcs,
    892					       formats, num_formats,
    893					       modifiers,
    894					       DRM_PLANE_TYPE_PRIMARY,
    895					       "primary %c", pipe_name(pipe));
    896	else
    897		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
    898					       0, plane_funcs,
    899					       formats, num_formats,
    900					       modifiers,
    901					       DRM_PLANE_TYPE_PRIMARY,
    902					       "plane %c",
    903					       plane_name(plane->i9xx_plane));
    904
    905	kfree(modifiers);
    906
    907	if (ret)
    908		goto fail;
    909
    910	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
    911		supported_rotations =
    912			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
    913			DRM_MODE_REFLECT_X;
    914	} else if (DISPLAY_VER(dev_priv) >= 4) {
    915		supported_rotations =
    916			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
    917	} else {
    918		supported_rotations = DRM_MODE_ROTATE_0;
    919	}
    920
    921	if (DISPLAY_VER(dev_priv) >= 4)
    922		drm_plane_create_rotation_property(&plane->base,
    923						   DRM_MODE_ROTATE_0,
    924						   supported_rotations);
    925
    926	zpos = 0;
    927	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
    928
    929	intel_plane_helper_add(plane);
    930
    931	return plane;
    932
    933fail:
    934	intel_plane_free(plane);
    935
    936	return ERR_PTR(ret);
    937}
    938
    939static int i9xx_format_to_fourcc(int format)
    940{
    941	switch (format) {
    942	case DISP_FORMAT_8BPP:
    943		return DRM_FORMAT_C8;
    944	case DISP_FORMAT_BGRA555:
    945		return DRM_FORMAT_ARGB1555;
    946	case DISP_FORMAT_BGRX555:
    947		return DRM_FORMAT_XRGB1555;
    948	case DISP_FORMAT_BGRX565:
    949		return DRM_FORMAT_RGB565;
    950	default:
    951	case DISP_FORMAT_BGRX888:
    952		return DRM_FORMAT_XRGB8888;
    953	case DISP_FORMAT_RGBX888:
    954		return DRM_FORMAT_XBGR8888;
    955	case DISP_FORMAT_BGRA888:
    956		return DRM_FORMAT_ARGB8888;
    957	case DISP_FORMAT_RGBA888:
    958		return DRM_FORMAT_ABGR8888;
    959	case DISP_FORMAT_BGRX101010:
    960		return DRM_FORMAT_XRGB2101010;
    961	case DISP_FORMAT_RGBX101010:
    962		return DRM_FORMAT_XBGR2101010;
    963	case DISP_FORMAT_BGRA101010:
    964		return DRM_FORMAT_ARGB2101010;
    965	case DISP_FORMAT_RGBA101010:
    966		return DRM_FORMAT_ABGR2101010;
    967	case DISP_FORMAT_RGBX161616:
    968		return DRM_FORMAT_XBGR16161616F;
    969	}
    970}
    971
    972void
    973i9xx_get_initial_plane_config(struct intel_crtc *crtc,
    974			      struct intel_initial_plane_config *plane_config)
    975{
    976	struct drm_device *dev = crtc->base.dev;
    977	struct drm_i915_private *dev_priv = to_i915(dev);
    978	struct intel_plane *plane = to_intel_plane(crtc->base.primary);
    979	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
    980	enum pipe pipe;
    981	u32 val, base, offset;
    982	int fourcc, pixel_format;
    983	unsigned int aligned_height;
    984	struct drm_framebuffer *fb;
    985	struct intel_framebuffer *intel_fb;
    986
    987	if (!plane->get_hw_state(plane, &pipe))
    988		return;
    989
    990	drm_WARN_ON(dev, pipe != crtc->pipe);
    991
    992	intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
    993	if (!intel_fb) {
    994		drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
    995		return;
    996	}
    997
    998	fb = &intel_fb->base;
    999
   1000	fb->dev = dev;
   1001
   1002	val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
   1003
   1004	if (DISPLAY_VER(dev_priv) >= 4) {
   1005		if (val & DISP_TILED) {
   1006			plane_config->tiling = I915_TILING_X;
   1007			fb->modifier = I915_FORMAT_MOD_X_TILED;
   1008		}
   1009
   1010		if (val & DISP_ROTATE_180)
   1011			plane_config->rotation = DRM_MODE_ROTATE_180;
   1012	}
   1013
   1014	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B &&
   1015	    val & DISP_MIRROR)
   1016		plane_config->rotation |= DRM_MODE_REFLECT_X;
   1017
   1018	pixel_format = val & DISP_FORMAT_MASK;
   1019	fourcc = i9xx_format_to_fourcc(pixel_format);
   1020	fb->format = drm_format_info(fourcc);
   1021
   1022	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
   1023		offset = intel_de_read(dev_priv, DSPOFFSET(i9xx_plane));
   1024		base = intel_de_read(dev_priv, DSPSURF(i9xx_plane)) & DISP_ADDR_MASK;
   1025	} else if (DISPLAY_VER(dev_priv) >= 4) {
   1026		if (plane_config->tiling)
   1027			offset = intel_de_read(dev_priv,
   1028					       DSPTILEOFF(i9xx_plane));
   1029		else
   1030			offset = intel_de_read(dev_priv,
   1031					       DSPLINOFF(i9xx_plane));
   1032		base = intel_de_read(dev_priv, DSPSURF(i9xx_plane)) & DISP_ADDR_MASK;
   1033	} else {
   1034		base = intel_de_read(dev_priv, DSPADDR(i9xx_plane));
   1035	}
   1036	plane_config->base = base;
   1037
   1038	val = intel_de_read(dev_priv, PIPESRC(pipe));
   1039	fb->width = REG_FIELD_GET(PIPESRC_WIDTH_MASK, val) + 1;
   1040	fb->height = REG_FIELD_GET(PIPESRC_HEIGHT_MASK, val) + 1;
   1041
   1042	val = intel_de_read(dev_priv, DSPSTRIDE(i9xx_plane));
   1043	fb->pitches[0] = val & 0xffffffc0;
   1044
   1045	aligned_height = intel_fb_align_height(fb, 0, fb->height);
   1046
   1047	plane_config->size = fb->pitches[0] * aligned_height;
   1048
   1049	drm_dbg_kms(&dev_priv->drm,
   1050		    "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
   1051		    crtc->base.name, plane->base.name, fb->width, fb->height,
   1052		    fb->format->cpp[0] * 8, base, fb->pitches[0],
   1053		    plane_config->size);
   1054
   1055	plane_config->fb = intel_fb;
   1056}