diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_display.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_display.c | 4019 | 
1 files changed, 2389 insertions, 1630 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 301897791627..aa453953908b 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -46,6 +46,7 @@  #include "display/intel_crt.h"  #include "display/intel_ddi.h"  #include "display/intel_dp.h" +#include "display/intel_dp_mst.h"  #include "display/intel_dsi.h"  #include "display/intel_dvo.h"  #include "display/intel_gmbus.h" @@ -86,8 +87,8 @@  /* Primary plane formats for gen <= 3 */  static const u32 i8xx_primary_formats[] = {  	DRM_FORMAT_C8, -	DRM_FORMAT_RGB565,  	DRM_FORMAT_XRGB1555, +	DRM_FORMAT_RGB565,  	DRM_FORMAT_XRGB8888,  }; @@ -112,6 +113,21 @@ static const u32 i965_primary_formats[] = {  	DRM_FORMAT_XBGR16161616F,  }; +/* Primary plane formats for vlv/chv */ +static const u32 vlv_primary_formats[] = { +	DRM_FORMAT_C8, +	DRM_FORMAT_RGB565, +	DRM_FORMAT_XRGB8888, +	DRM_FORMAT_XBGR8888, +	DRM_FORMAT_ARGB8888, +	DRM_FORMAT_ABGR8888, +	DRM_FORMAT_XRGB2101010, +	DRM_FORMAT_XBGR2101010, +	DRM_FORMAT_ARGB2101010, +	DRM_FORMAT_ABGR2101010, +	DRM_FORMAT_XBGR16161616F, +}; +  static const u64 i9xx_format_modifiers[] = {  	I915_FORMAT_MOD_X_TILED,  	DRM_FORMAT_MOD_LINEAR, @@ -130,8 +146,8 @@ static const u64 cursor_format_modifiers[] = {  static void i9xx_crtc_clock_get(struct intel_crtc *crtc,  				struct intel_crtc_state *pipe_config); -static void ironlake_pch_clock_get(struct intel_crtc *crtc, -				   struct intel_crtc_state *pipe_config); +static void ilk_pch_clock_get(struct intel_crtc *crtc, +			      struct intel_crtc_state *pipe_config);  static int intel_framebuffer_init(struct intel_framebuffer *ifb,  				  struct drm_i915_gem_object *obj, @@ -142,21 +158,18 @@ static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_sta  					 const struct intel_link_m_n *m_n,  					 const struct intel_link_m_n *m2_n2);  static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state); -static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state); -static void haswell_set_pipeconf(const struct intel_crtc_state *crtc_state); +static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state); +static void hsw_set_pipeconf(const struct intel_crtc_state *crtc_state);  static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state);  static void vlv_prepare_pll(struct intel_crtc *crtc,  			    const struct intel_crtc_state *pipe_config);  static void chv_prepare_pll(struct intel_crtc *crtc,  			    const struct intel_crtc_state *pipe_config); -static void intel_crtc_init_scalers(struct intel_crtc *crtc, -				    struct intel_crtc_state *crtc_state); -static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state); -static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state); -static void ironlake_pfit_enable(const struct intel_crtc_state *crtc_state); +static void skl_pfit_enable(const struct intel_crtc_state *crtc_state); +static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state);  static void intel_modeset_setup_hw_state(struct drm_device *dev,  					 struct drm_modeset_acquire_ctx *ctx); -static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc); +static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);  struct intel_limit {  	struct { @@ -357,7 +370,7 @@ static const struct intel_limit intel_limits_g4x_dual_channel_lvds = {  	},  }; -static const struct intel_limit intel_limits_pineview_sdvo = { +static const struct intel_limit pnv_limits_sdvo = {  	.dot = { .min = 20000, .max = 400000},  	.vco = { .min = 1700000, .max = 3500000 },  	/* Pineview's Ncounter is a ring counter */ @@ -372,7 +385,7 @@ static const struct intel_limit intel_limits_pineview_sdvo = {  		.p2_slow = 10, .p2_fast = 5 },  }; -static const struct intel_limit intel_limits_pineview_lvds = { +static const struct intel_limit pnv_limits_lvds = {  	.dot = { .min = 20000, .max = 400000 },  	.vco = { .min = 1700000, .max = 3500000 },  	.n = { .min = 3, .max = 6 }, @@ -390,7 +403,7 @@ static const struct intel_limit intel_limits_pineview_lvds = {   * We calculate clock using (register_value + 2) for N/M1/M2, so here   * the range value for them is (actual_value - 2).   */ -static const struct intel_limit intel_limits_ironlake_dac = { +static const struct intel_limit ilk_limits_dac = {  	.dot = { .min = 25000, .max = 350000 },  	.vco = { .min = 1760000, .max = 3510000 },  	.n = { .min = 1, .max = 5 }, @@ -403,7 +416,7 @@ static const struct intel_limit intel_limits_ironlake_dac = {  		.p2_slow = 10, .p2_fast = 5 },  }; -static const struct intel_limit intel_limits_ironlake_single_lvds = { +static const struct intel_limit ilk_limits_single_lvds = {  	.dot = { .min = 25000, .max = 350000 },  	.vco = { .min = 1760000, .max = 3510000 },  	.n = { .min = 1, .max = 3 }, @@ -416,7 +429,7 @@ static const struct intel_limit intel_limits_ironlake_single_lvds = {  		.p2_slow = 14, .p2_fast = 14 },  }; -static const struct intel_limit intel_limits_ironlake_dual_lvds = { +static const struct intel_limit ilk_limits_dual_lvds = {  	.dot = { .min = 25000, .max = 350000 },  	.vco = { .min = 1760000, .max = 3510000 },  	.n = { .min = 1, .max = 3 }, @@ -430,7 +443,7 @@ static const struct intel_limit intel_limits_ironlake_dual_lvds = {  };  /* LVDS 100mhz refclk limits. */ -static const struct intel_limit intel_limits_ironlake_single_lvds_100m = { +static const struct intel_limit ilk_limits_single_lvds_100m = {  	.dot = { .min = 25000, .max = 350000 },  	.vco = { .min = 1760000, .max = 3510000 },  	.n = { .min = 1, .max = 2 }, @@ -443,7 +456,7 @@ static const struct intel_limit intel_limits_ironlake_single_lvds_100m = {  		.p2_slow = 14, .p2_fast = 14 },  }; -static const struct intel_limit intel_limits_ironlake_dual_lvds_100m = { +static const struct intel_limit ilk_limits_dual_lvds_100m = {  	.dot = { .min = 25000, .max = 350000 },  	.vco = { .min = 1760000, .max = 3510000 },  	.n = { .min = 1, .max = 3 }, @@ -530,7 +543,7 @@ icl_wa_scalerclkgating(struct drm_i915_private *dev_priv, enum pipe pipe,  static bool  needs_modeset(const struct intel_crtc_state *state)  { -	return drm_atomic_crtc_needs_modeset(&state->base); +	return drm_atomic_crtc_needs_modeset(&state->uapi);  }  bool @@ -541,10 +554,9 @@ is_trans_port_sync_mode(const struct intel_crtc_state *crtc_state)  }  static bool -is_trans_port_sync_master(const struct intel_crtc_state *crtc_state) +is_trans_port_sync_slave(const struct intel_crtc_state *crtc_state)  { -	return (crtc_state->master_transcoder == INVALID_TRANSCODER && -		crtc_state->sync_mode_slaves_mask); +	return crtc_state->master_transcoder != INVALID_TRANSCODER;  }  /* @@ -658,7 +670,7 @@ i9xx_select_p2_div(const struct intel_limit *limit,  		   const struct intel_crtc_state *crtc_state,  		   int target)  { -	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); +	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);  	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {  		/* @@ -694,7 +706,7 @@ i9xx_find_best_dpll(const struct intel_limit *limit,  		    int target, int refclk, struct dpll *match_clock,  		    struct dpll *best_clock)  { -	struct drm_device *dev = crtc_state->base.crtc->dev; +	struct drm_device *dev = crtc_state->uapi.crtc->dev;  	struct dpll clock;  	int err = target; @@ -752,7 +764,7 @@ pnv_find_best_dpll(const struct intel_limit *limit,  		   int target, int refclk, struct dpll *match_clock,  		   struct dpll *best_clock)  { -	struct drm_device *dev = crtc_state->base.crtc->dev; +	struct drm_device *dev = crtc_state->uapi.crtc->dev;  	struct dpll clock;  	int err = target; @@ -808,7 +820,7 @@ g4x_find_best_dpll(const struct intel_limit *limit,  		   int target, int refclk, struct dpll *match_clock,  		   struct dpll *best_clock)  { -	struct drm_device *dev = crtc_state->base.crtc->dev; +	struct drm_device *dev = crtc_state->uapi.crtc->dev;  	struct dpll clock;  	int max_n;  	bool found = false; @@ -902,7 +914,7 @@ vlv_find_best_dpll(const struct intel_limit *limit,  		   int target, int refclk, struct dpll *match_clock,  		   struct dpll *best_clock)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_device *dev = crtc->base.dev;  	struct dpll clock;  	unsigned int bestppm = 1000000; @@ -962,7 +974,7 @@ chv_find_best_dpll(const struct intel_limit *limit,  		   int target, int refclk, struct dpll *match_clock,  		   struct dpll *best_clock)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_device *dev = crtc->base.dev;  	unsigned int best_error_ppm;  	struct dpll clock; @@ -1025,33 +1037,6 @@ bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state,  				  NULL, best_clock);  } -bool intel_crtc_active(struct intel_crtc *crtc) -{ -	/* Be paranoid as we can arrive here with only partial -	 * state retrieved from the hardware during setup. -	 * -	 * We can ditch the adjusted_mode.crtc_clock check as soon -	 * as Haswell has gained clock readout/fastboot support. -	 * -	 * We can ditch the crtc->primary->state->fb check as soon as we can -	 * properly reconstruct framebuffers. -	 * -	 * FIXME: The intel_crtc->active here should be switched to -	 * crtc->state->active once we have proper CRTC states wired up -	 * for atomic. -	 */ -	return crtc->active && crtc->base.primary->state->fb && -		crtc->config->base.adjusted_mode.crtc_clock; -} - -enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, -					     enum pipe pipe) -{ -	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); - -	return crtc->config->cpu_transcoder; -} -  static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv,  				    enum pipe pipe)  { @@ -1095,7 +1080,7 @@ static void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc)  static void  intel_wait_for_pipe_off(const struct intel_crtc_state *old_crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	if (INTEL_GEN(dev_priv) >= 4) { @@ -1145,11 +1130,15 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,  			  enum pipe pipe, bool state)  {  	bool cur_state; -	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, -								      pipe);  	if (HAS_DDI(dev_priv)) { -		/* DDI does not have a specific FDI_TX register */ +		/* +		 * DDI does not have a specific FDI_TX register. +		 * +		 * FDI is never fed from EDP transcoder +		 * so pipe->transcoder cast is fine here. +		 */ +		enum transcoder cpu_transcoder = (enum transcoder)pipe;  		u32 val = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));  		cur_state = !!(val & TRANS_DDI_FUNC_ENABLE);  	} else { @@ -1266,11 +1255,9 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe)  }  void assert_pipe(struct drm_i915_private *dev_priv, -		 enum pipe pipe, bool state) +		 enum transcoder cpu_transcoder, bool state)  {  	bool cur_state; -	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, -								      pipe);  	enum intel_display_power_domain power_domain;  	intel_wakeref_t wakeref; @@ -1290,8 +1277,9 @@ void assert_pipe(struct drm_i915_private *dev_priv,  	}  	I915_STATE_WARN(cur_state != state, -	     "pipe %c assertion failure (expected %s, current %s)\n", -			pipe_name(pipe), onoff(state), onoff(cur_state)); +			"transcoder %s assertion failure (expected %s, current %s)\n", +			transcoder_name(cpu_transcoder), +			onoff(state), onoff(cur_state));  }  static void assert_plane(struct intel_plane *plane, bool state) @@ -1418,7 +1406,7 @@ static void vlv_enable_pll(struct intel_crtc *crtc,  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum pipe pipe = crtc->pipe; -	assert_pipe_disabled(dev_priv, pipe); +	assert_pipe_disabled(dev_priv, pipe_config->cpu_transcoder);  	/* PLL is protected by panel, make sure we can write it */  	assert_panel_unlocked(dev_priv, pipe); @@ -1467,7 +1455,7 @@ static void chv_enable_pll(struct intel_crtc *crtc,  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum pipe pipe = crtc->pipe; -	assert_pipe_disabled(dev_priv, pipe); +	assert_pipe_disabled(dev_priv, pipe_config->cpu_transcoder);  	/* PLL is protected by panel, make sure we can write it */  	assert_panel_unlocked(dev_priv, pipe); @@ -1514,7 +1502,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc,  	u32 dpll = crtc_state->dpll_hw_state.dpll;  	int i; -	assert_pipe_disabled(dev_priv, crtc->pipe); +	assert_pipe_disabled(dev_priv, crtc_state->cpu_transcoder);  	/* PLL is protected by panel, make sure we can write it */  	if (i9xx_has_pps(dev_priv)) @@ -1554,7 +1542,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc,  static void i9xx_disable_pll(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum pipe pipe = crtc->pipe; @@ -1563,7 +1551,7 @@ static void i9xx_disable_pll(const struct intel_crtc_state *crtc_state)  		return;  	/* Make sure the pipe isn't still relying on us */ -	assert_pipe_disabled(dev_priv, pipe); +	assert_pipe_disabled(dev_priv, crtc_state->cpu_transcoder);  	I915_WRITE(DPLL(pipe), DPLL_VGA_MODE_DIS);  	POSTING_READ(DPLL(pipe)); @@ -1574,7 +1562,7 @@ static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)  	u32 val;  	/* Make sure the pipe isn't still relying on us */ -	assert_pipe_disabled(dev_priv, pipe); +	assert_pipe_disabled(dev_priv, (enum transcoder)pipe);  	val = DPLL_INTEGRATED_REF_CLK_VLV |  		DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS; @@ -1591,7 +1579,7 @@ static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)  	u32 val;  	/* Make sure the pipe isn't still relying on us */ -	assert_pipe_disabled(dev_priv, pipe); +	assert_pipe_disabled(dev_priv, (enum transcoder)pipe);  	val = DPLL_SSC_REF_CLK_CHV |  		DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS; @@ -1643,9 +1631,9 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,  		     I915_READ(dpll_reg) & port_mask, expected_mask);  } -static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) +static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum pipe pipe = crtc->pipe;  	i915_reg_t reg; @@ -1659,11 +1647,16 @@ static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_s  	assert_fdi_rx_enabled(dev_priv, pipe);  	if (HAS_PCH_CPT(dev_priv)) { -		/* Workaround: Set the timing override bit before enabling the -		 * pch transcoder. */  		reg = TRANS_CHICKEN2(pipe);  		val = I915_READ(reg); +		/* +		 * Workaround: Set the timing override bit +		 * before enabling the pch transcoder. +		 */  		val |= TRANS_CHICKEN2_TIMING_OVERRIDE; +		/* Configure frame start delay to match the CPU */ +		val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; +		val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);  		I915_WRITE(reg, val);  	} @@ -1672,6 +1665,10 @@ static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_s  	pipeconf_val = I915_READ(PIPECONF(pipe));  	if (HAS_PCH_IBX(dev_priv)) { +		/* Configure frame start delay to match the CPU */ +		val &= ~TRANS_FRAME_START_DELAY_MASK; +		val |= TRANS_FRAME_START_DELAY(0); +  		/*  		 * Make the BPC in transcoder be consistent with  		 * that in pipeconf reg. For HDMI we must use 8bpc @@ -1709,9 +1706,12 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,  	assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);  	assert_fdi_rx_enabled(dev_priv, PIPE_A); -	/* Workaround: set timing override bit. */  	val = I915_READ(TRANS_CHICKEN2(PIPE_A)); +	/* Workaround: set timing override bit. */  	val |= TRANS_CHICKEN2_TIMING_OVERRIDE; +	/* Configure frame start delay to match the CPU */ +	val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; +	val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);  	I915_WRITE(TRANS_CHICKEN2(PIPE_A), val);  	val = TRANS_ENABLE; @@ -1729,8 +1729,8 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,  		DRM_ERROR("Failed to enable PCH transcoder\n");  } -static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv, -					    enum pipe pipe) +static void ilk_disable_pch_transcoder(struct drm_i915_private *dev_priv, +				       enum pipe pipe)  {  	i915_reg_t reg;  	u32 val; @@ -1789,7 +1789,7 @@ enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)  static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state)  { -	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); +	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);  	/*  	 * On i965gm the hardware frame counter reads @@ -1809,16 +1809,25 @@ static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state  static void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); +	assert_vblank_disabled(&crtc->base);  	drm_crtc_set_max_vblank_count(&crtc->base,  				      intel_crtc_max_vblank_count(crtc_state));  	drm_crtc_vblank_on(&crtc->base);  } +void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state) +{ +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + +	drm_crtc_vblank_off(&crtc->base); +	assert_vblank_disabled(&crtc->base); +} +  static void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder;  	enum pipe pipe = crtc->pipe; @@ -1874,9 +1883,9 @@ static void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)  		intel_wait_for_pipe_scanline_moving(crtc);  } -static void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state) +void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;  	enum pipe pipe = crtc->pipe; @@ -1919,6 +1928,74 @@ static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv)  	return IS_GEN(dev_priv, 2) ? 2048 : 4096;  } +static bool is_ccs_plane(const struct drm_framebuffer *fb, int plane) +{ +	if (!is_ccs_modifier(fb->modifier)) +		return false; + +	return plane >= fb->format->num_planes / 2; +} + +static bool is_gen12_ccs_modifier(u64 modifier) +{ +	return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || +	       modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS; + +} + +static bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane) +{ +	return is_gen12_ccs_modifier(fb->modifier) && is_ccs_plane(fb, plane); +} + +static bool is_aux_plane(const struct drm_framebuffer *fb, int plane) +{ +	if (is_ccs_modifier(fb->modifier)) +		return is_ccs_plane(fb, plane); + +	return plane == 1; +} + +static int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane) +{ +	WARN_ON(!is_ccs_modifier(fb->modifier) || +		(main_plane && main_plane >= fb->format->num_planes / 2)); + +	return fb->format->num_planes / 2 + main_plane; +} + +static int ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane) +{ +	WARN_ON(!is_ccs_modifier(fb->modifier) || +		ccs_plane < fb->format->num_planes / 2); + +	return ccs_plane - fb->format->num_planes / 2; +} + +/* Return either the main plane's CCS or - if not a CCS FB - UV plane */ +int intel_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane) +{ +	if (is_ccs_modifier(fb->modifier)) +		return main_to_ccs_plane(fb, main_plane); + +	return 1; +} + +bool +intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info, +				    uint64_t modifier) +{ +	return info->is_yuv && +	       info->num_planes == (is_ccs_modifier(modifier) ? 4 : 2); +} + +static bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, +				   int color_plane) +{ +	return intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) && +	       color_plane == 1; +} +  static unsigned int  intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)  { @@ -1934,16 +2011,21 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)  		else  			return 512;  	case I915_FORMAT_MOD_Y_TILED_CCS: -		if (color_plane == 1) +		if (is_ccs_plane(fb, color_plane))  			return 128;  		/* fall through */ +	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: +	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: +		if (is_ccs_plane(fb, color_plane)) +			return 64; +		/* fall through */  	case I915_FORMAT_MOD_Y_TILED:  		if (IS_GEN(dev_priv, 2) || HAS_128_BYTE_Y_TILING(dev_priv))  			return 128;  		else  			return 512;  	case I915_FORMAT_MOD_Yf_TILED_CCS: -		if (color_plane == 1) +		if (is_ccs_plane(fb, color_plane))  			return 128;  		/* fall through */  	case I915_FORMAT_MOD_Yf_TILED: @@ -1970,6 +2052,9 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)  static unsigned int  intel_tile_height(const struct drm_framebuffer *fb, int color_plane)  { +	if (is_gen12_ccs_plane(fb, color_plane)) +		return 1; +  	return intel_tile_size(to_i915(fb->dev)) /  		intel_tile_width_bytes(fb, color_plane);  } @@ -1983,7 +2068,17 @@ static void intel_tile_dims(const struct drm_framebuffer *fb, int color_plane,  	unsigned int cpp = fb->format->cpp[color_plane];  	*tile_width = tile_width_bytes / cpp; -	*tile_height = intel_tile_size(to_i915(fb->dev)) / tile_width_bytes; +	*tile_height = intel_tile_height(fb, color_plane); +} + +static unsigned int intel_tile_row_size(const struct drm_framebuffer *fb, +					int color_plane) +{ +	unsigned int tile_width, tile_height; + +	intel_tile_dims(fb, color_plane, &tile_width, &tile_height); + +	return fb->pitches[color_plane] * tile_height;  }  unsigned int @@ -2060,7 +2155,8 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,  	struct drm_i915_private *dev_priv = to_i915(fb->dev);  	/* AUX_DIST needs only 4K alignment */ -	if (color_plane == 1) +	if ((INTEL_GEN(dev_priv) < 12 && is_aux_plane(fb, color_plane)) || +	    is_ccs_plane(fb, color_plane))  		return 4096;  	switch (fb->modifier) { @@ -2070,9 +2166,19 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,  		if (INTEL_GEN(dev_priv) >= 9)  			return 256 * 1024;  		return 0; +	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: +		if (is_semiplanar_uv_plane(fb, color_plane)) +			return intel_tile_row_size(fb, color_plane); +		/* Fall-through */ +	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: +		return 16 * 1024;  	case I915_FORMAT_MOD_Y_TILED_CCS:  	case I915_FORMAT_MOD_Yf_TILED_CCS:  	case I915_FORMAT_MOD_Y_TILED: +		if (INTEL_GEN(dev_priv) >= 12 && +		    is_semiplanar_uv_plane(fb, color_plane)) +			return intel_tile_row_size(fb, color_plane); +		/* Fall-through */  	case I915_FORMAT_MOD_Yf_TILED:  		return 1 * 1024 * 1024;  	default: @@ -2083,7 +2189,7 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,  static bool intel_plane_uses_fence(const struct intel_plane_state *plane_state)  { -	struct intel_plane *plane = to_intel_plane(plane_state->base.plane); +	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);  	return INTEL_GEN(dev_priv) < 4 || @@ -2109,6 +2215,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,  		return ERR_PTR(-EINVAL);  	alignment = intel_surf_alignment(fb, 0); +	if (WARN_ON(alignment && !is_power_of_2(alignment))) +		return ERR_PTR(-EINVAL);  	/* Note that the w/a also requires 64 PTE of padding following the  	 * bo. We currently fill all unused PTE with the shadow page and so @@ -2126,19 +2234,18 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,  	 * pin/unpin/fence and not more.  	 */  	wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); -	i915_gem_object_lock(obj);  	atomic_inc(&dev_priv->gpu_error.pending_fb_pin); -	pinctl = 0; - -	/* Valleyview is definitely limited to scanning out the first +	/* +	 * Valleyview is definitely limited to scanning out the first  	 * 512MiB. Lets presume this behaviour was inherited from the  	 * g4x display engine and that all earlier gen are similarly  	 * limited. Testing suggests that it is a little more  	 * complicated than this. For example, Cherryview appears quite  	 * happy to scanout from anywhere within its global aperture.  	 */ +	pinctl = 0;  	if (HAS_GMCH(dev_priv))  		pinctl |= PIN_MAPPABLE; @@ -2150,7 +2257,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,  	if (uses_fence && i915_vma_is_map_and_fenceable(vma)) {  		int ret; -		/* Install a fence for tiled scan-out. Pre-i965 always needs a +		/* +		 * Install a fence for tiled scan-out. Pre-i965 always needs a  		 * fence, whereas 965+ only requires a fence if using  		 * framebuffer compression.  For simplicity, we always, when  		 * possible, install a fence as the cost is not that onerous. @@ -2180,8 +2288,6 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,  	i915_vma_get(vma);  err:  	atomic_dec(&dev_priv->gpu_error.pending_fb_pin); - -	i915_gem_object_unlock(obj);  	intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);  	return vma;  } @@ -2216,7 +2322,7 @@ u32 intel_fb_xy_to_linear(int x, int y,  			  const struct intel_plane_state *state,  			  int color_plane)  { -	const struct drm_framebuffer *fb = state->base.fb; +	const struct drm_framebuffer *fb = state->hw.fb;  	unsigned int cpp = fb->format->cpp[color_plane];  	unsigned int pitch = state->color_plane[color_plane].stride; @@ -2264,9 +2370,10 @@ static u32 intel_adjust_tile_offset(int *x, int *y,  	return new_offset;  } -static bool is_surface_linear(u64 modifier, int color_plane) +static bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane)  { -	return modifier == DRM_FORMAT_MOD_LINEAR; +	return fb->modifier == DRM_FORMAT_MOD_LINEAR || +	       is_gen12_ccs_plane(fb, color_plane);  }  static u32 intel_adjust_aligned_offset(int *x, int *y, @@ -2281,7 +2388,7 @@ static u32 intel_adjust_aligned_offset(int *x, int *y,  	WARN_ON(new_offset > old_offset); -	if (!is_surface_linear(fb->modifier, color_plane)) { +	if (!is_surface_linear(fb, color_plane)) {  		unsigned int tile_size, tile_width, tile_height;  		unsigned int pitch_tiles; @@ -2317,8 +2424,8 @@ static u32 intel_plane_adjust_aligned_offset(int *x, int *y,  					     int color_plane,  					     u32 old_offset, u32 new_offset)  { -	return intel_adjust_aligned_offset(x, y, state->base.fb, color_plane, -					   state->base.rotation, +	return intel_adjust_aligned_offset(x, y, state->hw.fb, color_plane, +					   state->hw.rotation,  					   state->color_plane[color_plane].stride,  					   old_offset, new_offset);  } @@ -2348,10 +2455,7 @@ static u32 intel_compute_aligned_offset(struct drm_i915_private *dev_priv,  	unsigned int cpp = fb->format->cpp[color_plane];  	u32 offset, offset_aligned; -	if (alignment) -		alignment--; - -	if (!is_surface_linear(fb->modifier, color_plane)) { +	if (!is_surface_linear(fb, color_plane)) {  		unsigned int tile_size, tile_width, tile_height;  		unsigned int tile_rows, tiles, pitch_tiles; @@ -2372,17 +2476,24 @@ static u32 intel_compute_aligned_offset(struct drm_i915_private *dev_priv,  		*x %= tile_width;  		offset = (tile_rows * pitch_tiles + tiles) * tile_size; -		offset_aligned = offset & ~alignment; + +		offset_aligned = offset; +		if (alignment) +			offset_aligned = rounddown(offset_aligned, alignment);  		intel_adjust_tile_offset(x, y, tile_width, tile_height,  					 tile_size, pitch_tiles,  					 offset, offset_aligned);  	} else {  		offset = *y * pitch + *x * cpp; -		offset_aligned = offset & ~alignment; - -		*y = (offset & alignment) / pitch; -		*x = ((offset & alignment) - *y * pitch) / cpp; +		offset_aligned = offset; +		if (alignment) { +			offset_aligned = rounddown(offset_aligned, alignment); +			*y = (offset % alignment) / pitch; +			*x = ((offset % alignment) - *y * pitch) / cpp; +		} else { +			*y = *x = 0; +		}  	}  	return offset_aligned; @@ -2392,10 +2503,10 @@ static u32 intel_plane_compute_aligned_offset(int *x, int *y,  					      const struct intel_plane_state *state,  					      int color_plane)  { -	struct intel_plane *intel_plane = to_intel_plane(state->base.plane); +	struct intel_plane *intel_plane = to_intel_plane(state->uapi.plane);  	struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev); -	const struct drm_framebuffer *fb = state->base.fb; -	unsigned int rotation = state->base.rotation; +	const struct drm_framebuffer *fb = state->hw.fb; +	unsigned int rotation = state->hw.rotation;  	int pitch = state->color_plane[color_plane].stride;  	u32 alignment; @@ -2415,9 +2526,17 @@ static int intel_fb_offset_to_xy(int *x, int *y,  {  	struct drm_i915_private *dev_priv = to_i915(fb->dev);  	unsigned int height; +	u32 alignment; + +	if (INTEL_GEN(dev_priv) >= 12 && +	    is_semiplanar_uv_plane(fb, color_plane)) +		alignment = intel_tile_row_size(fb, color_plane); +	else if (fb->modifier != DRM_FORMAT_MOD_LINEAR) +		alignment = intel_tile_size(dev_priv); +	else +		alignment = 0; -	if (fb->modifier != DRM_FORMAT_MOD_LINEAR && -	    fb->offsets[color_plane] % intel_tile_size(dev_priv)) { +	if (alignment != 0 && fb->offsets[color_plane] % alignment) {  		DRM_DEBUG_KMS("Misaligned offset 0x%08x for color plane %d\n",  			      fb->offsets[color_plane], color_plane);  		return -EINVAL; @@ -2453,6 +2572,8 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier)  		return I915_TILING_X;  	case I915_FORMAT_MOD_Y_TILED:  	case I915_FORMAT_MOD_Y_TILED_CCS: +	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: +	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:  		return I915_TILING_Y;  	default:  		return I915_TILING_NONE; @@ -2473,7 +2594,7 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier)   * us a ratio of one byte in the CCS for each 8x16 pixels in the   * main surface.   */ -static const struct drm_format_info ccs_formats[] = { +static const struct drm_format_info skl_ccs_formats[] = {  	{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2,  	  .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },  	{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, @@ -2484,6 +2605,52 @@ static const struct drm_format_info ccs_formats[] = {  	  .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },  }; +/* + * Gen-12 compression uses 4 bits of CCS data for each cache line pair in the + * main surface. And each 64B CCS cache line represents an area of 4x1 Y-tiles + * in the main surface. With 4 byte pixels and each Y-tile having dimensions of + * 32x32 pixels, the ratio turns out to 1B in the CCS for every 2x32 pixels in + * the main surface. + */ +static const struct drm_format_info gen12_ccs_formats[] = { +	{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, +	  .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, +	  .hsub = 1, .vsub = 1, }, +	{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, +	  .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, +	  .hsub = 1, .vsub = 1, }, +	{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, +	  .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, +	  .hsub = 1, .vsub = 1, .has_alpha = true }, +	{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, +	  .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, +	  .hsub = 1, .vsub = 1, .has_alpha = true }, +	{ .format = DRM_FORMAT_YUYV, .num_planes = 2, +	  .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, +	  .hsub = 2, .vsub = 1, .is_yuv = true }, +	{ .format = DRM_FORMAT_YVYU, .num_planes = 2, +	  .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, +	  .hsub = 2, .vsub = 1, .is_yuv = true }, +	{ .format = DRM_FORMAT_UYVY, .num_planes = 2, +	  .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, +	  .hsub = 2, .vsub = 1, .is_yuv = true }, +	{ .format = DRM_FORMAT_VYUY, .num_planes = 2, +	  .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, +	  .hsub = 2, .vsub = 1, .is_yuv = true }, +	{ .format = DRM_FORMAT_NV12, .num_planes = 4, +	  .char_per_block = { 1, 2, 1, 1 }, .block_w = { 1, 1, 4, 4 }, .block_h = { 1, 1, 1, 1 }, +	  .hsub = 2, .vsub = 2, .is_yuv = true }, +	{ .format = DRM_FORMAT_P010, .num_planes = 4, +	  .char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 }, +	  .hsub = 2, .vsub = 2, .is_yuv = true }, +	{ .format = DRM_FORMAT_P012, .num_planes = 4, +	  .char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 }, +	  .hsub = 2, .vsub = 2, .is_yuv = true }, +	{ .format = DRM_FORMAT_P016, .num_planes = 4, +	  .char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 }, +	  .hsub = 2, .vsub = 2, .is_yuv = true }, +}; +  static const struct drm_format_info *  lookup_format_info(const struct drm_format_info formats[],  		   int num_formats, u32 format) @@ -2504,8 +2671,13 @@ intel_get_format_info(const struct drm_mode_fb_cmd2 *cmd)  	switch (cmd->modifier[0]) {  	case I915_FORMAT_MOD_Y_TILED_CCS:  	case I915_FORMAT_MOD_Yf_TILED_CCS: -		return lookup_format_info(ccs_formats, -					  ARRAY_SIZE(ccs_formats), +		return lookup_format_info(skl_ccs_formats, +					  ARRAY_SIZE(skl_ccs_formats), +					  cmd->pixel_format); +	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: +	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: +		return lookup_format_info(gen12_ccs_formats, +					  ARRAY_SIZE(gen12_ccs_formats),  					  cmd->pixel_format);  	default:  		return NULL; @@ -2514,10 +2686,18 @@ intel_get_format_info(const struct drm_mode_fb_cmd2 *cmd)  bool is_ccs_modifier(u64 modifier)  { -	return modifier == I915_FORMAT_MOD_Y_TILED_CCS || +	return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || +	       modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || +	       modifier == I915_FORMAT_MOD_Y_TILED_CCS ||  	       modifier == I915_FORMAT_MOD_Yf_TILED_CCS;  } +static int gen12_ccs_aux_stride(struct drm_framebuffer *fb, int ccs_plane) +{ +	return DIV_ROUND_UP(fb->pitches[ccs_to_main_plane(fb, ccs_plane)], +			    512) * 64; +} +  u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,  			      u32 pixel_format, u64 modifier)  { @@ -2562,8 +2742,9 @@ static u32  intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)  {  	struct drm_i915_private *dev_priv = to_i915(fb->dev); +	u32 tile_width; -	if (fb->modifier == DRM_FORMAT_MOD_LINEAR) { +	if (is_surface_linear(fb, color_plane)) {  		u32 max_stride = intel_plane_fb_max_stride(dev_priv,  							   fb->format->format,  							   fb->modifier); @@ -2572,20 +2753,41 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)  		 * To make remapping with linear generally feasible  		 * we need the stride to be page aligned.  		 */ -		if (fb->pitches[color_plane] > max_stride) +		if (fb->pitches[color_plane] > max_stride && +		    !is_ccs_modifier(fb->modifier))  			return intel_tile_size(dev_priv);  		else  			return 64; -	} else { -		return intel_tile_width_bytes(fb, color_plane);  	} + +	tile_width = intel_tile_width_bytes(fb, color_plane); +	if (is_ccs_modifier(fb->modifier)) { +		/* +		 * Display WA #0531: skl,bxt,kbl,glk +		 * +		 * Render decompression and plane width > 3840 +		 * combined with horizontal panning requires the +		 * plane stride to be a multiple of 4. We'll just +		 * require the entire fb to accommodate that to avoid +		 * potential runtime errors at plane configuration time. +		 */ +		if (IS_GEN(dev_priv, 9) && color_plane == 0 && fb->width > 3840) +			tile_width *= 4; +		/* +		 * The main surface pitch must be padded to a multiple of four +		 * tile widths. +		 */ +		else if (INTEL_GEN(dev_priv) >= 12) +			tile_width *= 4; +	} +	return tile_width;  }  bool intel_plane_can_remap(const struct intel_plane_state *plane_state)  { -	struct intel_plane *plane = to_intel_plane(plane_state->base.plane); +	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev); -	const struct drm_framebuffer *fb = plane_state->base.fb; +	const struct drm_framebuffer *fb = plane_state->hw.fb;  	int i;  	/* We don't want to deal with remapping with cursors */ @@ -2623,16 +2825,16 @@ bool intel_plane_can_remap(const struct intel_plane_state *plane_state)  static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state)  { -	struct intel_plane *plane = to_intel_plane(plane_state->base.plane); -	const struct drm_framebuffer *fb = plane_state->base.fb; -	unsigned int rotation = plane_state->base.rotation; +	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); +	const struct drm_framebuffer *fb = plane_state->hw.fb; +	unsigned int rotation = plane_state->hw.rotation;  	u32 stride, max_stride;  	/*  	 * No remapping for invisible planes since we don't have  	 * an actual source viewport to remap.  	 */ -	if (!plane_state->base.visible) +	if (!plane_state->uapi.visible)  		return false;  	if (!intel_plane_can_remap(plane_state)) @@ -2649,12 +2851,171 @@ static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state)  	return stride > max_stride;  } +static void +intel_fb_plane_get_subsampling(int *hsub, int *vsub, +			       const struct drm_framebuffer *fb, +			       int color_plane) +{ +	int main_plane; + +	if (color_plane == 0) { +		*hsub = 1; +		*vsub = 1; + +		return; +	} + +	/* +	 * TODO: Deduct the subsampling from the char block for all CCS +	 * formats and planes. +	 */ +	if (!is_gen12_ccs_plane(fb, color_plane)) { +		*hsub = fb->format->hsub; +		*vsub = fb->format->vsub; + +		return; +	} + +	main_plane = ccs_to_main_plane(fb, color_plane); +	*hsub = drm_format_info_block_width(fb->format, color_plane) / +		drm_format_info_block_width(fb->format, main_plane); + +	/* +	 * The min stride check in the core framebuffer_check() function +	 * assumes that format->hsub applies to every plane except for the +	 * first plane. That's incorrect for the CCS AUX plane of the first +	 * plane, but for the above check to pass we must define the block +	 * width with that subsampling applied to it. Adjust the width here +	 * accordingly, so we can calculate the actual subsampling factor. +	 */ +	if (main_plane == 0) +		*hsub *= fb->format->hsub; + +	*vsub = 32; +} +static int +intel_fb_check_ccs_xy(struct drm_framebuffer *fb, int ccs_plane, int x, int y) +{ +	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); +	int main_plane; +	int hsub, vsub; +	int tile_width, tile_height; +	int ccs_x, ccs_y; +	int main_x, main_y; + +	if (!is_ccs_plane(fb, ccs_plane)) +		return 0; + +	intel_tile_dims(fb, ccs_plane, &tile_width, &tile_height); +	intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane); + +	tile_width *= hsub; +	tile_height *= vsub; + +	ccs_x = (x * hsub) % tile_width; +	ccs_y = (y * vsub) % tile_height; + +	main_plane = ccs_to_main_plane(fb, ccs_plane); +	main_x = intel_fb->normal[main_plane].x % tile_width; +	main_y = intel_fb->normal[main_plane].y % tile_height; + +	/* +	 * CCS doesn't have its own x/y offset register, so the intra CCS tile +	 * x/y offsets must match between CCS and the main surface. +	 */ +	if (main_x != ccs_x || main_y != ccs_y) { +		DRM_DEBUG_KMS("Bad CCS x/y (main %d,%d ccs %d,%d) full (main %d,%d ccs %d,%d)\n", +			      main_x, main_y, +			      ccs_x, ccs_y, +			      intel_fb->normal[main_plane].x, +			      intel_fb->normal[main_plane].y, +			      x, y); +		return -EINVAL; +	} + +	return 0; +} + +static void +intel_fb_plane_dims(int *w, int *h, struct drm_framebuffer *fb, int color_plane) +{ +	int main_plane = is_ccs_plane(fb, color_plane) ? +			 ccs_to_main_plane(fb, color_plane) : 0; +	int main_hsub, main_vsub; +	int hsub, vsub; + +	intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb, main_plane); +	intel_fb_plane_get_subsampling(&hsub, &vsub, fb, color_plane); +	*w = fb->width / main_hsub / hsub; +	*h = fb->height / main_vsub / vsub; +} + +/* + * Setup the rotated view for an FB plane and return the size the GTT mapping + * requires for this view. + */ +static u32 +setup_fb_rotation(int plane, const struct intel_remapped_plane_info *plane_info, +		  u32 gtt_offset_rotated, int x, int y, +		  unsigned int width, unsigned int height, +		  unsigned int tile_size, +		  unsigned int tile_width, unsigned int tile_height, +		  struct drm_framebuffer *fb) +{ +	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); +	struct intel_rotation_info *rot_info = &intel_fb->rot_info; +	unsigned int pitch_tiles; +	struct drm_rect r; + +	/* Y or Yf modifiers required for 90/270 rotation */ +	if (fb->modifier != I915_FORMAT_MOD_Y_TILED && +	    fb->modifier != I915_FORMAT_MOD_Yf_TILED) +		return 0; + +	if (WARN_ON(plane >= ARRAY_SIZE(rot_info->plane))) +		return 0; + +	rot_info->plane[plane] = *plane_info; + +	intel_fb->rotated[plane].pitch = plane_info->height * tile_height; + +	/* rotate the x/y offsets to match the GTT view */ +	drm_rect_init(&r, x, y, width, height); +	drm_rect_rotate(&r, +			plane_info->width * tile_width, +			plane_info->height * tile_height, +			DRM_MODE_ROTATE_270); +	x = r.x1; +	y = r.y1; + +	/* rotate the tile dimensions to match the GTT view */ +	pitch_tiles = intel_fb->rotated[plane].pitch / tile_height; +	swap(tile_width, tile_height); + +	/* +	 * We only keep the x/y offsets, so push all of the +	 * gtt offset into the x/y offsets. +	 */ +	intel_adjust_tile_offset(&x, &y, +				 tile_width, tile_height, +				 tile_size, pitch_tiles, +				 gtt_offset_rotated * tile_size, 0); + +	/* +	 * First pixel of the framebuffer from +	 * the start of the rotated gtt mapping. +	 */ +	intel_fb->rotated[plane].x = x; +	intel_fb->rotated[plane].y = y; + +	return plane_info->width * plane_info->height; +} +  static int  intel_fill_fb_info(struct drm_i915_private *dev_priv,  		   struct drm_framebuffer *fb)  {  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); -	struct intel_rotation_info *rot_info = &intel_fb->rot_info;  	struct drm_i915_gem_object *obj = intel_fb_obj(fb);  	u32 gtt_offset_rotated = 0;  	unsigned int max_size = 0; @@ -2669,8 +3030,7 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,  		int ret;  		cpp = fb->format->cpp[i]; -		width = drm_framebuffer_plane_width(fb->width, fb, i); -		height = drm_framebuffer_plane_height(fb->height, fb, i); +		intel_fb_plane_dims(&width, &height, fb, i);  		ret = intel_fb_offset_to_xy(&x, &y, fb, i);  		if (ret) { @@ -2679,36 +3039,9 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,  			return ret;  		} -		if (is_ccs_modifier(fb->modifier) && i == 1) { -			int hsub = fb->format->hsub; -			int vsub = fb->format->vsub; -			int tile_width, tile_height; -			int main_x, main_y; -			int ccs_x, ccs_y; - -			intel_tile_dims(fb, i, &tile_width, &tile_height); -			tile_width *= hsub; -			tile_height *= vsub; - -			ccs_x = (x * hsub) % tile_width; -			ccs_y = (y * vsub) % tile_height; -			main_x = intel_fb->normal[0].x % tile_width; -			main_y = intel_fb->normal[0].y % tile_height; - -			/* -			 * CCS doesn't have its own x/y offset register, so the intra CCS tile -			 * x/y offsets must match between CCS and the main surface. -			 */ -			if (main_x != ccs_x || main_y != ccs_y) { -				DRM_DEBUG_KMS("Bad CCS x/y (main %d,%d ccs %d,%d) full (main %d,%d ccs %d,%d)\n", -					      main_x, main_y, -					      ccs_x, ccs_y, -					      intel_fb->normal[0].x, -					      intel_fb->normal[0].y, -					      x, y); -				return -EINVAL; -			} -		} +		ret = intel_fb_check_ccs_xy(fb, i, x, y); +		if (ret) +			return ret;  		/*  		 * The fence (if used) is aligned to the start of the object @@ -2739,23 +3072,21 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,  						      tile_size);  		offset /= tile_size; -		if (!is_surface_linear(fb->modifier, i)) { +		if (!is_surface_linear(fb, i)) { +			struct intel_remapped_plane_info plane_info;  			unsigned int tile_width, tile_height; -			unsigned int pitch_tiles; -			struct drm_rect r;  			intel_tile_dims(fb, i, &tile_width, &tile_height); -			rot_info->plane[i].offset = offset; -			rot_info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], tile_width * cpp); -			rot_info->plane[i].width = DIV_ROUND_UP(x + width, tile_width); -			rot_info->plane[i].height = DIV_ROUND_UP(y + height, tile_height); - -			intel_fb->rotated[i].pitch = -				rot_info->plane[i].height * tile_height; +			plane_info.offset = offset; +			plane_info.stride = DIV_ROUND_UP(fb->pitches[i], +							 tile_width * cpp); +			plane_info.width = DIV_ROUND_UP(x + width, tile_width); +			plane_info.height = DIV_ROUND_UP(y + height, +							 tile_height);  			/* how many tiles does this plane need */ -			size = rot_info->plane[i].stride * rot_info->plane[i].height; +			size = plane_info.stride * plane_info.height;  			/*  			 * If the plane isn't horizontally tile aligned,  			 * we need one more tile. @@ -2763,36 +3094,13 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,  			if (x != 0)  				size++; -			/* rotate the x/y offsets to match the GTT view */ -			drm_rect_init(&r, x, y, width, height); -			drm_rect_rotate(&r, -					rot_info->plane[i].width * tile_width, -					rot_info->plane[i].height * tile_height, -					DRM_MODE_ROTATE_270); -			x = r.x1; -			y = r.y1; - -			/* rotate the tile dimensions to match the GTT view */ -			pitch_tiles = intel_fb->rotated[i].pitch / tile_height; -			swap(tile_width, tile_height); - -			/* -			 * We only keep the x/y offsets, so push all of the -			 * gtt offset into the x/y offsets. -			 */ -			intel_adjust_tile_offset(&x, &y, -						 tile_width, tile_height, -						 tile_size, pitch_tiles, -						 gtt_offset_rotated * tile_size, 0); - -			gtt_offset_rotated += rot_info->plane[i].width * rot_info->plane[i].height; - -			/* -			 * First pixel of the framebuffer from -			 * the start of the rotated gtt mapping. -			 */ -			intel_fb->rotated[i].x = x; -			intel_fb->rotated[i].y = y; +			gtt_offset_rotated += +				setup_fb_rotation(i, &plane_info, +						  gtt_offset_rotated, +						  x, y, width, height, +						  tile_size, +						  tile_width, tile_height, +						  fb);  		} else {  			size = DIV_ROUND_UP((y + height) * fb->pitches[i] +  					    x * cpp, tile_size); @@ -2815,11 +3123,11 @@ static void  intel_plane_remap_gtt(struct intel_plane_state *plane_state)  {  	struct drm_i915_private *dev_priv = -		to_i915(plane_state->base.plane->dev); -	struct drm_framebuffer *fb = plane_state->base.fb; +		to_i915(plane_state->uapi.plane->dev); +	struct drm_framebuffer *fb = plane_state->hw.fb;  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);  	struct intel_rotation_info *info = &plane_state->view.rotated; -	unsigned int rotation = plane_state->base.rotation; +	unsigned int rotation = plane_state->hw.rotation;  	int i, num_planes = fb->format->num_planes;  	unsigned int tile_size = intel_tile_size(dev_priv);  	unsigned int src_x, src_y; @@ -2830,20 +3138,20 @@ intel_plane_remap_gtt(struct intel_plane_state *plane_state)  	plane_state->view.type = drm_rotation_90_or_270(rotation) ?  		I915_GGTT_VIEW_ROTATED : I915_GGTT_VIEW_REMAPPED; -	src_x = plane_state->base.src.x1 >> 16; -	src_y = plane_state->base.src.y1 >> 16; -	src_w = drm_rect_width(&plane_state->base.src) >> 16; -	src_h = drm_rect_height(&plane_state->base.src) >> 16; +	src_x = plane_state->uapi.src.x1 >> 16; +	src_y = plane_state->uapi.src.y1 >> 16; +	src_w = drm_rect_width(&plane_state->uapi.src) >> 16; +	src_h = drm_rect_height(&plane_state->uapi.src) >> 16;  	WARN_ON(is_ccs_modifier(fb->modifier));  	/* Make src coordinates relative to the viewport */ -	drm_rect_translate(&plane_state->base.src, +	drm_rect_translate(&plane_state->uapi.src,  			   -(src_x << 16), -(src_y << 16));  	/* Rotate src coordinates to match rotated GTT view */  	if (drm_rotation_90_or_270(rotation)) -		drm_rect_rotate(&plane_state->base.src, +		drm_rect_rotate(&plane_state->uapi.src,  				src_w << 16, src_h << 16,  				DRM_MODE_ROTATE_270); @@ -2876,6 +3184,7 @@ intel_plane_remap_gtt(struct intel_plane_state *plane_state)  						      DRM_MODE_ROTATE_0, tile_size);  		offset /= tile_size; +		WARN_ON(i >= ARRAY_SIZE(info->plane));  		info->plane[i].offset = offset;  		info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i],  						     tile_width * cpp); @@ -2925,8 +3234,8 @@ static int  intel_plane_compute_gtt(struct intel_plane_state *plane_state)  {  	const struct intel_framebuffer *fb = -		to_intel_framebuffer(plane_state->base.fb); -	unsigned int rotation = plane_state->base.rotation; +		to_intel_framebuffer(plane_state->hw.fb); +	unsigned int rotation = plane_state->hw.rotation;  	int i, num_planes;  	if (!fb) @@ -2963,7 +3272,7 @@ intel_plane_compute_gtt(struct intel_plane_state *plane_state)  	/* Rotate src coordinates to match rotated GTT view */  	if (drm_rotation_90_or_270(rotation)) -		drm_rect_rotate(&plane_state->base.src, +		drm_rect_rotate(&plane_state->uapi.src,  				fb->base.width << 16, fb->base.height << 16,  				DRM_MODE_ROTATE_270); @@ -2975,6 +3284,8 @@ static int i9xx_format_to_fourcc(int format)  	switch (format) {  	case DISPPLANE_8BPP:  		return DRM_FORMAT_C8; +	case DISPPLANE_BGRA555: +		return DRM_FORMAT_ARGB1555;  	case DISPPLANE_BGRX555:  		return DRM_FORMAT_XRGB1555;  	case DISPPLANE_BGRX565: @@ -2984,10 +3295,18 @@ static int i9xx_format_to_fourcc(int format)  		return DRM_FORMAT_XRGB8888;  	case DISPPLANE_RGBX888:  		return DRM_FORMAT_XBGR8888; +	case DISPPLANE_BGRA888: +		return DRM_FORMAT_ARGB8888; +	case DISPPLANE_RGBA888: +		return DRM_FORMAT_ABGR8888;  	case DISPPLANE_BGRX101010:  		return DRM_FORMAT_XRGB2101010;  	case DISPPLANE_RGBX101010:  		return DRM_FORMAT_XBGR2101010; +	case DISPPLANE_BGRA101010: +		return DRM_FORMAT_ARGB2101010; +	case DISPPLANE_RGBA101010: +		return DRM_FORMAT_ABGR2101010;  	case DISPPLANE_RGBX161616:  		return DRM_FORMAT_XBGR16161616F;  	} @@ -3032,10 +3351,17 @@ int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)  				return DRM_FORMAT_XRGB8888;  		}  	case PLANE_CTL_FORMAT_XRGB_2101010: -		if (rgb_order) -			return DRM_FORMAT_XBGR2101010; -		else -			return DRM_FORMAT_XRGB2101010; +		if (rgb_order) { +			if (alpha) +				return DRM_FORMAT_ABGR2101010; +			else +				return DRM_FORMAT_XBGR2101010; +		} else { +			if (alpha) +				return DRM_FORMAT_ARGB2101010; +			else +				return DRM_FORMAT_XRGB2101010; +		}  	case PLANE_CTL_FORMAT_XRGB_16161616F:  		if (rgb_order) {  			if (alpha) @@ -3131,19 +3457,19 @@ intel_set_plane_visible(struct intel_crtc_state *crtc_state,  			struct intel_plane_state *plane_state,  			bool visible)  { -	struct intel_plane *plane = to_intel_plane(plane_state->base.plane); +	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); -	plane_state->base.visible = visible; +	plane_state->uapi.visible = visible;  	if (visible) -		crtc_state->base.plane_mask |= drm_plane_mask(&plane->base); +		crtc_state->uapi.plane_mask |= drm_plane_mask(&plane->base);  	else -		crtc_state->base.plane_mask &= ~drm_plane_mask(&plane->base); +		crtc_state->uapi.plane_mask &= ~drm_plane_mask(&plane->base);  }  static void fixup_active_planes(struct intel_crtc_state *crtc_state)  { -	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); +	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);  	struct drm_plane *plane;  	/* @@ -3154,13 +3480,14 @@ static void fixup_active_planes(struct intel_crtc_state *crtc_state)  	crtc_state->active_planes = 0;  	drm_for_each_plane_mask(plane, &dev_priv->drm, -				crtc_state->base.plane_mask) +				crtc_state->uapi.plane_mask)  		crtc_state->active_planes |= BIT(to_intel_plane(plane)->id);  }  static void intel_plane_disable_noatomic(struct intel_crtc *crtc,  					 struct intel_plane *plane)  { +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	struct intel_crtc_state *crtc_state =  		to_intel_crtc_state(crtc->base.state);  	struct intel_plane_state *plane_state = @@ -3176,7 +3503,27 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc,  	crtc_state->min_cdclk[plane->id] = 0;  	if (plane->id == PLANE_PRIMARY) -		intel_pre_disable_primary_noatomic(&crtc->base); +		hsw_disable_ips(crtc_state); + +	/* +	 * Vblank time updates from the shadow to live plane control register +	 * are blocked if the memory self-refresh mode is active at that +	 * moment. So to make sure the plane gets truly disabled, disable +	 * first the self-refresh mode. The self-refresh enable bit in turn +	 * will be checked/applied by the HW only at the next frame start +	 * event which is after the vblank start event, so we need to have a +	 * wait-for-vblank between disabling the plane and the pipe. +	 */ +	if (HAS_GMCH(dev_priv) && +	    intel_set_memory_cxsr(dev_priv, false)) +		intel_wait_for_vblank(dev_priv, crtc->pipe); + +	/* +	 * Gen2 reports pipe underruns whenever all planes are disabled. +	 * So disable underrun reporting before all the planes get disabled. +	 */ +	if (IS_GEN(dev_priv, 2) && !crtc_state->active_planes) +		intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false);  	intel_disable_plane(plane, crtc_state);  } @@ -3229,7 +3576,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,  			continue;  		if (intel_plane_ggtt_offset(state) == plane_config->base) { -			fb = state->base.fb; +			fb = state->hw.fb;  			drm_framebuffer_get(fb);  			goto valid_fb;  		} @@ -3247,11 +3594,11 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,  	return;  valid_fb: -	intel_state->base.rotation = plane_config->rotation; +	intel_state->hw.rotation = plane_config->rotation;  	intel_fill_fb_ggtt_view(&intel_state->view, fb, -				intel_state->base.rotation); +				intel_state->hw.rotation);  	intel_state->color_plane[0].stride = -		intel_fb_pitch(fb, 0, intel_state->base.rotation); +		intel_fb_pitch(fb, 0, intel_state->hw.rotation);  	intel_state->vma =  		intel_pin_and_fence_fb_obj(fb, @@ -3279,14 +3626,15 @@ valid_fb:  	plane_state->crtc_w = fb->width;  	plane_state->crtc_h = fb->height; -	intel_state->base.src = drm_plane_state_src(plane_state); -	intel_state->base.dst = drm_plane_state_dest(plane_state); +	intel_state->uapi.src = drm_plane_state_src(plane_state); +	intel_state->uapi.dst = drm_plane_state_dest(plane_state);  	if (plane_config->tiling)  		dev_priv->preserve_bios_swizzle = true;  	plane_state->fb = fb;  	plane_state->crtc = &intel_crtc->base; +	intel_plane_copy_uapi_to_hw_state(intel_state, intel_state);  	atomic_or(to_intel_plane(primary)->frontbuffer_bit,  		  &to_intel_frontbuffer(fb)->bits); @@ -3317,6 +3665,7 @@ static int skl_max_plane_width(const struct drm_framebuffer *fb,  			return 5120;  	case I915_FORMAT_MOD_Y_TILED_CCS:  	case I915_FORMAT_MOD_Yf_TILED_CCS: +	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:  		/* FIXME AUX plane? */  	case I915_FORMAT_MOD_Y_TILED:  	case I915_FORMAT_MOD_Yf_TILED: @@ -3375,17 +3724,20 @@ static int icl_max_plane_height(void)  	return 4320;  } -static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state, -					   int main_x, int main_y, u32 main_offset) -{ -	const struct drm_framebuffer *fb = plane_state->base.fb; -	int hsub = fb->format->hsub; -	int vsub = fb->format->vsub; -	int aux_x = plane_state->color_plane[1].x; -	int aux_y = plane_state->color_plane[1].y; -	u32 aux_offset = plane_state->color_plane[1].offset; -	u32 alignment = intel_surf_alignment(fb, 1); - +static bool +skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state, +			       int main_x, int main_y, u32 main_offset, +			       int ccs_plane) +{ +	const struct drm_framebuffer *fb = plane_state->hw.fb; +	int aux_x = plane_state->color_plane[ccs_plane].x; +	int aux_y = plane_state->color_plane[ccs_plane].y; +	u32 aux_offset = plane_state->color_plane[ccs_plane].offset; +	u32 alignment = intel_surf_alignment(fb, ccs_plane); +	int hsub; +	int vsub; + +	intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);  	while (aux_offset >= main_offset && aux_y <= main_y) {  		int x, y; @@ -3397,8 +3749,12 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state  		x = aux_x / hsub;  		y = aux_y / vsub; -		aux_offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 1, -							       aux_offset, aux_offset - alignment); +		aux_offset = intel_plane_adjust_aligned_offset(&x, &y, +							       plane_state, +							       ccs_plane, +							       aux_offset, +							       aux_offset - +								alignment);  		aux_x = x * hsub + aux_x % hsub;  		aux_y = y * vsub + aux_y % vsub;  	} @@ -3406,25 +3762,28 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state  	if (aux_x != main_x || aux_y != main_y)  		return false; -	plane_state->color_plane[1].offset = aux_offset; -	plane_state->color_plane[1].x = aux_x; -	plane_state->color_plane[1].y = aux_y; +	plane_state->color_plane[ccs_plane].offset = aux_offset; +	plane_state->color_plane[ccs_plane].x = aux_x; +	plane_state->color_plane[ccs_plane].y = aux_y;  	return true;  }  static int skl_check_main_surface(struct intel_plane_state *plane_state)  { -	struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); -	const struct drm_framebuffer *fb = plane_state->base.fb; -	unsigned int rotation = plane_state->base.rotation; -	int x = plane_state->base.src.x1 >> 16; -	int y = plane_state->base.src.y1 >> 16; -	int w = drm_rect_width(&plane_state->base.src) >> 16; -	int h = drm_rect_height(&plane_state->base.src) >> 16; +	struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev); +	const struct drm_framebuffer *fb = plane_state->hw.fb; +	unsigned int rotation = plane_state->hw.rotation; +	int x = plane_state->uapi.src.x1 >> 16; +	int y = plane_state->uapi.src.y1 >> 16; +	int w = drm_rect_width(&plane_state->uapi.src) >> 16; +	int h = drm_rect_height(&plane_state->uapi.src) >> 16;  	int max_width;  	int max_height; -	u32 alignment, offset, aux_offset = plane_state->color_plane[1].offset; +	u32 alignment; +	u32 offset; +	int aux_plane = intel_main_to_aux_plane(fb, 0); +	u32 aux_offset = plane_state->color_plane[aux_plane].offset;  	if (INTEL_GEN(dev_priv) >= 11)  		max_width = icl_max_plane_width(fb, 0, rotation); @@ -3447,6 +3806,8 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)  	intel_add_fb_offsets(&x, &y, plane_state, 0);  	offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 0);  	alignment = intel_surf_alignment(fb, 0); +	if (WARN_ON(alignment && !is_power_of_2(alignment))) +		return -EINVAL;  	/*  	 * AUX surface offset is specified as the distance from the @@ -3482,7 +3843,8 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)  	 * they match with the main surface x/y offsets.  	 */  	if (is_ccs_modifier(fb->modifier)) { -		while (!skl_check_main_ccs_coordinates(plane_state, x, y, offset)) { +		while (!skl_check_main_ccs_coordinates(plane_state, x, y, +						       offset, aux_plane)) {  			if (offset == 0)  				break; @@ -3490,7 +3852,8 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)  								   offset, offset - alignment);  		} -		if (x != plane_state->color_plane[1].x || y != plane_state->color_plane[1].y) { +		if (x != plane_state->color_plane[aux_plane].x || +		    y != plane_state->color_plane[aux_plane].y) {  			DRM_DEBUG_KMS("Unable to find suitable display surface offset due to CCS\n");  			return -EINVAL;  		} @@ -3504,7 +3867,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)  	 * Put the final coordinates back so that the src  	 * coordinate checks will see the right values.  	 */ -	drm_rect_translate_to(&plane_state->base.src, +	drm_rect_translate_to(&plane_state->uapi.src,  			      x << 16, y << 16);  	return 0; @@ -3512,18 +3875,20 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)  static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)  { -	const struct drm_framebuffer *fb = plane_state->base.fb; -	unsigned int rotation = plane_state->base.rotation; -	int max_width = skl_max_plane_width(fb, 1, rotation); +	const struct drm_framebuffer *fb = plane_state->hw.fb; +	unsigned int rotation = plane_state->hw.rotation; +	int uv_plane = 1; +	int max_width = skl_max_plane_width(fb, uv_plane, rotation);  	int max_height = 4096; -	int x = plane_state->base.src.x1 >> 17; -	int y = plane_state->base.src.y1 >> 17; -	int w = drm_rect_width(&plane_state->base.src) >> 17; -	int h = drm_rect_height(&plane_state->base.src) >> 17; +	int x = plane_state->uapi.src.x1 >> 17; +	int y = plane_state->uapi.src.y1 >> 17; +	int w = drm_rect_width(&plane_state->uapi.src) >> 17; +	int h = drm_rect_height(&plane_state->uapi.src) >> 17;  	u32 offset; -	intel_add_fb_offsets(&x, &y, plane_state, 1); -	offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 1); +	intel_add_fb_offsets(&x, &y, plane_state, uv_plane); +	offset = intel_plane_compute_aligned_offset(&x, &y, +						    plane_state, uv_plane);  	/* FIXME not quite sure how/if these apply to the chroma plane */  	if (w > max_width || h > max_height) { @@ -3532,62 +3897,126 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)  		return -EINVAL;  	} -	plane_state->color_plane[1].offset = offset; -	plane_state->color_plane[1].x = x; -	plane_state->color_plane[1].y = y; +	if (is_ccs_modifier(fb->modifier)) { +		int ccs_plane = main_to_ccs_plane(fb, uv_plane); +		int aux_offset = plane_state->color_plane[ccs_plane].offset; +		int alignment = intel_surf_alignment(fb, uv_plane); + +		if (offset > aux_offset) +			offset = intel_plane_adjust_aligned_offset(&x, &y, +								   plane_state, +								   uv_plane, +								   offset, +								   aux_offset & ~(alignment - 1)); + +		while (!skl_check_main_ccs_coordinates(plane_state, x, y, +						       offset, ccs_plane)) { +			if (offset == 0) +				break; + +			offset = intel_plane_adjust_aligned_offset(&x, &y, +								   plane_state, +								   uv_plane, +								   offset, offset - alignment); +		} + +		if (x != plane_state->color_plane[ccs_plane].x || +		    y != plane_state->color_plane[ccs_plane].y) { +			DRM_DEBUG_KMS("Unable to find suitable display surface offset due to CCS\n"); +			return -EINVAL; +		} +	} + +	plane_state->color_plane[uv_plane].offset = offset; +	plane_state->color_plane[uv_plane].x = x; +	plane_state->color_plane[uv_plane].y = y;  	return 0;  }  static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)  { -	const struct drm_framebuffer *fb = plane_state->base.fb; -	int src_x = plane_state->base.src.x1 >> 16; -	int src_y = plane_state->base.src.y1 >> 16; -	int hsub = fb->format->hsub; -	int vsub = fb->format->vsub; -	int x = src_x / hsub; -	int y = src_y / vsub; +	const struct drm_framebuffer *fb = plane_state->hw.fb; +	int src_x = plane_state->uapi.src.x1 >> 16; +	int src_y = plane_state->uapi.src.y1 >> 16;  	u32 offset; +	int ccs_plane; + +	for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) { +		int main_hsub, main_vsub; +		int hsub, vsub; +		int x, y; + +		if (!is_ccs_plane(fb, ccs_plane)) +			continue; + +		intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb, +					       ccs_to_main_plane(fb, ccs_plane)); +		intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane); + +		hsub *= main_hsub; +		vsub *= main_vsub; +		x = src_x / hsub; +		y = src_y / vsub; -	intel_add_fb_offsets(&x, &y, plane_state, 1); -	offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 1); +		intel_add_fb_offsets(&x, &y, plane_state, ccs_plane); -	plane_state->color_plane[1].offset = offset; -	plane_state->color_plane[1].x = x * hsub + src_x % hsub; -	plane_state->color_plane[1].y = y * vsub + src_y % vsub; +		offset = intel_plane_compute_aligned_offset(&x, &y, +							    plane_state, +							    ccs_plane); + +		plane_state->color_plane[ccs_plane].offset = offset; +		plane_state->color_plane[ccs_plane].x = (x * hsub + +							 src_x % hsub) / +							main_hsub; +		plane_state->color_plane[ccs_plane].y = (y * vsub + +							 src_y % vsub) / +							main_vsub; +	}  	return 0;  }  int skl_check_plane_surface(struct intel_plane_state *plane_state)  { -	const struct drm_framebuffer *fb = plane_state->base.fb; +	const struct drm_framebuffer *fb = plane_state->hw.fb;  	int ret; +	bool needs_aux = false;  	ret = intel_plane_compute_gtt(plane_state);  	if (ret)  		return ret; -	if (!plane_state->base.visible) +	if (!plane_state->uapi.visible)  		return 0;  	/* -	 * Handle the AUX surface first since -	 * the main surface setup depends on it. +	 * Handle the AUX surface first since the main surface setup depends on +	 * it.  	 */ -	if (drm_format_info_is_yuv_semiplanar(fb->format)) { -		ret = skl_check_nv12_aux_surface(plane_state); +	if (is_ccs_modifier(fb->modifier)) { +		needs_aux = true; +		ret = skl_check_ccs_aux_surface(plane_state);  		if (ret)  			return ret; -	} else if (is_ccs_modifier(fb->modifier)) { -		ret = skl_check_ccs_aux_surface(plane_state); +	} + +	if (intel_format_info_is_yuv_semiplanar(fb->format, +						fb->modifier)) { +		needs_aux = true; +		ret = skl_check_nv12_aux_surface(plane_state);  		if (ret)  			return ret; -	} else { -		plane_state->color_plane[1].offset = ~0xfff; -		plane_state->color_plane[1].x = 0; -		plane_state->color_plane[1].y = 0; +	} + +	if (!needs_aux) { +		int i; + +		for (i = 1; i < fb->format->num_planes; i++) { +			plane_state->color_plane[i].offset = ~0xfff; +			plane_state->color_plane[i].x = 0; +			plane_state->color_plane[i].y = 0; +		}  	}  	ret = skl_check_main_surface(plane_state); @@ -3601,7 +4030,7 @@ static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,  			     const struct intel_plane_state *plane_state,  			     unsigned int *num, unsigned int *den)  { -	const struct drm_framebuffer *fb = plane_state->base.fb; +	const struct drm_framebuffer *fb = plane_state->hw.fb;  	unsigned int cpp = fb->format->cpp[0];  	/* @@ -3673,7 +4102,7 @@ i9xx_plane_max_stride(struct intel_plane *plane,  static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	u32 dspcntr = 0; @@ -3693,9 +4122,9 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,  			  const struct intel_plane_state *plane_state)  {  	struct drm_i915_private *dev_priv = -		to_i915(plane_state->base.plane->dev); -	const struct drm_framebuffer *fb = plane_state->base.fb; -	unsigned int rotation = plane_state->base.rotation; +		to_i915(plane_state->uapi.plane->dev); +	const struct drm_framebuffer *fb = plane_state->hw.fb; +	unsigned int rotation = plane_state->hw.rotation;  	u32 dspcntr;  	dspcntr = DISPLAY_PLANE_ENABLE; @@ -3711,6 +4140,9 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,  	case DRM_FORMAT_XRGB1555:  		dspcntr |= DISPPLANE_BGRX555;  		break; +	case DRM_FORMAT_ARGB1555: +		dspcntr |= DISPPLANE_BGRA555; +		break;  	case DRM_FORMAT_RGB565:  		dspcntr |= DISPPLANE_BGRX565;  		break; @@ -3720,12 +4152,24 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,  	case DRM_FORMAT_XBGR8888:  		dspcntr |= DISPPLANE_RGBX888;  		break; +	case DRM_FORMAT_ARGB8888: +		dspcntr |= DISPPLANE_BGRA888; +		break; +	case DRM_FORMAT_ABGR8888: +		dspcntr |= DISPPLANE_RGBA888; +		break;  	case DRM_FORMAT_XRGB2101010:  		dspcntr |= DISPPLANE_BGRX101010;  		break;  	case DRM_FORMAT_XBGR2101010:  		dspcntr |= DISPPLANE_RGBX101010;  		break; +	case DRM_FORMAT_ARGB2101010: +		dspcntr |= DISPPLANE_BGRA101010; +		break; +	case DRM_FORMAT_ABGR2101010: +		dspcntr |= DISPPLANE_RGBA101010; +		break;  	case DRM_FORMAT_XBGR16161616F:  		dspcntr |= DISPPLANE_RGBX161616;  		break; @@ -3750,8 +4194,8 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,  int i9xx_check_plane_surface(struct intel_plane_state *plane_state)  {  	struct drm_i915_private *dev_priv = -		to_i915(plane_state->base.plane->dev); -	const struct drm_framebuffer *fb = plane_state->base.fb; +		to_i915(plane_state->uapi.plane->dev); +	const struct drm_framebuffer *fb = plane_state->hw.fb;  	int src_x, src_y, src_w;  	u32 offset;  	int ret; @@ -3760,12 +4204,12 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)  	if (ret)  		return ret; -	if (!plane_state->base.visible) +	if (!plane_state->uapi.visible)  		return 0; -	src_w = drm_rect_width(&plane_state->base.src) >> 16; -	src_x = plane_state->base.src.x1 >> 16; -	src_y = plane_state->base.src.y1 >> 16; +	src_w = drm_rect_width(&plane_state->uapi.src) >> 16; +	src_x = plane_state->uapi.src.x1 >> 16; +	src_y = plane_state->uapi.src.y1 >> 16;  	/* Undocumented hardware limit on i965/g4x/vlv/chv */  	if (HAS_GMCH(dev_priv) && fb->format->cpp[0] == 8 && src_w > 2048) @@ -3783,14 +4227,14 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)  	 * Put the final coordinates back so that the src  	 * coordinate checks will see the right values.  	 */ -	drm_rect_translate_to(&plane_state->base.src, +	drm_rect_translate_to(&plane_state->uapi.src,  			      src_x << 16, src_y << 16);  	/* HSW/BDW do this automagically in hardware */  	if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) { -		unsigned int rotation = plane_state->base.rotation; -		int src_w = drm_rect_width(&plane_state->base.src) >> 16; -		int src_h = drm_rect_height(&plane_state->base.src) >> 16; +		unsigned int rotation = plane_state->hw.rotation; +		int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; +		int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;  		if (rotation & DRM_MODE_ROTATE_180) {  			src_x += src_w - 1; @@ -3827,15 +4271,15 @@ static int  i9xx_plane_check(struct intel_crtc_state *crtc_state,  		 struct intel_plane_state *plane_state)  { -	struct intel_plane *plane = to_intel_plane(plane_state->base.plane); +	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);  	int ret;  	ret = chv_plane_check_rotation(plane_state);  	if (ret)  		return ret; -	ret = drm_atomic_helper_check_plane_state(&plane_state->base, -						  &crtc_state->base, +	ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, +						  &crtc_state->uapi,  						  DRM_PLANE_HELPER_NO_SCALING,  						  DRM_PLANE_HELPER_NO_SCALING,  						  i9xx_plane_has_windowing(plane), @@ -3847,7 +4291,7 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state,  	if (ret)  		return ret; -	if (!plane_state->base.visible) +	if (!plane_state->uapi.visible)  		return 0;  	ret = intel_plane_check_src_coordinates(plane_state); @@ -3868,10 +4312,10 @@ static void i9xx_update_plane(struct intel_plane *plane,  	u32 linear_offset;  	int x = plane_state->color_plane[0].x;  	int y = plane_state->color_plane[0].y; -	int crtc_x = plane_state->base.dst.x1; -	int crtc_y = plane_state->base.dst.y1; -	int crtc_w = drm_rect_width(&plane_state->base.dst); -	int crtc_h = drm_rect_height(&plane_state->base.dst); +	int crtc_x = plane_state->uapi.dst.x1; +	int crtc_y = plane_state->uapi.dst.y1; +	int crtc_w = drm_rect_width(&plane_state->uapi.dst); +	int crtc_h = drm_rect_height(&plane_state->uapi.dst);  	unsigned long irqflags;  	u32 dspaddr_offset;  	u32 dspcntr; @@ -4011,7 +4455,7 @@ static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)   */  static void skl_detach_scalers(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);  	const struct intel_crtc_scaler_state *scaler_state =  		&crtc_state->scaler_state;  	int i; @@ -4030,7 +4474,7 @@ static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb,  	 * The stride is either expressed as a multiple of 64 bytes chunks for  	 * linear buffers or in number of tiles for tiled buffers.  	 */ -	if (fb->modifier == DRM_FORMAT_MOD_LINEAR) +	if (is_surface_linear(fb, color_plane))  		return 64;  	else if (drm_rotation_90_or_270(rotation))  		return intel_tile_height(fb, color_plane); @@ -4041,8 +4485,8 @@ static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb,  u32 skl_plane_stride(const struct intel_plane_state *plane_state,  		     int color_plane)  { -	const struct drm_framebuffer *fb = plane_state->base.fb; -	unsigned int rotation = plane_state->base.rotation; +	const struct drm_framebuffer *fb = plane_state->hw.fb; +	unsigned int rotation = plane_state->hw.rotation;  	u32 stride = plane_state->color_plane[color_plane].stride;  	if (color_plane >= fb->format->num_planes) @@ -4065,8 +4509,10 @@ static u32 skl_plane_ctl_format(u32 pixel_format)  	case DRM_FORMAT_ARGB8888:  		return PLANE_CTL_FORMAT_XRGB_8888;  	case DRM_FORMAT_XBGR2101010: +	case DRM_FORMAT_ABGR2101010:  		return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX;  	case DRM_FORMAT_XRGB2101010: +	case DRM_FORMAT_ARGB2101010:  		return PLANE_CTL_FORMAT_XRGB_2101010;  	case DRM_FORMAT_XBGR16161616F:  	case DRM_FORMAT_ABGR16161616F: @@ -4111,10 +4557,10 @@ static u32 skl_plane_ctl_format(u32 pixel_format)  static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)  { -	if (!plane_state->base.fb->format->has_alpha) +	if (!plane_state->hw.fb->format->has_alpha)  		return PLANE_CTL_ALPHA_DISABLE; -	switch (plane_state->base.pixel_blend_mode) { +	switch (plane_state->hw.pixel_blend_mode) {  	case DRM_MODE_BLEND_PIXEL_NONE:  		return PLANE_CTL_ALPHA_DISABLE;  	case DRM_MODE_BLEND_PREMULTI: @@ -4122,17 +4568,17 @@ static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)  	case DRM_MODE_BLEND_COVERAGE:  		return PLANE_CTL_ALPHA_HW_PREMULTIPLY;  	default: -		MISSING_CASE(plane_state->base.pixel_blend_mode); +		MISSING_CASE(plane_state->hw.pixel_blend_mode);  		return PLANE_CTL_ALPHA_DISABLE;  	}  }  static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)  { -	if (!plane_state->base.fb->format->has_alpha) +	if (!plane_state->hw.fb->format->has_alpha)  		return PLANE_COLOR_ALPHA_DISABLE; -	switch (plane_state->base.pixel_blend_mode) { +	switch (plane_state->hw.pixel_blend_mode) {  	case DRM_MODE_BLEND_PIXEL_NONE:  		return PLANE_COLOR_ALPHA_DISABLE;  	case DRM_MODE_BLEND_PREMULTI: @@ -4140,7 +4586,7 @@ static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state  	case DRM_MODE_BLEND_COVERAGE:  		return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;  	default: -		MISSING_CASE(plane_state->base.pixel_blend_mode); +		MISSING_CASE(plane_state->hw.pixel_blend_mode);  		return PLANE_COLOR_ALPHA_DISABLE;  	}  } @@ -4156,6 +4602,12 @@ static u32 skl_plane_ctl_tiling(u64 fb_modifier)  		return PLANE_CTL_TILED_Y;  	case I915_FORMAT_MOD_Y_TILED_CCS:  		return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; +	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: +		return PLANE_CTL_TILED_Y | +		       PLANE_CTL_RENDER_DECOMPRESSION_ENABLE | +		       PLANE_CTL_CLEAR_COLOR_DISABLE; +	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: +		return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;  	case I915_FORMAT_MOD_Yf_TILED:  		return PLANE_CTL_TILED_YF;  	case I915_FORMAT_MOD_Yf_TILED_CCS: @@ -4206,7 +4658,7 @@ static u32 cnl_plane_ctl_flip(unsigned int reflect)  u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)  { -	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); +	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);  	u32 plane_ctl = 0;  	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) @@ -4225,9 +4677,9 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,  		  const struct intel_plane_state *plane_state)  {  	struct drm_i915_private *dev_priv = -		to_i915(plane_state->base.plane->dev); -	const struct drm_framebuffer *fb = plane_state->base.fb; -	unsigned int rotation = plane_state->base.rotation; +		to_i915(plane_state->uapi.plane->dev); +	const struct drm_framebuffer *fb = plane_state->hw.fb; +	unsigned int rotation = plane_state->hw.rotation;  	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;  	u32 plane_ctl; @@ -4237,10 +4689,10 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,  		plane_ctl |= skl_plane_ctl_alpha(plane_state);  		plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE; -		if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) +		if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)  			plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709; -		if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) +		if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)  			plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;  	} @@ -4262,7 +4714,7 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,  u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)  { -	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); +	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);  	u32 plane_color_ctl = 0;  	if (INTEL_GEN(dev_priv) >= 11) @@ -4281,21 +4733,21 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,  			const struct intel_plane_state *plane_state)  {  	struct drm_i915_private *dev_priv = -		to_i915(plane_state->base.plane->dev); -	const struct drm_framebuffer *fb = plane_state->base.fb; -	struct intel_plane *plane = to_intel_plane(plane_state->base.plane); +		to_i915(plane_state->uapi.plane->dev); +	const struct drm_framebuffer *fb = plane_state->hw.fb; +	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);  	u32 plane_color_ctl = 0;  	plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;  	plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);  	if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) { -		if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) +		if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)  			plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;  		else  			plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV601_TO_RGB709; -		if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) +		if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)  			plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;  	} else if (fb->format->is_yuv) {  		plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE; @@ -4483,7 +4935,7 @@ static void icl_set_pipe_chicken(struct intel_crtc *crtc)  static void icl_enable_trans_port_sync(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	u32 trans_ddi_func_ctl2_val;  	u8 master_select; @@ -4511,20 +4963,6 @@ static void icl_enable_trans_port_sync(const struct intel_crtc_state *crtc_state  		   trans_ddi_func_ctl2_val);  } -static void icl_disable_transcoder_port_sync(const struct intel_crtc_state *old_crtc_state) -{ -	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); -	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - -	if (old_crtc_state->master_transcoder == INVALID_TRANSCODER) -		return; - -	DRM_DEBUG_KMS("Disabling Transcoder Port Sync on Slave Transcoder %s\n", -		      transcoder_name(old_crtc_state->cpu_transcoder)); - -	I915_WRITE(TRANS_DDI_FUNC_CTL2(old_crtc_state->cpu_transcoder), 0); -} -  static void intel_fdi_normal_train(struct intel_crtc *crtc)  {  	struct drm_device *dev = crtc->base.dev; @@ -4567,8 +5005,8 @@ static void intel_fdi_normal_train(struct intel_crtc *crtc)  }  /* The FDI link training functions for ILK/Ibexpeak. */ -static void ironlake_fdi_link_train(struct intel_crtc *crtc, -				    const struct intel_crtc_state *crtc_state) +static void ilk_fdi_link_train(struct intel_crtc *crtc, +			       const struct intel_crtc_state *crtc_state)  {  	struct drm_device *dev = crtc->base.dev;  	struct drm_i915_private *dev_priv = to_i915(dev); @@ -4577,7 +5015,7 @@ static void ironlake_fdi_link_train(struct intel_crtc *crtc,  	u32 temp, tries;  	/* FDI needs bits from pipe first */ -	assert_pipe_enabled(dev_priv, pipe); +	assert_pipe_enabled(dev_priv, crtc_state->cpu_transcoder);  	/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit  	   for train result */ @@ -4920,9 +5358,9 @@ train_done:  	DRM_DEBUG_KMS("FDI train done.\n");  } -static void ironlake_fdi_pll_enable(const struct intel_crtc_state *crtc_state) +static void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);  	enum pipe pipe = intel_crtc->pipe;  	i915_reg_t reg; @@ -4957,7 +5395,7 @@ static void ironlake_fdi_pll_enable(const struct intel_crtc_state *crtc_state)  	}  } -static void ironlake_fdi_pll_disable(struct intel_crtc *intel_crtc) +static void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc)  {  	struct drm_device *dev = intel_crtc->base.dev;  	struct drm_i915_private *dev_priv = to_i915(dev); @@ -4987,12 +5425,10 @@ static void ironlake_fdi_pll_disable(struct intel_crtc *intel_crtc)  	udelay(100);  } -static void ironlake_fdi_disable(struct drm_crtc *crtc) +static void ilk_fdi_disable(struct intel_crtc *crtc)  { -	struct drm_device *dev = crtc->dev; -	struct drm_i915_private *dev_priv = to_i915(dev); -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	enum pipe pipe = intel_crtc->pipe; +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	enum pipe pipe = crtc->pipe;  	i915_reg_t reg;  	u32 temp; @@ -5083,9 +5519,9 @@ void lpt_disable_iclkip(struct drm_i915_private *dev_priv)  /* Program iCLKIP clock to the desired frequency */  static void lpt_program_iclkip(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); -	int clock = crtc_state->base.adjusted_mode.crtc_clock; +	int clock = crtc_state->hw.adjusted_mode.crtc_clock;  	u32 divsel, phaseinc, auxdiv, phasedir = 0;  	u32 temp; @@ -5196,10 +5632,10 @@ int lpt_get_iclkip(struct drm_i915_private *dev_priv)  				 desired_divisor << auxdiv);  } -static void ironlake_pch_transcoder_set_timings(const struct intel_crtc_state *crtc_state, -						enum pipe pch_transcoder) +static void ilk_pch_transcoder_set_timings(const struct intel_crtc_state *crtc_state, +					   enum pipe pch_transcoder)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; @@ -5240,9 +5676,9 @@ static void cpt_set_fdi_bc_bifurcation(struct drm_i915_private *dev_priv, bool e  	POSTING_READ(SOUTH_CHICKEN1);  } -static void ivybridge_update_fdi_bc_bifurcation(const struct intel_crtc_state *crtc_state) +static void ivb_update_fdi_bc_bifurcation(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	switch (crtc->pipe) { @@ -5272,7 +5708,7 @@ static struct intel_encoder *  intel_get_crtc_new_encoder(const struct intel_atomic_state *state,  			   const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	const struct drm_connector_state *connector_state;  	const struct drm_connector *connector;  	struct intel_encoder *encoder = NULL; @@ -5301,10 +5737,10 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state,   *   - DP transcoding bits   *   - transcoder   */ -static void ironlake_pch_enable(const struct intel_atomic_state *state, -				const struct intel_crtc_state *crtc_state) +static void ilk_pch_enable(const struct intel_atomic_state *state, +			   const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_device *dev = crtc->base.dev;  	struct drm_i915_private *dev_priv = to_i915(dev);  	enum pipe pipe = crtc->pipe; @@ -5313,7 +5749,7 @@ static void ironlake_pch_enable(const struct intel_atomic_state *state,  	assert_pch_transcoder_disabled(dev_priv, pipe);  	if (IS_IVYBRIDGE(dev_priv)) -		ivybridge_update_fdi_bc_bifurcation(crtc_state); +		ivb_update_fdi_bc_bifurcation(crtc_state);  	/* Write the TU size bits before fdi link training, so that error  	 * detection works. */ @@ -5350,7 +5786,7 @@ static void ironlake_pch_enable(const struct intel_atomic_state *state,  	/* set transcoder timing, panel must allow it */  	assert_panel_unlocked(dev_priv, pipe); -	ironlake_pch_transcoder_set_timings(crtc_state, pipe); +	ilk_pch_transcoder_set_timings(crtc_state, pipe);  	intel_fdi_normal_train(crtc); @@ -5358,7 +5794,7 @@ static void ironlake_pch_enable(const struct intel_atomic_state *state,  	if (HAS_PCH_CPT(dev_priv) &&  	    intel_crtc_has_dp_encoder(crtc_state)) {  		const struct drm_display_mode *adjusted_mode = -			&crtc_state->base.adjusted_mode; +			&crtc_state->hw.adjusted_mode;  		u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;  		i915_reg_t reg = TRANS_DP_CTL(pipe);  		enum port port; @@ -5382,13 +5818,13 @@ static void ironlake_pch_enable(const struct intel_atomic_state *state,  		I915_WRITE(reg, temp);  	} -	ironlake_enable_pch_transcoder(crtc_state); +	ilk_enable_pch_transcoder(crtc_state);  }  static void lpt_pch_enable(const struct intel_atomic_state *state,  			   const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; @@ -5397,14 +5833,14 @@ static void lpt_pch_enable(const struct intel_atomic_state *state,  	lpt_program_iclkip(crtc_state);  	/* Set transcoder timing. */ -	ironlake_pch_transcoder_set_timings(crtc_state, PIPE_A); +	ilk_pch_transcoder_set_timings(crtc_state, PIPE_A);  	lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);  } -static void cpt_verify_modeset(struct drm_device *dev, enum pipe pipe) +static void cpt_verify_modeset(struct drm_i915_private *dev_priv, +			       enum pipe pipe)  { -	struct drm_i915_private *dev_priv = to_i915(dev);  	i915_reg_t dslreg = PIPEDSL(pipe);  	u32 temp; @@ -5500,15 +5936,16 @@ static int  skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,  		  unsigned int scaler_user, int *scaler_id,  		  int src_w, int src_h, int dst_w, int dst_h, -		  const struct drm_format_info *format, bool need_scaler) +		  const struct drm_format_info *format, +		  u64 modifier, bool need_scaler)  {  	struct intel_crtc_scaler_state *scaler_state =  		&crtc_state->scaler_state;  	struct intel_crtc *intel_crtc = -		to_intel_crtc(crtc_state->base.crtc); +		to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);  	const struct drm_display_mode *adjusted_mode = -		&crtc_state->base.adjusted_mode; +		&crtc_state->hw.adjusted_mode;  	/*  	 * Src coordinates are already rotated by 270 degrees for @@ -5524,7 +5961,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,  	 * Once NV12 is enabled, handle it here while allocating scaler  	 * for NV12.  	 */ -	if (INTEL_GEN(dev_priv) >= 9 && crtc_state->base.enable && +	if (INTEL_GEN(dev_priv) >= 9 && crtc_state->hw.enable &&  	    need_scaler && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {  		DRM_DEBUG_KMS("Pipe/Plane scaling not supported with IF-ID mode\n");  		return -EINVAL; @@ -5554,7 +5991,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,  		return 0;  	} -	if (format && drm_format_info_is_yuv_semiplanar(format) && +	if (format && intel_format_info_is_yuv_semiplanar(format, modifier) &&  	    (src_h < SKL_MIN_YUV_420_SRC_H || src_w < SKL_MIN_YUV_420_SRC_W)) {  		DRM_DEBUG_KMS("Planar YUV: src dimensions not met\n");  		return -EINVAL; @@ -5596,17 +6033,18 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,   */  int skl_update_scaler_crtc(struct intel_crtc_state *state)  { -	const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode; +	const struct drm_display_mode *adjusted_mode = &state->hw.adjusted_mode;  	bool need_scaler = false;  	if (state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)  		need_scaler = true; -	return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX, +	return skl_update_scaler(state, !state->hw.active, SKL_CRTC_INDEX,  				 &state->scaler_state.scaler_id,  				 state->pipe_src_w, state->pipe_src_h,  				 adjusted_mode->crtc_hdisplay, -				 adjusted_mode->crtc_vdisplay, NULL, need_scaler); +				 adjusted_mode->crtc_vdisplay, NULL, 0, +				 need_scaler);  }  /** @@ -5622,26 +6060,28 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,  				   struct intel_plane_state *plane_state)  {  	struct intel_plane *intel_plane = -		to_intel_plane(plane_state->base.plane); +		to_intel_plane(plane_state->uapi.plane);  	struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev); -	struct drm_framebuffer *fb = plane_state->base.fb; +	struct drm_framebuffer *fb = plane_state->hw.fb;  	int ret; -	bool force_detach = !fb || !plane_state->base.visible; +	bool force_detach = !fb || !plane_state->uapi.visible;  	bool need_scaler = false;  	/* Pre-gen11 and SDR planes always need a scaler for planar formats. */  	if (!icl_is_hdr_plane(dev_priv, intel_plane->id) && -	    fb && drm_format_info_is_yuv_semiplanar(fb->format)) +	    fb && intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))  		need_scaler = true;  	ret = skl_update_scaler(crtc_state, force_detach,  				drm_plane_index(&intel_plane->base),  				&plane_state->scaler_id, -				drm_rect_width(&plane_state->base.src) >> 16, -				drm_rect_height(&plane_state->base.src) >> 16, -				drm_rect_width(&plane_state->base.dst), -				drm_rect_height(&plane_state->base.dst), -				fb ? fb->format : NULL, need_scaler); +				drm_rect_width(&plane_state->uapi.src) >> 16, +				drm_rect_height(&plane_state->uapi.src) >> 16, +				drm_rect_width(&plane_state->uapi.dst), +				drm_rect_height(&plane_state->uapi.dst), +				fb ? fb->format : NULL, +				fb ? fb->modifier : 0, +				need_scaler);  	if (ret || plane_state->scaler_id < 0)  		return ret; @@ -5663,6 +6103,8 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,  	case DRM_FORMAT_ARGB8888:  	case DRM_FORMAT_XRGB2101010:  	case DRM_FORMAT_XBGR2101010: +	case DRM_FORMAT_ARGB2101010: +	case DRM_FORMAT_ABGR2101010:  	case DRM_FORMAT_YUYV:  	case DRM_FORMAT_YVYU:  	case DRM_FORMAT_UYVY: @@ -5695,17 +6137,18 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,  	return 0;  } -static void skylake_scaler_disable(struct intel_crtc *crtc) +void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state)  { +	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);  	int i;  	for (i = 0; i < crtc->num_scalers; i++)  		skl_detach_scaler(crtc, i);  } -static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state) +static void skl_pfit_enable(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum pipe pipe = crtc->pipe;  	const struct intel_crtc_scaler_state *scaler_state = @@ -5740,9 +6183,9 @@ static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state)  	}  } -static void ironlake_pfit_enable(const struct intel_crtc_state *crtc_state) +static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum pipe pipe = crtc->pipe; @@ -5763,7 +6206,7 @@ static void ironlake_pfit_enable(const struct intel_crtc_state *crtc_state)  void hsw_enable_ips(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_device *dev = crtc->base.dev;  	struct drm_i915_private *dev_priv = to_i915(dev); @@ -5799,7 +6242,7 @@ void hsw_enable_ips(const struct intel_crtc_state *crtc_state)  void hsw_disable_ips(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_device *dev = crtc->base.dev;  	struct drm_i915_private *dev_priv = to_i915(dev); @@ -5834,77 +6277,10 @@ static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc)  	 */  } -/** - * intel_post_enable_primary - Perform operations after enabling primary plane - * @crtc: the CRTC whose primary plane was just enabled - * @new_crtc_state: the enabling state - * - * Performs potentially sleeping operations that must be done after the primary - * plane is enabled, such as updating FBC and IPS.  Note that this may be - * called due to an explicit primary plane update, or due to an implicit - * re-enable that is caused when a sprite plane is updated to no longer - * completely hide the primary plane. - */ -static void -intel_post_enable_primary(struct drm_crtc *crtc, -			  const struct intel_crtc_state *new_crtc_state) -{ -	struct drm_device *dev = crtc->dev; -	struct drm_i915_private *dev_priv = to_i915(dev); -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	enum pipe pipe = intel_crtc->pipe; - -	/* -	 * Gen2 reports pipe underruns whenever all planes are disabled. -	 * So don't enable underrun reporting before at least some planes -	 * are enabled. -	 * FIXME: Need to fix the logic to work when we turn off all planes -	 * but leave the pipe running. -	 */ -	if (IS_GEN(dev_priv, 2)) -		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - -	/* Underruns don't always raise interrupts, so check manually. */ -	intel_check_cpu_fifo_underruns(dev_priv); -	intel_check_pch_fifo_underruns(dev_priv); -} - -/* FIXME get rid of this and use pre_plane_update */ -static void -intel_pre_disable_primary_noatomic(struct drm_crtc *crtc) -{ -	struct drm_device *dev = crtc->dev; -	struct drm_i915_private *dev_priv = to_i915(dev); -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	enum pipe pipe = intel_crtc->pipe; - -	/* -	 * Gen2 reports pipe underruns whenever all planes are disabled. -	 * So disable underrun reporting before all the planes get disabled. -	 */ -	if (IS_GEN(dev_priv, 2)) -		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); - -	hsw_disable_ips(to_intel_crtc_state(crtc->state)); - -	/* -	 * Vblank time updates from the shadow to live plane control register -	 * are blocked if the memory self-refresh mode is active at that -	 * moment. So to make sure the plane gets truly disabled, disable -	 * first the self-refresh mode. The self-refresh enable bit in turn -	 * will be checked/applied by the HW only at the next frame start -	 * event which is after the vblank start event, so we need to have a -	 * wait-for-vblank between disabling the plane and the pipe. -	 */ -	if (HAS_GMCH(dev_priv) && -	    intel_set_memory_cxsr(dev_priv, false)) -		intel_wait_for_vblank(dev_priv, pipe); -} -  static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_state,  				       const struct intel_crtc_state *new_crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	if (!old_crtc_state->ips_enabled) @@ -5920,7 +6296,7 @@ static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_s  	 * Disable IPS before we program the LUT.  	 */  	if (IS_HASWELL(dev_priv) && -	    (new_crtc_state->base.color_mgmt_changed || +	    (new_crtc_state->uapi.color_mgmt_changed ||  	     new_crtc_state->update_pipe) &&  	    new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)  		return true; @@ -5931,7 +6307,7 @@ static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_s  static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_state,  				       const struct intel_crtc_state *new_crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	if (!new_crtc_state->ips_enabled) @@ -5947,7 +6323,7 @@ static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_s  	 * Re-enable IPS after the LUT has been programmed.  	 */  	if (IS_HASWELL(dev_priv) && -	    (new_crtc_state->base.color_mgmt_changed || +	    (new_crtc_state->uapi.color_mgmt_changed ||  	     new_crtc_state->update_pipe) &&  	    new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)  		return true; @@ -5957,15 +6333,16 @@ static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_s  	 * forcibly enable IPS on the first fastset.  	 */  	if (new_crtc_state->update_pipe && -	    old_crtc_state->base.adjusted_mode.private_flags & I915_MODE_FLAG_INHERITED) +	    old_crtc_state->hw.adjusted_mode.private_flags & I915_MODE_FLAG_INHERITED)  		return true;  	return !old_crtc_state->ips_enabled;  } -static bool needs_nv12_wa(struct drm_i915_private *dev_priv, -			  const struct intel_crtc_state *crtc_state) +static bool needs_nv12_wa(const struct intel_crtc_state *crtc_state)  { +	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); +  	if (!crtc_state->nv12_planes)  		return false; @@ -5976,9 +6353,10 @@ static bool needs_nv12_wa(struct drm_i915_private *dev_priv,  	return false;  } -static bool needs_scalerclk_wa(struct drm_i915_private *dev_priv, -			       const struct intel_crtc_state *crtc_state) +static bool needs_scalerclk_wa(const struct intel_crtc_state *crtc_state)  { +	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); +  	/* Wa_2006604312:icl */  	if (crtc_state->scaler_state.scaler_users > 0 && IS_ICELAKE(dev_priv))  		return true; @@ -5986,89 +6364,82 @@ static bool needs_scalerclk_wa(struct drm_i915_private *dev_priv,  	return false;  } -static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) +static bool planes_enabling(const struct intel_crtc_state *old_crtc_state, +			    const struct intel_crtc_state *new_crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); -	struct drm_device *dev = crtc->base.dev; -	struct drm_i915_private *dev_priv = to_i915(dev); -	struct drm_atomic_state *state = old_crtc_state->base.state; -	struct intel_crtc_state *pipe_config = -		intel_atomic_get_new_crtc_state(to_intel_atomic_state(state), -						crtc); -	struct drm_plane *primary = crtc->base.primary; -	struct drm_plane_state *old_primary_state = -		drm_atomic_get_old_plane_state(state, primary); +	return (!old_crtc_state->active_planes || needs_modeset(new_crtc_state)) && +		new_crtc_state->active_planes; +} -	intel_frontbuffer_flip(to_i915(crtc->base.dev), pipe_config->fb_bits); +static bool planes_disabling(const struct intel_crtc_state *old_crtc_state, +			     const struct intel_crtc_state *new_crtc_state) +{ +	return old_crtc_state->active_planes && +		(!new_crtc_state->active_planes || needs_modeset(new_crtc_state)); +} -	if (pipe_config->update_wm_post && pipe_config->base.active) -		intel_update_watermarks(crtc); +static void intel_post_plane_update(struct intel_atomic_state *state, +				    struct intel_crtc *crtc) +{ +	struct drm_i915_private *dev_priv = to_i915(state->base.dev); +	struct intel_plane *primary = to_intel_plane(crtc->base.primary); +	const struct intel_crtc_state *old_crtc_state = +		intel_atomic_get_old_crtc_state(state, crtc); +	const struct intel_crtc_state *new_crtc_state = +		intel_atomic_get_new_crtc_state(state, crtc); +	const struct intel_plane_state *new_primary_state = +		intel_atomic_get_new_plane_state(state, primary); +	enum pipe pipe = crtc->pipe; -	if (hsw_post_update_enable_ips(old_crtc_state, pipe_config)) -		hsw_enable_ips(pipe_config); +	intel_frontbuffer_flip(dev_priv, new_crtc_state->fb_bits); -	if (old_primary_state) { -		struct drm_plane_state *new_primary_state = -			drm_atomic_get_new_plane_state(state, primary); +	if (new_crtc_state->update_wm_post && new_crtc_state->hw.active) +		intel_update_watermarks(crtc); -		intel_fbc_post_update(crtc); +	if (hsw_post_update_enable_ips(old_crtc_state, new_crtc_state)) +		hsw_enable_ips(new_crtc_state); -		if (new_primary_state->visible && -		    (needs_modeset(pipe_config) || -		     !old_primary_state->visible)) -			intel_post_enable_primary(&crtc->base, pipe_config); -	} +	if (new_primary_state) +		intel_fbc_post_update(crtc); -	if (needs_nv12_wa(dev_priv, old_crtc_state) && -	    !needs_nv12_wa(dev_priv, pipe_config)) -		skl_wa_827(dev_priv, crtc->pipe, false); +	if (needs_nv12_wa(old_crtc_state) && +	    !needs_nv12_wa(new_crtc_state)) +		skl_wa_827(dev_priv, pipe, false); -	if (needs_scalerclk_wa(dev_priv, old_crtc_state) && -	    !needs_scalerclk_wa(dev_priv, pipe_config)) -		icl_wa_scalerclkgating(dev_priv, crtc->pipe, false); +	if (needs_scalerclk_wa(old_crtc_state) && +	    !needs_scalerclk_wa(new_crtc_state)) +		icl_wa_scalerclkgating(dev_priv, pipe, false);  } -static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, -				   struct intel_crtc_state *pipe_config) +static void intel_pre_plane_update(struct intel_atomic_state *state, +				   struct intel_crtc *crtc)  { -	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); -	struct drm_device *dev = crtc->base.dev; -	struct drm_i915_private *dev_priv = to_i915(dev); -	struct drm_atomic_state *state = old_crtc_state->base.state; -	struct drm_plane *primary = crtc->base.primary; -	struct drm_plane_state *old_primary_state = -		drm_atomic_get_old_plane_state(state, primary); -	bool modeset = needs_modeset(pipe_config); -	struct intel_atomic_state *intel_state = -		to_intel_atomic_state(state); +	struct drm_i915_private *dev_priv = to_i915(state->base.dev); +	struct intel_plane *primary = to_intel_plane(crtc->base.primary); +	const struct intel_crtc_state *old_crtc_state = +		intel_atomic_get_old_crtc_state(state, crtc); +	const struct intel_crtc_state *new_crtc_state = +		intel_atomic_get_new_crtc_state(state, crtc); +	const struct intel_plane_state *new_primary_state = +		intel_atomic_get_new_plane_state(state, primary); +	enum pipe pipe = crtc->pipe; -	if (hsw_pre_update_disable_ips(old_crtc_state, pipe_config)) +	if (hsw_pre_update_disable_ips(old_crtc_state, new_crtc_state))  		hsw_disable_ips(old_crtc_state); -	if (old_primary_state) { -		struct intel_plane_state *new_primary_state = -			intel_atomic_get_new_plane_state(intel_state, -							 to_intel_plane(primary)); - -		intel_fbc_pre_update(crtc, pipe_config, new_primary_state); -		/* -		 * Gen2 reports pipe underruns whenever all planes are disabled. -		 * So disable underrun reporting before all the planes get disabled. -		 */ -		if (IS_GEN(dev_priv, 2) && old_primary_state->visible && -		    (modeset || !new_primary_state->base.visible)) -			intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); -	} +	if (new_primary_state && +	    intel_fbc_pre_update(crtc, new_crtc_state, new_primary_state)) +		intel_wait_for_vblank(dev_priv, pipe);  	/* Display WA 827 */ -	if (!needs_nv12_wa(dev_priv, old_crtc_state) && -	    needs_nv12_wa(dev_priv, pipe_config)) -		skl_wa_827(dev_priv, crtc->pipe, true); +	if (!needs_nv12_wa(old_crtc_state) && +	    needs_nv12_wa(new_crtc_state)) +		skl_wa_827(dev_priv, pipe, true);  	/* Wa_2006604312:icl */ -	if (!needs_scalerclk_wa(dev_priv, old_crtc_state) && -	    needs_scalerclk_wa(dev_priv, pipe_config)) -		icl_wa_scalerclkgating(dev_priv, crtc->pipe, true); +	if (!needs_scalerclk_wa(old_crtc_state) && +	    needs_scalerclk_wa(new_crtc_state)) +		icl_wa_scalerclkgating(dev_priv, pipe, true);  	/*  	 * Vblank time updates from the shadow to live plane control register @@ -6079,9 +6450,9 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state,  	 * event which is after the vblank start event, so we need to have a  	 * wait-for-vblank between disabling the plane and the pipe.  	 */ -	if (HAS_GMCH(dev_priv) && old_crtc_state->base.active && -	    pipe_config->disable_cxsr && intel_set_memory_cxsr(dev_priv, false)) -		intel_wait_for_vblank(dev_priv, crtc->pipe); +	if (HAS_GMCH(dev_priv) && old_crtc_state->hw.active && +	    new_crtc_state->disable_cxsr && intel_set_memory_cxsr(dev_priv, false)) +		intel_wait_for_vblank(dev_priv, pipe);  	/*  	 * IVB workaround: must disable low power watermarks for at least @@ -6090,36 +6461,45 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state,  	 *  	 * WaCxSRDisabledForSpriteScaling:ivb  	 */ -	if (pipe_config->disable_lp_wm && ilk_disable_lp_wm(dev) && -	    old_crtc_state->base.active) -		intel_wait_for_vblank(dev_priv, crtc->pipe); +	if (old_crtc_state->hw.active && +	    new_crtc_state->disable_lp_wm && ilk_disable_lp_wm(dev_priv)) +		intel_wait_for_vblank(dev_priv, pipe);  	/* -	 * If we're doing a modeset, we're done.  No need to do any pre-vblank -	 * watermark programming here. +	 * If we're doing a modeset we don't need to do any +	 * pre-vblank watermark programming here.  	 */ -	if (needs_modeset(pipe_config)) -		return; +	if (!needs_modeset(new_crtc_state)) { +		/* +		 * For platforms that support atomic watermarks, program the +		 * 'intermediate' watermarks immediately.  On pre-gen9 platforms, these +		 * will be the intermediate values that are safe for both pre- and +		 * post- vblank; when vblank happens, the 'active' values will be set +		 * to the final 'target' values and we'll do this again to get the +		 * optimal watermarks.  For gen9+ platforms, the values we program here +		 * will be the final target values which will get automatically latched +		 * at vblank time; no further programming will be necessary. +		 * +		 * If a platform hasn't been transitioned to atomic watermarks yet, +		 * we'll continue to update watermarks the old way, if flags tell +		 * us to. +		 */ +		if (dev_priv->display.initial_watermarks) +			dev_priv->display.initial_watermarks(state, crtc); +		else if (new_crtc_state->update_wm_pre) +			intel_update_watermarks(crtc); +	}  	/* -	 * For platforms that support atomic watermarks, program the -	 * 'intermediate' watermarks immediately.  On pre-gen9 platforms, these -	 * will be the intermediate values that are safe for both pre- and -	 * post- vblank; when vblank happens, the 'active' values will be set -	 * to the final 'target' values and we'll do this again to get the -	 * optimal watermarks.  For gen9+ platforms, the values we program here -	 * will be the final target values which will get automatically latched -	 * at vblank time; no further programming will be necessary. +	 * Gen2 reports pipe underruns whenever all planes are disabled. +	 * So disable underrun reporting before all the planes get disabled.  	 * -	 * If a platform hasn't been transitioned to atomic watermarks yet, -	 * we'll continue to update watermarks the old way, if flags tell -	 * us to. +	 * We do this after .initial_watermarks() so that we have a +	 * chance of catching underruns with the intermediate watermarks +	 * vs. the old plane configuration.  	 */ -	if (dev_priv->display.initial_watermarks != NULL) -		dev_priv->display.initial_watermarks(intel_state, -						     pipe_config); -	else if (pipe_config->update_wm_pre) -		intel_update_watermarks(crtc); +	if (IS_GEN(dev_priv, 2) && planes_disabling(old_crtc_state, new_crtc_state)) +		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);  }  static void intel_crtc_disable_planes(struct intel_atomic_state *state, @@ -6143,7 +6523,7 @@ static void intel_crtc_disable_planes(struct intel_atomic_state *state,  		intel_disable_plane(plane, new_crtc_state); -		if (old_plane_state->base.visible) +		if (old_plane_state->uapi.visible)  			fb_bits |= plane->frontbuffer_bit;  	} @@ -6167,45 +6547,29 @@ intel_connector_primary_encoder(struct intel_connector *connector)  	if (connector->mst_port)  		return &dp_to_dig_port(connector->mst_port)->base; -	encoder = intel_attached_encoder(&connector->base); +	encoder = intel_attached_encoder(connector);  	WARN_ON(!encoder);  	return encoder;  } -static bool -intel_connector_needs_modeset(struct intel_atomic_state *state, -			      const struct drm_connector_state *old_conn_state, -			      const struct drm_connector_state *new_conn_state) -{ -	struct intel_crtc *old_crtc = old_conn_state->crtc ? -				      to_intel_crtc(old_conn_state->crtc) : NULL; -	struct intel_crtc *new_crtc = new_conn_state->crtc ? -				      to_intel_crtc(new_conn_state->crtc) : NULL; - -	return new_crtc != old_crtc || -	       (new_crtc && -		needs_modeset(intel_atomic_get_new_crtc_state(state, new_crtc))); -} -  static void intel_encoders_update_prepare(struct intel_atomic_state *state)  { -	struct drm_connector_state *old_conn_state;  	struct drm_connector_state *new_conn_state; -	struct drm_connector *conn; +	struct drm_connector *connector;  	int i; -	for_each_oldnew_connector_in_state(&state->base, conn, -					   old_conn_state, new_conn_state, i) { +	for_each_new_connector_in_state(&state->base, connector, new_conn_state, +					i) { +		struct intel_connector *intel_connector;  		struct intel_encoder *encoder;  		struct intel_crtc *crtc; -		if (!intel_connector_needs_modeset(state, -						   old_conn_state, -						   new_conn_state)) +		if (!intel_connector_needs_modeset(state, connector))  			continue; -		encoder = intel_connector_primary_encoder(to_intel_connector(conn)); +		intel_connector = to_intel_connector(connector); +		encoder = intel_connector_primary_encoder(intel_connector);  		if (!encoder->update_prepare)  			continue; @@ -6217,22 +6581,21 @@ static void intel_encoders_update_prepare(struct intel_atomic_state *state)  static void intel_encoders_update_complete(struct intel_atomic_state *state)  { -	struct drm_connector_state *old_conn_state;  	struct drm_connector_state *new_conn_state; -	struct drm_connector *conn; +	struct drm_connector *connector;  	int i; -	for_each_oldnew_connector_in_state(&state->base, conn, -					   old_conn_state, new_conn_state, i) { +	for_each_new_connector_in_state(&state->base, connector, new_conn_state, +					i) { +		struct intel_connector *intel_connector;  		struct intel_encoder *encoder;  		struct intel_crtc *crtc; -		if (!intel_connector_needs_modeset(state, -						   old_conn_state, -						   new_conn_state)) +		if (!intel_connector_needs_modeset(state, connector))  			continue; -		encoder = intel_connector_primary_encoder(to_intel_connector(conn)); +		intel_connector = to_intel_connector(connector); +		encoder = intel_connector_primary_encoder(intel_connector);  		if (!encoder->update_complete)  			continue; @@ -6242,11 +6605,12 @@ static void intel_encoders_update_complete(struct intel_atomic_state *state)  	}  } -static void intel_encoders_pre_pll_enable(struct intel_crtc *crtc, -					  struct intel_crtc_state *crtc_state, -					  struct intel_atomic_state *state) +static void intel_encoders_pre_pll_enable(struct intel_atomic_state *state, +					  struct intel_crtc *crtc)  { -	struct drm_connector_state *conn_state; +	const struct intel_crtc_state *crtc_state = +		intel_atomic_get_new_crtc_state(state, crtc); +	const struct drm_connector_state *conn_state;  	struct drm_connector *conn;  	int i; @@ -6262,11 +6626,12 @@ static void intel_encoders_pre_pll_enable(struct intel_crtc *crtc,  	}  } -static void intel_encoders_pre_enable(struct intel_crtc *crtc, -				      struct intel_crtc_state *crtc_state, -				      struct intel_atomic_state *state) +static void intel_encoders_pre_enable(struct intel_atomic_state *state, +				      struct intel_crtc *crtc)  { -	struct drm_connector_state *conn_state; +	const struct intel_crtc_state *crtc_state = +		intel_atomic_get_new_crtc_state(state, crtc); +	const struct drm_connector_state *conn_state;  	struct drm_connector *conn;  	int i; @@ -6282,11 +6647,12 @@ static void intel_encoders_pre_enable(struct intel_crtc *crtc,  	}  } -static void intel_encoders_enable(struct intel_crtc *crtc, -				  struct intel_crtc_state *crtc_state, -				  struct intel_atomic_state *state) +static void intel_encoders_enable(struct intel_atomic_state *state, +				  struct intel_crtc *crtc)  { -	struct drm_connector_state *conn_state; +	const struct intel_crtc_state *crtc_state = +		intel_atomic_get_new_crtc_state(state, crtc); +	const struct drm_connector_state *conn_state;  	struct drm_connector *conn;  	int i; @@ -6303,11 +6669,12 @@ static void intel_encoders_enable(struct intel_crtc *crtc,  	}  } -static void intel_encoders_disable(struct intel_crtc *crtc, -				   struct intel_crtc_state *old_crtc_state, -				   struct intel_atomic_state *state) +static void intel_encoders_disable(struct intel_atomic_state *state, +				   struct intel_crtc *crtc)  { -	struct drm_connector_state *old_conn_state; +	const struct intel_crtc_state *old_crtc_state = +		intel_atomic_get_old_crtc_state(state, crtc); +	const struct drm_connector_state *old_conn_state;  	struct drm_connector *conn;  	int i; @@ -6324,11 +6691,12 @@ static void intel_encoders_disable(struct intel_crtc *crtc,  	}  } -static void intel_encoders_post_disable(struct intel_crtc *crtc, -					struct intel_crtc_state *old_crtc_state, -					struct intel_atomic_state *state) +static void intel_encoders_post_disable(struct intel_atomic_state *state, +					struct intel_crtc *crtc)  { -	struct drm_connector_state *old_conn_state; +	const struct intel_crtc_state *old_crtc_state = +		intel_atomic_get_old_crtc_state(state, crtc); +	const struct drm_connector_state *old_conn_state;  	struct drm_connector *conn;  	int i; @@ -6344,11 +6712,12 @@ static void intel_encoders_post_disable(struct intel_crtc *crtc,  	}  } -static void intel_encoders_post_pll_disable(struct intel_crtc *crtc, -					    struct intel_crtc_state *old_crtc_state, -					    struct intel_atomic_state *state) +static void intel_encoders_post_pll_disable(struct intel_atomic_state *state, +					    struct intel_crtc *crtc)  { -	struct drm_connector_state *old_conn_state; +	const struct intel_crtc_state *old_crtc_state = +		intel_atomic_get_old_crtc_state(state, crtc); +	const struct drm_connector_state *old_conn_state;  	struct drm_connector *conn;  	int i; @@ -6364,11 +6733,12 @@ static void intel_encoders_post_pll_disable(struct intel_crtc *crtc,  	}  } -static void intel_encoders_update_pipe(struct intel_crtc *crtc, -				       struct intel_crtc_state *crtc_state, -				       struct intel_atomic_state *state) +static void intel_encoders_update_pipe(struct intel_atomic_state *state, +				       struct intel_crtc *crtc)  { -	struct drm_connector_state *conn_state; +	const struct intel_crtc_state *crtc_state = +		intel_atomic_get_new_crtc_state(state, crtc); +	const struct drm_connector_state *conn_state;  	struct drm_connector *conn;  	int i; @@ -6386,22 +6756,21 @@ static void intel_encoders_update_pipe(struct intel_crtc *crtc,  static void intel_disable_primary_plane(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct intel_plane *plane = to_intel_plane(crtc->base.primary);  	plane->disable_plane(plane, crtc_state);  } -static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, -				 struct intel_atomic_state *state) +static void ilk_crtc_enable(struct intel_atomic_state *state, +			    struct intel_crtc *crtc)  { -	struct drm_crtc *crtc = pipe_config->base.crtc; -	struct drm_device *dev = crtc->dev; -	struct drm_i915_private *dev_priv = to_i915(dev); -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	enum pipe pipe = intel_crtc->pipe; +	const struct intel_crtc_state *new_crtc_state = +		intel_atomic_get_new_crtc_state(state, crtc); +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	enum pipe pipe = crtc->pipe; -	if (WARN_ON(intel_crtc->active)) +	if (WARN_ON(crtc->active))  		return;  	/* @@ -6417,61 +6786,59 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,  	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);  	intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); -	if (pipe_config->has_pch_encoder) -		intel_prepare_shared_dpll(pipe_config); +	if (new_crtc_state->has_pch_encoder) +		intel_prepare_shared_dpll(new_crtc_state); -	if (intel_crtc_has_dp_encoder(pipe_config)) -		intel_dp_set_m_n(pipe_config, M1_N1); +	if (intel_crtc_has_dp_encoder(new_crtc_state)) +		intel_dp_set_m_n(new_crtc_state, M1_N1); -	intel_set_pipe_timings(pipe_config); -	intel_set_pipe_src_size(pipe_config); +	intel_set_pipe_timings(new_crtc_state); +	intel_set_pipe_src_size(new_crtc_state); -	if (pipe_config->has_pch_encoder) { -		intel_cpu_transcoder_set_m_n(pipe_config, -					     &pipe_config->fdi_m_n, NULL); -	} +	if (new_crtc_state->has_pch_encoder) +		intel_cpu_transcoder_set_m_n(new_crtc_state, +					     &new_crtc_state->fdi_m_n, NULL); -	ironlake_set_pipeconf(pipe_config); +	ilk_set_pipeconf(new_crtc_state); -	intel_crtc->active = true; +	crtc->active = true; -	intel_encoders_pre_enable(intel_crtc, pipe_config, state); +	intel_encoders_pre_enable(state, crtc); -	if (pipe_config->has_pch_encoder) { +	if (new_crtc_state->has_pch_encoder) {  		/* Note: FDI PLL enabling _must_ be done before we enable the  		 * cpu pipes, hence this is separate from all the other fdi/pch  		 * enabling. */ -		ironlake_fdi_pll_enable(pipe_config); +		ilk_fdi_pll_enable(new_crtc_state);  	} else {  		assert_fdi_tx_disabled(dev_priv, pipe);  		assert_fdi_rx_disabled(dev_priv, pipe);  	} -	ironlake_pfit_enable(pipe_config); +	ilk_pfit_enable(new_crtc_state);  	/*  	 * On ILK+ LUT must be loaded before the pipe is running but with  	 * clocks enabled  	 */ -	intel_color_load_luts(pipe_config); -	intel_color_commit(pipe_config); +	intel_color_load_luts(new_crtc_state); +	intel_color_commit(new_crtc_state);  	/* update DSPCNTR to configure gamma for pipe bottom color */ -	intel_disable_primary_plane(pipe_config); +	intel_disable_primary_plane(new_crtc_state); -	if (dev_priv->display.initial_watermarks != NULL) -		dev_priv->display.initial_watermarks(state, pipe_config); -	intel_enable_pipe(pipe_config); +	if (dev_priv->display.initial_watermarks) +		dev_priv->display.initial_watermarks(state, crtc); +	intel_enable_pipe(new_crtc_state); -	if (pipe_config->has_pch_encoder) -		ironlake_pch_enable(state, pipe_config); +	if (new_crtc_state->has_pch_encoder) +		ilk_pch_enable(state, new_crtc_state); -	assert_vblank_disabled(crtc); -	intel_crtc_vblank_on(pipe_config); +	intel_crtc_vblank_on(new_crtc_state); -	intel_encoders_enable(intel_crtc, pipe_config, state); +	intel_encoders_enable(state, crtc);  	if (HAS_PCH_CPT(dev_priv)) -		cpt_verify_modeset(dev, intel_crtc->pipe); +		cpt_verify_modeset(dev_priv, pipe);  	/*  	 * Must wait for vblank to avoid spurious PCH FIFO underruns. @@ -6479,7 +6846,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,  	 * some interlaced HDMI modes. Let's do the double wait always  	 * in case there are more corner cases we don't know about.  	 */ -	if (pipe_config->has_pch_encoder) { +	if (new_crtc_state->has_pch_encoder) {  		intel_wait_for_vblank(dev_priv, pipe);  		intel_wait_for_vblank(dev_priv, pipe);  	} @@ -6526,103 +6893,112 @@ static void icl_pipe_mbus_enable(struct intel_crtc *crtc)  	I915_WRITE(PIPE_MBUS_DBOX_CTL(pipe), val);  } -static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, -				struct intel_atomic_state *state) +static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state)  { -	struct drm_crtc *crtc = pipe_config->base.crtc; -	struct drm_i915_private *dev_priv = to_i915(crtc->dev); -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	enum pipe pipe = intel_crtc->pipe, hsw_workaround_pipe; -	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	i915_reg_t reg = CHICKEN_TRANS(crtc_state->cpu_transcoder); +	u32 val; + +	val = I915_READ(reg); +	val &= ~HSW_FRAME_START_DELAY_MASK; +	val |= HSW_FRAME_START_DELAY(0); +	I915_WRITE(reg, val); +} + +static void hsw_crtc_enable(struct intel_atomic_state *state, +			    struct intel_crtc *crtc) +{ +	const struct intel_crtc_state *new_crtc_state = +		intel_atomic_get_new_crtc_state(state, crtc); +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	enum pipe pipe = crtc->pipe, hsw_workaround_pipe; +	enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder;  	bool psl_clkgate_wa; -	if (WARN_ON(intel_crtc->active)) +	if (WARN_ON(crtc->active))  		return; -	intel_encoders_pre_pll_enable(intel_crtc, pipe_config, state); +	intel_encoders_pre_pll_enable(state, crtc); -	if (pipe_config->shared_dpll) -		intel_enable_shared_dpll(pipe_config); +	if (new_crtc_state->shared_dpll) +		intel_enable_shared_dpll(new_crtc_state); -	intel_encoders_pre_enable(intel_crtc, pipe_config, state); +	intel_encoders_pre_enable(state, crtc); -	if (intel_crtc_has_dp_encoder(pipe_config)) -		intel_dp_set_m_n(pipe_config, M1_N1); +	if (intel_crtc_has_dp_encoder(new_crtc_state)) +		intel_dp_set_m_n(new_crtc_state, M1_N1);  	if (!transcoder_is_dsi(cpu_transcoder)) -		intel_set_pipe_timings(pipe_config); +		intel_set_pipe_timings(new_crtc_state);  	if (INTEL_GEN(dev_priv) >= 11) -		icl_enable_trans_port_sync(pipe_config); +		icl_enable_trans_port_sync(new_crtc_state); -	intel_set_pipe_src_size(pipe_config); +	intel_set_pipe_src_size(new_crtc_state);  	if (cpu_transcoder != TRANSCODER_EDP && -	    !transcoder_is_dsi(cpu_transcoder)) { +	    !transcoder_is_dsi(cpu_transcoder))  		I915_WRITE(PIPE_MULT(cpu_transcoder), -			   pipe_config->pixel_multiplier - 1); -	} +			   new_crtc_state->pixel_multiplier - 1); -	if (pipe_config->has_pch_encoder) { -		intel_cpu_transcoder_set_m_n(pipe_config, -					     &pipe_config->fdi_m_n, NULL); -	} +	if (new_crtc_state->has_pch_encoder) +		intel_cpu_transcoder_set_m_n(new_crtc_state, +					     &new_crtc_state->fdi_m_n, NULL); -	if (!transcoder_is_dsi(cpu_transcoder)) -		haswell_set_pipeconf(pipe_config); +	if (!transcoder_is_dsi(cpu_transcoder)) { +		hsw_set_frame_start_delay(new_crtc_state); +		hsw_set_pipeconf(new_crtc_state); +	}  	if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) -		bdw_set_pipemisc(pipe_config); +		bdw_set_pipemisc(new_crtc_state); -	intel_crtc->active = true; +	crtc->active = true;  	/* Display WA #1180: WaDisableScalarClockGating: glk, cnl */  	psl_clkgate_wa = (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) && -			 pipe_config->pch_pfit.enabled; +		new_crtc_state->pch_pfit.enabled;  	if (psl_clkgate_wa)  		glk_pipe_scaler_clock_gating_wa(dev_priv, pipe, true);  	if (INTEL_GEN(dev_priv) >= 9) -		skylake_pfit_enable(pipe_config); +		skl_pfit_enable(new_crtc_state);  	else -		ironlake_pfit_enable(pipe_config); +		ilk_pfit_enable(new_crtc_state);  	/*  	 * On ILK+ LUT must be loaded before the pipe is running but with  	 * clocks enabled  	 */ -	intel_color_load_luts(pipe_config); -	intel_color_commit(pipe_config); +	intel_color_load_luts(new_crtc_state); +	intel_color_commit(new_crtc_state);  	/* update DSPCNTR to configure gamma/csc for pipe bottom color */  	if (INTEL_GEN(dev_priv) < 9) -		intel_disable_primary_plane(pipe_config); +		intel_disable_primary_plane(new_crtc_state);  	if (INTEL_GEN(dev_priv) >= 11) -		icl_set_pipe_chicken(intel_crtc); +		icl_set_pipe_chicken(crtc);  	if (!transcoder_is_dsi(cpu_transcoder)) -		intel_ddi_enable_transcoder_func(pipe_config); +		intel_ddi_enable_transcoder_func(new_crtc_state); -	if (dev_priv->display.initial_watermarks != NULL) -		dev_priv->display.initial_watermarks(state, pipe_config); +	if (dev_priv->display.initial_watermarks) +		dev_priv->display.initial_watermarks(state, crtc);  	if (INTEL_GEN(dev_priv) >= 11) -		icl_pipe_mbus_enable(intel_crtc); +		icl_pipe_mbus_enable(crtc);  	/* XXX: Do the pipe assertions at the right place for BXT DSI. */  	if (!transcoder_is_dsi(cpu_transcoder)) -		intel_enable_pipe(pipe_config); +		intel_enable_pipe(new_crtc_state); -	if (pipe_config->has_pch_encoder) -		lpt_pch_enable(state, pipe_config); - -	if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) -		intel_ddi_set_vc_payload_alloc(pipe_config, true); +	if (new_crtc_state->has_pch_encoder) +		lpt_pch_enable(state, new_crtc_state); -	assert_vblank_disabled(crtc); -	intel_crtc_vblank_on(pipe_config); +	intel_crtc_vblank_on(new_crtc_state); -	intel_encoders_enable(intel_crtc, pipe_config, state); +	intel_encoders_enable(state, crtc);  	if (psl_clkgate_wa) {  		intel_wait_for_vblank(dev_priv, pipe); @@ -6631,16 +7007,16 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,  	/* If we change the relative order between pipe/planes enabling, we need  	 * to change the workaround. */ -	hsw_workaround_pipe = pipe_config->hsw_workaround_pipe; +	hsw_workaround_pipe = new_crtc_state->hsw_workaround_pipe;  	if (IS_HASWELL(dev_priv) && hsw_workaround_pipe != INVALID_PIPE) {  		intel_wait_for_vblank(dev_priv, hsw_workaround_pipe);  		intel_wait_for_vblank(dev_priv, hsw_workaround_pipe);  	}  } -static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state) +void ilk_pfit_disable(const struct intel_crtc_state *old_crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum pipe pipe = crtc->pipe; @@ -6653,14 +7029,13 @@ static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state)  	}  } -static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, -				  struct intel_atomic_state *state) +static void ilk_crtc_disable(struct intel_atomic_state *state, +			     struct intel_crtc *crtc)  { -	struct drm_crtc *crtc = old_crtc_state->base.crtc; -	struct drm_device *dev = crtc->dev; -	struct drm_i915_private *dev_priv = to_i915(dev); -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	enum pipe pipe = intel_crtc->pipe; +	const struct intel_crtc_state *old_crtc_state = +		intel_atomic_get_old_crtc_state(state, crtc); +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	enum pipe pipe = crtc->pipe;  	/*  	 * Sometimes spurious CPU pipe underruns happen when the @@ -6670,22 +7045,21 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state,  	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);  	intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); -	intel_encoders_disable(intel_crtc, old_crtc_state, state); +	intel_encoders_disable(state, crtc); -	drm_crtc_vblank_off(crtc); -	assert_vblank_disabled(crtc); +	intel_crtc_vblank_off(old_crtc_state);  	intel_disable_pipe(old_crtc_state); -	ironlake_pfit_disable(old_crtc_state); +	ilk_pfit_disable(old_crtc_state);  	if (old_crtc_state->has_pch_encoder) -		ironlake_fdi_disable(crtc); +		ilk_fdi_disable(crtc); -	intel_encoders_post_disable(intel_crtc, old_crtc_state, state); +	intel_encoders_post_disable(state, crtc);  	if (old_crtc_state->has_pch_encoder) { -		ironlake_disable_pch_transcoder(dev_priv, pipe); +		ilk_disable_pch_transcoder(dev_priv, pipe);  		if (HAS_PCH_CPT(dev_priv)) {  			i915_reg_t reg; @@ -6705,54 +7079,27 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state,  			I915_WRITE(PCH_DPLL_SEL, temp);  		} -		ironlake_fdi_pll_disable(intel_crtc); +		ilk_fdi_pll_disable(crtc);  	}  	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);  	intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);  } -static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, -				 struct intel_atomic_state *state) +static void hsw_crtc_disable(struct intel_atomic_state *state, +			     struct intel_crtc *crtc)  { -	struct drm_crtc *crtc = old_crtc_state->base.crtc; -	struct drm_i915_private *dev_priv = to_i915(crtc->dev); -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; - -	intel_encoders_disable(intel_crtc, old_crtc_state, state); - -	drm_crtc_vblank_off(crtc); -	assert_vblank_disabled(crtc); - -	/* XXX: Do the pipe assertions at the right place for BXT DSI. */ -	if (!transcoder_is_dsi(cpu_transcoder)) -		intel_disable_pipe(old_crtc_state); - -	if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) -		intel_ddi_set_vc_payload_alloc(old_crtc_state, false); - -	if (INTEL_GEN(dev_priv) >= 11) -		icl_disable_transcoder_port_sync(old_crtc_state); - -	if (!transcoder_is_dsi(cpu_transcoder)) -		intel_ddi_disable_transcoder_func(old_crtc_state); - -	intel_dsc_disable(old_crtc_state); - -	if (INTEL_GEN(dev_priv) >= 9) -		skylake_scaler_disable(intel_crtc); -	else -		ironlake_pfit_disable(old_crtc_state); - -	intel_encoders_post_disable(intel_crtc, old_crtc_state, state); - -	intel_encoders_post_pll_disable(intel_crtc, old_crtc_state, state); +	/* +	 * FIXME collapse everything to one hook. +	 * Need care with mst->ddi interactions. +	 */ +	intel_encoders_disable(state, crtc); +	intel_encoders_post_disable(state, crtc);  }  static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	if (!crtc_state->gmch_pfit.control) @@ -6763,7 +7110,7 @@ static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state)  	 * according to register description and PRM.  	 */  	WARN_ON(I915_READ(PFIT_CONTROL) & PFIT_ENABLE); -	assert_pipe_disabled(dev_priv, crtc->pipe); +	assert_pipe_disabled(dev_priv, crtc_state->cpu_transcoder);  	I915_WRITE(PFIT_PGM_RATIOS, crtc_state->gmch_pfit.pgm_ratios);  	I915_WRITE(PFIT_CONTROL, crtc_state->gmch_pfit.control); @@ -6888,14 +7235,14 @@ intel_aux_power_domain(struct intel_digital_port *dig_port)  static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	struct drm_encoder *encoder;  	enum pipe pipe = crtc->pipe;  	u64 mask;  	enum transcoder transcoder = crtc_state->cpu_transcoder; -	if (!crtc_state->base.active) +	if (!crtc_state->hw.active)  		return 0;  	mask = BIT_ULL(POWER_DOMAIN_PIPE(pipe)); @@ -6905,7 +7252,7 @@ static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state)  		mask |= BIT_ULL(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));  	drm_for_each_encoder_mask(encoder, &dev_priv->drm, -				  crtc_state->base.encoder_mask) { +				  crtc_state->uapi.encoder_mask) {  		struct intel_encoder *intel_encoder = to_intel_encoder(encoder);  		mask |= BIT_ULL(intel_encoder->power_domain); @@ -6923,7 +7270,7 @@ static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state)  static u64  modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum intel_display_power_domain domain;  	u64 domains, new_domains, old_domains; @@ -6949,146 +7296,140 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv,  		intel_display_power_put_unchecked(dev_priv, domain);  } -static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, -				   struct intel_atomic_state *state) +static void valleyview_crtc_enable(struct intel_atomic_state *state, +				   struct intel_crtc *crtc)  { -	struct drm_crtc *crtc = pipe_config->base.crtc; -	struct drm_device *dev = crtc->dev; -	struct drm_i915_private *dev_priv = to_i915(dev); -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	enum pipe pipe = intel_crtc->pipe; +	const struct intel_crtc_state *new_crtc_state = +		intel_atomic_get_new_crtc_state(state, crtc); +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	enum pipe pipe = crtc->pipe; -	if (WARN_ON(intel_crtc->active)) +	if (WARN_ON(crtc->active))  		return; -	if (intel_crtc_has_dp_encoder(pipe_config)) -		intel_dp_set_m_n(pipe_config, M1_N1); +	if (intel_crtc_has_dp_encoder(new_crtc_state)) +		intel_dp_set_m_n(new_crtc_state, M1_N1); -	intel_set_pipe_timings(pipe_config); -	intel_set_pipe_src_size(pipe_config); +	intel_set_pipe_timings(new_crtc_state); +	intel_set_pipe_src_size(new_crtc_state);  	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {  		I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY);  		I915_WRITE(CHV_CANVAS(pipe), 0);  	} -	i9xx_set_pipeconf(pipe_config); +	i9xx_set_pipeconf(new_crtc_state); -	intel_crtc->active = true; +	crtc->active = true;  	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); -	intel_encoders_pre_pll_enable(intel_crtc, pipe_config, state); +	intel_encoders_pre_pll_enable(state, crtc);  	if (IS_CHERRYVIEW(dev_priv)) { -		chv_prepare_pll(intel_crtc, pipe_config); -		chv_enable_pll(intel_crtc, pipe_config); +		chv_prepare_pll(crtc, new_crtc_state); +		chv_enable_pll(crtc, new_crtc_state);  	} else { -		vlv_prepare_pll(intel_crtc, pipe_config); -		vlv_enable_pll(intel_crtc, pipe_config); +		vlv_prepare_pll(crtc, new_crtc_state); +		vlv_enable_pll(crtc, new_crtc_state);  	} -	intel_encoders_pre_enable(intel_crtc, pipe_config, state); +	intel_encoders_pre_enable(state, crtc); -	i9xx_pfit_enable(pipe_config); +	i9xx_pfit_enable(new_crtc_state); -	intel_color_load_luts(pipe_config); -	intel_color_commit(pipe_config); +	intel_color_load_luts(new_crtc_state); +	intel_color_commit(new_crtc_state);  	/* update DSPCNTR to configure gamma for pipe bottom color */ -	intel_disable_primary_plane(pipe_config); +	intel_disable_primary_plane(new_crtc_state); -	dev_priv->display.initial_watermarks(state, pipe_config); -	intel_enable_pipe(pipe_config); +	dev_priv->display.initial_watermarks(state, crtc); +	intel_enable_pipe(new_crtc_state); -	assert_vblank_disabled(crtc); -	intel_crtc_vblank_on(pipe_config); +	intel_crtc_vblank_on(new_crtc_state); -	intel_encoders_enable(intel_crtc, pipe_config, state); +	intel_encoders_enable(state, crtc);  }  static void i9xx_set_pll_dividers(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	I915_WRITE(FP0(crtc->pipe), crtc_state->dpll_hw_state.fp0);  	I915_WRITE(FP1(crtc->pipe), crtc_state->dpll_hw_state.fp1);  } -static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, -			     struct intel_atomic_state *state) +static void i9xx_crtc_enable(struct intel_atomic_state *state, +			     struct intel_crtc *crtc)  { -	struct drm_crtc *crtc = pipe_config->base.crtc; -	struct drm_device *dev = crtc->dev; -	struct drm_i915_private *dev_priv = to_i915(dev); -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	enum pipe pipe = intel_crtc->pipe; +	const struct intel_crtc_state *new_crtc_state = +		intel_atomic_get_new_crtc_state(state, crtc); +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	enum pipe pipe = crtc->pipe; -	if (WARN_ON(intel_crtc->active)) +	if (WARN_ON(crtc->active))  		return; -	i9xx_set_pll_dividers(pipe_config); +	i9xx_set_pll_dividers(new_crtc_state); -	if (intel_crtc_has_dp_encoder(pipe_config)) -		intel_dp_set_m_n(pipe_config, M1_N1); +	if (intel_crtc_has_dp_encoder(new_crtc_state)) +		intel_dp_set_m_n(new_crtc_state, M1_N1); -	intel_set_pipe_timings(pipe_config); -	intel_set_pipe_src_size(pipe_config); +	intel_set_pipe_timings(new_crtc_state); +	intel_set_pipe_src_size(new_crtc_state); -	i9xx_set_pipeconf(pipe_config); +	i9xx_set_pipeconf(new_crtc_state); -	intel_crtc->active = true; +	crtc->active = true;  	if (!IS_GEN(dev_priv, 2))  		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); -	intel_encoders_pre_enable(intel_crtc, pipe_config, state); +	intel_encoders_pre_enable(state, crtc); -	i9xx_enable_pll(intel_crtc, pipe_config); +	i9xx_enable_pll(crtc, new_crtc_state); -	i9xx_pfit_enable(pipe_config); +	i9xx_pfit_enable(new_crtc_state); -	intel_color_load_luts(pipe_config); -	intel_color_commit(pipe_config); +	intel_color_load_luts(new_crtc_state); +	intel_color_commit(new_crtc_state);  	/* update DSPCNTR to configure gamma for pipe bottom color */ -	intel_disable_primary_plane(pipe_config); +	intel_disable_primary_plane(new_crtc_state); -	if (dev_priv->display.initial_watermarks != NULL) -		dev_priv->display.initial_watermarks(state, -						     pipe_config); +	if (dev_priv->display.initial_watermarks) +		dev_priv->display.initial_watermarks(state, crtc);  	else -		intel_update_watermarks(intel_crtc); -	intel_enable_pipe(pipe_config); +		intel_update_watermarks(crtc); +	intel_enable_pipe(new_crtc_state); -	assert_vblank_disabled(crtc); -	intel_crtc_vblank_on(pipe_config); +	intel_crtc_vblank_on(new_crtc_state); -	intel_encoders_enable(intel_crtc, pipe_config, state); +	intel_encoders_enable(state, crtc);  }  static void i9xx_pfit_disable(const struct intel_crtc_state *old_crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	if (!old_crtc_state->gmch_pfit.control)  		return; -	assert_pipe_disabled(dev_priv, crtc->pipe); +	assert_pipe_disabled(dev_priv, old_crtc_state->cpu_transcoder);  	DRM_DEBUG_KMS("disabling pfit, current: 0x%08x\n",  		      I915_READ(PFIT_CONTROL));  	I915_WRITE(PFIT_CONTROL, 0);  } -static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, -			      struct intel_atomic_state *state) +static void i9xx_crtc_disable(struct intel_atomic_state *state, +			      struct intel_crtc *crtc)  { -	struct drm_crtc *crtc = old_crtc_state->base.crtc; -	struct drm_device *dev = crtc->dev; -	struct drm_i915_private *dev_priv = to_i915(dev); -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	enum pipe pipe = intel_crtc->pipe; +	struct intel_crtc_state *old_crtc_state = +		intel_atomic_get_old_crtc_state(state, crtc); +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	enum pipe pipe = crtc->pipe;  	/*  	 * On gen2 planes are double buffered but the pipe isn't, so we must @@ -7097,16 +7438,15 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,  	if (IS_GEN(dev_priv, 2))  		intel_wait_for_vblank(dev_priv, pipe); -	intel_encoders_disable(intel_crtc, old_crtc_state, state); +	intel_encoders_disable(state, crtc); -	drm_crtc_vblank_off(crtc); -	assert_vblank_disabled(crtc); +	intel_crtc_vblank_off(old_crtc_state);  	intel_disable_pipe(old_crtc_state);  	i9xx_pfit_disable(old_crtc_state); -	intel_encoders_post_disable(intel_crtc, old_crtc_state, state); +	intel_encoders_post_disable(state, crtc);  	if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DSI)) {  		if (IS_CHERRYVIEW(dev_priv)) @@ -7117,92 +7457,97 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,  			i9xx_disable_pll(old_crtc_state);  	} -	intel_encoders_post_pll_disable(intel_crtc, old_crtc_state, state); +	intel_encoders_post_pll_disable(state, crtc);  	if (!IS_GEN(dev_priv, 2))  		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);  	if (!dev_priv->display.initial_watermarks) -		intel_update_watermarks(intel_crtc); +		intel_update_watermarks(crtc);  	/* clock the pipe down to 640x480@60 to potentially save power */  	if (IS_I830(dev_priv))  		i830_enable_pipe(dev_priv, pipe);  } -static void intel_crtc_disable_noatomic(struct drm_crtc *crtc, +static void intel_crtc_disable_noatomic(struct intel_crtc *crtc,  					struct drm_modeset_acquire_ctx *ctx)  {  	struct intel_encoder *encoder; -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	struct drm_i915_private *dev_priv = to_i915(crtc->dev); +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	struct intel_bw_state *bw_state =  		to_intel_bw_state(dev_priv->bw_obj.state); +	struct intel_crtc_state *crtc_state = +		to_intel_crtc_state(crtc->base.state);  	enum intel_display_power_domain domain;  	struct intel_plane *plane; -	u64 domains;  	struct drm_atomic_state *state; -	struct intel_crtc_state *crtc_state; +	struct intel_crtc_state *temp_crtc_state; +	enum pipe pipe = crtc->pipe; +	u64 domains;  	int ret; -	if (!intel_crtc->active) +	if (!crtc_state->hw.active)  		return; -	for_each_intel_plane_on_crtc(&dev_priv->drm, intel_crtc, plane) { +	for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {  		const struct intel_plane_state *plane_state =  			to_intel_plane_state(plane->base.state); -		if (plane_state->base.visible) -			intel_plane_disable_noatomic(intel_crtc, plane); +		if (plane_state->uapi.visible) +			intel_plane_disable_noatomic(crtc, plane);  	} -	state = drm_atomic_state_alloc(crtc->dev); +	state = drm_atomic_state_alloc(&dev_priv->drm);  	if (!state) {  		DRM_DEBUG_KMS("failed to disable [CRTC:%d:%s], out of memory", -			      crtc->base.id, crtc->name); +			      crtc->base.base.id, crtc->base.name);  		return;  	}  	state->acquire_ctx = ctx;  	/* Everything's already locked, -EDEADLK can't happen. */ -	crtc_state = intel_atomic_get_crtc_state(state, intel_crtc); -	ret = drm_atomic_add_affected_connectors(state, crtc); +	temp_crtc_state = intel_atomic_get_crtc_state(state, crtc); +	ret = drm_atomic_add_affected_connectors(state, &crtc->base); -	WARN_ON(IS_ERR(crtc_state) || ret); +	WARN_ON(IS_ERR(temp_crtc_state) || ret); -	dev_priv->display.crtc_disable(crtc_state, to_intel_atomic_state(state)); +	dev_priv->display.crtc_disable(to_intel_atomic_state(state), crtc);  	drm_atomic_state_put(state);  	DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n", -		      crtc->base.id, crtc->name); +		      crtc->base.base.id, crtc->base.name); -	WARN_ON(drm_atomic_set_mode_for_crtc(crtc->state, NULL) < 0); -	crtc->state->active = false; -	intel_crtc->active = false; -	crtc->enabled = false; -	crtc->state->connector_mask = 0; -	crtc->state->encoder_mask = 0; +	crtc->active = false; +	crtc->base.enabled = false; + +	WARN_ON(drm_atomic_set_mode_for_crtc(&crtc_state->uapi, NULL) < 0); +	crtc_state->uapi.active = false; +	crtc_state->uapi.connector_mask = 0; +	crtc_state->uapi.encoder_mask = 0; +	intel_crtc_free_hw_state(crtc_state); +	memset(&crtc_state->hw, 0, sizeof(crtc_state->hw)); -	for_each_encoder_on_crtc(crtc->dev, crtc, encoder) +	for_each_encoder_on_crtc(&dev_priv->drm, &crtc->base, encoder)  		encoder->base.crtc = NULL; -	intel_fbc_disable(intel_crtc); -	intel_update_watermarks(intel_crtc); -	intel_disable_shared_dpll(to_intel_crtc_state(crtc->state)); +	intel_fbc_disable(crtc); +	intel_update_watermarks(crtc); +	intel_disable_shared_dpll(crtc_state); -	domains = intel_crtc->enabled_power_domains; +	domains = crtc->enabled_power_domains;  	for_each_power_domain(domain, domains)  		intel_display_power_put_unchecked(dev_priv, domain); -	intel_crtc->enabled_power_domains = 0; +	crtc->enabled_power_domains = 0; -	dev_priv->active_pipes &= ~BIT(intel_crtc->pipe); -	dev_priv->min_cdclk[intel_crtc->pipe] = 0; -	dev_priv->min_voltage_level[intel_crtc->pipe] = 0; +	dev_priv->active_pipes &= ~BIT(pipe); +	dev_priv->min_cdclk[pipe] = 0; +	dev_priv->min_voltage_level[pipe] = 0; -	bw_state->data_rate[intel_crtc->pipe] = 0; -	bw_state->num_active_planes[intel_crtc->pipe] = 0; +	bw_state->data_rate[pipe] = 0; +	bw_state->num_active_planes[pipe] = 0;  }  /* @@ -7252,8 +7597,8 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state,  		if (!crtc_state)  			return; -		I915_STATE_WARN(!crtc_state->base.active, -		      "connector is active, but attached crtc isn't\n"); +		I915_STATE_WARN(!crtc_state->hw.active, +				"connector is active, but attached crtc isn't\n");  		if (!encoder || encoder->type == INTEL_OUTPUT_DP_MST)  			return; @@ -7264,8 +7609,8 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state,  		I915_STATE_WARN(conn_state->crtc != encoder->base.crtc,  			"attached encoder crtc differs from connector crtc\n");  	} else { -		I915_STATE_WARN(crtc_state && crtc_state->base.active, -			"attached crtc is active, but connector isn't\n"); +		I915_STATE_WARN(crtc_state && crtc_state->hw.active, +				"attached crtc is active, but connector isn't\n");  		I915_STATE_WARN(!crtc_state && conn_state->best_encoder,  			"best encoder set without crtc!\n");  	} @@ -7273,17 +7618,17 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state,  static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)  { -	if (crtc_state->base.enable && crtc_state->has_pch_encoder) +	if (crtc_state->hw.enable && crtc_state->has_pch_encoder)  		return crtc_state->fdi_lanes;  	return 0;  } -static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, -				     struct intel_crtc_state *pipe_config) +static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, +			       struct intel_crtc_state *pipe_config)  {  	struct drm_i915_private *dev_priv = to_i915(dev); -	struct drm_atomic_state *state = pipe_config->base.state; +	struct drm_atomic_state *state = pipe_config->uapi.state;  	struct intel_crtc *other_crtc;  	struct intel_crtc_state *other_crtc_state; @@ -7352,11 +7697,11 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,  }  #define RETRY 1 -static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc, -				       struct intel_crtc_state *pipe_config) +static int ilk_fdi_compute_config(struct intel_crtc *intel_crtc, +				  struct intel_crtc_state *pipe_config)  {  	struct drm_device *dev = intel_crtc->base.dev; -	const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; +	const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;  	int lane, link_bw, fdi_dotclock, ret;  	bool needs_recompute = false; @@ -7372,15 +7717,15 @@ retry:  	fdi_dotclock = adjusted_mode->crtc_clock; -	lane = ironlake_get_lanes_required(fdi_dotclock, link_bw, -					   pipe_config->pipe_bpp); +	lane = ilk_get_lanes_required(fdi_dotclock, link_bw, +				      pipe_config->pipe_bpp);  	pipe_config->fdi_lanes = lane;  	intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,  			       link_bw, &pipe_config->fdi_m_n, false, false); -	ret = ironlake_check_fdi_lanes(dev, intel_crtc->pipe, pipe_config); +	ret = ilk_check_fdi_lanes(dev, intel_crtc->pipe, pipe_config);  	if (ret == -EDEADLK)  		return ret; @@ -7402,7 +7747,7 @@ retry:  bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	/* IPS only exists on ULT machines and is tied to pipe A. */ @@ -7432,9 +7777,9 @@ bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)  static bool hsw_compute_ips_config(struct intel_crtc_state *crtc_state)  {  	struct drm_i915_private *dev_priv = -		to_i915(crtc_state->base.crtc->dev); +		to_i915(crtc_state->uapi.crtc->dev);  	struct intel_atomic_state *intel_state = -		to_intel_atomic_state(crtc_state->base.state); +		to_intel_atomic_state(crtc_state->uapi.state);  	if (!hsw_crtc_state_ips_capable(crtc_state))  		return false; @@ -7473,7 +7818,7 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)  {  	u32 pixel_rate; -	pixel_rate = pipe_config->base.adjusted_mode.crtc_clock; +	pixel_rate = pipe_config->hw.adjusted_mode.crtc_clock;  	/*  	 * We only use IF-ID interlacing. If we ever use @@ -7506,12 +7851,12 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)  static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)  { -	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); +	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);  	if (HAS_GMCH(dev_priv))  		/* FIXME calculate proper pipe pixel rate for GMCH pfit */  		crtc_state->pixel_rate = -			crtc_state->base.adjusted_mode.crtc_clock; +			crtc_state->hw.adjusted_mode.crtc_clock;  	else  		crtc_state->pixel_rate =  			ilk_pipe_pixel_rate(crtc_state); @@ -7521,7 +7866,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,  				     struct intel_crtc_state *pipe_config)  {  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); -	const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; +	const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;  	int clock_limit = dev_priv->max_dotclk_freq;  	if (INTEL_GEN(dev_priv) < 4) { @@ -7547,7 +7892,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,  	if ((pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||  	     pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) && -	     pipe_config->base.ctm) { +	     pipe_config->hw.ctm) {  		/*  		 * There is only one pipe CSC unit per pipe, and we need that  		 * for output conversion from RGB->YCBCR. So if CTM is already @@ -7586,7 +7931,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,  	intel_crtc_compute_pixel_rate(pipe_config);  	if (pipe_config->has_pch_encoder) -		return ironlake_fdi_compute_config(crtc, pipe_config); +		return ilk_fdi_compute_config(crtc, pipe_config);  	return 0;  } @@ -7741,7 +8086,7 @@ static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe  static void intel_pch_transcoder_set_m_n(const struct intel_crtc_state *crtc_state,  					 const struct intel_link_m_n *m_n)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum pipe pipe = crtc->pipe; @@ -7768,7 +8113,7 @@ static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_sta  					 const struct intel_link_m_n *m_n,  					 const struct intel_link_m_n *m2_n2)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum pipe pipe = crtc->pipe;  	enum transcoder transcoder = crtc_state->cpu_transcoder; @@ -8077,11 +8422,11 @@ int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,  	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);  	struct intel_crtc_state *pipe_config; -	pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL); +	pipe_config = intel_crtc_state_alloc(crtc);  	if (!pipe_config)  		return -ENOMEM; -	pipe_config->base.crtc = &crtc->base; +	pipe_config->cpu_transcoder = (enum transcoder)pipe;  	pipe_config->pixel_multiplier = 1;  	pipe_config->dpll = *dpll; @@ -8241,11 +8586,11 @@ static void i8xx_compute_dpll(struct intel_crtc *crtc,  static void intel_set_pipe_timings(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum pipe pipe = crtc->pipe;  	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; -	const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; +	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;  	u32 crtc_vtotal, crtc_vblank_end;  	int vsyncshift = 0; @@ -8303,7 +8648,7 @@ static void intel_set_pipe_timings(const struct intel_crtc_state *crtc_state)  static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum pipe pipe = crtc->pipe; @@ -8317,7 +8662,7 @@ static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state)  static bool intel_pipe_is_interlaced(const struct intel_crtc_state *crtc_state)  { -	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); +	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);  	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;  	if (IS_GEN(dev_priv, 2)) @@ -8339,39 +8684,39 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc,  	u32 tmp;  	tmp = I915_READ(HTOTAL(cpu_transcoder)); -	pipe_config->base.adjusted_mode.crtc_hdisplay = (tmp & 0xffff) + 1; -	pipe_config->base.adjusted_mode.crtc_htotal = ((tmp >> 16) & 0xffff) + 1; +	pipe_config->hw.adjusted_mode.crtc_hdisplay = (tmp & 0xffff) + 1; +	pipe_config->hw.adjusted_mode.crtc_htotal = ((tmp >> 16) & 0xffff) + 1;  	if (!transcoder_is_dsi(cpu_transcoder)) {  		tmp = I915_READ(HBLANK(cpu_transcoder)); -		pipe_config->base.adjusted_mode.crtc_hblank_start = +		pipe_config->hw.adjusted_mode.crtc_hblank_start =  							(tmp & 0xffff) + 1; -		pipe_config->base.adjusted_mode.crtc_hblank_end = +		pipe_config->hw.adjusted_mode.crtc_hblank_end =  						((tmp >> 16) & 0xffff) + 1;  	}  	tmp = I915_READ(HSYNC(cpu_transcoder)); -	pipe_config->base.adjusted_mode.crtc_hsync_start = (tmp & 0xffff) + 1; -	pipe_config->base.adjusted_mode.crtc_hsync_end = ((tmp >> 16) & 0xffff) + 1; +	pipe_config->hw.adjusted_mode.crtc_hsync_start = (tmp & 0xffff) + 1; +	pipe_config->hw.adjusted_mode.crtc_hsync_end = ((tmp >> 16) & 0xffff) + 1;  	tmp = I915_READ(VTOTAL(cpu_transcoder)); -	pipe_config->base.adjusted_mode.crtc_vdisplay = (tmp & 0xffff) + 1; -	pipe_config->base.adjusted_mode.crtc_vtotal = ((tmp >> 16) & 0xffff) + 1; +	pipe_config->hw.adjusted_mode.crtc_vdisplay = (tmp & 0xffff) + 1; +	pipe_config->hw.adjusted_mode.crtc_vtotal = ((tmp >> 16) & 0xffff) + 1;  	if (!transcoder_is_dsi(cpu_transcoder)) {  		tmp = I915_READ(VBLANK(cpu_transcoder)); -		pipe_config->base.adjusted_mode.crtc_vblank_start = +		pipe_config->hw.adjusted_mode.crtc_vblank_start =  							(tmp & 0xffff) + 1; -		pipe_config->base.adjusted_mode.crtc_vblank_end = +		pipe_config->hw.adjusted_mode.crtc_vblank_end =  						((tmp >> 16) & 0xffff) + 1;  	}  	tmp = I915_READ(VSYNC(cpu_transcoder)); -	pipe_config->base.adjusted_mode.crtc_vsync_start = (tmp & 0xffff) + 1; -	pipe_config->base.adjusted_mode.crtc_vsync_end = ((tmp >> 16) & 0xffff) + 1; +	pipe_config->hw.adjusted_mode.crtc_vsync_start = (tmp & 0xffff) + 1; +	pipe_config->hw.adjusted_mode.crtc_vsync_end = ((tmp >> 16) & 0xffff) + 1;  	if (intel_pipe_is_interlaced(pipe_config)) { -		pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_INTERLACE; -		pipe_config->base.adjusted_mode.crtc_vtotal += 1; -		pipe_config->base.adjusted_mode.crtc_vblank_end += 1; +		pipe_config->hw.adjusted_mode.flags |= DRM_MODE_FLAG_INTERLACE; +		pipe_config->hw.adjusted_mode.crtc_vtotal += 1; +		pipe_config->hw.adjusted_mode.crtc_vblank_end += 1;  	}  } @@ -8386,27 +8731,27 @@ static void intel_get_pipe_src_size(struct intel_crtc *crtc,  	pipe_config->pipe_src_h = (tmp & 0xffff) + 1;  	pipe_config->pipe_src_w = ((tmp >> 16) & 0xffff) + 1; -	pipe_config->base.mode.vdisplay = pipe_config->pipe_src_h; -	pipe_config->base.mode.hdisplay = pipe_config->pipe_src_w; +	pipe_config->hw.mode.vdisplay = pipe_config->pipe_src_h; +	pipe_config->hw.mode.hdisplay = pipe_config->pipe_src_w;  }  void intel_mode_from_pipe_config(struct drm_display_mode *mode,  				 struct intel_crtc_state *pipe_config)  { -	mode->hdisplay = pipe_config->base.adjusted_mode.crtc_hdisplay; -	mode->htotal = pipe_config->base.adjusted_mode.crtc_htotal; -	mode->hsync_start = pipe_config->base.adjusted_mode.crtc_hsync_start; -	mode->hsync_end = pipe_config->base.adjusted_mode.crtc_hsync_end; +	mode->hdisplay = pipe_config->hw.adjusted_mode.crtc_hdisplay; +	mode->htotal = pipe_config->hw.adjusted_mode.crtc_htotal; +	mode->hsync_start = pipe_config->hw.adjusted_mode.crtc_hsync_start; +	mode->hsync_end = pipe_config->hw.adjusted_mode.crtc_hsync_end; -	mode->vdisplay = pipe_config->base.adjusted_mode.crtc_vdisplay; -	mode->vtotal = pipe_config->base.adjusted_mode.crtc_vtotal; -	mode->vsync_start = pipe_config->base.adjusted_mode.crtc_vsync_start; -	mode->vsync_end = pipe_config->base.adjusted_mode.crtc_vsync_end; +	mode->vdisplay = pipe_config->hw.adjusted_mode.crtc_vdisplay; +	mode->vtotal = pipe_config->hw.adjusted_mode.crtc_vtotal; +	mode->vsync_start = pipe_config->hw.adjusted_mode.crtc_vsync_start; +	mode->vsync_end = pipe_config->hw.adjusted_mode.crtc_vsync_end; -	mode->flags = pipe_config->base.adjusted_mode.flags; +	mode->flags = pipe_config->hw.adjusted_mode.flags;  	mode->type = DRM_MODE_TYPE_DRIVER; -	mode->clock = pipe_config->base.adjusted_mode.crtc_clock; +	mode->clock = pipe_config->hw.adjusted_mode.crtc_clock;  	mode->hsync = drm_mode_hsync(mode);  	mode->vrefresh = drm_mode_vrefresh(mode); @@ -8415,7 +8760,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,  static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	u32 pipeconf; @@ -8452,7 +8797,7 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)  		}  	} -	if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { +	if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {  		if (INTEL_GEN(dev_priv) < 4 ||  		    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO))  			pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION; @@ -8468,6 +8813,8 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)  	pipeconf |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode); +	pipeconf |= PIPECONF_FRAME_START_DELAY(0); +  	I915_WRITE(PIPECONF(crtc->pipe), pipeconf);  	POSTING_READ(PIPECONF(crtc->pipe));  } @@ -8567,9 +8914,9 @@ static int pnv_crtc_compute_clock(struct intel_crtc *crtc,  			DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);  		} -		limit = &intel_limits_pineview_lvds; +		limit = &pnv_limits_lvds;  	} else { -		limit = &intel_limits_pineview_sdvo; +		limit = &pnv_limits_sdvo;  	}  	if (!crtc_state->clock_set && @@ -8861,7 +9208,7 @@ bdw_get_pipemisc_output_format(struct intel_crtc *crtc)  static void i9xx_get_pipe_color_config(struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct intel_plane *plane = to_intel_plane(crtc->base.primary);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; @@ -8985,7 +9332,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,  	 * but in case the pipe is enabled w/o any ports we need a sane  	 * default.  	 */ -	pipe_config->base.adjusted_mode.crtc_clock = +	pipe_config->hw.adjusted_mode.crtc_clock =  		pipe_config->port_clock / pipe_config->pixel_multiplier;  	ret = true; @@ -8996,7 +9343,7 @@ out:  	return ret;  } -static void ironlake_init_pch_refclk(struct drm_i915_private *dev_priv) +static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv)  {  	struct intel_encoder *encoder;  	int i; @@ -9494,14 +9841,14 @@ static void lpt_init_pch_refclk(struct drm_i915_private *dev_priv)  void intel_init_pch_refclk(struct drm_i915_private *dev_priv)  {  	if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) -		ironlake_init_pch_refclk(dev_priv); +		ilk_init_pch_refclk(dev_priv);  	else if (HAS_PCH_LPT(dev_priv))  		lpt_init_pch_refclk(dev_priv);  } -static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state) +static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum pipe pipe = crtc->pipe;  	u32 val; @@ -9529,7 +9876,7 @@ static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state)  	if (crtc_state->dither)  		val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP); -	if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) +	if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)  		val |= PIPECONF_INTERLACED_ILK;  	else  		val |= PIPECONF_PROGRESSIVE; @@ -9549,13 +9896,15 @@ static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state)  	val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode); +	val |= PIPECONF_FRAME_START_DELAY(0); +  	I915_WRITE(PIPECONF(pipe), val);  	POSTING_READ(PIPECONF(pipe));  } -static void haswell_set_pipeconf(const struct intel_crtc_state *crtc_state) +static void hsw_set_pipeconf(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;  	u32 val = 0; @@ -9563,7 +9912,7 @@ static void haswell_set_pipeconf(const struct intel_crtc_state *crtc_state)  	if (IS_HASWELL(dev_priv) && crtc_state->dither)  		val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP); -	if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) +	if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)  		val |= PIPECONF_INTERLACED_ILK;  	else  		val |= PIPECONF_PROGRESSIVE; @@ -9578,7 +9927,7 @@ static void haswell_set_pipeconf(const struct intel_crtc_state *crtc_state)  static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	u32 val = 0; @@ -9641,7 +9990,7 @@ int bdw_get_pipemisc_bpp(struct intel_crtc *crtc)  	}  } -int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp) +int ilk_get_lanes_required(int target_clock, int link_bw, int bpp)  {  	/*  	 * Account for spread spectrum to avoid @@ -9652,14 +10001,14 @@ int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp)  	return DIV_ROUND_UP(bps, link_bw * 8);  } -static bool ironlake_needs_fb_cb_tune(struct dpll *dpll, int factor) +static bool ilk_needs_fb_cb_tune(struct dpll *dpll, int factor)  {  	return i9xx_dpll_compute_m(dpll) < factor * dpll->n;  } -static void ironlake_compute_dpll(struct intel_crtc *crtc, -				  struct intel_crtc_state *crtc_state, -				  struct dpll *reduced_clock) +static void ilk_compute_dpll(struct intel_crtc *crtc, +			     struct intel_crtc_state *crtc_state, +			     struct dpll *reduced_clock)  {  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	u32 dpll, fp, fp2; @@ -9679,7 +10028,7 @@ static void ironlake_compute_dpll(struct intel_crtc *crtc,  	fp = i9xx_dpll_compute_fp(&crtc_state->dpll); -	if (ironlake_needs_fb_cb_tune(&crtc_state->dpll, factor)) +	if (ilk_needs_fb_cb_tune(&crtc_state->dpll, factor))  		fp |= FP_CB_TUNE;  	if (reduced_clock) { @@ -9759,12 +10108,12 @@ static void ironlake_compute_dpll(struct intel_crtc *crtc,  	crtc_state->dpll_hw_state.fp1 = fp2;  } -static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, -				       struct intel_crtc_state *crtc_state) +static int ilk_crtc_compute_clock(struct intel_crtc *crtc, +				  struct intel_crtc_state *crtc_state)  {  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	struct intel_atomic_state *state = -		to_intel_atomic_state(crtc_state->base.state); +		to_intel_atomic_state(crtc_state->uapi.state);  	const struct intel_limit *limit;  	int refclk = 120000; @@ -9784,17 +10133,17 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,  		if (intel_is_dual_link_lvds(dev_priv)) {  			if (refclk == 100000) -				limit = &intel_limits_ironlake_dual_lvds_100m; +				limit = &ilk_limits_dual_lvds_100m;  			else -				limit = &intel_limits_ironlake_dual_lvds; +				limit = &ilk_limits_dual_lvds;  		} else {  			if (refclk == 100000) -				limit = &intel_limits_ironlake_single_lvds_100m; +				limit = &ilk_limits_single_lvds_100m;  			else -				limit = &intel_limits_ironlake_single_lvds; +				limit = &ilk_limits_single_lvds;  		}  	} else { -		limit = &intel_limits_ironlake_dac; +		limit = &ilk_limits_dac;  	}  	if (!crtc_state->clock_set && @@ -9804,7 +10153,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,  		return -EINVAL;  	} -	ironlake_compute_dpll(crtc, crtc_state, NULL); +	ilk_compute_dpll(crtc, crtc_state, NULL);  	if (!intel_reserve_shared_dplls(state, crtc, NULL)) {  		DRM_DEBUG_KMS("failed to find PLL for pipe %c\n", @@ -9879,15 +10228,15 @@ void intel_dp_get_m_n(struct intel_crtc *crtc,  					     &pipe_config->dp_m2_n2);  } -static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc, -					struct intel_crtc_state *pipe_config) +static void ilk_get_fdi_m_n_config(struct intel_crtc *crtc, +				   struct intel_crtc_state *pipe_config)  {  	intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder,  				     &pipe_config->fdi_m_n, NULL);  } -static void skylake_get_pfit_config(struct intel_crtc *crtc, -				    struct intel_crtc_state *pipe_config) +static void skl_get_pfit_config(struct intel_crtc *crtc, +				struct intel_crtc_state *pipe_config)  {  	struct drm_device *dev = crtc->base.dev;  	struct drm_i915_private *dev_priv = to_i915(dev); @@ -9918,8 +10267,8 @@ static void skylake_get_pfit_config(struct intel_crtc *crtc,  }  static void -skylake_get_initial_plane_config(struct intel_crtc *crtc, -				 struct intel_initial_plane_config *plane_config) +skl_get_initial_plane_config(struct intel_crtc *crtc, +			     struct intel_initial_plane_config *plane_config)  {  	struct drm_device *dev = crtc->base.dev;  	struct drm_i915_private *dev_priv = to_i915(dev); @@ -9977,7 +10326,11 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,  	case PLANE_CTL_TILED_Y:  		plane_config->tiling = I915_TILING_Y;  		if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) -			fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS; +			fb->modifier = INTEL_GEN(dev_priv) >= 12 ? +				I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS : +				I915_FORMAT_MOD_Y_TILED_CCS; +		else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE) +			fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;  		else  			fb->modifier = I915_FORMAT_MOD_Y_TILED;  		break; @@ -10044,8 +10397,8 @@ error:  	kfree(intel_fb);  } -static void ironlake_get_pfit_config(struct intel_crtc *crtc, -				     struct intel_crtc_state *pipe_config) +static void ilk_get_pfit_config(struct intel_crtc *crtc, +				struct intel_crtc_state *pipe_config)  {  	struct drm_device *dev = crtc->base.dev;  	struct drm_i915_private *dev_priv = to_i915(dev); @@ -10068,8 +10421,8 @@ static void ironlake_get_pfit_config(struct intel_crtc *crtc,  	}  } -static bool ironlake_get_pipe_config(struct intel_crtc *crtc, -				     struct intel_crtc_state *pipe_config) +static bool ilk_get_pipe_config(struct intel_crtc *crtc, +				struct intel_crtc_state *pipe_config)  {  	struct drm_device *dev = crtc->base.dev;  	struct drm_i915_private *dev_priv = to_i915(dev); @@ -10140,7 +10493,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,  		pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>  					  FDI_DP_PORT_WIDTH_SHIFT) + 1; -		ironlake_get_fdi_m_n_config(crtc, pipe_config); +		ilk_get_fdi_m_n_config(crtc, pipe_config);  		if (HAS_PCH_IBX(dev_priv)) {  			/* @@ -10168,7 +10521,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,  			((tmp & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK)  			 >> PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT) + 1; -		ironlake_pch_clock_get(crtc, pipe_config); +		ilk_pch_clock_get(crtc, pipe_config);  	} else {  		pipe_config->pixel_multiplier = 1;  	} @@ -10176,7 +10529,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,  	intel_get_pipe_timings(crtc, pipe_config);  	intel_get_pipe_src_size(crtc, pipe_config); -	ironlake_get_pfit_config(crtc, pipe_config); +	ilk_get_pfit_config(crtc, pipe_config);  	ret = true; @@ -10185,12 +10538,13 @@ out:  	return ret;  } -static int haswell_crtc_compute_clock(struct intel_crtc *crtc, -				      struct intel_crtc_state *crtc_state) + +static int hsw_crtc_compute_clock(struct intel_crtc *crtc, +				  struct intel_crtc_state *crtc_state)  {  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	struct intel_atomic_state *state = -		to_intel_atomic_state(crtc_state->base.state); +		to_intel_atomic_state(crtc_state->uapi.state);  	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||  	    INTEL_GEN(dev_priv) >= 11) { @@ -10207,9 +10561,8 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc,  	return 0;  } -static void cannonlake_get_ddi_pll(struct drm_i915_private *dev_priv, -				   enum port port, -				   struct intel_crtc_state *pipe_config) +static void cnl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, +			    struct intel_crtc_state *pipe_config)  {  	enum intel_dpll_id id;  	u32 temp; @@ -10223,9 +10576,8 @@ static void cannonlake_get_ddi_pll(struct drm_i915_private *dev_priv,  	pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id);  } -static void icelake_get_ddi_pll(struct drm_i915_private *dev_priv, -				enum port port, -				struct intel_crtc_state *pipe_config) +static void icl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, +			    struct intel_crtc_state *pipe_config)  {  	enum phy phy = intel_port_to_phy(dev_priv, port);  	enum icl_port_dpll_id port_dpll_id; @@ -10284,9 +10636,8 @@ static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv,  	pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id);  } -static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv, -				enum port port, -				struct intel_crtc_state *pipe_config) +static void skl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, +			    struct intel_crtc_state *pipe_config)  {  	enum intel_dpll_id id;  	u32 temp; @@ -10300,9 +10651,8 @@ static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv,  	pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id);  } -static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv, -				enum port port, -				struct intel_crtc_state *pipe_config) +static void hsw_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, +			    struct intel_crtc_state *pipe_config)  {  	enum intel_dpll_id id;  	u32 ddi_pll_sel = I915_READ(PORT_CLK_SEL(port)); @@ -10403,6 +10753,9 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,  		case TRANS_DDI_EDP_INPUT_C_ONOFF:  			trans_pipe = PIPE_C;  			break; +		case TRANS_DDI_EDP_INPUT_D_ONOFF: +			trans_pipe = PIPE_D; +			break;  		}  		if (trans_pipe == crtc->pipe) { @@ -10487,31 +10840,36 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,  	return transcoder_is_dsi(pipe_config->cpu_transcoder);  } -static void haswell_get_ddi_port_state(struct intel_crtc *crtc, -				       struct intel_crtc_state *pipe_config) +static void hsw_get_ddi_port_state(struct intel_crtc *crtc, +				   struct intel_crtc_state *pipe_config)  {  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;  	struct intel_shared_dpll *pll;  	enum port port;  	u32 tmp; -	tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder)); - -	if (INTEL_GEN(dev_priv) >= 12) -		port = TGL_TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp); -	else -		port = TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp); +	if (transcoder_is_dsi(cpu_transcoder)) { +		port = (cpu_transcoder == TRANSCODER_DSI_A) ? +						PORT_A : PORT_B; +	} else { +		tmp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); +		if (INTEL_GEN(dev_priv) >= 12) +			port = TGL_TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp); +		else +			port = TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp); +	}  	if (INTEL_GEN(dev_priv) >= 11) -		icelake_get_ddi_pll(dev_priv, port, pipe_config); +		icl_get_ddi_pll(dev_priv, port, pipe_config);  	else if (IS_CANNONLAKE(dev_priv)) -		cannonlake_get_ddi_pll(dev_priv, port, pipe_config); +		cnl_get_ddi_pll(dev_priv, port, pipe_config);  	else if (IS_GEN9_BC(dev_priv)) -		skylake_get_ddi_pll(dev_priv, port, pipe_config); +		skl_get_ddi_pll(dev_priv, port, pipe_config);  	else if (IS_GEN9_LP(dev_priv))  		bxt_get_ddi_pll(dev_priv, port, pipe_config);  	else -		haswell_get_ddi_pll(dev_priv, port, pipe_config); +		hsw_get_ddi_pll(dev_priv, port, pipe_config);  	pll = pipe_config->shared_dpll;  	if (pll) { @@ -10532,7 +10890,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,  		pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>  					  FDI_DP_PORT_WIDTH_SHIFT) + 1; -		ironlake_get_fdi_m_n_config(crtc, pipe_config); +		ilk_get_fdi_m_n_config(crtc, pipe_config);  	}  } @@ -10554,9 +10912,9 @@ static enum transcoder transcoder_master_readout(struct drm_i915_private *dev_pr  		return master_select - 1;  } -static void icelake_get_trans_port_sync_config(struct intel_crtc_state *crtc_state) +static void icl_get_trans_port_sync_config(struct intel_crtc_state *crtc_state)  { -	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); +	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);  	u32 transcoders;  	enum transcoder cpu_transcoder; @@ -10589,8 +10947,8 @@ static void icelake_get_trans_port_sync_config(struct intel_crtc_state *crtc_sta  		crtc_state->sync_mode_slaves_mask);  } -static bool haswell_get_pipe_config(struct intel_crtc *crtc, -				    struct intel_crtc_state *pipe_config) +static bool hsw_get_pipe_config(struct intel_crtc *crtc, +				struct intel_crtc_state *pipe_config)  {  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	intel_wakeref_t wakerefs[POWER_DOMAIN_NUM], wf; @@ -10598,8 +10956,6 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,  	u64 power_domain_mask;  	bool active; -	intel_crtc_init_scalers(crtc, pipe_config); -  	pipe_config->master_transcoder = INVALID_TRANSCODER;  	power_domain = POWER_DOMAIN_PIPE(crtc->pipe); @@ -10627,7 +10983,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,  	if (!transcoder_is_dsi(pipe_config->cpu_transcoder) ||  	    INTEL_GEN(dev_priv) >= 11) { -		haswell_get_ddi_port_state(crtc, pipe_config); +		hsw_get_ddi_port_state(crtc, pipe_config);  		intel_get_pipe_timings(crtc, pipe_config);  	} @@ -10684,9 +11040,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,  		power_domain_mask |= BIT_ULL(power_domain);  		if (INTEL_GEN(dev_priv) >= 9) -			skylake_get_pfit_config(crtc, pipe_config); +			skl_get_pfit_config(crtc, pipe_config);  		else -			ironlake_get_pfit_config(crtc, pipe_config); +			ilk_get_pfit_config(crtc, pipe_config);  	}  	if (hsw_crtc_supports_ips(crtc)) { @@ -10712,7 +11068,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,  	if (INTEL_GEN(dev_priv) >= 11 &&  	    !transcoder_is_dsi(pipe_config->cpu_transcoder)) -		icelake_get_trans_port_sync_config(pipe_config); +		icl_get_trans_port_sync_config(pipe_config);  out:  	for_each_power_domain(power_domain, power_domain_mask) @@ -10725,13 +11081,13 @@ out:  static u32 intel_cursor_base(const struct intel_plane_state *plane_state)  {  	struct drm_i915_private *dev_priv = -		to_i915(plane_state->base.plane->dev); -	const struct drm_framebuffer *fb = plane_state->base.fb; +		to_i915(plane_state->uapi.plane->dev); +	const struct drm_framebuffer *fb = plane_state->hw.fb;  	const struct drm_i915_gem_object *obj = intel_fb_obj(fb);  	u32 base;  	if (INTEL_INFO(dev_priv)->display.cursor_needs_physical) -		base = obj->phys_handle->busaddr; +		base = sg_dma_address(obj->mm.pages->sgl);  	else  		base = intel_plane_ggtt_offset(plane_state); @@ -10740,8 +11096,8 @@ static u32 intel_cursor_base(const struct intel_plane_state *plane_state)  static u32 intel_cursor_position(const struct intel_plane_state *plane_state)  { -	int x = plane_state->base.dst.x1; -	int y = plane_state->base.dst.y1; +	int x = plane_state->uapi.dst.x1; +	int y = plane_state->uapi.dst.y1;  	u32 pos = 0;  	if (x < 0) { @@ -10762,9 +11118,9 @@ static u32 intel_cursor_position(const struct intel_plane_state *plane_state)  static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)  {  	const struct drm_mode_config *config = -		&plane_state->base.plane->dev->mode_config; -	int width = drm_rect_width(&plane_state->base.dst); -	int height = drm_rect_height(&plane_state->base.dst); +		&plane_state->uapi.plane->dev->mode_config; +	int width = drm_rect_width(&plane_state->uapi.dst); +	int height = drm_rect_height(&plane_state->uapi.dst);  	return width > 0 && width <= config->cursor_width &&  		height > 0 && height <= config->cursor_height; @@ -10773,8 +11129,8 @@ static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)  static int intel_cursor_check_surface(struct intel_plane_state *plane_state)  {  	struct drm_i915_private *dev_priv = -		to_i915(plane_state->base.plane->dev); -	unsigned int rotation = plane_state->base.rotation; +		to_i915(plane_state->uapi.plane->dev); +	unsigned int rotation = plane_state->hw.rotation;  	int src_x, src_y;  	u32 offset;  	int ret; @@ -10783,11 +11139,11 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state)  	if (ret)  		return ret; -	if (!plane_state->base.visible) +	if (!plane_state->uapi.visible)  		return 0; -	src_x = plane_state->base.src.x1 >> 16; -	src_y = plane_state->base.src.y1 >> 16; +	src_x = plane_state->uapi.src.x1 >> 16; +	src_y = plane_state->uapi.src.y1 >> 16;  	intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);  	offset = intel_plane_compute_aligned_offset(&src_x, &src_y, @@ -10802,14 +11158,14 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state)  	 * Put the final coordinates back so that the src  	 * coordinate checks will see the right values.  	 */ -	drm_rect_translate_to(&plane_state->base.src, +	drm_rect_translate_to(&plane_state->uapi.src,  			      src_x << 16, src_y << 16);  	/* ILK+ do this automagically in hardware */  	if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) { -		const struct drm_framebuffer *fb = plane_state->base.fb; -		int src_w = drm_rect_width(&plane_state->base.src) >> 16; -		int src_h = drm_rect_height(&plane_state->base.src) >> 16; +		const struct drm_framebuffer *fb = plane_state->hw.fb; +		int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; +		int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;  		offset += (src_h * src_w - 1) * fb->format->cpp[0];  	} @@ -10824,7 +11180,7 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state)  static int intel_check_cursor(struct intel_crtc_state *crtc_state,  			      struct intel_plane_state *plane_state)  { -	const struct drm_framebuffer *fb = plane_state->base.fb; +	const struct drm_framebuffer *fb = plane_state->hw.fb;  	int ret;  	if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) { @@ -10832,8 +11188,8 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,  		return -EINVAL;  	} -	ret = drm_atomic_helper_check_plane_state(&plane_state->base, -						  &crtc_state->base, +	ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, +						  &crtc_state->uapi,  						  DRM_PLANE_HELPER_NO_SCALING,  						  DRM_PLANE_HELPER_NO_SCALING,  						  true, true); @@ -10841,14 +11197,14 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,  		return ret;  	/* Use the unclipped src/dst rectangles, which we program to hw */ -	plane_state->base.src = drm_plane_state_src(&plane_state->base); -	plane_state->base.dst = drm_plane_state_dest(&plane_state->base); +	plane_state->uapi.src = drm_plane_state_src(&plane_state->uapi); +	plane_state->uapi.dst = drm_plane_state_dest(&plane_state->uapi);  	ret = intel_cursor_check_surface(plane_state);  	if (ret)  		return ret; -	if (!plane_state->base.visible) +	if (!plane_state->uapi.visible)  		return 0;  	ret = intel_plane_check_src_coordinates(plane_state); @@ -10886,7 +11242,7 @@ static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,  static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)  { -	int width = drm_rect_width(&plane_state->base.dst); +	int width = drm_rect_width(&plane_state->uapi.dst);  	/*  	 * 845g/865g are only limited by the width of their cursors, @@ -10898,7 +11254,7 @@ static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)  static int i845_check_cursor(struct intel_crtc_state *crtc_state,  			     struct intel_plane_state *plane_state)  { -	const struct drm_framebuffer *fb = plane_state->base.fb; +	const struct drm_framebuffer *fb = plane_state->hw.fb;  	int ret;  	ret = intel_check_cursor(crtc_state, plane_state); @@ -10912,12 +11268,12 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_state,  	/* Check for which cursor types we support */  	if (!i845_cursor_size_ok(plane_state)) {  		DRM_DEBUG("Cursor dimension %dx%d not supported\n", -			  drm_rect_width(&plane_state->base.dst), -			  drm_rect_height(&plane_state->base.dst)); +			  drm_rect_width(&plane_state->uapi.dst), +			  drm_rect_height(&plane_state->uapi.dst));  		return -EINVAL;  	} -	WARN_ON(plane_state->base.visible && +	WARN_ON(plane_state->uapi.visible &&  		plane_state->color_plane[0].stride != fb->pitches[0]);  	switch (fb->pitches[0]) { @@ -10945,9 +11301,9 @@ static void i845_update_cursor(struct intel_plane *plane,  	u32 cntl = 0, base = 0, pos = 0, size = 0;  	unsigned long irqflags; -	if (plane_state && plane_state->base.visible) { -		unsigned int width = drm_rect_width(&plane_state->base.dst); -		unsigned int height = drm_rect_height(&plane_state->base.dst); +	if (plane_state && plane_state->uapi.visible) { +		unsigned int width = drm_rect_width(&plane_state->uapi.dst); +		unsigned int height = drm_rect_height(&plane_state->uapi.dst);  		cntl = plane_state->ctl |  			i845_cursor_ctl_crtc(crtc_state); @@ -11020,7 +11376,7 @@ i9xx_cursor_max_stride(struct intel_plane *plane,  static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	u32 cntl = 0; @@ -11043,13 +11399,13 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,  			   const struct intel_plane_state *plane_state)  {  	struct drm_i915_private *dev_priv = -		to_i915(plane_state->base.plane->dev); +		to_i915(plane_state->uapi.plane->dev);  	u32 cntl = 0;  	if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))  		cntl |= MCURSOR_TRICKLE_FEED_DISABLE; -	switch (drm_rect_width(&plane_state->base.dst)) { +	switch (drm_rect_width(&plane_state->uapi.dst)) {  	case 64:  		cntl |= MCURSOR_MODE_64_ARGB_AX;  		break; @@ -11060,11 +11416,11 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,  		cntl |= MCURSOR_MODE_256_ARGB_AX;  		break;  	default: -		MISSING_CASE(drm_rect_width(&plane_state->base.dst)); +		MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));  		return 0;  	} -	if (plane_state->base.rotation & DRM_MODE_ROTATE_180) +	if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)  		cntl |= MCURSOR_ROTATE_180;  	return cntl; @@ -11073,9 +11429,9 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,  static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)  {  	struct drm_i915_private *dev_priv = -		to_i915(plane_state->base.plane->dev); -	int width = drm_rect_width(&plane_state->base.dst); -	int height = drm_rect_height(&plane_state->base.dst); +		to_i915(plane_state->uapi.plane->dev); +	int width = drm_rect_width(&plane_state->uapi.dst); +	int height = drm_rect_height(&plane_state->uapi.dst);  	if (!intel_cursor_size_ok(plane_state))  		return false; @@ -11097,7 +11453,7 @@ static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)  	 * cursors.  	 */  	if (HAS_CUR_FBC(dev_priv) && -	    plane_state->base.rotation & DRM_MODE_ROTATE_0) { +	    plane_state->hw.rotation & DRM_MODE_ROTATE_0) {  		if (height < 8 || height > width)  			return false;  	} else { @@ -11111,9 +11467,9 @@ static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)  static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,  			     struct intel_plane_state *plane_state)  { -	struct intel_plane *plane = to_intel_plane(plane_state->base.plane); +	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev); -	const struct drm_framebuffer *fb = plane_state->base.fb; +	const struct drm_framebuffer *fb = plane_state->hw.fb;  	enum pipe pipe = plane->pipe;  	int ret; @@ -11128,19 +11484,19 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,  	/* Check for which cursor types we support */  	if (!i9xx_cursor_size_ok(plane_state)) {  		DRM_DEBUG("Cursor dimension %dx%d not supported\n", -			  drm_rect_width(&plane_state->base.dst), -			  drm_rect_height(&plane_state->base.dst)); +			  drm_rect_width(&plane_state->uapi.dst), +			  drm_rect_height(&plane_state->uapi.dst));  		return -EINVAL;  	} -	WARN_ON(plane_state->base.visible && +	WARN_ON(plane_state->uapi.visible &&  		plane_state->color_plane[0].stride != fb->pitches[0]);  	if (fb->pitches[0] != -	    drm_rect_width(&plane_state->base.dst) * fb->format->cpp[0]) { +	    drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {  		DRM_DEBUG_KMS("Invalid cursor stride (%u) (cursor width %d)\n",  			      fb->pitches[0], -			      drm_rect_width(&plane_state->base.dst)); +			      drm_rect_width(&plane_state->uapi.dst));  		return -EINVAL;  	} @@ -11155,7 +11511,7 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,  	 * Refuse the put the cursor into that compromised position.  	 */  	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C && -	    plane_state->base.visible && plane_state->base.dst.x1 < 0) { +	    plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {  		DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n");  		return -EINVAL;  	} @@ -11174,9 +11530,9 @@ static void i9xx_update_cursor(struct intel_plane *plane,  	u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;  	unsigned long irqflags; -	if (plane_state && plane_state->base.visible) { -		unsigned width = drm_rect_width(&plane_state->base.dst); -		unsigned height = drm_rect_height(&plane_state->base.dst); +	if (plane_state && plane_state->uapi.visible) { +		unsigned width = drm_rect_width(&plane_state->uapi.dst); +		unsigned height = drm_rect_height(&plane_state->uapi.dst);  		cntl = plane_state->ctl |  			i9xx_cursor_ctl_crtc(crtc_state); @@ -11332,7 +11688,7 @@ int intel_get_load_detect_pipe(struct drm_connector *connector,  {  	struct intel_crtc *intel_crtc;  	struct intel_encoder *intel_encoder = -		intel_attached_encoder(connector); +		intel_attached_encoder(to_intel_connector(connector));  	struct drm_crtc *possible_crtc;  	struct drm_encoder *encoder = &intel_encoder->base;  	struct drm_crtc *crtc = NULL; @@ -11431,9 +11787,9 @@ found:  		goto fail;  	} -	crtc_state->base.active = crtc_state->base.enable = true; +	crtc_state->uapi.active = true; -	ret = drm_atomic_set_mode_for_crtc(&crtc_state->base, +	ret = drm_atomic_set_mode_for_crtc(&crtc_state->uapi,  					   &load_detect_mode);  	if (ret)  		goto fail; @@ -11486,7 +11842,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,  				    struct drm_modeset_acquire_ctx *ctx)  {  	struct intel_encoder *intel_encoder = -		intel_attached_encoder(connector); +		intel_attached_encoder(to_intel_connector(connector));  	struct drm_encoder *encoder = &intel_encoder->base;  	struct drm_atomic_state *state = old->restore_state;  	int ret; @@ -11629,8 +11985,8 @@ int intel_dotclock_calculate(int link_freq,  	return div_u64(mul_u32_u32(m_n->link_m, link_freq), m_n->link_n);  } -static void ironlake_pch_clock_get(struct intel_crtc *crtc, -				   struct intel_crtc_state *pipe_config) +static void ilk_pch_clock_get(struct intel_crtc *crtc, +			      struct intel_crtc_state *pipe_config)  {  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -11642,11 +11998,38 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc,  	 * we may need some idea for the dotclock anyway.  	 * Calculate one based on the FDI configuration.  	 */ -	pipe_config->base.adjusted_mode.crtc_clock = +	pipe_config->hw.adjusted_mode.crtc_clock =  		intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config),  					 &pipe_config->fdi_m_n);  } +static void intel_crtc_state_reset(struct intel_crtc_state *crtc_state, +				   struct intel_crtc *crtc) +{ +	memset(crtc_state, 0, sizeof(*crtc_state)); + +	__drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base); + +	crtc_state->cpu_transcoder = INVALID_TRANSCODER; +	crtc_state->master_transcoder = INVALID_TRANSCODER; +	crtc_state->hsw_workaround_pipe = INVALID_PIPE; +	crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID; +	crtc_state->scaler_state.scaler_id = -1; +	crtc_state->mst_master_transcoder = INVALID_TRANSCODER; +} + +static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc) +{ +	struct intel_crtc_state *crtc_state; + +	crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL); + +	if (crtc_state) +		intel_crtc_state_reset(crtc_state, crtc); + +	return crtc_state; +} +  /* Returns the currently programmed mode of the given encoder. */  struct drm_display_mode *  intel_encoder_current_mode(struct intel_encoder *encoder) @@ -11666,14 +12049,12 @@ intel_encoder_current_mode(struct intel_encoder *encoder)  	if (!mode)  		return NULL; -	crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); +	crtc_state = intel_crtc_state_alloc(crtc);  	if (!crtc_state) {  		kfree(mode);  		return NULL;  	} -	crtc_state->base.crtc = &crtc->base; -  	if (!dev_priv->display.get_pipe_config(crtc, crtc_state)) {  		kfree(crtc_state);  		kfree(mode); @@ -11711,18 +12092,18 @@ static bool intel_wm_need_update(const struct intel_plane_state *cur,  				 struct intel_plane_state *new)  {  	/* Update watermarks on tiling or size changes. */ -	if (new->base.visible != cur->base.visible) +	if (new->uapi.visible != cur->uapi.visible)  		return true; -	if (!cur->base.fb || !new->base.fb) +	if (!cur->hw.fb || !new->hw.fb)  		return false; -	if (cur->base.fb->modifier != new->base.fb->modifier || -	    cur->base.rotation != new->base.rotation || -	    drm_rect_width(&new->base.src) != drm_rect_width(&cur->base.src) || -	    drm_rect_height(&new->base.src) != drm_rect_height(&cur->base.src) || -	    drm_rect_width(&new->base.dst) != drm_rect_width(&cur->base.dst) || -	    drm_rect_height(&new->base.dst) != drm_rect_height(&cur->base.dst)) +	if (cur->hw.fb->modifier != new->hw.fb->modifier || +	    cur->hw.rotation != new->hw.rotation || +	    drm_rect_width(&new->uapi.src) != drm_rect_width(&cur->uapi.src) || +	    drm_rect_height(&new->uapi.src) != drm_rect_height(&cur->uapi.src) || +	    drm_rect_width(&new->uapi.dst) != drm_rect_width(&cur->uapi.dst) || +	    drm_rect_height(&new->uapi.dst) != drm_rect_height(&cur->uapi.dst))  		return true;  	return false; @@ -11730,10 +12111,10 @@ static bool intel_wm_need_update(const struct intel_plane_state *cur,  static bool needs_scaling(const struct intel_plane_state *state)  { -	int src_w = drm_rect_width(&state->base.src) >> 16; -	int src_h = drm_rect_height(&state->base.src) >> 16; -	int dst_w = drm_rect_width(&state->base.dst); -	int dst_h = drm_rect_height(&state->base.dst); +	int src_w = drm_rect_width(&state->uapi.src) >> 16; +	int src_h = drm_rect_height(&state->uapi.src) >> 16; +	int dst_w = drm_rect_width(&state->uapi.dst); +	int dst_h = drm_rect_height(&state->uapi.dst);  	return (src_w != dst_w || src_h != dst_h);  } @@ -11743,12 +12124,12 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat  				    const struct intel_plane_state *old_plane_state,  				    struct intel_plane_state *plane_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); -	struct intel_plane *plane = to_intel_plane(plane_state->base.plane); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); +	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	bool mode_changed = needs_modeset(crtc_state); -	bool was_crtc_enabled = old_crtc_state->base.active; -	bool is_crtc_enabled = crtc_state->base.active; +	bool was_crtc_enabled = old_crtc_state->hw.active; +	bool is_crtc_enabled = crtc_state->hw.active;  	bool turn_off, turn_on, visible, was_visible;  	int ret; @@ -11758,8 +12139,8 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat  			return ret;  	} -	was_visible = old_plane_state->base.visible; -	visible = plane_state->base.visible; +	was_visible = old_plane_state->uapi.visible; +	visible = plane_state->uapi.visible;  	if (!was_crtc_enabled && WARN_ON(was_visible))  		was_visible = false; @@ -11775,7 +12156,7 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat  	 * only combine the results from all planes in the current place?  	 */  	if (!is_crtc_enabled) { -		plane_state->base.visible = visible = false; +		plane_state->uapi.visible = visible = false;  		crtc_state->active_planes &= ~BIT(plane->id);  		crtc_state->data_rate[plane->id] = 0;  		crtc_state->min_cdclk[plane->id] = 0; @@ -11916,9 +12297,9 @@ static int icl_add_linked_planes(struct intel_atomic_state *state)  static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); -	struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->base.state); +	struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state);  	struct intel_plane *plane, *linked;  	struct intel_plane_state *plane_state;  	int i; @@ -11935,7 +12316,7 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)  			continue;  		plane_state->planar_linked_plane = NULL; -		if (plane_state->planar_slave && !plane_state->base.visible) { +		if (plane_state->planar_slave && !plane_state->uapi.visible) {  			crtc_state->active_planes &= ~BIT(plane->id);  			crtc_state->update_planes |= BIT(plane->id);  		} @@ -11981,6 +12362,26 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)  		crtc_state->active_planes |= BIT(linked->id);  		crtc_state->update_planes |= BIT(linked->id);  		DRM_DEBUG_KMS("Using %s as Y plane for %s\n", linked->base.name, plane->base.name); + +		/* Copy parameters to slave plane */ +		linked_state->ctl = plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE; +		linked_state->color_ctl = plane_state->color_ctl; +		linked_state->view = plane_state->view; +		memcpy(linked_state->color_plane, plane_state->color_plane, +		       sizeof(linked_state->color_plane)); + +		intel_plane_copy_uapi_to_hw_state(linked_state, plane_state); +		linked_state->uapi.src = plane_state->uapi.src; +		linked_state->uapi.dst = plane_state->uapi.dst; + +		if (icl_is_hdr_plane(dev_priv, plane->id)) { +			if (linked->id == PLANE_SPRITE5) +				plane_state->cus_ctl |= PLANE_CUS_PLANE_7; +			else if (linked->id == PLANE_SPRITE4) +				plane_state->cus_ctl |= PLANE_CUS_PLANE_6; +			else +				MISSING_CASE(linked->id); +		}  	}  	return 0; @@ -11988,97 +12389,130 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)  static bool c8_planes_changed(const struct intel_crtc_state *new_crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);  	struct intel_atomic_state *state = -		to_intel_atomic_state(new_crtc_state->base.state); +		to_intel_atomic_state(new_crtc_state->uapi.state);  	const struct intel_crtc_state *old_crtc_state =  		intel_atomic_get_old_crtc_state(state, crtc);  	return !old_crtc_state->c8_planes != !new_crtc_state->c8_planes;  } -static int icl_add_sync_mode_crtcs(struct intel_crtc_state *crtc_state) +static bool +intel_atomic_is_master_connector(struct intel_crtc_state *crtc_state)  { -	struct drm_crtc *crtc = crtc_state->base.crtc; -	struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->base.state); -	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); -	struct drm_connector *master_connector, *connector; +	struct drm_crtc *crtc = crtc_state->uapi.crtc; +	struct drm_atomic_state *state = crtc_state->uapi.state; +	struct drm_connector *connector;  	struct drm_connector_state *connector_state; +	int i; + +	for_each_new_connector_in_state(state, connector, connector_state, i) { +		if (connector_state->crtc != crtc) +			continue; +		if (connector->has_tile && +		    connector->tile_h_loc == connector->num_h_tile - 1 && +		    connector->tile_v_loc == connector->num_v_tile - 1) +			return true; +	} + +	return false; +} + +static void reset_port_sync_mode_state(struct intel_crtc_state *crtc_state) +{ +	crtc_state->master_transcoder = INVALID_TRANSCODER; +	crtc_state->sync_mode_slaves_mask = 0; +} + +static int icl_compute_port_sync_crtc_state(struct drm_connector *connector, +					    struct intel_crtc_state *crtc_state, +					    int num_tiled_conns) +{ +	struct drm_crtc *crtc = crtc_state->uapi.crtc; +	struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state); +	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); +	struct drm_connector *master_connector;  	struct drm_connector_list_iter conn_iter;  	struct drm_crtc *master_crtc = NULL;  	struct drm_crtc_state *master_crtc_state;  	struct intel_crtc_state *master_pipe_config; -	int i, tile_group_id;  	if (INTEL_GEN(dev_priv) < 11)  		return 0; +	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP)) +		return 0; +  	/*  	 * In case of tiled displays there could be one or more slaves but there is  	 * only one master. Lets make the CRTC used by the connector corresponding  	 * to the last horizonal and last vertical tile a master/genlock CRTC.  	 * All the other CRTCs corresponding to other tiles of the same Tile group  	 * are the slave CRTCs and hold a pointer to their genlock CRTC. +	 * If all tiles not present do not make master slave assignments.  	 */ -	for_each_new_connector_in_state(&state->base, connector, connector_state, i) { -		if (connector_state->crtc != crtc) -			continue; -		if (!connector->has_tile) +	if (!connector->has_tile || +	    crtc_state->hw.mode.hdisplay != connector->tile_h_size || +	    crtc_state->hw.mode.vdisplay != connector->tile_v_size || +	    num_tiled_conns < connector->num_h_tile * connector->num_v_tile) { +		reset_port_sync_mode_state(crtc_state); +		return 0; +	} +	/* Last Horizontal and last vertical tile connector is a master +	 * Master's crtc state is already populated in slave for port sync +	 */ +	if (connector->tile_h_loc == connector->num_h_tile - 1 && +	    connector->tile_v_loc == connector->num_v_tile - 1) +		return 0; + +	/* Loop through all connectors and configure the Slave crtc_state +	 * to point to the correct master. +	 */ +	drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); +	drm_for_each_connector_iter(master_connector, &conn_iter) { +		struct drm_connector_state *master_conn_state = NULL; + +		if (!(master_connector->has_tile && +		      master_connector->tile_group->id == connector->tile_group->id))  			continue; -		if (crtc_state->base.mode.hdisplay != connector->tile_h_size || -		    crtc_state->base.mode.vdisplay != connector->tile_v_size) -			return 0; -		if (connector->tile_h_loc == connector->num_h_tile - 1 && -		    connector->tile_v_loc == connector->num_v_tile - 1) +		if (master_connector->tile_h_loc != master_connector->num_h_tile - 1 || +		    master_connector->tile_v_loc != master_connector->num_v_tile - 1)  			continue; -		crtc_state->sync_mode_slaves_mask = 0; -		tile_group_id = connector->tile_group->id; -		drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); -		drm_for_each_connector_iter(master_connector, &conn_iter) { -			struct drm_connector_state *master_conn_state = NULL; - -			if (!master_connector->has_tile) -				continue; -			if (master_connector->tile_h_loc != master_connector->num_h_tile - 1 || -			    master_connector->tile_v_loc != master_connector->num_v_tile - 1) -				continue; -			if (master_connector->tile_group->id != tile_group_id) -				continue; -			master_conn_state = drm_atomic_get_connector_state(&state->base, -									   master_connector); -			if (IS_ERR(master_conn_state)) { -				drm_connector_list_iter_end(&conn_iter); -				return PTR_ERR(master_conn_state); -			} -			if (master_conn_state->crtc) { -				master_crtc = master_conn_state->crtc; -				break; -			} +		master_conn_state = drm_atomic_get_connector_state(&state->base, +								   master_connector); +		if (IS_ERR(master_conn_state)) { +			drm_connector_list_iter_end(&conn_iter); +			return PTR_ERR(master_conn_state);  		} -		drm_connector_list_iter_end(&conn_iter); - -		if (!master_crtc) { -			DRM_DEBUG_KMS("Could not find Master CRTC for Slave CRTC %d\n", -				      connector_state->crtc->base.id); -			return -EINVAL; +		if (master_conn_state->crtc) { +			master_crtc = master_conn_state->crtc; +			break;  		} +	} +	drm_connector_list_iter_end(&conn_iter); -		master_crtc_state = drm_atomic_get_crtc_state(&state->base, -							      master_crtc); -		if (IS_ERR(master_crtc_state)) -			return PTR_ERR(master_crtc_state); - -		master_pipe_config = to_intel_crtc_state(master_crtc_state); -		crtc_state->master_transcoder = master_pipe_config->cpu_transcoder; -		master_pipe_config->sync_mode_slaves_mask |= -			BIT(crtc_state->cpu_transcoder); -		DRM_DEBUG_KMS("Master Transcoder = %s added for Slave CRTC = %d, slave transcoder bitmask = %d\n", -			      transcoder_name(crtc_state->master_transcoder), -			      crtc_state->base.crtc->base.id, -			      master_pipe_config->sync_mode_slaves_mask); +	if (!master_crtc) { +		DRM_DEBUG_KMS("Could not find Master CRTC for Slave CRTC %d\n", +			      crtc->base.id); +		return -EINVAL;  	} +	master_crtc_state = drm_atomic_get_crtc_state(&state->base, +						      master_crtc); +	if (IS_ERR(master_crtc_state)) +		return PTR_ERR(master_crtc_state); + +	master_pipe_config = to_intel_crtc_state(master_crtc_state); +	crtc_state->master_transcoder = master_pipe_config->cpu_transcoder; +	master_pipe_config->sync_mode_slaves_mask |= +		BIT(crtc_state->cpu_transcoder); +	DRM_DEBUG_KMS("Master Transcoder = %s added for Slave CRTC = %d, slave transcoder bitmask = %d\n", +		      transcoder_name(crtc_state->master_transcoder), +		      crtc->base.id, +		      master_pipe_config->sync_mode_slaves_mask); +  	return 0;  } @@ -12092,10 +12526,10 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,  	int ret;  	if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv) && -	    mode_changed && !crtc_state->base.active) +	    mode_changed && !crtc_state->hw.active)  		crtc_state->update_wm_post = true; -	if (mode_changed && crtc_state->base.enable && +	if (mode_changed && crtc_state->hw.enable &&  	    dev_priv->display.crtc_compute_clock &&  	    !WARN_ON(crtc_state->shared_dpll)) {  		ret = dev_priv->display.crtc_compute_clock(crtc, crtc_state); @@ -12108,10 +12542,10 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,  	 * when C8 planes are getting enabled/disabled.  	 */  	if (c8_planes_changed(crtc_state)) -		crtc_state->base.color_mgmt_changed = true; +		crtc_state->uapi.color_mgmt_changed = true;  	if (mode_changed || crtc_state->update_pipe || -	    crtc_state->base.color_mgmt_changed) { +	    crtc_state->uapi.color_mgmt_changed) {  		ret = intel_color_check(crtc_state);  		if (ret)  			return ret; @@ -12224,7 +12658,7 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc,  			  struct intel_crtc_state *pipe_config)  {  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); -	struct drm_atomic_state *state = pipe_config->base.state; +	struct drm_atomic_state *state = pipe_config->uapi.state;  	struct drm_connector *connector;  	struct drm_connector_state *connector_state;  	int bpp, i; @@ -12281,7 +12715,7 @@ static void  intel_dump_infoframe(struct drm_i915_private *dev_priv,  		     const union hdmi_infoframe *frame)  { -	if ((drm_debug & DRM_UT_KMS) == 0) +	if (!drm_debug_enabled(DRM_UT_KMS))  		return;  	hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, frame); @@ -12349,14 +12783,14 @@ static const char *output_formats(enum intel_output_format format)  static void intel_dump_plane_state(const struct intel_plane_state *plane_state)  { -	struct intel_plane *plane = to_intel_plane(plane_state->base.plane); -	const struct drm_framebuffer *fb = plane_state->base.fb; +	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); +	const struct drm_framebuffer *fb = plane_state->hw.fb;  	struct drm_format_name_buf format_name;  	if (!fb) {  		DRM_DEBUG_KMS("[PLANE:%d:%s] fb: [NOFB], visible: %s\n",  			      plane->base.base.id, plane->base.name, -			      yesno(plane_state->base.visible)); +			      yesno(plane_state->uapi.visible));  		return;  	} @@ -12364,20 +12798,20 @@ static void intel_dump_plane_state(const struct intel_plane_state *plane_state)  		      plane->base.base.id, plane->base.name,  		      fb->base.id, fb->width, fb->height,  		      drm_get_format_name(fb->format->format, &format_name), -		      yesno(plane_state->base.visible)); +		      yesno(plane_state->uapi.visible));  	DRM_DEBUG_KMS("\trotation: 0x%x, scaler: %d\n", -		      plane_state->base.rotation, plane_state->scaler_id); -	if (plane_state->base.visible) +		      plane_state->hw.rotation, plane_state->scaler_id); +	if (plane_state->uapi.visible)  		DRM_DEBUG_KMS("\tsrc: " DRM_RECT_FP_FMT " dst: " DRM_RECT_FMT "\n", -			      DRM_RECT_FP_ARG(&plane_state->base.src), -			      DRM_RECT_ARG(&plane_state->base.dst)); +			      DRM_RECT_FP_ARG(&plane_state->uapi.src), +			      DRM_RECT_ARG(&plane_state->uapi.dst));  }  static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,  				   struct intel_atomic_state *state,  				   const char *context)  { -	struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	const struct intel_plane_state *plane_state;  	struct intel_plane *plane; @@ -12386,14 +12820,14 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,  	DRM_DEBUG_KMS("[CRTC:%d:%s] enable: %s %s\n",  		      crtc->base.base.id, crtc->base.name, -		      yesno(pipe_config->base.enable), context); +		      yesno(pipe_config->hw.enable), context); -	if (!pipe_config->base.enable) +	if (!pipe_config->hw.enable)  		goto dump_planes;  	snprintf_output_types(buf, sizeof(buf), pipe_config->output_types);  	DRM_DEBUG_KMS("active: %s, output_types: %s (0x%x), output format: %s\n", -		      yesno(pipe_config->base.active), +		      yesno(pipe_config->hw.active),  		      buf, pipe_config->output_types,  		      output_formats(pipe_config->output_format)); @@ -12433,10 +12867,10 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,  		intel_dump_infoframe(dev_priv, &pipe_config->infoframes.hdmi);  	DRM_DEBUG_KMS("requested mode:\n"); -	drm_mode_debug_printmodeline(&pipe_config->base.mode); +	drm_mode_debug_printmodeline(&pipe_config->hw.mode);  	DRM_DEBUG_KMS("adjusted mode:\n"); -	drm_mode_debug_printmodeline(&pipe_config->base.adjusted_mode); -	intel_dump_crtc_timings(&pipe_config->base.adjusted_mode); +	drm_mode_debug_printmodeline(&pipe_config->hw.adjusted_mode); +	intel_dump_crtc_timings(&pipe_config->hw.adjusted_mode);  	DRM_DEBUG_KMS("port clock: %d, pipe src size: %dx%d, pixel rate %d\n",  		      pipe_config->port_clock,  		      pipe_config->pipe_src_w, pipe_config->pipe_src_h, @@ -12474,6 +12908,9 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,  			      pipe_config->csc_mode, pipe_config->gamma_mode,  			      pipe_config->gamma_enable, pipe_config->csc_enable); +	DRM_DEBUG_KMS("MST master transcoder: %s\n", +		      transcoder_name(pipe_config->mst_master_transcoder)); +  dump_planes:  	if (!state)  		return; @@ -12556,22 +12993,59 @@ static bool check_digital_port_conflicts(struct intel_atomic_state *state)  	return ret;  } +static void +intel_crtc_copy_uapi_to_hw_state_nomodeset(struct intel_crtc_state *crtc_state) +{ +	intel_crtc_copy_color_blobs(crtc_state); +} + +static void +intel_crtc_copy_uapi_to_hw_state(struct intel_crtc_state *crtc_state) +{ +	crtc_state->hw.enable = crtc_state->uapi.enable; +	crtc_state->hw.active = crtc_state->uapi.active; +	crtc_state->hw.mode = crtc_state->uapi.mode; +	crtc_state->hw.adjusted_mode = crtc_state->uapi.adjusted_mode; +	intel_crtc_copy_uapi_to_hw_state_nomodeset(crtc_state); +} + +static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state) +{ +	crtc_state->uapi.enable = crtc_state->hw.enable; +	crtc_state->uapi.active = crtc_state->hw.active; +	WARN_ON(drm_atomic_set_mode_for_crtc(&crtc_state->uapi, &crtc_state->hw.mode) < 0); + +	crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode; + +	/* copy color blobs to uapi */ +	drm_property_replace_blob(&crtc_state->uapi.degamma_lut, +				  crtc_state->hw.degamma_lut); +	drm_property_replace_blob(&crtc_state->uapi.gamma_lut, +				  crtc_state->hw.gamma_lut); +	drm_property_replace_blob(&crtc_state->uapi.ctm, +				  crtc_state->hw.ctm); +} +  static int -clear_intel_crtc_state(struct intel_crtc_state *crtc_state) +intel_crtc_prepare_cleared_state(struct intel_crtc_state *crtc_state)  { -	struct drm_i915_private *dev_priv = -		to_i915(crtc_state->base.crtc->dev); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	struct intel_crtc_state *saved_state; -	saved_state = kzalloc(sizeof(*saved_state), GFP_KERNEL); +	saved_state = intel_crtc_state_alloc(crtc);  	if (!saved_state)  		return -ENOMEM; +	/* free the old crtc_state->hw members */ +	intel_crtc_free_hw_state(crtc_state); +  	/* FIXME: before the switch to atomic started, a new pipe_config was  	 * kzalloc'd. Code that depends on any field being zero should be  	 * fixed, so that the crtc_state can be safely duplicated. For now,  	 * only fields that are know to not cause problems are preserved. */ +	saved_state->uapi = crtc_state->uapi;  	saved_state->scaler_state = crtc_state->scaler_state;  	saved_state->shared_dpll = crtc_state->shared_dpll;  	saved_state->dpll_hw_state = crtc_state->dpll_hw_state; @@ -12583,37 +13057,34 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)  		saved_state->wm = crtc_state->wm;  	/*  	 * Save the slave bitmask which gets filled for master crtc state during -	 * slave atomic check call. +	 * slave atomic check call. For all other CRTCs reset the port sync variables +	 * crtc_state->master_transcoder needs to be set to INVALID  	 */ -	if (is_trans_port_sync_master(crtc_state)) +	reset_port_sync_mode_state(saved_state); +	if (intel_atomic_is_master_connector(crtc_state))  		saved_state->sync_mode_slaves_mask =  			crtc_state->sync_mode_slaves_mask; -	/* Keep base drm_crtc_state intact, only clear our extended struct */ -	BUILD_BUG_ON(offsetof(struct intel_crtc_state, base)); -	memcpy(&crtc_state->base + 1, &saved_state->base + 1, -	       sizeof(*crtc_state) - sizeof(crtc_state->base)); - +	memcpy(crtc_state, saved_state, sizeof(*crtc_state));  	kfree(saved_state); + +	intel_crtc_copy_uapi_to_hw_state(crtc_state); +  	return 0;  }  static int  intel_modeset_pipe_config(struct intel_crtc_state *pipe_config)  { -	struct drm_crtc *crtc = pipe_config->base.crtc; -	struct drm_atomic_state *state = pipe_config->base.state; +	struct drm_crtc *crtc = pipe_config->uapi.crtc; +	struct drm_atomic_state *state = pipe_config->uapi.state;  	struct intel_encoder *encoder;  	struct drm_connector *connector;  	struct drm_connector_state *connector_state;  	int base_bpp, ret; -	int i; +	int i, tile_group_id = -1, num_tiled_conns = 0;  	bool retry = true; -	ret = clear_intel_crtc_state(pipe_config); -	if (ret) -		return ret; -  	pipe_config->cpu_transcoder =  		(enum transcoder) to_intel_crtc(crtc)->pipe; @@ -12622,13 +13093,13 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config)  	 * positive or negative polarity is requested, treat this as meaning  	 * negative polarity.  	 */ -	if (!(pipe_config->base.adjusted_mode.flags & +	if (!(pipe_config->hw.adjusted_mode.flags &  	      (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC))) -		pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_NHSYNC; +		pipe_config->hw.adjusted_mode.flags |= DRM_MODE_FLAG_NHSYNC; -	if (!(pipe_config->base.adjusted_mode.flags & +	if (!(pipe_config->hw.adjusted_mode.flags &  	      (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))) -		pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC; +		pipe_config->hw.adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC;  	ret = compute_baseline_pipe_bpp(to_intel_crtc(crtc),  					pipe_config); @@ -12645,7 +13116,7 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config)  	 * computation to clearly distinguish it from the adjusted mode, which  	 * can be changed by the connectors in the below retry loop.  	 */ -	drm_mode_get_hv_timing(&pipe_config->base.mode, +	drm_mode_get_hv_timing(&pipe_config->hw.mode,  			       &pipe_config->pipe_src_w,  			       &pipe_config->pipe_src_h); @@ -12678,16 +13149,25 @@ encoder_retry:  	pipe_config->pixel_multiplier = 1;  	/* Fill in default crtc timings, allow encoders to overwrite them. */ -	drm_mode_set_crtcinfo(&pipe_config->base.adjusted_mode, +	drm_mode_set_crtcinfo(&pipe_config->hw.adjusted_mode,  			      CRTC_STEREO_DOUBLE); -	/* Set the crtc_state defaults for trans_port_sync */ -	pipe_config->master_transcoder = INVALID_TRANSCODER; -	ret = icl_add_sync_mode_crtcs(pipe_config); -	if (ret) { -		DRM_DEBUG_KMS("Cannot assign Sync Mode CRTCs: %d\n", -			      ret); -		return ret; +	/* Get tile_group_id of tiled connector */ +	for_each_new_connector_in_state(state, connector, connector_state, i) { +		if (connector_state->crtc == crtc && +		    connector->has_tile) { +			tile_group_id = connector->tile_group->id; +			break; +		} +	} + +	/* Get total number of tiled connectors in state that belong to +	 * this tile group. +	 */ +	for_each_new_connector_in_state(state, connector, connector_state, i) { +		if (connector->has_tile && +		    connector->tile_group->id == tile_group_id) +			num_tiled_conns++;  	}  	/* Pass our mode to the connectors and the CRTC to give them a chance to @@ -12698,6 +13178,14 @@ encoder_retry:  		if (connector_state->crtc != crtc)  			continue; +		ret = icl_compute_port_sync_crtc_state(connector, pipe_config, +						       num_tiled_conns); +		if (ret) { +			DRM_DEBUG_KMS("Cannot assign Sync Mode CRTCs: %d\n", +				      ret); +			return ret; +		} +  		encoder = to_intel_encoder(connector_state->best_encoder);  		ret = encoder->compute_config(encoder, pipe_config,  					      connector_state); @@ -12712,7 +13200,7 @@ encoder_retry:  	/* Set default port clock if not overwritten by the encoder. Needs to be  	 * done afterwards in case the encoder adjusts the mode. */  	if (!pipe_config->port_clock) -		pipe_config->port_clock = pipe_config->base.adjusted_mode.crtc_clock +		pipe_config->port_clock = pipe_config->hw.adjusted_mode.crtc_clock  			* pipe_config->pixel_multiplier;  	ret = intel_crtc_compute_config(to_intel_crtc(crtc), pipe_config); @@ -12741,6 +13229,12 @@ encoder_retry:  	DRM_DEBUG_KMS("hw max bpp: %i, pipe bpp: %i, dithering: %i\n",  		      base_bpp, pipe_config->pipe_bpp, pipe_config->dither); +	/* +	 * Make drm_calc_timestamping_constants in +	 * drm_atomic_helper_update_legacy_modeset_state() happy +	 */ +	pipe_config->uapi.adjusted_mode = pipe_config->hw.adjusted_mode; +  	return 0;  } @@ -12819,7 +13313,7 @@ pipe_config_infoframe_mismatch(struct drm_i915_private *dev_priv,  			       const union hdmi_infoframe *b)  {  	if (fastset) { -		if ((drm_debug & DRM_UT_KMS) == 0) +		if (!drm_debug_enabled(DRM_UT_KMS))  			return;  		DRM_DEBUG_KMS("fastset mismatch in %s infoframe\n", name); @@ -12879,13 +13373,13 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,  			  const struct intel_crtc_state *pipe_config,  			  bool fastset)  { -	struct drm_i915_private *dev_priv = to_i915(current_config->base.crtc->dev); -	struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); +	struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc->dev); +	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);  	bool ret = true;  	u32 bp_gamma = 0;  	bool fixup_inherited = fastset && -		(current_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED) && -		!(pipe_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED); +		(current_config->hw.mode.private_flags & I915_MODE_FLAG_INHERITED) && +		!(pipe_config->hw.mode.private_flags & I915_MODE_FLAG_INHERITED);  	if (fixup_inherited && !fastboot_enabled(dev_priv)) {  		DRM_DEBUG_KMS("initial modeset and fastboot not set\n"); @@ -13074,19 +13568,19 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,  	PIPE_CONF_CHECK_X(output_types); -	PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hdisplay); -	PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_htotal); -	PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hblank_start); -	PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hblank_end); -	PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hsync_start); -	PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hsync_end); +	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hdisplay); +	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_htotal); +	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_start); +	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_end); +	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_start); +	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_end); -	PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vdisplay); -	PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vtotal); -	PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vblank_start); -	PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vblank_end); -	PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vsync_start); -	PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vsync_end); +	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vdisplay); +	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vtotal); +	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_start); +	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_end); +	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_start); +	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_end);  	PIPE_CONF_CHECK_I(pixel_multiplier);  	PIPE_CONF_CHECK_I(output_format); @@ -13103,17 +13597,17 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,  	PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio); -	PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, +	PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,  			      DRM_MODE_FLAG_INTERLACE);  	if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) { -		PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, +		PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,  				      DRM_MODE_FLAG_PHSYNC); -		PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, +		PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,  				      DRM_MODE_FLAG_NHSYNC); -		PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, +		PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,  				      DRM_MODE_FLAG_PVSYNC); -		PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, +		PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,  				      DRM_MODE_FLAG_NVSYNC);  	} @@ -13152,7 +13646,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,  		bp_gamma = intel_color_get_gamma_bit_precision(pipe_config);  		if (bp_gamma) -			PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, base.gamma_lut, bp_gamma); +			PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, hw.gamma_lut, bp_gamma);  	} @@ -13197,7 +13691,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,  	if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5)  		PIPE_CONF_CHECK_I(pipe_bpp); -	PIPE_CONF_CHECK_CLOCK_FUZZY(base.adjusted_mode.crtc_clock); +	PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock);  	PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock);  	PIPE_CONF_CHECK_I(min_voltage_level); @@ -13212,6 +13706,12 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,  	PIPE_CONF_CHECK_I(sync_mode_slaves_mask);  	PIPE_CONF_CHECK_I(master_transcoder); +	PIPE_CONF_CHECK_I(dsc.compression_enable); +	PIPE_CONF_CHECK_I(dsc.dsc_split); +	PIPE_CONF_CHECK_I(dsc.compressed_bpp); + +	PIPE_CONF_CHECK_I(mst_master_transcoder); +  #undef PIPE_CONF_CHECK_X  #undef PIPE_CONF_CHECK_I  #undef PIPE_CONF_CHECK_BOOL @@ -13231,7 +13731,7 @@ static void intel_pipe_config_sanity_check(struct drm_i915_private *dev_priv,  	if (pipe_config->has_pch_encoder) {  		int fdi_dotclock = intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config),  							    &pipe_config->fdi_m_n); -		int dotclock = pipe_config->base.adjusted_mode.crtc_clock; +		int dotclock = pipe_config->hw.adjusted_mode.crtc_clock;  		/*  		 * FDI already provided one idea for the dotclock. @@ -13259,7 +13759,7 @@ static void verify_wm_state(struct intel_crtc *crtc,  	const enum pipe pipe = crtc->pipe;  	int plane, level, max_level = ilk_wm_max_level(dev_priv); -	if (INTEL_GEN(dev_priv) < 9 || !new_crtc_state->base.active) +	if (INTEL_GEN(dev_priv) < 9 || !new_crtc_state->hw.active)  		return;  	hw = kzalloc(sizeof(*hw), GFP_KERNEL); @@ -13464,16 +13964,14 @@ verify_crtc_state(struct intel_crtc *crtc,  	struct drm_device *dev = crtc->base.dev;  	struct drm_i915_private *dev_priv = to_i915(dev);  	struct intel_encoder *encoder; -	struct intel_crtc_state *pipe_config; -	struct drm_atomic_state *state; +	struct intel_crtc_state *pipe_config = old_crtc_state; +	struct drm_atomic_state *state = old_crtc_state->uapi.state;  	bool active; -	state = old_crtc_state->base.state; -	__drm_atomic_helper_crtc_destroy_state(&old_crtc_state->base); -	pipe_config = old_crtc_state; -	memset(pipe_config, 0, sizeof(*pipe_config)); -	pipe_config->base.crtc = &crtc->base; -	pipe_config->base.state = state; +	__drm_atomic_helper_crtc_destroy_state(&old_crtc_state->uapi); +	intel_crtc_free_hw_state(old_crtc_state); +	intel_crtc_state_reset(old_crtc_state, crtc); +	old_crtc_state->uapi.state = state;  	DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.base.id, crtc->base.name); @@ -13481,23 +13979,26 @@ verify_crtc_state(struct intel_crtc *crtc,  	/* we keep both pipes enabled on 830 */  	if (IS_I830(dev_priv)) -		active = new_crtc_state->base.active; +		active = new_crtc_state->hw.active; -	I915_STATE_WARN(new_crtc_state->base.active != active, -	     "crtc active state doesn't match with hw state " -	     "(expected %i, found %i)\n", new_crtc_state->base.active, active); +	I915_STATE_WARN(new_crtc_state->hw.active != active, +			"crtc active state doesn't match with hw state " +			"(expected %i, found %i)\n", +			new_crtc_state->hw.active, active); -	I915_STATE_WARN(crtc->active != new_crtc_state->base.active, -	     "transitional active state does not match atomic hw state " -	     "(expected %i, found %i)\n", new_crtc_state->base.active, crtc->active); +	I915_STATE_WARN(crtc->active != new_crtc_state->hw.active, +			"transitional active state does not match atomic hw state " +			"(expected %i, found %i)\n", +			new_crtc_state->hw.active, crtc->active);  	for_each_encoder_on_crtc(dev, &crtc->base, encoder) {  		enum pipe pipe;  		active = encoder->get_hw_state(encoder, &pipe); -		I915_STATE_WARN(active != new_crtc_state->base.active, -			"[ENCODER:%i] active %i with crtc active %i\n", -			encoder->base.base.id, active, new_crtc_state->base.active); +		I915_STATE_WARN(active != new_crtc_state->hw.active, +				"[ENCODER:%i] active %i with crtc active %i\n", +				encoder->base.base.id, active, +				new_crtc_state->hw.active);  		I915_STATE_WARN(active && crtc->pipe != pipe,  				"Encoder connected to wrong pipe %c\n", @@ -13509,7 +14010,7 @@ verify_crtc_state(struct intel_crtc *crtc,  	intel_crtc_compute_pixel_rate(pipe_config); -	if (!new_crtc_state->base.active) +	if (!new_crtc_state->hw.active)  		return;  	intel_pipe_config_sanity_check(dev_priv, pipe_config); @@ -13532,7 +14033,7 @@ intel_verify_planes(struct intel_atomic_state *state)  	for_each_new_intel_plane_in_state(state, plane,  					  plane_state, i)  		assert_plane(plane, plane_state->planar_slave || -			     plane_state->base.visible); +			     plane_state->uapi.visible);  }  static void @@ -13571,7 +14072,7 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv,  	crtc_mask = drm_crtc_mask(&crtc->base); -	if (new_crtc_state->base.active) +	if (new_crtc_state->hw.active)  		I915_STATE_WARN(!(pll->active_mask & crtc_mask),  				"pll active mismatch (expected pipe %c in active mask 0x%02x)\n",  				pipe_name(drm_crtc_index(&crtc->base)), pll->active_mask); @@ -13650,10 +14151,10 @@ intel_modeset_verify_disabled(struct drm_i915_private *dev_priv,  static void  intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	const struct drm_display_mode *adjusted_mode = -		&crtc_state->base.adjusted_mode; +		&crtc_state->hw.adjusted_mode;  	drm_calc_timestamping_constants(&crtc->base, adjusted_mode); @@ -13724,7 +14225,7 @@ static void intel_modeset_clear_plls(struct intel_atomic_state *state)   * multiple pipes, and planes are enabled after the pipe, we need to wait at   * least 2 vblanks on the first pipe before enabling planes on the second pipe.   */ -static int haswell_mode_set_planes_workaround(struct intel_atomic_state *state) +static int hsw_mode_set_planes_workaround(struct intel_atomic_state *state)  {  	struct intel_crtc_state *crtc_state;  	struct intel_crtc *crtc; @@ -13735,7 +14236,7 @@ static int haswell_mode_set_planes_workaround(struct intel_atomic_state *state)  	/* look at all crtc's that are going to be enabled in during modeset */  	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { -		if (!crtc_state->base.active || +		if (!crtc_state->hw.active ||  		    !needs_modeset(crtc_state))  			continue; @@ -13760,7 +14261,7 @@ static int haswell_mode_set_planes_workaround(struct intel_atomic_state *state)  		crtc_state->hsw_workaround_pipe = INVALID_PIPE; -		if (!crtc_state->base.active || +		if (!crtc_state->hw.active ||  		    needs_modeset(crtc_state))  			continue; @@ -13797,12 +14298,12 @@ static int intel_modeset_checks(struct intel_atomic_state *state)  	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,  					    new_crtc_state, i) { -		if (new_crtc_state->base.active) +		if (new_crtc_state->hw.active)  			state->active_pipes |= BIT(crtc->pipe);  		else  			state->active_pipes &= ~BIT(crtc->pipe); -		if (old_crtc_state->base.active != new_crtc_state->base.active) +		if (old_crtc_state->hw.active != new_crtc_state->hw.active)  			state->active_pipe_changes |= BIT(crtc->pipe);  	} @@ -13819,7 +14320,7 @@ static int intel_modeset_checks(struct intel_atomic_state *state)  	intel_modeset_clear_plls(state);  	if (IS_HASWELL(dev_priv)) -		return haswell_mode_set_planes_workaround(state); +		return hsw_mode_set_planes_workaround(state);  	return 0;  } @@ -13847,9 +14348,13 @@ static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_sta  	if (!intel_pipe_config_compare(old_crtc_state, new_crtc_state, true))  		return; -	new_crtc_state->base.mode_changed = false; +	new_crtc_state->uapi.mode_changed = false;  	new_crtc_state->update_pipe = true; +} +static void intel_crtc_copy_fastset(const struct intel_crtc_state *old_crtc_state, +				    struct intel_crtc_state *new_crtc_state) +{  	/*  	 * If we're not doing the full modeset we want to  	 * keep the current M/N values as they may be @@ -13972,6 +14477,93 @@ static int intel_atomic_check_crtcs(struct intel_atomic_state *state)  	return 0;  } +static bool intel_cpu_transcoders_need_modeset(struct intel_atomic_state *state, +					       u8 transcoders) +{ +	const struct intel_crtc_state *new_crtc_state; +	struct intel_crtc *crtc; +	int i; + +	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { +		if (new_crtc_state->hw.enable && +		    transcoders & BIT(new_crtc_state->cpu_transcoder) && +		    needs_modeset(new_crtc_state)) +			return true; +	} + +	return false; +} + +static int +intel_modeset_all_tiles(struct intel_atomic_state *state, int tile_grp_id) +{ +	struct drm_i915_private *dev_priv = to_i915(state->base.dev); +	struct drm_connector *connector; +	struct drm_connector_list_iter conn_iter; +	int ret = 0; + +	drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); +	drm_for_each_connector_iter(connector, &conn_iter) { +		struct drm_connector_state *conn_state; +		struct drm_crtc_state *crtc_state; + +		if (!connector->has_tile || +		    connector->tile_group->id != tile_grp_id) +			continue; +		conn_state = drm_atomic_get_connector_state(&state->base, +							    connector); +		if (IS_ERR(conn_state)) { +			ret =  PTR_ERR(conn_state); +			break; +		} + +		if (!conn_state->crtc) +			continue; + +		crtc_state = drm_atomic_get_crtc_state(&state->base, +						       conn_state->crtc); +		if (IS_ERR(crtc_state)) { +			ret = PTR_ERR(crtc_state); +			break; +		} +		crtc_state->mode_changed = true; +		ret = drm_atomic_add_affected_connectors(&state->base, +							 conn_state->crtc); +		if (ret) +			break; +	} +	drm_connector_list_iter_end(&conn_iter); + +	return ret; +} + +static int +intel_atomic_check_tiled_conns(struct intel_atomic_state *state) +{ +	struct drm_i915_private *dev_priv = to_i915(state->base.dev); +	struct drm_connector *connector; +	struct drm_connector_state *old_conn_state, *new_conn_state; +	int i, ret; + +	if (INTEL_GEN(dev_priv) < 11) +		return 0; + +	/* Is tiled, mark all other tiled CRTCs as needing a modeset */ +	for_each_oldnew_connector_in_state(&state->base, connector, +					   old_conn_state, new_conn_state, i) { +		if (!connector->has_tile) +			continue; +		if (!intel_connector_needs_modeset(state, connector)) +			continue; + +		ret = intel_modeset_all_tiles(state, connector->tile_group->id); +		if (ret) +			return ret; +	} + +	return 0; +} +  /**   * intel_atomic_check - validate state object   * @dev: drm device @@ -13990,33 +14582,101 @@ static int intel_atomic_check(struct drm_device *dev,  	/* Catch I915_MODE_FLAG_INHERITED */  	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,  					    new_crtc_state, i) { -		if (new_crtc_state->base.mode.private_flags != -		    old_crtc_state->base.mode.private_flags) -			new_crtc_state->base.mode_changed = true; +		if (new_crtc_state->hw.mode.private_flags != +		    old_crtc_state->hw.mode.private_flags) +			new_crtc_state->uapi.mode_changed = true;  	}  	ret = drm_atomic_helper_check_modeset(dev, &state->base);  	if (ret)  		goto fail; +	/** +	 * This check adds all the connectors in current state that belong to +	 * the same tile group to a full modeset. +	 * This function directly sets the mode_changed to true and we also call +	 * drm_atomic_add_affected_connectors(). Hence we are not explicitly +	 * calling drm_atomic_helper_check_modeset() after this. +	 * +	 * Fixme: Handle some corner cases where one of the +	 * tiled connectors gets disconnected and tile info is lost but since it +	 * was previously synced to other conn, we need to add that to the modeset. +	 */ +	ret = intel_atomic_check_tiled_conns(state); +	if (ret) +		goto fail; +  	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,  					    new_crtc_state, i) { -		if (!needs_modeset(new_crtc_state)) +		if (!needs_modeset(new_crtc_state)) { +			/* Light copy */ +			intel_crtc_copy_uapi_to_hw_state_nomodeset(new_crtc_state); +  			continue; +		} -		if (!new_crtc_state->base.enable) { -			any_ms = true; +		if (!new_crtc_state->uapi.enable) { +			intel_crtc_copy_uapi_to_hw_state(new_crtc_state);  			continue;  		} +		ret = intel_crtc_prepare_cleared_state(new_crtc_state); +		if (ret) +			goto fail; +  		ret = intel_modeset_pipe_config(new_crtc_state);  		if (ret)  			goto fail;  		intel_crtc_check_fastset(old_crtc_state, new_crtc_state); +	} + +	/** +	 * Check if fastset is allowed by external dependencies like other +	 * pipes and transcoders. +	 * +	 * Right now it only forces a fullmodeset when the MST master +	 * transcoder did not changed but the pipe of the master transcoder +	 * needs a fullmodeset so all slaves also needs to do a fullmodeset or +	 * in case of port synced crtcs, if one of the synced crtcs +	 * needs a full modeset, all other synced crtcs should be +	 * forced a full modeset. +	 */ +	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { +		if (!new_crtc_state->hw.enable || needs_modeset(new_crtc_state)) +			continue; + +		if (intel_dp_mst_is_slave_trans(new_crtc_state)) { +			enum transcoder master = new_crtc_state->mst_master_transcoder; + +			if (intel_cpu_transcoders_need_modeset(state, BIT(master))) { +				new_crtc_state->uapi.mode_changed = true; +				new_crtc_state->update_pipe = false; +			} +		} -		if (needs_modeset(new_crtc_state)) +		if (is_trans_port_sync_mode(new_crtc_state)) { +			u8 trans = new_crtc_state->sync_mode_slaves_mask | +				   BIT(new_crtc_state->master_transcoder); + +			if (intel_cpu_transcoders_need_modeset(state, trans)) { +				new_crtc_state->uapi.mode_changed = true; +				new_crtc_state->update_pipe = false; +			} +		} +	} + +	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, +					    new_crtc_state, i) { +		if (needs_modeset(new_crtc_state)) {  			any_ms = true; +			continue; +		} + +		if (!new_crtc_state->update_pipe) +			continue; + +		intel_crtc_copy_fastset(old_crtc_state, new_crtc_state);  	}  	if (any_ms && !check_digital_port_conflicts(state)) { @@ -14106,7 +14766,7 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,  {  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); -	if (!IS_GEN(dev_priv, 2)) +	if (!IS_GEN(dev_priv, 2) || crtc_state->active_planes)  		intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true);  	if (crtc_state->has_pch_encoder) { @@ -14120,7 +14780,7 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,  static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state,  			       const struct intel_crtc_state *new_crtc_state)  { -	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); +	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	/* @@ -14138,12 +14798,12 @@ static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state,  		skl_detach_scalers(new_crtc_state);  		if (new_crtc_state->pch_pfit.enabled) -			skylake_pfit_enable(new_crtc_state); +			skl_pfit_enable(new_crtc_state);  	} else if (HAS_PCH_SPLIT(dev_priv)) {  		if (new_crtc_state->pch_pfit.enabled) -			ironlake_pfit_enable(new_crtc_state); +			ilk_pfit_enable(new_crtc_state);  		else if (old_crtc_state->pch_pfit.enabled) -			ironlake_pfit_disable(old_crtc_state); +			ilk_pfit_disable(old_crtc_state);  	}  	if (INTEL_GEN(dev_priv) >= 11) @@ -14154,6 +14814,7 @@ static void commit_pipe_config(struct intel_atomic_state *state,  			       struct intel_crtc_state *old_crtc_state,  			       struct intel_crtc_state *new_crtc_state)  { +	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);  	bool modeset = needs_modeset(new_crtc_state); @@ -14162,7 +14823,7 @@ static void commit_pipe_config(struct intel_atomic_state *state,  	 * CRTC was enabled.  	 */  	if (!modeset) { -		if (new_crtc_state->base.color_mgmt_changed || +		if (new_crtc_state->uapi.color_mgmt_changed ||  		    new_crtc_state->update_pipe)  			intel_color_commit(new_crtc_state); @@ -14177,8 +14838,7 @@ static void commit_pipe_config(struct intel_atomic_state *state,  	}  	if (dev_priv->display.atomic_update_watermarks) -		dev_priv->display.atomic_update_watermarks(state, -							   new_crtc_state); +		dev_priv->display.atomic_update_watermarks(state, crtc);  }  static void intel_update_crtc(struct intel_crtc *crtc, @@ -14195,20 +14855,20 @@ static void intel_update_crtc(struct intel_crtc *crtc,  	if (modeset) {  		intel_crtc_update_active_timings(new_crtc_state); -		dev_priv->display.crtc_enable(new_crtc_state, state); +		dev_priv->display.crtc_enable(state, crtc);  		/* vblanks work again, re-enable pipe CRC. */  		intel_crtc_enable_pipe_crc(crtc);  	} else {  		if (new_crtc_state->preload_luts && -		    (new_crtc_state->base.color_mgmt_changed || +		    (new_crtc_state->uapi.color_mgmt_changed ||  		     new_crtc_state->update_pipe))  			intel_color_load_luts(new_crtc_state); -		intel_pre_plane_update(old_crtc_state, new_crtc_state); +		intel_pre_plane_update(state, crtc);  		if (new_crtc_state->update_pipe) -			intel_encoders_update_pipe(crtc, new_crtc_state, state); +			intel_encoders_update_pipe(state, crtc);  	}  	if (new_crtc_state->update_pipe && !new_crtc_state->enable_fbc) @@ -14235,13 +14895,13 @@ static void intel_update_crtc(struct intel_crtc *crtc,  	 * of enabling them on the CRTC's first fastset.  	 */  	if (new_crtc_state->update_pipe && !modeset && -	    old_crtc_state->base.mode.private_flags & I915_MODE_FLAG_INHERITED) +	    old_crtc_state->hw.mode.private_flags & I915_MODE_FLAG_INHERITED)  		intel_crtc_arm_fifo_underrun(crtc, new_crtc_state);  }  static struct intel_crtc *intel_get_slave_crtc(const struct intel_crtc_state *new_crtc_state)  { -	struct drm_i915_private *dev_priv = to_i915(new_crtc_state->base.crtc->dev); +	struct drm_i915_private *dev_priv = to_i915(new_crtc_state->uapi.crtc->dev);  	enum transcoder slave_transcoder;  	WARN_ON(!is_power_of_2(new_crtc_state->sync_mode_slaves_mask)); @@ -14266,97 +14926,60 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state,  	 */  	intel_crtc_disable_pipe_crc(crtc); -	dev_priv->display.crtc_disable(old_crtc_state, state); +	dev_priv->display.crtc_disable(state, crtc);  	crtc->active = false;  	intel_fbc_disable(crtc);  	intel_disable_shared_dpll(old_crtc_state); -	/* -	 * Underruns don't always raise interrupts, -	 * so check manually. -	 */ -	intel_check_cpu_fifo_underruns(dev_priv); -	intel_check_pch_fifo_underruns(dev_priv); -  	/* FIXME unify this for all platforms */ -	if (!new_crtc_state->base.active && +	if (!new_crtc_state->hw.active &&  	    !HAS_GMCH(dev_priv) &&  	    dev_priv->display.initial_watermarks) -		dev_priv->display.initial_watermarks(state, -						     new_crtc_state); -} - -static void intel_trans_port_sync_modeset_disables(struct intel_atomic_state *state, -						   struct intel_crtc *crtc, -						   struct intel_crtc_state *old_crtc_state, -						   struct intel_crtc_state *new_crtc_state) -{ -	struct intel_crtc *slave_crtc = intel_get_slave_crtc(new_crtc_state); -	struct intel_crtc_state *new_slave_crtc_state = -		intel_atomic_get_new_crtc_state(state, slave_crtc); -	struct intel_crtc_state *old_slave_crtc_state = -		intel_atomic_get_old_crtc_state(state, slave_crtc); - -	WARN_ON(!slave_crtc || !new_slave_crtc_state || -		!old_slave_crtc_state); - -	/* Disable Slave first */ -	intel_pre_plane_update(old_slave_crtc_state, new_slave_crtc_state); -	if (old_slave_crtc_state->base.active) -		intel_old_crtc_state_disables(state, -					      old_slave_crtc_state, -					      new_slave_crtc_state, -					      slave_crtc); - -	/* Disable Master */ -	intel_pre_plane_update(old_crtc_state, new_crtc_state); -	if (old_crtc_state->base.active) -		intel_old_crtc_state_disables(state, -					      old_crtc_state, -					      new_crtc_state, -					      crtc); +		dev_priv->display.initial_watermarks(state, crtc);  }  static void intel_commit_modeset_disables(struct intel_atomic_state *state)  {  	struct intel_crtc_state *new_crtc_state, *old_crtc_state;  	struct intel_crtc *crtc; +	u32 handled = 0;  	int i; -	/* -	 * Disable CRTC/pipes in reverse order because some features(MST in -	 * TGL+) requires master and slave relationship between pipes, so it -	 * should always pick the lowest pipe as master as it will be enabled -	 * first and disable in the reverse order so the master will be the -	 * last one to be disabled. -	 */ -	for_each_oldnew_intel_crtc_in_state_reverse(state, crtc, old_crtc_state, -						    new_crtc_state, i) { +	/* Only disable port sync and MST slaves */ +	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, +					    new_crtc_state, i) {  		if (!needs_modeset(new_crtc_state))  			continue; +		if (!old_crtc_state->hw.active) +			continue; +  		/* In case of Transcoder port Sync master slave CRTCs can be  		 * assigned in any order and we need to make sure that  		 * slave CRTCs are disabled first and then master CRTC since  		 * Slave vblanks are masked till Master Vblanks.  		 */ -		if (is_trans_port_sync_mode(new_crtc_state)) { -			if (is_trans_port_sync_master(new_crtc_state)) -				intel_trans_port_sync_modeset_disables(state, -								       crtc, -								       old_crtc_state, -								       new_crtc_state); -			else -				continue; -		} else { -			intel_pre_plane_update(old_crtc_state, new_crtc_state); +		if (!is_trans_port_sync_slave(old_crtc_state) && +		    !intel_dp_mst_is_slave_trans(old_crtc_state)) +			continue; -			if (old_crtc_state->base.active) -				intel_old_crtc_state_disables(state, -							      old_crtc_state, -							      new_crtc_state, -							      crtc); -		} +		intel_pre_plane_update(state, crtc); +		intel_old_crtc_state_disables(state, old_crtc_state, +					      new_crtc_state, crtc); +		handled |= BIT(crtc->pipe); +	} + +	/* Disable everything else left on */ +	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, +					    new_crtc_state, i) { +		if (!needs_modeset(new_crtc_state) || +		    (handled & BIT(crtc->pipe))) +			continue; + +		intel_pre_plane_update(state, crtc); +		if (old_crtc_state->hw.active) +			intel_old_crtc_state_disables(state, old_crtc_state, +						      new_crtc_state, crtc);  	}  } @@ -14367,7 +14990,7 @@ static void intel_commit_modeset_enables(struct intel_atomic_state *state)  	int i;  	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { -		if (!new_crtc_state->base.active) +		if (!new_crtc_state->hw.active)  			continue;  		intel_update_crtc(crtc, state, old_crtc_state, @@ -14382,7 +15005,7 @@ static void intel_crtc_enable_trans_port_sync(struct intel_crtc *crtc,  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);  	intel_crtc_update_active_timings(new_crtc_state); -	dev_priv->display.crtc_enable(new_crtc_state, state); +	dev_priv->display.crtc_enable(state, crtc);  	intel_crtc_enable_pipe_crc(crtc);  } @@ -14398,10 +15021,14 @@ static void intel_set_dp_tp_ctl_normal(struct intel_crtc *crtc,  		if (conn_state->crtc == &crtc->base)  			break;  	} -	intel_dp = enc_to_intel_dp(&intel_attached_encoder(conn)->base); +	intel_dp = enc_to_intel_dp(intel_attached_encoder(to_intel_connector(conn)));  	intel_dp_stop_link_train(intel_dp);  } +/* + * TODO: This is only called from port sync and it is identical to what will be + * executed again in intel_update_crtc() over port sync pipes + */  static void intel_post_crtc_enable_updates(struct intel_crtc *crtc,  					   struct intel_atomic_state *state)  { @@ -14432,7 +15059,7 @@ static void intel_post_crtc_enable_updates(struct intel_crtc *crtc,  	 * of enabling them on the CRTC's first fastset.  	 */  	if (new_crtc_state->update_pipe && !modeset && -	    old_crtc_state->base.mode.private_flags & I915_MODE_FLAG_INHERITED) +	    old_crtc_state->hw.mode.private_flags & I915_MODE_FLAG_INHERITED)  		intel_crtc_arm_fifo_underrun(crtc, new_crtc_state);  } @@ -14487,17 +15114,25 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);  	struct intel_crtc *crtc;  	struct intel_crtc_state *old_crtc_state, *new_crtc_state; -	unsigned int updated = 0; -	bool progress; -	int i;  	u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;  	u8 required_slices = state->wm_results.ddb.enabled_slices;  	struct skl_ddb_entry entries[I915_MAX_PIPES] = {}; +	const u8 num_pipes = INTEL_NUM_PIPES(dev_priv); +	u8 update_pipes = 0, modeset_pipes = 0; +	int i; + +	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { +		if (!new_crtc_state->hw.active) +			continue; -	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i)  		/* ignore allocations for crtc's that have been turned off. */ -		if (new_crtc_state->base.active) +		if (!needs_modeset(new_crtc_state)) {  			entries[i] = old_crtc_state->wm.skl.ddb; +			update_pipes |= BIT(crtc->pipe); +		} else { +			modeset_pipes |= BIT(crtc->pipe); +		} +	}  	/* If 2nd DBuf slice required, enable it here */  	if (INTEL_GEN(dev_priv) >= 11 && required_slices > hw_enabled_slices) @@ -14506,27 +15141,29 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)  	/*  	 * Whenever the number of active pipes changes, we need to make sure we  	 * update the pipes in the right order so that their ddb allocations -	 * never overlap with eachother inbetween CRTC updates. Otherwise we'll +	 * never overlap with each other between CRTC updates. Otherwise we'll  	 * cause pipe underruns and other bad stuff. +	 * +	 * So first lets enable all pipes that do not need a fullmodeset as +	 * those don't have any external dependency.  	 */ -	do { -		progress = false; - -		for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { +	while (update_pipes) { +		for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, +						    new_crtc_state, i) {  			enum pipe pipe = crtc->pipe; -			bool vbl_wait = false; -			bool modeset = needs_modeset(new_crtc_state); -			if (updated & BIT(crtc->pipe) || !new_crtc_state->base.active) +			if ((update_pipes & BIT(pipe)) == 0)  				continue;  			if (skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb, -							entries, -							INTEL_NUM_PIPES(dev_priv), i)) +							entries, num_pipes, i))  				continue; -			updated |= BIT(pipe);  			entries[i] = new_crtc_state->wm.skl.ddb; +			update_pipes &= ~BIT(pipe); + +			intel_update_crtc(crtc, state, old_crtc_state, +					  new_crtc_state);  			/*  			 * If this is an already active pipe, it's DDB changed, @@ -14536,29 +15173,71 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)  			 */  			if (!skl_ddb_entry_equal(&new_crtc_state->wm.skl.ddb,  						 &old_crtc_state->wm.skl.ddb) && -			    !modeset && -			    state->wm_results.dirty_pipes != updated) -				vbl_wait = true; - -			if (modeset && is_trans_port_sync_mode(new_crtc_state)) { -				if (is_trans_port_sync_master(new_crtc_state)) -					intel_update_trans_port_sync_crtcs(crtc, -									   state, -									   old_crtc_state, -									   new_crtc_state); -				else -					continue; -			} else { -				intel_update_crtc(crtc, state, old_crtc_state, -						  new_crtc_state); -			} - -			if (vbl_wait) +			    (update_pipes | modeset_pipes))  				intel_wait_for_vblank(dev_priv, pipe); +		} +	} + +	/* +	 * Enable all pipes that needs a modeset and do not depends on other +	 * pipes +	 */ +	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, +					    new_crtc_state, i) { +		enum pipe pipe = crtc->pipe; + +		if ((modeset_pipes & BIT(pipe)) == 0) +			continue; + +		if (intel_dp_mst_is_slave_trans(new_crtc_state) || +		    is_trans_port_sync_slave(new_crtc_state)) +			continue; + +		WARN_ON(skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb, +						    entries, num_pipes, i)); -			progress = true; +		entries[i] = new_crtc_state->wm.skl.ddb; +		modeset_pipes &= ~BIT(pipe); + +		if (is_trans_port_sync_mode(new_crtc_state)) { +			struct intel_crtc *slave_crtc; + +			intel_update_trans_port_sync_crtcs(crtc, state, +							   old_crtc_state, +							   new_crtc_state); + +			slave_crtc = intel_get_slave_crtc(new_crtc_state); +			/* TODO: update entries[] of slave */ +			modeset_pipes &= ~BIT(slave_crtc->pipe); + +		} else { +			intel_update_crtc(crtc, state, old_crtc_state, +					  new_crtc_state);  		} -	} while (progress); +	} + +	/* +	 * Finally enable all pipes that needs a modeset and depends on +	 * other pipes, right now it is only MST slaves as both port sync slave +	 * and master are enabled together +	 */ +	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, +					    new_crtc_state, i) { +		enum pipe pipe = crtc->pipe; + +		if ((modeset_pipes & BIT(pipe)) == 0) +			continue; + +		WARN_ON(skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb, +						    entries, num_pipes, i)); + +		entries[i] = new_crtc_state->wm.skl.ddb; +		modeset_pipes &= ~BIT(pipe); + +		intel_update_crtc(crtc, state, old_crtc_state, new_crtc_state); +	} + +	WARN_ON(modeset_pipes);  	/* If 2nd DBuf slice is no more required disable it */  	if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices) @@ -14679,12 +15358,13 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)  		bool modeset = needs_modeset(new_crtc_state);  		/* Complete events for now disable pipes here. */ -		if (modeset && !new_crtc_state->base.active && new_crtc_state->base.event) { +		if (modeset && !new_crtc_state->hw.active && new_crtc_state->uapi.event) {  			spin_lock_irq(&dev->event_lock); -			drm_crtc_send_vblank_event(&crtc->base, new_crtc_state->base.event); +			drm_crtc_send_vblank_event(&crtc->base, +						   new_crtc_state->uapi.event);  			spin_unlock_irq(&dev->event_lock); -			new_crtc_state->base.event = NULL; +			new_crtc_state->uapi.event = NULL;  		}  	} @@ -14715,10 +15395,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)  	drm_atomic_helper_wait_for_flip_done(dev, &state->base);  	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { -		if (new_crtc_state->base.active && +		if (new_crtc_state->hw.active &&  		    !needs_modeset(new_crtc_state) &&  		    !new_crtc_state->preload_luts && -		    (new_crtc_state->base.color_mgmt_changed || +		    (new_crtc_state->uapi.color_mgmt_changed ||  		     new_crtc_state->update_pipe))  			intel_color_load_luts(new_crtc_state);  	} @@ -14730,14 +15410,25 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)  	 *  	 * TODO: Move this (and other cleanup) to an async worker eventually.  	 */ -	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { +	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, +					    new_crtc_state, i) { +		/* +		 * Gen2 reports pipe underruns whenever all planes are disabled. +		 * So re-enable underrun reporting after some planes get enabled. +		 * +		 * We do this before .optimize_watermarks() so that we have a +		 * chance of catching underruns with the intermediate watermarks +		 * vs. the new plane configuration. +		 */ +		if (IS_GEN(dev_priv, 2) && planes_enabling(old_crtc_state, new_crtc_state)) +			intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true); +  		if (dev_priv->display.optimize_watermarks) -			dev_priv->display.optimize_watermarks(state, -							      new_crtc_state); +			dev_priv->display.optimize_watermarks(state, crtc);  	}  	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { -		intel_post_plane_update(old_crtc_state); +		intel_post_plane_update(state, crtc);  		if (put_domains[i])  			modeset_put_power_domains(dev_priv, put_domains[i]); @@ -14745,6 +15436,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)  		intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state);  	} +	/* Underruns don't always raise interrupts, so check manually */ +	intel_check_cpu_fifo_underruns(dev_priv); +	intel_check_pch_fifo_underruns(dev_priv); +  	if (state->modeset)  		intel_verify_planes(state); @@ -14818,8 +15513,8 @@ static void intel_atomic_track_fbs(struct intel_atomic_state *state)  	for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,  					     new_plane_state, i) -		intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->base.fb), -					to_intel_frontbuffer(new_plane_state->base.fb), +		intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb), +					to_intel_frontbuffer(new_plane_state->hw.fb),  					plane->frontbuffer_bit);  } @@ -14986,9 +15681,9 @@ static void add_rps_boost_after_vblank(struct drm_crtc *crtc,  static int intel_plane_pin_fb(struct intel_plane_state *plane_state)  { -	struct intel_plane *plane = to_intel_plane(plane_state->base.plane); +	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev); -	struct drm_framebuffer *fb = plane_state->base.fb; +	struct drm_framebuffer *fb = plane_state->hw.fb;  	struct i915_vma *vma;  	if (plane->id == PLANE_CURSOR && @@ -15051,9 +15746,9 @@ intel_prepare_plane_fb(struct drm_plane *plane,  	struct intel_plane_state *new_plane_state =  		to_intel_plane_state(_new_plane_state);  	struct intel_atomic_state *intel_state = -		to_intel_atomic_state(new_plane_state->base.state); +		to_intel_atomic_state(new_plane_state->uapi.state);  	struct drm_i915_private *dev_priv = to_i915(plane->dev); -	struct drm_framebuffer *fb = new_plane_state->base.fb; +	struct drm_framebuffer *fb = new_plane_state->hw.fb;  	struct drm_i915_gem_object *obj = intel_fb_obj(fb);  	struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb);  	int ret; @@ -15084,9 +15779,9 @@ intel_prepare_plane_fb(struct drm_plane *plane,  		}  	} -	if (new_plane_state->base.fence) { /* explicit fencing */ +	if (new_plane_state->uapi.fence) { /* explicit fencing */  		ret = i915_sw_fence_await_dma_fence(&intel_state->commit_ready, -						    new_plane_state->base.fence, +						    new_plane_state->uapi.fence,  						    I915_FENCE_TIMEOUT,  						    GFP_KERNEL);  		if (ret < 0) @@ -15109,7 +15804,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,  	fb_obj_bump_render_priority(obj);  	i915_gem_object_flush_frontbuffer(obj, ORIGIN_DIRTYFB); -	if (!new_plane_state->base.fence) { /* implicit fencing */ +	if (!new_plane_state->uapi.fence) { /* implicit fencing */  		struct dma_fence *fence;  		ret = i915_sw_fence_await_reservation(&intel_state->commit_ready, @@ -15121,13 +15816,13 @@ intel_prepare_plane_fb(struct drm_plane *plane,  		fence = dma_resv_get_excl_rcu(obj->base.resv);  		if (fence) { -			add_rps_boost_after_vblank(new_plane_state->base.crtc, +			add_rps_boost_after_vblank(new_plane_state->hw.crtc,  						   fence);  			dma_fence_put(fence);  		}  	} else { -		add_rps_boost_after_vblank(new_plane_state->base.crtc, -					   new_plane_state->base.fence); +		add_rps_boost_after_vblank(new_plane_state->hw.crtc, +					   new_plane_state->uapi.fence);  	}  	/* @@ -15160,7 +15855,7 @@ intel_cleanup_plane_fb(struct drm_plane *plane,  	struct intel_plane_state *old_plane_state =  		to_intel_plane_state(_old_plane_state);  	struct intel_atomic_state *intel_state = -		to_intel_atomic_state(old_plane_state->base.state); +		to_intel_atomic_state(old_plane_state->uapi.state);  	struct drm_i915_private *dev_priv = to_i915(plane->dev);  	if (intel_state->rps_interactive) { @@ -15224,8 +15919,12 @@ static bool i965_plane_format_mod_supported(struct drm_plane *_plane,  	case DRM_FORMAT_RGB565:  	case DRM_FORMAT_XRGB8888:  	case DRM_FORMAT_XBGR8888: +	case DRM_FORMAT_ARGB8888: +	case DRM_FORMAT_ABGR8888:  	case DRM_FORMAT_XRGB2101010:  	case DRM_FORMAT_XBGR2101010: +	case DRM_FORMAT_ARGB2101010: +	case DRM_FORMAT_ABGR2101010:  	case DRM_FORMAT_XBGR16161616F:  		return modifier == DRM_FORMAT_MOD_LINEAR ||  			modifier == I915_FORMAT_MOD_X_TILED; @@ -15283,7 +15982,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane,  	 * When crtc is inactive or there is a modeset pending,  	 * wait for it to complete in the slowpath  	 */ -	if (!crtc_state->base.active || needs_modeset(crtc_state) || +	if (!crtc_state->hw.active || needs_modeset(crtc_state) ||  	    crtc_state->update_pipe)  		goto slow; @@ -15292,8 +15991,8 @@ intel_legacy_cursor_update(struct drm_plane *_plane,  	 * the plane.  This prevents our async update's changes from getting  	 * overridden by a previous synchronous update's state.  	 */ -	if (old_plane_state->base.commit && -	    !try_wait_for_completion(&old_plane_state->base.commit->hw_done)) +	if (old_plane_state->uapi.commit && +	    !try_wait_for_completion(&old_plane_state->uapi.commit->hw_done))  		goto slow;  	/* @@ -15301,12 +16000,12 @@ intel_legacy_cursor_update(struct drm_plane *_plane,  	 * take the slowpath. Only changing fb or position should be  	 * in the fastpath.  	 */ -	if (old_plane_state->base.crtc != &crtc->base || -	    old_plane_state->base.src_w != src_w || -	    old_plane_state->base.src_h != src_h || -	    old_plane_state->base.crtc_w != crtc_w || -	    old_plane_state->base.crtc_h != crtc_h || -	    !old_plane_state->base.fb != !fb) +	if (old_plane_state->uapi.crtc != &crtc->base || +	    old_plane_state->uapi.src_w != src_w || +	    old_plane_state->uapi.src_h != src_h || +	    old_plane_state->uapi.crtc_w != crtc_w || +	    old_plane_state->uapi.crtc_h != crtc_h || +	    !old_plane_state->uapi.fb != !fb)  		goto slow;  	new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base)); @@ -15319,16 +16018,16 @@ intel_legacy_cursor_update(struct drm_plane *_plane,  		goto out_free;  	} -	drm_atomic_set_fb_for_plane(&new_plane_state->base, fb); +	drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb); -	new_plane_state->base.src_x = src_x; -	new_plane_state->base.src_y = src_y; -	new_plane_state->base.src_w = src_w; -	new_plane_state->base.src_h = src_h; -	new_plane_state->base.crtc_x = crtc_x; -	new_plane_state->base.crtc_y = crtc_y; -	new_plane_state->base.crtc_w = crtc_w; -	new_plane_state->base.crtc_h = crtc_h; +	new_plane_state->uapi.src_x = src_x; +	new_plane_state->uapi.src_y = src_y; +	new_plane_state->uapi.src_w = src_w; +	new_plane_state->uapi.src_h = src_h; +	new_plane_state->uapi.crtc_x = crtc_x; +	new_plane_state->uapi.crtc_y = crtc_y; +	new_plane_state->uapi.crtc_w = crtc_w; +	new_plane_state->uapi.crtc_h = crtc_h;  	ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,  						  old_plane_state, new_plane_state); @@ -15339,13 +16038,14 @@ intel_legacy_cursor_update(struct drm_plane *_plane,  	if (ret)  		goto out_free; -	intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->base.fb), ORIGIN_FLIP); -	intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->base.fb), -				to_intel_frontbuffer(new_plane_state->base.fb), +	intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb), +				ORIGIN_FLIP); +	intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb), +				to_intel_frontbuffer(new_plane_state->hw.fb),  				plane->frontbuffer_bit);  	/* Swap plane state */ -	plane->base.state = &new_plane_state->base; +	plane->base.state = &new_plane_state->uapi;  	/*  	 * We cannot swap crtc_state as it may be in use by an atomic commit or @@ -15359,7 +16059,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane,  	 */  	crtc_state->active_planes = new_crtc_state->active_planes; -	if (new_plane_state->base.visible) +	if (new_plane_state->uapi.visible)  		intel_update_plane(plane, crtc_state, new_plane_state);  	else  		intel_disable_plane(plane, crtc_state); @@ -15368,11 +16068,11 @@ intel_legacy_cursor_update(struct drm_plane *_plane,  out_free:  	if (new_crtc_state) -		intel_crtc_destroy_state(&crtc->base, &new_crtc_state->base); +		intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi);  	if (ret) -		intel_plane_destroy_state(&plane->base, &new_plane_state->base); +		intel_plane_destroy_state(&plane->base, &new_plane_state->uapi);  	else -		intel_plane_destroy_state(&plane->base, &old_plane_state->base); +		intel_plane_destroy_state(&plane->base, &old_plane_state->uapi);  	return ret;  slow: @@ -15414,7 +16114,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)  	const struct drm_plane_funcs *plane_funcs;  	unsigned int supported_rotations;  	unsigned int possible_crtcs; -	const u64 *modifiers;  	const u32 *formats;  	int num_formats;  	int ret, zpos; @@ -15446,7 +16145,10 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)  		fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;  	} -	if (INTEL_GEN(dev_priv) >= 4) { +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { +		formats = vlv_primary_formats; +		num_formats = ARRAY_SIZE(vlv_primary_formats); +	} else if (INTEL_GEN(dev_priv) >= 4) {  		/*  		 * WaFP16GammaEnabling:ivb  		 * "Workaround : When using the 64-bit format, the plane @@ -15467,51 +16169,45 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)  			formats = i965_primary_formats;  			num_formats = ARRAY_SIZE(i965_primary_formats);  		} -		modifiers = i9xx_format_modifiers; - -		plane->max_stride = i9xx_plane_max_stride; -		plane->update_plane = i9xx_update_plane; -		plane->disable_plane = i9xx_disable_plane; -		plane->get_hw_state = i9xx_plane_get_hw_state; -		plane->check_plane = i9xx_plane_check; - -		if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) -			plane->min_cdclk = hsw_plane_min_cdclk; -		else if (IS_IVYBRIDGE(dev_priv)) -			plane->min_cdclk = ivb_plane_min_cdclk; -		else if (IS_CHERRYVIEW(dev_priv) || IS_VALLEYVIEW(dev_priv)) -			plane->min_cdclk = vlv_plane_min_cdclk; -		else -			plane->min_cdclk = i9xx_plane_min_cdclk; - -		plane_funcs = &i965_plane_funcs;  	} else {  		formats = i8xx_primary_formats;  		num_formats = ARRAY_SIZE(i8xx_primary_formats); -		modifiers = i9xx_format_modifiers; +	} -		plane->max_stride = i9xx_plane_max_stride; -		plane->update_plane = i9xx_update_plane; -		plane->disable_plane = i9xx_disable_plane; -		plane->get_hw_state = i9xx_plane_get_hw_state; -		plane->check_plane = i9xx_plane_check; +	if (INTEL_GEN(dev_priv) >= 4) +		plane_funcs = &i965_plane_funcs; +	else +		plane_funcs = &i8xx_plane_funcs; + +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) +		plane->min_cdclk = vlv_plane_min_cdclk; +	else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) +		plane->min_cdclk = hsw_plane_min_cdclk; +	else if (IS_IVYBRIDGE(dev_priv)) +		plane->min_cdclk = ivb_plane_min_cdclk; +	else  		plane->min_cdclk = i9xx_plane_min_cdclk; -		plane_funcs = &i8xx_plane_funcs; -	} +	plane->max_stride = i9xx_plane_max_stride; +	plane->update_plane = i9xx_update_plane; +	plane->disable_plane = i9xx_disable_plane; +	plane->get_hw_state = i9xx_plane_get_hw_state; +	plane->check_plane = i9xx_plane_check;  	possible_crtcs = BIT(pipe);  	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))  		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,  					       possible_crtcs, plane_funcs, -					       formats, num_formats, modifiers, +					       formats, num_formats, +					       i9xx_format_modifiers,  					       DRM_PLANE_TYPE_PRIMARY,  					       "primary %c", pipe_name(pipe));  	else  		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,  					       possible_crtcs, plane_funcs, -					       formats, num_formats, modifiers, +					       formats, num_formats, +					       i9xx_format_modifiers,  					       DRM_PLANE_TYPE_PRIMARY,  					       "plane %c",  					       plane_name(plane->i9xx_plane)); @@ -15615,28 +16311,6 @@ fail:  	return ERR_PTR(ret);  } -static void intel_crtc_init_scalers(struct intel_crtc *crtc, -				    struct intel_crtc_state *crtc_state) -{ -	struct intel_crtc_scaler_state *scaler_state = -		&crtc_state->scaler_state; -	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); -	int i; - -	crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[crtc->pipe]; -	if (!crtc->num_scalers) -		return; - -	for (i = 0; i < crtc->num_scalers; i++) { -		struct intel_scaler *scaler = &scaler_state->scalers[i]; - -		scaler->in_use = 0; -		scaler->mode = 0; -	} - -	scaler_state->scaler_id = -1; -} -  #define INTEL_CRTC_FUNCS \  	.gamma_set = drm_atomic_helper_legacy_gamma_set, \  	.set_config = drm_atomic_helper_set_config, \ @@ -15704,33 +16378,53 @@ static const struct drm_crtc_funcs i8xx_crtc_funcs = {  	.disable_vblank = i8xx_disable_vblank,  }; +static struct intel_crtc *intel_crtc_alloc(void) +{ +	struct intel_crtc_state *crtc_state; +	struct intel_crtc *crtc; + +	crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); +	if (!crtc) +		return ERR_PTR(-ENOMEM); + +	crtc_state = intel_crtc_state_alloc(crtc); +	if (!crtc_state) { +		kfree(crtc); +		return ERR_PTR(-ENOMEM); +	} + +	crtc->base.state = &crtc_state->uapi; +	crtc->config = crtc_state; + +	return crtc; +} + +static void intel_crtc_free(struct intel_crtc *crtc) +{ +	intel_crtc_destroy_state(&crtc->base, crtc->base.state); +	kfree(crtc); +} +  static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)  { +	struct intel_plane *primary, *cursor;  	const struct drm_crtc_funcs *funcs; -	struct intel_crtc *intel_crtc; -	struct intel_crtc_state *crtc_state = NULL; -	struct intel_plane *primary = NULL; -	struct intel_plane *cursor = NULL; +	struct intel_crtc *crtc;  	int sprite, ret; -	intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); -	if (!intel_crtc) -		return -ENOMEM; +	crtc = intel_crtc_alloc(); +	if (IS_ERR(crtc)) +		return PTR_ERR(crtc); -	crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); -	if (!crtc_state) { -		ret = -ENOMEM; -		goto fail; -	} -	__drm_atomic_helper_crtc_reset(&intel_crtc->base, &crtc_state->base); -	intel_crtc->config = crtc_state; +	crtc->pipe = pipe; +	crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe];  	primary = intel_primary_plane_create(dev_priv, pipe);  	if (IS_ERR(primary)) {  		ret = PTR_ERR(primary);  		goto fail;  	} -	intel_crtc->plane_ids_mask |= BIT(primary->id); +	crtc->plane_ids_mask |= BIT(primary->id);  	for_each_sprite(dev_priv, pipe, sprite) {  		struct intel_plane *plane; @@ -15740,7 +16434,7 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)  			ret = PTR_ERR(plane);  			goto fail;  		} -		intel_crtc->plane_ids_mask |= BIT(plane->id); +		crtc->plane_ids_mask |= BIT(plane->id);  	}  	cursor = intel_cursor_plane_create(dev_priv, pipe); @@ -15748,7 +16442,7 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)  		ret = PTR_ERR(cursor);  		goto fail;  	} -	intel_crtc->plane_ids_mask |= BIT(cursor->id); +	crtc->plane_ids_mask |= BIT(cursor->id);  	if (HAS_GMCH(dev_priv)) {  		if (IS_CHERRYVIEW(dev_priv) || @@ -15769,42 +16463,32 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)  			funcs = &ilk_crtc_funcs;  	} -	ret = drm_crtc_init_with_planes(&dev_priv->drm, &intel_crtc->base, +	ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base,  					&primary->base, &cursor->base,  					funcs, "pipe %c", pipe_name(pipe));  	if (ret)  		goto fail; -	intel_crtc->pipe = pipe; - -	/* initialize shared scalers */ -	intel_crtc_init_scalers(intel_crtc, crtc_state); -  	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) ||  	       dev_priv->pipe_to_crtc_mapping[pipe] != NULL); -	dev_priv->pipe_to_crtc_mapping[pipe] = intel_crtc; +	dev_priv->pipe_to_crtc_mapping[pipe] = crtc;  	if (INTEL_GEN(dev_priv) < 9) {  		enum i9xx_plane_id i9xx_plane = primary->i9xx_plane;  		BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||  		       dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL); -		dev_priv->plane_to_crtc_mapping[i9xx_plane] = intel_crtc; +		dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc;  	} -	intel_color_init(intel_crtc); +	intel_color_init(crtc); -	WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe); +	WARN_ON(drm_crtc_index(&crtc->base) != crtc->pipe);  	return 0;  fail: -	/* -	 * drm_mode_config_cleanup() will free up any -	 * crtcs/planes already initialized. -	 */ -	kfree(crtc_state); -	kfree(intel_crtc); +	intel_crtc_free(crtc);  	return ret;  } @@ -16291,8 +16975,11 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,  	}  	/* FIXME need to adjust LINOFF/TILEOFF accordingly. */ -	if (mode_cmd->offsets[0] != 0) +	if (mode_cmd->offsets[0] != 0) { +		DRM_DEBUG_KMS("plane 0 offset (0x%08x) must be 0\n", +			      mode_cmd->offsets[0]);  		goto err; +	}  	drm_helper_mode_fill_fb_struct(&dev_priv->drm, fb, mode_cmd); @@ -16305,26 +16992,23 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,  		}  		stride_alignment = intel_fb_stride_alignment(fb, i); - -		/* -		 * Display WA #0531: skl,bxt,kbl,glk -		 * -		 * Render decompression and plane width > 3840 -		 * combined with horizontal panning requires the -		 * plane stride to be a multiple of 4. We'll just -		 * require the entire fb to accommodate that to avoid -		 * potential runtime errors at plane configuration time. -		 */ -		if (IS_GEN(dev_priv, 9) && i == 0 && fb->width > 3840 && -		    is_ccs_modifier(fb->modifier)) -			stride_alignment *= 4; -  		if (fb->pitches[i] & (stride_alignment - 1)) {  			DRM_DEBUG_KMS("plane %d pitch (%d) must be at least %u byte aligned\n",  				      i, fb->pitches[i], stride_alignment);  			goto err;  		} +		if (is_gen12_ccs_plane(fb, i)) { +			int ccs_aux_stride = gen12_ccs_aux_stride(fb, i); + +			if (fb->pitches[i] != ccs_aux_stride) { +				DRM_DEBUG_KMS("ccs aux plane %d pitch (%d) must be %d\n", +					      i, +					      fb->pitches[i], ccs_aux_stride); +				goto err; +			} +		} +  		fb->obj[i] = &obj->base;  	} @@ -16522,29 +17206,28 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)  	intel_init_cdclk_hooks(dev_priv);  	if (INTEL_GEN(dev_priv) >= 9) { -		dev_priv->display.get_pipe_config = haswell_get_pipe_config; +		dev_priv->display.get_pipe_config = hsw_get_pipe_config;  		dev_priv->display.get_initial_plane_config = -			skylake_get_initial_plane_config; -		dev_priv->display.crtc_compute_clock = -			haswell_crtc_compute_clock; -		dev_priv->display.crtc_enable = haswell_crtc_enable; -		dev_priv->display.crtc_disable = haswell_crtc_disable; +			skl_get_initial_plane_config; +		dev_priv->display.crtc_compute_clock = hsw_crtc_compute_clock; +		dev_priv->display.crtc_enable = hsw_crtc_enable; +		dev_priv->display.crtc_disable = hsw_crtc_disable;  	} else if (HAS_DDI(dev_priv)) { -		dev_priv->display.get_pipe_config = haswell_get_pipe_config; +		dev_priv->display.get_pipe_config = hsw_get_pipe_config;  		dev_priv->display.get_initial_plane_config =  			i9xx_get_initial_plane_config;  		dev_priv->display.crtc_compute_clock = -			haswell_crtc_compute_clock; -		dev_priv->display.crtc_enable = haswell_crtc_enable; -		dev_priv->display.crtc_disable = haswell_crtc_disable; +			hsw_crtc_compute_clock; +		dev_priv->display.crtc_enable = hsw_crtc_enable; +		dev_priv->display.crtc_disable = hsw_crtc_disable;  	} else if (HAS_PCH_SPLIT(dev_priv)) { -		dev_priv->display.get_pipe_config = ironlake_get_pipe_config; +		dev_priv->display.get_pipe_config = ilk_get_pipe_config;  		dev_priv->display.get_initial_plane_config =  			i9xx_get_initial_plane_config;  		dev_priv->display.crtc_compute_clock = -			ironlake_crtc_compute_clock; -		dev_priv->display.crtc_enable = ironlake_crtc_enable; -		dev_priv->display.crtc_disable = ironlake_crtc_disable; +			ilk_crtc_compute_clock; +		dev_priv->display.crtc_enable = ilk_crtc_enable; +		dev_priv->display.crtc_disable = ilk_crtc_disable;  	} else if (IS_CHERRYVIEW(dev_priv)) {  		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;  		dev_priv->display.get_initial_plane_config = @@ -16590,14 +17273,12 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)  	}  	if (IS_GEN(dev_priv, 5)) { -		dev_priv->display.fdi_link_train = ironlake_fdi_link_train; +		dev_priv->display.fdi_link_train = ilk_fdi_link_train;  	} else if (IS_GEN(dev_priv, 6)) {  		dev_priv->display.fdi_link_train = gen6_fdi_link_train;  	} else if (IS_IVYBRIDGE(dev_priv)) {  		/* FIXME: detect B0+ stepping and use auto training */  		dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; -	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { -		dev_priv->display.fdi_link_train = hsw_fdi_link_train;  	}  	if (INTEL_GEN(dev_priv) >= 9) @@ -16687,7 +17368,7 @@ retry:  	/* Write calculated watermark values back */  	for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) {  		crtc_state->wm.need_postvbl_update = true; -		dev_priv->display.optimize_watermarks(intel_state, crtc_state); +		dev_priv->display.optimize_watermarks(intel_state, crtc);  		to_intel_crtc_state(crtc->base.state)->wm = crtc_state->wm;  	} @@ -16719,8 +17400,7 @@ static int intel_initial_commit(struct drm_device *dev)  {  	struct drm_atomic_state *state = NULL;  	struct drm_modeset_acquire_ctx ctx; -	struct drm_crtc *crtc; -	struct drm_crtc_state *crtc_state; +	struct intel_crtc *crtc;  	int ret = 0;  	state = drm_atomic_state_alloc(dev); @@ -16732,15 +17412,17 @@ static int intel_initial_commit(struct drm_device *dev)  retry:  	state->acquire_ctx = &ctx; -	drm_for_each_crtc(crtc, dev) { -		crtc_state = drm_atomic_get_crtc_state(state, crtc); +	for_each_intel_crtc(dev, crtc) { +		struct intel_crtc_state *crtc_state = +			intel_atomic_get_crtc_state(state, crtc); +  		if (IS_ERR(crtc_state)) {  			ret = PTR_ERR(crtc_state);  			goto out;  		} -		if (crtc_state->active) { -			ret = drm_atomic_add_affected_planes(state, crtc); +		if (crtc_state->hw.active) { +			ret = drm_atomic_add_affected_planes(state, &crtc->base);  			if (ret)  				goto out; @@ -16750,7 +17432,25 @@ retry:  			 * having a proper LUT loaded. Remove once we  			 * have readout for pipe gamma enable.  			 */ -			crtc_state->color_mgmt_changed = true; +			crtc_state->uapi.color_mgmt_changed = true; + +			/* +			 * FIXME hack to force full modeset when DSC is being +			 * used. +			 * +			 * As long as we do not have full state readout and +			 * config comparison of crtc_state->dsc, we have no way +			 * to ensure reliable fastset. Remove once we have +			 * readout for DSC. +			 */ +			if (crtc_state->dsc.compression_enable) { +				ret = drm_atomic_add_affected_connectors(state, +									 &crtc->base); +				if (ret) +					goto out; +				crtc_state->uapi.mode_changed = true; +				drm_dbg_kms(dev, "Force full modeset for DSC\n"); +			}  		}  	} @@ -17073,31 +17773,76 @@ static bool has_pch_trancoder(struct drm_i915_private *dev_priv,  		(HAS_PCH_LPT_H(dev_priv) && pch_transcoder == PIPE_A);  } -static void intel_sanitize_crtc(struct intel_crtc *crtc, -				struct drm_modeset_acquire_ctx *ctx) +static void intel_sanitize_frame_start_delay(const struct intel_crtc_state *crtc_state)  { -	struct drm_device *dev = crtc->base.dev; -	struct drm_i915_private *dev_priv = to_i915(dev); -	struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; -	/* Clear any frame start delays used for debugging left by the BIOS */ -	if (crtc->active && !transcoder_is_dsi(cpu_transcoder)) { +	if (INTEL_GEN(dev_priv) >= 9 || +	    IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) { +		i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder); +		u32 val; + +		if (transcoder_is_dsi(cpu_transcoder)) +			return; + +		val = I915_READ(reg); +		val &= ~HSW_FRAME_START_DELAY_MASK; +		val |= HSW_FRAME_START_DELAY(0); +		I915_WRITE(reg, val); +	} else {  		i915_reg_t reg = PIPECONF(cpu_transcoder); +		u32 val; -		I915_WRITE(reg, -			   I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); +		val = I915_READ(reg); +		val &= ~PIPECONF_FRAME_START_DELAY_MASK; +		val |= PIPECONF_FRAME_START_DELAY(0); +		I915_WRITE(reg, val);  	} -	if (crtc_state->base.active) { +	if (!crtc_state->has_pch_encoder) +		return; + +	if (HAS_PCH_IBX(dev_priv)) { +		i915_reg_t reg = PCH_TRANSCONF(crtc->pipe); +		u32 val; + +		val = I915_READ(reg); +		val &= ~TRANS_FRAME_START_DELAY_MASK; +		val |= TRANS_FRAME_START_DELAY(0); +		I915_WRITE(reg, val); +	} else { +		enum pipe pch_transcoder = intel_crtc_pch_transcoder(crtc); +		i915_reg_t reg = TRANS_CHICKEN2(pch_transcoder); +		u32 val; + +		val = I915_READ(reg); +		val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; +		val |= TRANS_CHICKEN2_FRAME_START_DELAY(0); +		I915_WRITE(reg, val); +	} +} + +static void intel_sanitize_crtc(struct intel_crtc *crtc, +				struct drm_modeset_acquire_ctx *ctx) +{ +	struct drm_device *dev = crtc->base.dev; +	struct drm_i915_private *dev_priv = to_i915(dev); +	struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); + +	if (crtc_state->hw.active) {  		struct intel_plane *plane; +		/* Clear any frame start delays used for debugging left by the BIOS */ +		intel_sanitize_frame_start_delay(crtc_state); +  		/* Disable everything but the primary plane */  		for_each_intel_plane_on_crtc(dev, crtc, plane) {  			const struct intel_plane_state *plane_state =  				to_intel_plane_state(plane->base.state); -			if (plane_state->base.visible && +			if (plane_state->uapi.visible &&  			    plane->base.type != DRM_PLANE_TYPE_PRIMARY)  				intel_plane_disable_noatomic(crtc, plane);  		} @@ -17114,10 +17859,10 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,  	/* Adjust the state of the output pipe according to whether we  	 * have active connectors/encoders. */ -	if (crtc_state->base.active && !intel_crtc_has_encoders(crtc)) -		intel_crtc_disable_noatomic(&crtc->base, ctx); +	if (crtc_state->hw.active && !intel_crtc_has_encoders(crtc)) +		intel_crtc_disable_noatomic(crtc, ctx); -	if (crtc_state->base.active || HAS_GMCH(dev_priv)) { +	if (crtc_state->hw.active || HAS_GMCH(dev_priv)) {  		/*  		 * We start out with underrun reporting disabled to avoid races.  		 * For correct bookkeeping mark this on active crtcs. @@ -17148,7 +17893,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,  static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)  { -	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); +	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);  	/*  	 * Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram @@ -17161,7 +17906,7 @@ static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)  	 * road.  	 */  	return IS_GEN(dev_priv, 6) && -		crtc_state->base.active && +		crtc_state->hw.active &&  		crtc_state->shared_dpll &&  		crtc_state->port_clock == 0;  } @@ -17178,7 +17923,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)  	 * encoder is active and trying to read from a pipe) and the  	 * pipe itself being active. */  	bool has_active_crtc = crtc_state && -		crtc_state->base.active; +		crtc_state->hw.active;  	if (crtc_state && has_bogus_dpll_config(crtc_state)) {  		DRM_DEBUG_KMS("BIOS has misprogrammed the hardware. Disabling pipe %c\n", @@ -17282,22 +18027,22 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)  		struct intel_crtc_state *crtc_state =  			to_intel_crtc_state(crtc->base.state); -		__drm_atomic_helper_crtc_destroy_state(&crtc_state->base); -		memset(crtc_state, 0, sizeof(*crtc_state)); -		__drm_atomic_helper_crtc_reset(&crtc->base, &crtc_state->base); +		__drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi); +		intel_crtc_free_hw_state(crtc_state); +		intel_crtc_state_reset(crtc_state, crtc); -		crtc_state->base.active = crtc_state->base.enable = +		crtc_state->hw.active = crtc_state->hw.enable =  			dev_priv->display.get_pipe_config(crtc, crtc_state); -		crtc->base.enabled = crtc_state->base.enable; -		crtc->active = crtc_state->base.active; +		crtc->base.enabled = crtc_state->hw.enable; +		crtc->active = crtc_state->hw.active; -		if (crtc_state->base.active) +		if (crtc_state->hw.active)  			dev_priv->active_pipes |= BIT(crtc->pipe);  		DRM_DEBUG_KMS("[CRTC:%d:%s] hw state readout: %s\n",  			      crtc->base.base.id, crtc->base.name, -			      enableddisabled(crtc_state->base.active)); +			      enableddisabled(crtc_state->hw.active));  	}  	readout_plane_state(dev_priv); @@ -17319,7 +18064,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)  			struct intel_crtc_state *crtc_state =  				to_intel_crtc_state(crtc->base.state); -			if (crtc_state->base.active && +			if (crtc_state->hw.active &&  			    crtc_state->shared_dpll == pll)  				pll->state.crtc_mask |= 1 << crtc->pipe;  		} @@ -17364,15 +18109,15 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)  			crtc = to_intel_crtc(encoder->base.crtc);  			crtc_state = crtc ? to_intel_crtc_state(crtc->base.state) : NULL; -			if (crtc_state && crtc_state->base.active) { +			if (crtc_state && crtc_state->hw.active) {  				/*  				 * This has to be done during hardware readout  				 * because anything calling .crtc_disable may  				 * rely on the connector_mask being accurate.  				 */ -				crtc_state->base.connector_mask |= +				crtc_state->uapi.connector_mask |=  					drm_connector_mask(&connector->base); -				crtc_state->base.encoder_mask |= +				crtc_state->uapi.encoder_mask |=  					drm_encoder_mask(&encoder->base);  			}  		} else { @@ -17393,16 +18138,15 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)  		struct intel_plane *plane;  		int min_cdclk = 0; -		if (crtc_state->base.active) { -			struct drm_display_mode mode; +		if (crtc_state->hw.active) { +			struct drm_display_mode *mode = &crtc_state->hw.mode; -			intel_mode_from_pipe_config(&crtc_state->base.adjusted_mode, +			intel_mode_from_pipe_config(&crtc_state->hw.adjusted_mode,  						    crtc_state); -			mode = crtc_state->base.adjusted_mode; -			mode.hdisplay = crtc_state->pipe_src_w; -			mode.vdisplay = crtc_state->pipe_src_h; -			WARN_ON(drm_atomic_set_mode_for_crtc(&crtc_state->base, &mode)); +			*mode = crtc_state->hw.adjusted_mode; +			mode->hdisplay = crtc_state->pipe_src_w; +			mode->vdisplay = crtc_state->pipe_src_h;  			/*  			 * The initial mode needs to be set in order to keep @@ -17413,11 +18157,13 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)  			 * set a flag to indicate that a full recalculation is  			 * needed on the next commit.  			 */ -			crtc_state->base.mode.private_flags = I915_MODE_FLAG_INHERITED; +			mode->private_flags = I915_MODE_FLAG_INHERITED;  			intel_crtc_compute_pixel_rate(crtc_state);  			intel_crtc_update_active_timings(crtc_state); + +			intel_crtc_copy_hw_to_uapi_state(crtc_state);  		}  		for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) { @@ -17428,14 +18174,14 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)  			 * FIXME don't have the fb yet, so can't  			 * use intel_plane_data_rate() :(  			 */ -			if (plane_state->base.visible) +			if (plane_state->uapi.visible)  				crtc_state->data_rate[plane->id] =  					4 * crtc_state->pixel_rate;  			/*  			 * FIXME don't have the fb yet, so can't  			 * use plane->min_cdclk() :(  			 */ -			if (plane_state->base.visible && plane->min_cdclk) { +			if (plane_state->uapi.visible && plane->min_cdclk) {  				if (crtc_state->double_wide ||  				    INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))  					crtc_state->min_cdclk[plane->id] = @@ -17449,7 +18195,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)  				      crtc_state->min_cdclk[plane->id]);  		} -		if (crtc_state->base.active) { +		if (crtc_state->hw.active) {  			min_cdclk = intel_crtc_compute_min_cdclk(crtc_state);  			if (WARN_ON(min_cdclk < 0))  				min_cdclk = 0; @@ -17490,8 +18236,11 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv)  static void intel_early_display_was(struct drm_i915_private *dev_priv)  { -	/* Display WA #1185 WaDisableDARBFClkGating:cnl,glk */ -	if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv)) +	/* +	 * Display WA #1185 WaDisableDARBFClkGating:cnl,glk,icl,ehl,tgl +	 * Also known as Wa_14010480278. +	 */ +	if (IS_GEN_RANGE(dev_priv, 10, 12) || IS_GEMINILAKE(dev_priv))  		I915_WRITE(GEN9_CLKGATE_DIS_0, I915_READ(GEN9_CLKGATE_DIS_0) |  			   DARBF_GATING_DIS); @@ -17572,7 +18321,6 @@ intel_modeset_setup_hw_state(struct drm_device *dev,  			     struct drm_modeset_acquire_ctx *ctx)  {  	struct drm_i915_private *dev_priv = to_i915(dev); -	struct intel_crtc_state *crtc_state;  	struct intel_encoder *encoder;  	struct intel_crtc *crtc;  	intel_wakeref_t wakeref; @@ -17592,7 +18340,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev,  		/* We need to sanitize only the MST primary port. */  		if (encoder->type != INTEL_OUTPUT_DP_MST &&  		    intel_phy_is_tc(dev_priv, phy)) -			intel_tc_port_sanitize(enc_to_dig_port(&encoder->base)); +			intel_tc_port_sanitize(enc_to_dig_port(encoder));  	}  	get_encoder_power_domains(dev_priv); @@ -17605,11 +18353,12 @@ intel_modeset_setup_hw_state(struct drm_device *dev,  	 * waits, so we need vblank interrupts restored beforehand.  	 */  	for_each_intel_crtc(&dev_priv->drm, crtc) { -		crtc_state = to_intel_crtc_state(crtc->base.state); +		struct intel_crtc_state *crtc_state = +			to_intel_crtc_state(crtc->base.state);  		drm_crtc_vblank_reset(&crtc->base); -		if (crtc_state->base.active) +		if (crtc_state->hw.active)  			intel_crtc_vblank_on(crtc_state);  	} @@ -17619,7 +18368,9 @@ intel_modeset_setup_hw_state(struct drm_device *dev,  		intel_sanitize_encoder(encoder);  	for_each_intel_crtc(&dev_priv->drm, crtc) { -		crtc_state = to_intel_crtc_state(crtc->base.state); +		struct intel_crtc_state *crtc_state = +			to_intel_crtc_state(crtc->base.state); +  		intel_sanitize_crtc(crtc, ctx);  		intel_dump_pipe_config(crtc_state, NULL, "[setup_hw_state]");  	} @@ -17652,17 +18403,16 @@ intel_modeset_setup_hw_state(struct drm_device *dev,  	}  	for_each_intel_crtc(dev, crtc) { +		struct intel_crtc_state *crtc_state = +			to_intel_crtc_state(crtc->base.state);  		u64 put_domains; -		crtc_state = to_intel_crtc_state(crtc->base.state);  		put_domains = modeset_get_crtc_power_domains(crtc_state);  		if (WARN_ON(put_domains))  			modeset_put_power_domains(dev_priv, put_domains);  	}  	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref); - -	intel_fbc_init_pipe_state(dev_priv);  }  void intel_display_resume(struct drm_device *dev) @@ -17738,6 +18488,13 @@ void intel_modeset_driver_remove(struct drm_i915_private *i915)  	 */  	intel_hpd_poll_fini(i915); +	/* +	 * MST topology needs to be suspended so we don't have any calls to +	 * fbdev after it's finalized. MST will be destroyed later as part of +	 * drm_mode_config_cleanup() +	 */ +	intel_dp_mst_suspend(i915); +  	/* poll work can call into fbdev, hence clean that up afterwards */  	intel_fbdev_fini(i915); @@ -17756,6 +18513,8 @@ void intel_modeset_driver_remove(struct drm_i915_private *i915)  	intel_gmbus_teardown(i915); +	intel_bw_cleanup(i915); +  	destroy_workqueue(i915->flip_wq);  	destroy_workqueue(i915->modeset_wq);  |