[35/42] drm/i915: get rid of crtc->config in intel_display.c, part 2
diff mbox

Message ID 1431354318-11995-36-git-send-email-maarten.lankhorst@linux.intel.com
State New
Headers show

Commit Message

Maarten Lankhorst May 11, 2015, 2:25 p.m. UTC
Convert the rest of the file, but remove crtc->config in a separate
commit to hopefully allow easier bisecting.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 351 ++++++++++++++++++-----------------
 drivers/gpu/drm/i915/intel_dp.c      |   4 +-
 drivers/gpu/drm/i915/intel_drv.h     |   4 +-
 3 files changed, 186 insertions(+), 173 deletions(-)

Comments

Daniel Vetter May 12, 2015, 10:17 a.m. UTC | #1
On Mon, May 11, 2015 at 04:25:11PM +0200, Maarten Lankhorst wrote:
> Convert the rest of the file, but remove crtc->config in a separate
> commit to hopefully allow easier bisecting.
> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 351 ++++++++++++++++++-----------------
>  drivers/gpu/drm/i915/intel_dp.c      |   4 +-
>  drivers/gpu/drm/i915/intel_drv.h     |   4 +-
>  3 files changed, 186 insertions(+), 173 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index fb2ecb65aaaa..2c467cda74a4 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -88,14 +88,20 @@ static int intel_framebuffer_init(struct drm_device *dev,
>  				  struct intel_framebuffer *ifb,
>  				  struct drm_mode_fb_cmd2 *mode_cmd,
>  				  struct drm_i915_gem_object *obj);
> -static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc);
> -static void intel_set_pipe_timings(struct intel_crtc *intel_crtc);
> +static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc,
> +			      struct intel_crtc_state *pipe_config);
> +static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
> +				   struct intel_crtc_state *pipe_config);
>  static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
> +					 struct intel_crtc_state *pipe_config,
>  					 struct intel_link_m_n *m_n,
>  					 struct intel_link_m_n *m2_n2);
> -static void ironlake_set_pipeconf(struct drm_crtc *crtc);
> -static void haswell_set_pipeconf(struct drm_crtc *crtc);
> -static void intel_set_pipe_csc(struct drm_crtc *crtc);
> +static void ironlake_set_pipeconf(struct drm_crtc *crtc,
> +				  struct intel_crtc_state *pipe_config);
> +static void haswell_set_pipeconf(struct drm_crtc *crtc,
> +				 struct intel_crtc_state *pipe_config);
> +static void intel_set_pipe_csc(struct drm_crtc *crtc,
> +			       struct intel_crtc_state *pipe_config);
>  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,
> @@ -3021,7 +3027,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  	unsigned int rotation;
>  	int x_offset, y_offset;
>  	unsigned long surf_addr;
> -	struct intel_crtc_state *crtc_state = intel_crtc->config;
> +	struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->state);
>  	struct intel_plane_state *plane_state;
>  	int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
>  	int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
> @@ -3052,27 +3058,17 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  					       fb->pixel_format);
>  	surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj);
>  
> -	/*
> -	 * FIXME: intel_plane_state->src, dst aren't set when transitional
> -	 * update_plane helpers are called from legacy paths.
> -	 * Once full atomic crtc is available, below check can be avoided.
> -	 */
> -	if (drm_rect_width(&plane_state->src)) {
> -		scaler_id = plane_state->scaler_id;
> -		src_x = plane_state->src.x1 >> 16;
> -		src_y = plane_state->src.y1 >> 16;
> -		src_w = drm_rect_width(&plane_state->src) >> 16;
> -		src_h = drm_rect_height(&plane_state->src) >> 16;
> -		dst_x = plane_state->dst.x1;
> -		dst_y = plane_state->dst.y1;
> -		dst_w = drm_rect_width(&plane_state->dst);
> -		dst_h = drm_rect_height(&plane_state->dst);
> +	scaler_id = plane_state->scaler_id;
> +	src_x = plane_state->src.x1 >> 16;
> +	src_y = plane_state->src.y1 >> 16;
> +	src_w = drm_rect_width(&plane_state->src) >> 16;
> +	src_h = drm_rect_height(&plane_state->src) >> 16;
> +	dst_x = plane_state->dst.x1;
> +	dst_y = plane_state->dst.y1;
> +	dst_w = drm_rect_width(&plane_state->dst);
> +	dst_h = drm_rect_height(&plane_state->dst);
>  
> -		WARN_ON(x != src_x || y != src_y);
> -	} else {
> -		src_w = intel_crtc->config->pipe_src_w;
> -		src_h = intel_crtc->config->pipe_src_h;
> -	}
> +	WARN_ON(x != src_x || y != src_y);

This needs to be a separate commit with some justification for why we now
always have an updated rect ...

>  
>  	if (intel_rotation_90_or_270(rotation)) {
>  		/* stride = Surface height in tiles */
> @@ -4489,27 +4485,29 @@ skl_update_scaler_users(
>  	return 0;
>  }
>  
> -static void skylake_pfit_update(struct intel_crtc *crtc, int enable)
> +static void skylake_pfit_update(struct intel_crtc *crtc,

Random bikeshed while reading code: For consistency this should be called
skylake_pfit_enable.

> +				struct intel_crtc_state *pipe_config,
> +				int enable)
>  {
>  	struct drm_device *dev = crtc->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int pipe = crtc->pipe;
>  	struct intel_crtc_scaler_state *scaler_state =
> -		&crtc->config->scaler_state;
> +		&pipe_config->scaler_state;
>  
> -	DRM_DEBUG_KMS("for crtc_state = %p\n", crtc->config);
> +	DRM_DEBUG_KMS("for crtc_state = %p\n", pipe_config);
>  
>  	/* To update pfit, first update scaler state */
> -	skl_update_scaler_users(crtc, crtc->config, NULL, NULL, !enable);
> -	intel_atomic_setup_scalers(crtc->base.dev, crtc, crtc->config);
> +	skl_update_scaler_users(crtc, pipe_config, NULL, NULL, !enable);
> +	intel_atomic_setup_scalers(crtc->base.dev, crtc, pipe_config);
>  	skl_detach_scalers(crtc);
>  	if (!enable)
>  		return;
>  
> -	if (crtc->config->pch_pfit.enabled) {
> +	if (pipe_config->pch_pfit.enabled) {
>  		int id;
>  
> -		if (WARN_ON(crtc->config->scaler_state.scaler_id < 0)) {
> +		if (WARN_ON(pipe_config->scaler_state.scaler_id < 0)) {
>  			DRM_ERROR("Requesting pfit without getting a scaler first\n");
>  			return;
>  		}
> @@ -4517,20 +4515,21 @@ static void skylake_pfit_update(struct intel_crtc *crtc, int enable)
>  		id = scaler_state->scaler_id;
>  		I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
>  			PS_FILTER_MEDIUM | scaler_state->scalers[id].mode);
> -		I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos);
> -		I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size);
> +		I915_WRITE(SKL_PS_WIN_POS(pipe, id), pipe_config->pch_pfit.pos);
> +		I915_WRITE(SKL_PS_WIN_SZ(pipe, id), pipe_config->pch_pfit.size);
>  
> -		DRM_DEBUG_KMS("for crtc_state = %p scaler_id = %d\n", crtc->config, id);
> +		DRM_DEBUG_KMS("for crtc_state = %p scaler_id = %d\n", pipe_config, id);
>  	}
>  }
>  
> -static void ironlake_pfit_enable(struct intel_crtc *crtc)
> +static void ironlake_pfit_enable(struct intel_crtc *crtc,
> +				 struct intel_crtc_state *pipe_config)
>  {
>  	struct drm_device *dev = crtc->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int pipe = crtc->pipe;
>  
> -	if (crtc->config->pch_pfit.enabled) {
> +	if (pipe_config->pch_pfit.enabled) {
>  		/* Force use of hard-coded filter coefficients
>  		 * as some pre-programmed values are broken,
>  		 * e.g. x201.
> @@ -4540,8 +4539,8 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc)
>  						 PF_PIPE_SEL_IVB(pipe));
>  		else
>  			I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3);
> -		I915_WRITE(PF_WIN_POS(pipe), crtc->config->pch_pfit.pos);
> -		I915_WRITE(PF_WIN_SZ(pipe), crtc->config->pch_pfit.size);
> +		I915_WRITE(PF_WIN_POS(pipe), pipe_config->pch_pfit.pos);
> +		I915_WRITE(PF_WIN_SZ(pipe), pipe_config->pch_pfit.size);
>  	}
>  }
>  
> @@ -4550,7 +4549,7 @@ void hsw_enable_ips(struct intel_crtc *crtc)
>  	struct drm_device *dev = crtc->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  
> -	if (!crtc->config->ips_enabled)
> +	if (!to_intel_crtc_state(crtc->base.state)->ips_enabled)
>  		return;
>  
>  	/* We can only enable IPS after we enable a plane and wait for a vblank */
> @@ -4583,7 +4582,7 @@ void hsw_disable_ips(struct intel_crtc *crtc)
>  	struct drm_device *dev = crtc->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  
> -	if (!crtc->config->ips_enabled)
> +	if (!to_intel_crtc_state(crtc->base.state)->ips_enabled)
>  		return;
>  
>  	assert_plane_enabled(dev_priv, crtc->plane);
> @@ -4632,7 +4631,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
>  	/* Workaround : Do not read or write the pipe palette/gamma data while
>  	 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
>  	 */
> -	if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled &&
> +	if (IS_HASWELL(dev) && to_intel_crtc_state(crtc->state)->ips_enabled &&
>  	    ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
>  	     GAMMA_MODE_MODE_SPLIT)) {
>  		hsw_disable_ips(intel_crtc);
> @@ -4783,16 +4782,16 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  					  pipe_config->shared_dpll);
>  
>  	if (pipe_config->has_dp_encoder)
> -		intel_dp_set_m_n(intel_crtc, M1_N1);
> +		intel_dp_set_m_n(intel_crtc, pipe_config, M1_N1);
>  
> -	intel_set_pipe_timings(intel_crtc);
> +	intel_set_pipe_timings(intel_crtc, pipe_config);
>  
>  	if (pipe_config->has_pch_encoder) {
> -		intel_cpu_transcoder_set_m_n(intel_crtc,
> +		intel_cpu_transcoder_set_m_n(intel_crtc, pipe_config,
>  				     &pipe_config->fdi_m_n, NULL);
>  	}
>  
> -	ironlake_set_pipeconf(crtc);
> +	ironlake_set_pipeconf(crtc, pipe_config);
>  
>  	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
>  	intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
> @@ -4811,7 +4810,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  		assert_fdi_rx_disabled(dev_priv, pipe);
>  	}
>  
> -	ironlake_pfit_enable(intel_crtc);
> +	ironlake_pfit_enable(intel_crtc, pipe_config);
>  
>  	/*
>  	 * On ILK+ LUT must be loaded before the pipe is running but with
> @@ -4822,7 +4821,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  	intel_update_watermarks(crtc);
>  	intel_enable_pipe(intel_crtc);
>  
> -	if (intel_crtc->config->has_pch_encoder)
> +	if (pipe_config->has_pch_encoder)
>  		ironlake_pch_enable(crtc, pipe_config);
>  
>  	assert_vblank_disabled(crtc);
> @@ -4857,9 +4856,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>  		intel_enable_shared_dpll(dev_priv, pipe_config->shared_dpll);
>  
>  	if (pipe_config->has_dp_encoder)
> -		intel_dp_set_m_n(intel_crtc, M1_N1);
> +		intel_dp_set_m_n(intel_crtc, pipe_config, M1_N1);
>  
> -	intel_set_pipe_timings(intel_crtc);
> +	intel_set_pipe_timings(intel_crtc, pipe_config);
>  
>  	if (pipe_config->cpu_transcoder != TRANSCODER_EDP) {
>  		I915_WRITE(PIPE_MULT(pipe_config->cpu_transcoder),
> @@ -4867,13 +4866,13 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>  	}
>  
>  	if (pipe_config->has_pch_encoder) {
> -		intel_cpu_transcoder_set_m_n(intel_crtc,
> +		intel_cpu_transcoder_set_m_n(intel_crtc, pipe_config,
>  				     &pipe_config->fdi_m_n, NULL);
>  	}
>  
> -	haswell_set_pipeconf(crtc);
> +	haswell_set_pipeconf(crtc, pipe_config);
>  
> -	intel_set_pipe_csc(crtc);
> +	intel_set_pipe_csc(crtc, pipe_config);
>  
>  	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
>  	for_each_encoder_on_crtc(dev, crtc, encoder)
> @@ -4890,9 +4889,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>  	intel_ddi_enable_pipe_clock(intel_crtc);
>  
>  	if (INTEL_INFO(dev)->gen == 9)
> -		skylake_pfit_update(intel_crtc, 1);
> +		skylake_pfit_update(intel_crtc, pipe_config, 1);
>  	else if (INTEL_INFO(dev)->gen < 9)
> -		ironlake_pfit_enable(intel_crtc);
> +		ironlake_pfit_enable(intel_crtc, pipe_config);
>  	else
>  		MISSING_CASE(INTEL_INFO(dev)->gen);
>  
> @@ -4908,10 +4907,10 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>  	intel_update_watermarks(crtc);
>  	intel_enable_pipe(intel_crtc);
>  
> -	if (intel_crtc->config->has_pch_encoder)
> +	if (pipe_config->has_pch_encoder)
>  		lpt_pch_enable(dev_priv, pipe_config);
>  
> -	if (intel_crtc->config->dp_encoder_is_mst)
> +	if (pipe_config->dp_encoder_is_mst)
>  		intel_ddi_set_vc_payload_alloc(crtc,
>  					       pipe_config->cpu_transcoder,
>  					       true);
> @@ -4932,7 +4931,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>  	}
>  }
>  
> -static void ironlake_pfit_disable(struct intel_crtc *crtc)
> +static void ironlake_pfit_disable(struct intel_crtc *crtc,
> +				  struct intel_crtc_state *pipe_config)
>  {
>  	struct drm_device *dev = crtc->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -4940,7 +4940,7 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc)
>  
>  	/* To avoid upsetting the power well on haswell only disable the pfit if
>  	 * it's in use. The hw state code will make sure we get this right. */
> -	if (crtc->config->pch_pfit.enabled) {
> +	if (pipe_config->pch_pfit.enabled) {
>  		I915_WRITE(PF_CTL(pipe), 0);
>  		I915_WRITE(PF_WIN_POS(pipe), 0);
>  		I915_WRITE(PF_WIN_SZ(pipe), 0);
> @@ -4968,7 +4968,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc,
>  
>  	intel_disable_pipe(intel_crtc, old_state);
>  
> -	ironlake_pfit_disable(intel_crtc);
> +	ironlake_pfit_disable(intel_crtc, old_state);
>  
>  	for_each_encoder_on_crtc(dev, crtc, encoder)
>  		if (encoder->post_disable)
> @@ -5005,7 +5005,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc,
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>  	struct intel_encoder *encoder;
> -	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
> +	enum transcoder cpu_transcoder = old_state->cpu_transcoder;
>  
>  	for_each_encoder_on_crtc(dev, crtc, encoder) {
>  		intel_opregion_notify_encoder(encoder, false);
> @@ -5015,12 +5015,12 @@ static void haswell_crtc_disable(struct drm_crtc *crtc,
>  	drm_crtc_vblank_off(crtc);
>  	assert_vblank_disabled(crtc);
>  
> -	if (intel_crtc->config->has_pch_encoder)
> +	if (old_state->has_pch_encoder)
>  		intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
>  						      false);
>  	intel_disable_pipe(intel_crtc, old_state);
>  
> -	if (intel_crtc->config->dp_encoder_is_mst)
> +	if (old_state->dp_encoder_is_mst)
>  		intel_ddi_set_vc_payload_alloc(crtc,
>  					       old_state->cpu_transcoder,
>  					       false);
> @@ -5028,15 +5028,15 @@ static void haswell_crtc_disable(struct drm_crtc *crtc,
>  	intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
>  
>  	if (INTEL_INFO(dev)->gen == 9)
> -		skylake_pfit_update(intel_crtc, 0);
> +		skylake_pfit_update(intel_crtc, old_state, 0);
>  	else if (INTEL_INFO(dev)->gen < 9)
> -		ironlake_pfit_disable(intel_crtc);
> +		ironlake_pfit_disable(intel_crtc, old_state);
>  	else
>  		MISSING_CASE(INTEL_INFO(dev)->gen);
>  
>  	intel_ddi_disable_pipe_clock(intel_crtc, old_state->cpu_transcoder);
>  
> -	if (intel_crtc->config->has_pch_encoder) {
> +	if (old_state->has_pch_encoder) {
>  		lpt_disable_pch_transcoder(dev_priv);
>  		intel_ddi_fdi_disable(crtc, old_state);
>  	}
> @@ -5126,13 +5126,15 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
>  	enum pipe pipe = intel_crtc->pipe;
>  	unsigned long mask;
>  	enum transcoder transcoder;
> +	struct intel_crtc_state *pipe_config =
> +		to_intel_crtc_state(crtc->state);
>  
> -	transcoder = to_intel_crtc_state(crtc->state)->cpu_transcoder;
> +	transcoder = pipe_config->cpu_transcoder;
>  
>  	mask = BIT(POWER_DOMAIN_PIPE(pipe));
>  	mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
> -	if (intel_crtc->config->pch_pfit.enabled ||
> -	    intel_crtc->config->pch_pfit.force_thru)
> +	if (pipe_config->pch_pfit.enabled ||
> +	    pipe_config->pch_pfit.force_thru)
>  		mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
>  
>  	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
> @@ -5595,7 +5597,8 @@ static int intel_mode_max_pixclk(struct drm_device *dev,
>  			crtc_state =
>  				intel_atomic_get_crtc_state(state, intel_crtc);
>  		else
> -			crtc_state = intel_crtc->config;
> +			crtc_state = to_intel_crtc_state(intel_crtc->base.state);
> +
>  		if (IS_ERR(crtc_state))
>  			return PTR_ERR(crtc_state);
>  
> @@ -5743,9 +5746,9 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
>  	}
>  
>  	if (pipe_config->has_dp_encoder)
> -		intel_dp_set_m_n(intel_crtc, M1_N1);
> +		intel_dp_set_m_n(intel_crtc, pipe_config, M1_N1);
>  
> -	intel_set_pipe_timings(intel_crtc);
> +	intel_set_pipe_timings(intel_crtc, pipe_config);
>  
>  	if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) {
>  		struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -5754,7 +5757,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
>  		I915_WRITE(CHV_CANVAS(pipe), 0);
>  	}
>  
> -	i9xx_set_pipeconf(intel_crtc);
> +	i9xx_set_pipeconf(intel_crtc, pipe_config);
>  
>  	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
>  
> @@ -5787,15 +5790,6 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
>  		encoder->enable(encoder);
>  }
>  
> -static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
> -{
> -	struct drm_device *dev = crtc->base.dev;
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -
> -	I915_WRITE(FP0(crtc->pipe), crtc->config->dpll_hw_state.fp0);
> -	I915_WRITE(FP1(crtc->pipe), crtc->config->dpll_hw_state.fp1);
> -}
> -
>  static void i9xx_crtc_enable(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
> @@ -5808,14 +5802,15 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
>  	pipe_config = to_intel_crtc_state(crtc->state);
>  	WARN_ON(!pipe_config->base.active);
>  
> -	i9xx_set_pll_dividers(intel_crtc);
> +	I915_WRITE(FP0(pipe), pipe_config->dpll_hw_state.fp0);
> +	I915_WRITE(FP1(pipe), pipe_config->dpll_hw_state.fp1);
>  
> -	if (intel_crtc->config->has_dp_encoder)
> -		intel_dp_set_m_n(intel_crtc, M1_N1);
> +	if (pipe_config->has_dp_encoder)
> +		intel_dp_set_m_n(intel_crtc, pipe_config, M1_N1);
>  
> -	intel_set_pipe_timings(intel_crtc);
> +	intel_set_pipe_timings(intel_crtc, pipe_config);
>  
> -	i9xx_set_pipeconf(intel_crtc);
> +	i9xx_set_pipeconf(intel_crtc, pipe_config);
>  
>  	if (!IS_GEN2(dev))
>  		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
> @@ -5840,14 +5835,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
>  		encoder->enable(encoder);
>  }
>  
> -static void i9xx_pfit_disable(struct intel_crtc *crtc)
> +static void i9xx_pfit_disable(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = crtc->base.dev;
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -
> -	if (!crtc->config->gmch_pfit.control)
> -		return;
> -
>  	DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n",
>  			 I915_READ(PFIT_CONTROL));
>  	I915_WRITE(PFIT_CONTROL, 0);
> @@ -5878,7 +5867,8 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc,
>  
>  	intel_disable_pipe(intel_crtc, old_state);
>  
> -	i9xx_pfit_disable(intel_crtc);
> +	if (old_state->gmch_pfit.control)
> +		i9xx_pfit_disable(dev_priv);
>  
>  	for_each_encoder_on_crtc(dev, crtc, encoder)
>  		if (encoder->post_disable)
> @@ -6638,13 +6628,14 @@ static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
>  }
>  
>  static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
> +					 struct intel_crtc_state *pipe_config,
>  					 struct intel_link_m_n *m_n,
>  					 struct intel_link_m_n *m2_n2)
>  {
>  	struct drm_device *dev = crtc->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int pipe = crtc->pipe;
> -	enum transcoder transcoder = crtc->config->cpu_transcoder;
> +	enum transcoder transcoder = pipe_config->cpu_transcoder;
>  
>  	if (INTEL_INFO(dev)->gen >= 5) {
>  		I915_WRITE(PIPE_DATA_M1(transcoder), TU_SIZE(m_n->tu) | m_n->gmch_m);
> @@ -6656,7 +6647,7 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
>  		 * registers are not unnecessarily accessed).
>  		 */
>  		if (m2_n2 && (IS_CHERRYVIEW(dev) || INTEL_INFO(dev)->gen < 8) &&
> -			crtc->config->has_drrs) {
> +			pipe_config->has_drrs) {
>  			I915_WRITE(PIPE_DATA_M2(transcoder),
>  					TU_SIZE(m2_n2->tu) | m2_n2->gmch_m);
>  			I915_WRITE(PIPE_DATA_N2(transcoder), m2_n2->gmch_n);
> @@ -6671,29 +6662,31 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
>  	}
>  }
>  
> -void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n)
> +void intel_dp_set_m_n(struct intel_crtc *crtc,
> +		      struct intel_crtc_state *pipe_config,
> +		      enum link_m_n_set m_n)
>  {
>  	struct intel_link_m_n *dp_m_n, *dp_m2_n2 = NULL;
>  
>  	if (m_n == M1_N1) {
> -		dp_m_n = &crtc->config->dp_m_n;
> -		dp_m2_n2 = &crtc->config->dp_m2_n2;
> +		dp_m_n = &pipe_config->dp_m_n;
> +		dp_m2_n2 = &pipe_config->dp_m2_n2;
>  	} else if (m_n == M2_N2) {
>  
>  		/*
>  		 * M2_N2 registers are not supported. Hence m2_n2 divider value
>  		 * needs to be programmed into M1_N1.
>  		 */
> -		dp_m_n = &crtc->config->dp_m2_n2;
> +		dp_m_n = &pipe_config->dp_m2_n2;
>  	} else {
>  		DRM_ERROR("Unsupported divider value\n");
>  		return;
>  	}
>  
> -	if (crtc->config->has_pch_encoder)
> -		intel_pch_transcoder_set_m_n(crtc, &crtc->config->dp_m_n);
> +	if (pipe_config->has_pch_encoder)
> +		intel_pch_transcoder_set_m_n(crtc, &pipe_config->dp_m_n);
>  	else
> -		intel_cpu_transcoder_set_m_n(crtc, dp_m_n, dp_m2_n2);
> +		intel_cpu_transcoder_set_m_n(crtc, pipe_config, dp_m_n, dp_m2_n2);
>  }
>  
>  static void vlv_update_pll(struct intel_crtc *crtc,
> @@ -6976,9 +6969,6 @@ void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe)
>  	struct drm_crtc *crtc = intel_get_crtc_for_pipe(dev, pipe);
>  	struct intel_crtc_state *state = to_intel_crtc_state(crtc->state);
>  
> -	/* Is state->cpu_transcoder correct to use? */
> -	WARN_ON(crtc->state != &to_intel_crtc(crtc)->config->base);
> -
>  	/* Make sure the pipe isn't still relying on us */
>  	assert_pipe_disabled(dev_priv, state->cpu_transcoder, pipe);
>  
> @@ -7103,14 +7093,15 @@ static void i8xx_update_pll(struct intel_crtc *crtc,
>  	crtc_state->dpll_hw_state.dpll = dpll;
>  }
>  
> -static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
> +static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
> +				   struct intel_crtc_state *pipe_config)
>  {
>  	struct drm_device *dev = intel_crtc->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	enum pipe pipe = intel_crtc->pipe;
> -	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
> +	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
>  	struct drm_display_mode *adjusted_mode =
> -		&intel_crtc->config->base.adjusted_mode;
> +		&pipe_config->base.adjusted_mode;
>  	uint32_t crtc_vtotal, crtc_vblank_end;
>  	int vsyncshift = 0;
>  
> @@ -7168,8 +7159,8 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
>  	 * always be the user's requested size.
>  	 */
>  	I915_WRITE(PIPESRC(pipe),
> -		   ((intel_crtc->config->pipe_src_w - 1) << 16) |
> -		   (intel_crtc->config->pipe_src_h - 1));
> +		   ((pipe_config->pipe_src_w - 1) << 16) |
> +		    (pipe_config->pipe_src_h - 1));
>  }
>  
>  static void intel_get_pipe_timings(struct intel_crtc *crtc,
> @@ -7233,7 +7224,8 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
>  	mode->flags |= pipe_config->base.adjusted_mode.flags;
>  }
>  
> -static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
> +static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc,
> +			      struct intel_crtc_state *pipe_config)
>  {
>  	struct drm_device *dev = intel_crtc->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -7245,17 +7237,17 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
>  	    (intel_crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
>  		pipeconf |= I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE;
>  
> -	if (intel_crtc->config->double_wide)
> +	if (pipe_config->double_wide)
>  		pipeconf |= PIPECONF_DOUBLE_WIDE;
>  
>  	/* only g4x and later have fancy bpc/dither controls */
>  	if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
>  		/* Bspec claims that we can't use dithering for 30bpp pipes. */
> -		if (intel_crtc->config->dither && intel_crtc->config->pipe_bpp != 30)
> +		if (pipe_config->dither && pipe_config->pipe_bpp != 30)
>  			pipeconf |= PIPECONF_DITHER_EN |
>  				    PIPECONF_DITHER_TYPE_SP;
>  
> -		switch (intel_crtc->config->pipe_bpp) {
> +		switch (pipe_config->pipe_bpp) {
>  		case 18:
>  			pipeconf |= PIPECONF_6BPC;
>  			break;
> @@ -7280,7 +7272,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
>  		}
>  	}
>  
> -	if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
> +	if (pipe_config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
>  		if (INTEL_INFO(dev)->gen < 4 ||
>  		    intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_SDVO))
>  			pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
> @@ -7289,7 +7281,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
>  	} else
>  		pipeconf |= PIPECONF_PROGRESSIVE;
>  
> -	if (IS_VALLEYVIEW(dev) && intel_crtc->config->limited_color_range)
> +	if (IS_VALLEYVIEW(dev) && pipe_config->limited_color_range)
>  		pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
>  
>  	I915_WRITE(PIPECONF(intel_crtc->pipe), pipeconf);
> @@ -8027,7 +8019,8 @@ static int ironlake_get_refclk(struct intel_crtc_state *crtc_state)
>  	return 120000;
>  }
>  
> -static void ironlake_set_pipeconf(struct drm_crtc *crtc)
> +static void ironlake_set_pipeconf(struct drm_crtc *crtc,
> +				  struct intel_crtc_state *pipe_config)
>  {
>  	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> @@ -8036,7 +8029,7 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc)
>  
>  	val = 0;
>  
> -	switch (intel_crtc->config->pipe_bpp) {
> +	switch (pipe_config->pipe_bpp) {
>  	case 18:
>  		val |= PIPECONF_6BPC;
>  		break;
> @@ -8054,15 +8047,15 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc)
>  		BUG();
>  	}
>  
> -	if (intel_crtc->config->dither)
> +	if (pipe_config->dither)
>  		val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
>  
> -	if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
> +	if (pipe_config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
>  		val |= PIPECONF_INTERLACED_ILK;
>  	else
>  		val |= PIPECONF_PROGRESSIVE;
>  
> -	if (intel_crtc->config->limited_color_range)
> +	if (pipe_config->limited_color_range)
>  		val |= PIPECONF_COLOR_RANGE_SELECT;
>  
>  	I915_WRITE(PIPECONF(pipe), val);
> @@ -8076,7 +8069,8 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc)
>   * is supported, but eventually this should handle various
>   * RGB<->YCbCr scenarios as well.
>   */
> -static void intel_set_pipe_csc(struct drm_crtc *crtc)
> +static void intel_set_pipe_csc(struct drm_crtc *crtc,
> +			       struct intel_crtc_state *pipe_config)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -8091,7 +8085,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc)
>  	 * consideration.
>  	 */
>  
> -	if (intel_crtc->config->limited_color_range)
> +	if (pipe_config->limited_color_range)
>  		coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */
>  
>  	/*
> @@ -8115,7 +8109,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc)
>  	if (INTEL_INFO(dev)->gen > 6) {
>  		uint16_t postoff = 0;
>  
> -		if (intel_crtc->config->limited_color_range)
> +		if (pipe_config->limited_color_range)
>  			postoff = (16 * (1 << 12) / 255) & 0x1fff;
>  
>  		I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
> @@ -8126,28 +8120,29 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc)
>  	} else {
>  		uint32_t mode = CSC_MODE_YUV_TO_RGB;
>  
> -		if (intel_crtc->config->limited_color_range)
> +		if (pipe_config->limited_color_range)
>  			mode |= CSC_BLACK_SCREEN_OFFSET;
>  
>  		I915_WRITE(PIPE_CSC_MODE(pipe), mode);
>  	}
>  }
>  
> -static void haswell_set_pipeconf(struct drm_crtc *crtc)
> +static void haswell_set_pipeconf(struct drm_crtc *crtc,
> +				 struct intel_crtc_state *pipe_config)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>  	enum pipe pipe = intel_crtc->pipe;
> -	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
> +	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
>  	uint32_t val;
>  
>  	val = 0;
>  
> -	if (IS_HASWELL(dev) && intel_crtc->config->dither)
> +	if (IS_HASWELL(dev) && pipe_config->dither)
>  		val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
>  
> -	if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
> +	if (pipe_config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
>  		val |= PIPECONF_INTERLACED_ILK;
>  	else
>  		val |= PIPECONF_PROGRESSIVE;
> @@ -8161,7 +8156,7 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc)
>  	if (IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) {
>  		val = 0;
>  
> -		switch (intel_crtc->config->pipe_bpp) {
> +		switch (pipe_config->pipe_bpp) {
>  		case 18:
>  			val |= PIPEMISC_DITHER_6_BPC;
>  			break;
> @@ -8179,7 +8174,7 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc)
>  			BUG();
>  		}
>  
> -		if (intel_crtc->config->dither)
> +		if (pipe_config->dither)
>  			val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
>  
>  		I915_WRITE(PIPEMISC(pipe), val);
> @@ -8423,12 +8418,13 @@ static void intel_pch_transcoder_get_m_n(struct intel_crtc *crtc,
>  }
>  
>  static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc,
> -					 enum transcoder transcoder,
> +					 struct intel_crtc_state *pipe_config,
>  					 struct intel_link_m_n *m_n,
>  					 struct intel_link_m_n *m2_n2)
>  {
>  	struct drm_device *dev = crtc->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> +	enum transcoder transcoder = pipe_config->cpu_transcoder;
>  	enum pipe pipe = crtc->pipe;
>  
>  	if (INTEL_INFO(dev)->gen >= 5) {
> @@ -8444,7 +8440,7 @@ static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc,
>  		 * registers are not unnecessarily read).
>  		 */
>  		if (m2_n2 && INTEL_INFO(dev)->gen < 8 &&
> -			crtc->config->has_drrs) {
> +			pipe_config->has_drrs) {
>  			m2_n2->link_m = I915_READ(PIPE_LINK_M2(transcoder));
>  			m2_n2->link_n =	I915_READ(PIPE_LINK_N2(transcoder));
>  			m2_n2->gmch_m =	I915_READ(PIPE_DATA_M2(transcoder))
> @@ -8470,7 +8466,7 @@ void intel_dp_get_m_n(struct intel_crtc *crtc,
>  	if (pipe_config->has_pch_encoder)
>  		intel_pch_transcoder_get_m_n(crtc, &pipe_config->dp_m_n);
>  	else
> -		intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder,
> +		intel_cpu_transcoder_get_m_n(crtc, pipe_config,
>  					     &pipe_config->dp_m_n,
>  					     &pipe_config->dp_m2_n2);
>  }
> @@ -8478,7 +8474,7 @@ void intel_dp_get_m_n(struct intel_crtc *crtc,
>  static void ironlake_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,
> +	intel_cpu_transcoder_get_m_n(crtc, pipe_config,
>  				     &pipe_config->fdi_m_n, NULL);
>  }
>  
> @@ -9331,6 +9327,8 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	struct intel_crtc_state *pipe_config =
> +		to_intel_crtc_state(crtc->state);
>  	int pipe = intel_crtc->pipe;
>  	int x = crtc->cursor_x;
>  	int y = crtc->cursor_y;
> @@ -9339,10 +9337,10 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
>  	if (on)
>  		base = intel_crtc->cursor_addr;
>  
> -	if (x >= intel_crtc->config->pipe_src_w)
> +	if (x >= pipe_config->pipe_src_w)
>  		base = 0;
>  
> -	if (y >= intel_crtc->config->pipe_src_h)
> +	if (y >= pipe_config->pipe_src_h)
>  		base = 0;

Just curiosity: Shouldn't our clamping and visibility computation catch
this already?

>  
>  	if (x < 0) {
> @@ -9966,9 +9964,11 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
> +	struct intel_crtc_state *pipe_config =
> +		to_intel_crtc_state(crtc->state);
> +	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
>  	struct drm_display_mode *mode;
> -	struct intel_crtc_state pipe_config;
> +	struct intel_crtc_state fake_config;
>  	int htot = I915_READ(HTOTAL(cpu_transcoder));
>  	int hsync = I915_READ(HSYNC(cpu_transcoder));
>  	int vtot = I915_READ(VTOTAL(cpu_transcoder));
> @@ -9986,14 +9986,14 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
>  	 * Note, if LVDS ever uses a non-1 pixel multiplier, we'll need
>  	 * to use a real value here instead.
>  	 */
> -	pipe_config.cpu_transcoder = (enum transcoder) pipe;
> -	pipe_config.pixel_multiplier = 1;
> -	pipe_config.dpll_hw_state.dpll = I915_READ(DPLL(pipe));
> -	pipe_config.dpll_hw_state.fp0 = I915_READ(FP0(pipe));
> -	pipe_config.dpll_hw_state.fp1 = I915_READ(FP1(pipe));
> -	i9xx_crtc_clock_get(intel_crtc, &pipe_config);
> -
> -	mode->clock = pipe_config.port_clock / pipe_config.pixel_multiplier;
> +	fake_config.cpu_transcoder = (enum transcoder) pipe;
> +	fake_config.pixel_multiplier = 1;
> +	fake_config.dpll_hw_state.dpll = I915_READ(DPLL(pipe));
> +	fake_config.dpll_hw_state.fp0 = I915_READ(FP0(pipe));
> +	fake_config.dpll_hw_state.fp1 = I915_READ(FP1(pipe));
> +	i9xx_crtc_clock_get(intel_crtc, &fake_config);
> +
> +	mode->clock = fake_config.port_clock / fake_config.pixel_multiplier;
>  	mode->hdisplay = (htot & 0xffff) + 1;
>  	mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
>  	mode->hsync_start = (hsync & 0xffff) + 1;

s/pipe_config/fake_config is nice but should be split out imo.

> @@ -11839,12 +11839,13 @@ check_crtc_state(struct drm_device *dev)
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *crtc;
>  	struct intel_encoder *encoder;
> -	struct intel_crtc_state pipe_config;
> +	struct intel_crtc_state pipe_config, *sw_config;
>  
>  	for_each_intel_crtc(dev, crtc) {
>  		bool enabled = false;
>  		bool active = false;
>  
> +		sw_config = to_intel_crtc_state(crtc->base.state);
>  		memset(&pipe_config, 0, sizeof(pipe_config));
>  
>  		DRM_DEBUG_KMS("[CRTC:%d]\n",
> @@ -11887,11 +11888,11 @@ check_crtc_state(struct drm_device *dev)
>  		     "(expected %i, found %i)\n", crtc->base.state->active, active);
>  
>  		if (active &&
> -		    !intel_pipe_config_compare(dev, crtc->config, &pipe_config)) {
> +		    !intel_pipe_config_compare(dev, sw_config, &pipe_config)) {
>  			I915_STATE_WARN(1, "pipe state doesn't match!\n");
>  			intel_dump_pipe_config(crtc, &pipe_config,
>  					       "[hw state]");
> -			intel_dump_pipe_config(crtc, crtc->config,
> +			intel_dump_pipe_config(crtc, sw_config,
>  					       "[sw state]");
>  		}
>  	}
> @@ -11990,7 +11991,8 @@ static void update_scanline_offset(struct intel_crtc *crtc)
>  	 * one to the value.
>  	 */
>  	if (IS_GEN2(dev)) {
> -		const struct drm_display_mode *mode = &crtc->config->base.adjusted_mode;
> +		const struct drm_display_mode *mode =
> +			&crtc->base.state->adjusted_mode;
>  		int vtotal;
>  
>  		vtotal = mode->crtc_vtotal;
> @@ -13532,6 +13534,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
>  	crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL);
>  	if (!crtc_state)
>  		goto fail;
> +
>  	intel_crtc->config = crtc_state;
>  	intel_crtc->base.state = &crtc_state->base;
>  	crtc_state->base.crtc = &intel_crtc->base;
> @@ -14574,19 +14577,20 @@ intel_check_plane_mapping(struct intel_crtc *crtc)
>  	return true;
>  }
>  
> -static void intel_sanitize_crtc(struct intel_crtc *crtc)
> +static void intel_sanitize_crtc(struct intel_crtc *crtc,
> +				struct intel_crtc_state *pipe_config)
>  {
>  	struct drm_device *dev = crtc->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	u32 reg;
>  
>  	/* Clear any frame start delays used for debugging left by the BIOS */
> -	reg = PIPECONF(crtc->config->cpu_transcoder);
> +	reg = PIPECONF(pipe_config->cpu_transcoder);
>  	I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
>  
>  	/* restore vblank interrupts to correct state */
>  	drm_crtc_vblank_reset(&crtc->base);
> -	if (crtc->base.state->active) {
> +	if (pipe_config->base.active) {
>  		update_scanline_offset(crtc);
>  		drm_crtc_vblank_on(&crtc->base);
>  	}
> @@ -14626,14 +14630,14 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
>  				connector->encoder->connectors_active = false;
>  			}
>  
> -		WARN_ON(crtc->base.state->active);
> -		crtc->base.state->enable = false;
> -		crtc->base.state->active = false;
> +		WARN_ON(pipe_config->base.active);
> +		pipe_config->base.enable = false;
> +		pipe_config->base.active = false;
>  		crtc->base.enabled = false;
>  	}
>  
>  	if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
> -	    crtc->pipe == PIPE_A && !crtc->base.state->active) {
> +	    crtc->pipe == PIPE_A && !pipe_config->base.active) {
>  		/* BIOS forgot to enable pipe A, this mostly happens after
>  		 * resume. Force-enable the pipe to fix this, the update_dpms
>  		 * call below we restore the pipe to the right state, but leave
> @@ -14645,7 +14649,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
>  	 * have active connectors/encoders. */
>  	intel_crtc_update_dpms(&crtc->base);
>  
> -	if (crtc->base.state->active || HAS_GMCH_DISPLAY(dev)) {
> +	if (pipe_config->base.active || HAS_GMCH_DISPLAY(dev)) {
>  		/*
>  		 * We start out with underrun reporting disabled to avoid races.
>  		 * For correct bookkeeping mark this on active crtcs.
> @@ -14763,17 +14767,19 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev,
>  	for_each_intel_crtc(dev, crtc) {
>  		struct drm_plane *primary = crtc->base.primary;
>  		struct intel_plane_state *plane_state;
> +		struct intel_crtc_state *pipe_config =
> +			to_intel_crtc_state(crtc->base.state);
>  
> -		memset(crtc->config, 0, sizeof(*crtc->config));
> +		memset(pipe_config, 0, sizeof(*pipe_config));
>  
> -		crtc->config->quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE;
> +		pipe_config->quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE;
>  
>  		if (crtc->base.state->active)
>  			*crtc_mask |= drm_crtc_index(&crtc->base);
>  
> -		crtc->base.enabled = crtc->base.state->enable =
> -		crtc->base.state->active =
> -			dev_priv->display.get_pipe_config(crtc, crtc->config);
> +		crtc->base.enabled = pipe_config->base.enable =
> +		pipe_config->base.active =
> +			dev_priv->display.get_pipe_config(crtc, pipe_config);
>  
>  		plane_state = to_intel_plane_state(primary->state);
>  		plane_state->hw_enabled = plane_state->visible =
> @@ -14818,7 +14824,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev,
>  		if (encoder->get_hw_state(encoder, &pipe)) {
>  			crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
>  			encoder->base.crtc = &crtc->base;
> -			encoder->get_config(encoder, crtc->config);
> +			encoder->get_config(encoder,
> +				to_intel_crtc_state(crtc->base.state));
>  		} else {
>  			encoder->base.crtc = NULL;
>  		}
> @@ -14883,9 +14890,13 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
>  	}
>  
>  	for_each_pipe(dev_priv, pipe) {
> +		struct intel_crtc_state *pipe_config;
> +
>  		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
> -		intel_sanitize_crtc(crtc);
> -		intel_dump_pipe_config(crtc, crtc->config,
> +		pipe_config = to_intel_crtc_state(crtc->base.state);
> +
> +		intel_sanitize_crtc(crtc, pipe_config);

Another example where there's imo no need to pass around pipe_config
explictly. As I said I didn't highlight all of them.

> +		intel_dump_pipe_config(crtc, pipe_config,
>  				       "[setup_hw_state]");
>  	}
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index e6876faca7f0..abf8082be40c 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -5309,10 +5309,10 @@ static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
>  	if (INTEL_INFO(dev)->gen >= 8 && !IS_CHERRYVIEW(dev)) {
>  		switch (index) {
>  		case DRRS_HIGH_RR:
> -			intel_dp_set_m_n(intel_crtc, M1_N1);
> +			intel_dp_set_m_n(intel_crtc, pipe_config, M1_N1);
>  			break;
>  		case DRRS_LOW_RR:
> -			intel_dp_set_m_n(intel_crtc, M2_N2);
> +			intel_dp_set_m_n(intel_crtc, pipe_config, M2_N2);

Should be part of the drrs patch.

>  			break;
>  		case DRRS_MAX_RR:
>  		default:
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 7979a2f6838c..6767ed91faaf 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1102,7 +1102,9 @@ void bxt_enable_dc9(struct drm_i915_private *dev_priv);
>  void bxt_disable_dc9(struct drm_i915_private *dev_priv);
>  void intel_dp_get_m_n(struct intel_crtc *crtc,
>  		      struct intel_crtc_state *pipe_config);
> -void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n);
> +void intel_dp_set_m_n(struct intel_crtc *crtc,
> +		      struct intel_crtc_state *pipe_config,
> +		      enum link_m_n_set m_n);

Misplace hunk ;-)
-Daniel

>  int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
>  void
>  ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config,
> -- 
> 2.1.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Patch
diff mbox

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fb2ecb65aaaa..2c467cda74a4 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -88,14 +88,20 @@  static int intel_framebuffer_init(struct drm_device *dev,
 				  struct intel_framebuffer *ifb,
 				  struct drm_mode_fb_cmd2 *mode_cmd,
 				  struct drm_i915_gem_object *obj);
-static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc);
-static void intel_set_pipe_timings(struct intel_crtc *intel_crtc);
+static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc,
+			      struct intel_crtc_state *pipe_config);
+static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
+				   struct intel_crtc_state *pipe_config);
 static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
+					 struct intel_crtc_state *pipe_config,
 					 struct intel_link_m_n *m_n,
 					 struct intel_link_m_n *m2_n2);
-static void ironlake_set_pipeconf(struct drm_crtc *crtc);
-static void haswell_set_pipeconf(struct drm_crtc *crtc);
-static void intel_set_pipe_csc(struct drm_crtc *crtc);
+static void ironlake_set_pipeconf(struct drm_crtc *crtc,
+				  struct intel_crtc_state *pipe_config);
+static void haswell_set_pipeconf(struct drm_crtc *crtc,
+				 struct intel_crtc_state *pipe_config);
+static void intel_set_pipe_csc(struct drm_crtc *crtc,
+			       struct intel_crtc_state *pipe_config);
 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,
@@ -3021,7 +3027,7 @@  static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	unsigned int rotation;
 	int x_offset, y_offset;
 	unsigned long surf_addr;
-	struct intel_crtc_state *crtc_state = intel_crtc->config;
+	struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->state);
 	struct intel_plane_state *plane_state;
 	int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
 	int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
@@ -3052,27 +3058,17 @@  static void skylake_update_primary_plane(struct drm_crtc *crtc,
 					       fb->pixel_format);
 	surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj);
 
-	/*
-	 * FIXME: intel_plane_state->src, dst aren't set when transitional
-	 * update_plane helpers are called from legacy paths.
-	 * Once full atomic crtc is available, below check can be avoided.
-	 */
-	if (drm_rect_width(&plane_state->src)) {
-		scaler_id = plane_state->scaler_id;
-		src_x = plane_state->src.x1 >> 16;
-		src_y = plane_state->src.y1 >> 16;
-		src_w = drm_rect_width(&plane_state->src) >> 16;
-		src_h = drm_rect_height(&plane_state->src) >> 16;
-		dst_x = plane_state->dst.x1;
-		dst_y = plane_state->dst.y1;
-		dst_w = drm_rect_width(&plane_state->dst);
-		dst_h = drm_rect_height(&plane_state->dst);
+	scaler_id = plane_state->scaler_id;
+	src_x = plane_state->src.x1 >> 16;
+	src_y = plane_state->src.y1 >> 16;
+	src_w = drm_rect_width(&plane_state->src) >> 16;
+	src_h = drm_rect_height(&plane_state->src) >> 16;
+	dst_x = plane_state->dst.x1;
+	dst_y = plane_state->dst.y1;
+	dst_w = drm_rect_width(&plane_state->dst);
+	dst_h = drm_rect_height(&plane_state->dst);
 
-		WARN_ON(x != src_x || y != src_y);
-	} else {
-		src_w = intel_crtc->config->pipe_src_w;
-		src_h = intel_crtc->config->pipe_src_h;
-	}
+	WARN_ON(x != src_x || y != src_y);
 
 	if (intel_rotation_90_or_270(rotation)) {
 		/* stride = Surface height in tiles */
@@ -4489,27 +4485,29 @@  skl_update_scaler_users(
 	return 0;
 }
 
-static void skylake_pfit_update(struct intel_crtc *crtc, int enable)
+static void skylake_pfit_update(struct intel_crtc *crtc,
+				struct intel_crtc_state *pipe_config,
+				int enable)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe = crtc->pipe;
 	struct intel_crtc_scaler_state *scaler_state =
-		&crtc->config->scaler_state;
+		&pipe_config->scaler_state;
 
-	DRM_DEBUG_KMS("for crtc_state = %p\n", crtc->config);
+	DRM_DEBUG_KMS("for crtc_state = %p\n", pipe_config);
 
 	/* To update pfit, first update scaler state */
-	skl_update_scaler_users(crtc, crtc->config, NULL, NULL, !enable);
-	intel_atomic_setup_scalers(crtc->base.dev, crtc, crtc->config);
+	skl_update_scaler_users(crtc, pipe_config, NULL, NULL, !enable);
+	intel_atomic_setup_scalers(crtc->base.dev, crtc, pipe_config);
 	skl_detach_scalers(crtc);
 	if (!enable)
 		return;
 
-	if (crtc->config->pch_pfit.enabled) {
+	if (pipe_config->pch_pfit.enabled) {
 		int id;
 
-		if (WARN_ON(crtc->config->scaler_state.scaler_id < 0)) {
+		if (WARN_ON(pipe_config->scaler_state.scaler_id < 0)) {
 			DRM_ERROR("Requesting pfit without getting a scaler first\n");
 			return;
 		}
@@ -4517,20 +4515,21 @@  static void skylake_pfit_update(struct intel_crtc *crtc, int enable)
 		id = scaler_state->scaler_id;
 		I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
 			PS_FILTER_MEDIUM | scaler_state->scalers[id].mode);
-		I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos);
-		I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size);
+		I915_WRITE(SKL_PS_WIN_POS(pipe, id), pipe_config->pch_pfit.pos);
+		I915_WRITE(SKL_PS_WIN_SZ(pipe, id), pipe_config->pch_pfit.size);
 
-		DRM_DEBUG_KMS("for crtc_state = %p scaler_id = %d\n", crtc->config, id);
+		DRM_DEBUG_KMS("for crtc_state = %p scaler_id = %d\n", pipe_config, id);
 	}
 }
 
-static void ironlake_pfit_enable(struct intel_crtc *crtc)
+static void ironlake_pfit_enable(struct intel_crtc *crtc,
+				 struct intel_crtc_state *pipe_config)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe = crtc->pipe;
 
-	if (crtc->config->pch_pfit.enabled) {
+	if (pipe_config->pch_pfit.enabled) {
 		/* Force use of hard-coded filter coefficients
 		 * as some pre-programmed values are broken,
 		 * e.g. x201.
@@ -4540,8 +4539,8 @@  static void ironlake_pfit_enable(struct intel_crtc *crtc)
 						 PF_PIPE_SEL_IVB(pipe));
 		else
 			I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3);
-		I915_WRITE(PF_WIN_POS(pipe), crtc->config->pch_pfit.pos);
-		I915_WRITE(PF_WIN_SZ(pipe), crtc->config->pch_pfit.size);
+		I915_WRITE(PF_WIN_POS(pipe), pipe_config->pch_pfit.pos);
+		I915_WRITE(PF_WIN_SZ(pipe), pipe_config->pch_pfit.size);
 	}
 }
 
@@ -4550,7 +4549,7 @@  void hsw_enable_ips(struct intel_crtc *crtc)
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (!crtc->config->ips_enabled)
+	if (!to_intel_crtc_state(crtc->base.state)->ips_enabled)
 		return;
 
 	/* We can only enable IPS after we enable a plane and wait for a vblank */
@@ -4583,7 +4582,7 @@  void hsw_disable_ips(struct intel_crtc *crtc)
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (!crtc->config->ips_enabled)
+	if (!to_intel_crtc_state(crtc->base.state)->ips_enabled)
 		return;
 
 	assert_plane_enabled(dev_priv, crtc->plane);
@@ -4632,7 +4631,7 @@  static void intel_crtc_load_lut(struct drm_crtc *crtc)
 	/* Workaround : Do not read or write the pipe palette/gamma data while
 	 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
 	 */
-	if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled &&
+	if (IS_HASWELL(dev) && to_intel_crtc_state(crtc->state)->ips_enabled &&
 	    ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
 	     GAMMA_MODE_MODE_SPLIT)) {
 		hsw_disable_ips(intel_crtc);
@@ -4783,16 +4782,16 @@  static void ironlake_crtc_enable(struct drm_crtc *crtc)
 					  pipe_config->shared_dpll);
 
 	if (pipe_config->has_dp_encoder)
-		intel_dp_set_m_n(intel_crtc, M1_N1);
+		intel_dp_set_m_n(intel_crtc, pipe_config, M1_N1);
 
-	intel_set_pipe_timings(intel_crtc);
+	intel_set_pipe_timings(intel_crtc, pipe_config);
 
 	if (pipe_config->has_pch_encoder) {
-		intel_cpu_transcoder_set_m_n(intel_crtc,
+		intel_cpu_transcoder_set_m_n(intel_crtc, pipe_config,
 				     &pipe_config->fdi_m_n, NULL);
 	}
 
-	ironlake_set_pipeconf(crtc);
+	ironlake_set_pipeconf(crtc, pipe_config);
 
 	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 	intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
@@ -4811,7 +4810,7 @@  static void ironlake_crtc_enable(struct drm_crtc *crtc)
 		assert_fdi_rx_disabled(dev_priv, pipe);
 	}
 
-	ironlake_pfit_enable(intel_crtc);
+	ironlake_pfit_enable(intel_crtc, pipe_config);
 
 	/*
 	 * On ILK+ LUT must be loaded before the pipe is running but with
@@ -4822,7 +4821,7 @@  static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	intel_update_watermarks(crtc);
 	intel_enable_pipe(intel_crtc);
 
-	if (intel_crtc->config->has_pch_encoder)
+	if (pipe_config->has_pch_encoder)
 		ironlake_pch_enable(crtc, pipe_config);
 
 	assert_vblank_disabled(crtc);
@@ -4857,9 +4856,9 @@  static void haswell_crtc_enable(struct drm_crtc *crtc)
 		intel_enable_shared_dpll(dev_priv, pipe_config->shared_dpll);
 
 	if (pipe_config->has_dp_encoder)
-		intel_dp_set_m_n(intel_crtc, M1_N1);
+		intel_dp_set_m_n(intel_crtc, pipe_config, M1_N1);
 
-	intel_set_pipe_timings(intel_crtc);
+	intel_set_pipe_timings(intel_crtc, pipe_config);
 
 	if (pipe_config->cpu_transcoder != TRANSCODER_EDP) {
 		I915_WRITE(PIPE_MULT(pipe_config->cpu_transcoder),
@@ -4867,13 +4866,13 @@  static void haswell_crtc_enable(struct drm_crtc *crtc)
 	}
 
 	if (pipe_config->has_pch_encoder) {
-		intel_cpu_transcoder_set_m_n(intel_crtc,
+		intel_cpu_transcoder_set_m_n(intel_crtc, pipe_config,
 				     &pipe_config->fdi_m_n, NULL);
 	}
 
-	haswell_set_pipeconf(crtc);
+	haswell_set_pipeconf(crtc, pipe_config);
 
-	intel_set_pipe_csc(crtc);
+	intel_set_pipe_csc(crtc, pipe_config);
 
 	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 	for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -4890,9 +4889,9 @@  static void haswell_crtc_enable(struct drm_crtc *crtc)
 	intel_ddi_enable_pipe_clock(intel_crtc);
 
 	if (INTEL_INFO(dev)->gen == 9)
-		skylake_pfit_update(intel_crtc, 1);
+		skylake_pfit_update(intel_crtc, pipe_config, 1);
 	else if (INTEL_INFO(dev)->gen < 9)
-		ironlake_pfit_enable(intel_crtc);
+		ironlake_pfit_enable(intel_crtc, pipe_config);
 	else
 		MISSING_CASE(INTEL_INFO(dev)->gen);
 
@@ -4908,10 +4907,10 @@  static void haswell_crtc_enable(struct drm_crtc *crtc)
 	intel_update_watermarks(crtc);
 	intel_enable_pipe(intel_crtc);
 
-	if (intel_crtc->config->has_pch_encoder)
+	if (pipe_config->has_pch_encoder)
 		lpt_pch_enable(dev_priv, pipe_config);
 
-	if (intel_crtc->config->dp_encoder_is_mst)
+	if (pipe_config->dp_encoder_is_mst)
 		intel_ddi_set_vc_payload_alloc(crtc,
 					       pipe_config->cpu_transcoder,
 					       true);
@@ -4932,7 +4931,8 @@  static void haswell_crtc_enable(struct drm_crtc *crtc)
 	}
 }
 
-static void ironlake_pfit_disable(struct intel_crtc *crtc)
+static void ironlake_pfit_disable(struct intel_crtc *crtc,
+				  struct intel_crtc_state *pipe_config)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4940,7 +4940,7 @@  static void ironlake_pfit_disable(struct intel_crtc *crtc)
 
 	/* To avoid upsetting the power well on haswell only disable the pfit if
 	 * it's in use. The hw state code will make sure we get this right. */
-	if (crtc->config->pch_pfit.enabled) {
+	if (pipe_config->pch_pfit.enabled) {
 		I915_WRITE(PF_CTL(pipe), 0);
 		I915_WRITE(PF_WIN_POS(pipe), 0);
 		I915_WRITE(PF_WIN_SZ(pipe), 0);
@@ -4968,7 +4968,7 @@  static void ironlake_crtc_disable(struct drm_crtc *crtc,
 
 	intel_disable_pipe(intel_crtc, old_state);
 
-	ironlake_pfit_disable(intel_crtc);
+	ironlake_pfit_disable(intel_crtc, old_state);
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->post_disable)
@@ -5005,7 +5005,7 @@  static void haswell_crtc_disable(struct drm_crtc *crtc,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *encoder;
-	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
+	enum transcoder cpu_transcoder = old_state->cpu_transcoder;
 
 	for_each_encoder_on_crtc(dev, crtc, encoder) {
 		intel_opregion_notify_encoder(encoder, false);
@@ -5015,12 +5015,12 @@  static void haswell_crtc_disable(struct drm_crtc *crtc,
 	drm_crtc_vblank_off(crtc);
 	assert_vblank_disabled(crtc);
 
-	if (intel_crtc->config->has_pch_encoder)
+	if (old_state->has_pch_encoder)
 		intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
 						      false);
 	intel_disable_pipe(intel_crtc, old_state);
 
-	if (intel_crtc->config->dp_encoder_is_mst)
+	if (old_state->dp_encoder_is_mst)
 		intel_ddi_set_vc_payload_alloc(crtc,
 					       old_state->cpu_transcoder,
 					       false);
@@ -5028,15 +5028,15 @@  static void haswell_crtc_disable(struct drm_crtc *crtc,
 	intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
 
 	if (INTEL_INFO(dev)->gen == 9)
-		skylake_pfit_update(intel_crtc, 0);
+		skylake_pfit_update(intel_crtc, old_state, 0);
 	else if (INTEL_INFO(dev)->gen < 9)
-		ironlake_pfit_disable(intel_crtc);
+		ironlake_pfit_disable(intel_crtc, old_state);
 	else
 		MISSING_CASE(INTEL_INFO(dev)->gen);
 
 	intel_ddi_disable_pipe_clock(intel_crtc, old_state->cpu_transcoder);
 
-	if (intel_crtc->config->has_pch_encoder) {
+	if (old_state->has_pch_encoder) {
 		lpt_disable_pch_transcoder(dev_priv);
 		intel_ddi_fdi_disable(crtc, old_state);
 	}
@@ -5126,13 +5126,15 @@  static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
 	enum pipe pipe = intel_crtc->pipe;
 	unsigned long mask;
 	enum transcoder transcoder;
+	struct intel_crtc_state *pipe_config =
+		to_intel_crtc_state(crtc->state);
 
-	transcoder = to_intel_crtc_state(crtc->state)->cpu_transcoder;
+	transcoder = pipe_config->cpu_transcoder;
 
 	mask = BIT(POWER_DOMAIN_PIPE(pipe));
 	mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
-	if (intel_crtc->config->pch_pfit.enabled ||
-	    intel_crtc->config->pch_pfit.force_thru)
+	if (pipe_config->pch_pfit.enabled ||
+	    pipe_config->pch_pfit.force_thru)
 		mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
 
 	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
@@ -5595,7 +5597,8 @@  static int intel_mode_max_pixclk(struct drm_device *dev,
 			crtc_state =
 				intel_atomic_get_crtc_state(state, intel_crtc);
 		else
-			crtc_state = intel_crtc->config;
+			crtc_state = to_intel_crtc_state(intel_crtc->base.state);
+
 		if (IS_ERR(crtc_state))
 			return PTR_ERR(crtc_state);
 
@@ -5743,9 +5746,9 @@  static void valleyview_crtc_enable(struct drm_crtc *crtc)
 	}
 
 	if (pipe_config->has_dp_encoder)
-		intel_dp_set_m_n(intel_crtc, M1_N1);
+		intel_dp_set_m_n(intel_crtc, pipe_config, M1_N1);
 
-	intel_set_pipe_timings(intel_crtc);
+	intel_set_pipe_timings(intel_crtc, pipe_config);
 
 	if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) {
 		struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5754,7 +5757,7 @@  static void valleyview_crtc_enable(struct drm_crtc *crtc)
 		I915_WRITE(CHV_CANVAS(pipe), 0);
 	}
 
-	i9xx_set_pipeconf(intel_crtc);
+	i9xx_set_pipeconf(intel_crtc, pipe_config);
 
 	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 
@@ -5787,15 +5790,6 @@  static void valleyview_crtc_enable(struct drm_crtc *crtc)
 		encoder->enable(encoder);
 }
 
-static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	I915_WRITE(FP0(crtc->pipe), crtc->config->dpll_hw_state.fp0);
-	I915_WRITE(FP1(crtc->pipe), crtc->config->dpll_hw_state.fp1);
-}
-
 static void i9xx_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -5808,14 +5802,15 @@  static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	pipe_config = to_intel_crtc_state(crtc->state);
 	WARN_ON(!pipe_config->base.active);
 
-	i9xx_set_pll_dividers(intel_crtc);
+	I915_WRITE(FP0(pipe), pipe_config->dpll_hw_state.fp0);
+	I915_WRITE(FP1(pipe), pipe_config->dpll_hw_state.fp1);
 
-	if (intel_crtc->config->has_dp_encoder)
-		intel_dp_set_m_n(intel_crtc, M1_N1);
+	if (pipe_config->has_dp_encoder)
+		intel_dp_set_m_n(intel_crtc, pipe_config, M1_N1);
 
-	intel_set_pipe_timings(intel_crtc);
+	intel_set_pipe_timings(intel_crtc, pipe_config);
 
-	i9xx_set_pipeconf(intel_crtc);
+	i9xx_set_pipeconf(intel_crtc, pipe_config);
 
 	if (!IS_GEN2(dev))
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
@@ -5840,14 +5835,8 @@  static void i9xx_crtc_enable(struct drm_crtc *crtc)
 		encoder->enable(encoder);
 }
 
-static void i9xx_pfit_disable(struct intel_crtc *crtc)
+static void i9xx_pfit_disable(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (!crtc->config->gmch_pfit.control)
-		return;
-
 	DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n",
 			 I915_READ(PFIT_CONTROL));
 	I915_WRITE(PFIT_CONTROL, 0);
@@ -5878,7 +5867,8 @@  static void i9xx_crtc_disable(struct drm_crtc *crtc,
 
 	intel_disable_pipe(intel_crtc, old_state);
 
-	i9xx_pfit_disable(intel_crtc);
+	if (old_state->gmch_pfit.control)
+		i9xx_pfit_disable(dev_priv);
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->post_disable)
@@ -6638,13 +6628,14 @@  static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
 }
 
 static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
+					 struct intel_crtc_state *pipe_config,
 					 struct intel_link_m_n *m_n,
 					 struct intel_link_m_n *m2_n2)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe = crtc->pipe;
-	enum transcoder transcoder = crtc->config->cpu_transcoder;
+	enum transcoder transcoder = pipe_config->cpu_transcoder;
 
 	if (INTEL_INFO(dev)->gen >= 5) {
 		I915_WRITE(PIPE_DATA_M1(transcoder), TU_SIZE(m_n->tu) | m_n->gmch_m);
@@ -6656,7 +6647,7 @@  static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
 		 * registers are not unnecessarily accessed).
 		 */
 		if (m2_n2 && (IS_CHERRYVIEW(dev) || INTEL_INFO(dev)->gen < 8) &&
-			crtc->config->has_drrs) {
+			pipe_config->has_drrs) {
 			I915_WRITE(PIPE_DATA_M2(transcoder),
 					TU_SIZE(m2_n2->tu) | m2_n2->gmch_m);
 			I915_WRITE(PIPE_DATA_N2(transcoder), m2_n2->gmch_n);
@@ -6671,29 +6662,31 @@  static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
 	}
 }
 
-void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n)
+void intel_dp_set_m_n(struct intel_crtc *crtc,
+		      struct intel_crtc_state *pipe_config,
+		      enum link_m_n_set m_n)
 {
 	struct intel_link_m_n *dp_m_n, *dp_m2_n2 = NULL;
 
 	if (m_n == M1_N1) {
-		dp_m_n = &crtc->config->dp_m_n;
-		dp_m2_n2 = &crtc->config->dp_m2_n2;
+		dp_m_n = &pipe_config->dp_m_n;
+		dp_m2_n2 = &pipe_config->dp_m2_n2;
 	} else if (m_n == M2_N2) {
 
 		/*
 		 * M2_N2 registers are not supported. Hence m2_n2 divider value
 		 * needs to be programmed into M1_N1.
 		 */
-		dp_m_n = &crtc->config->dp_m2_n2;
+		dp_m_n = &pipe_config->dp_m2_n2;
 	} else {
 		DRM_ERROR("Unsupported divider value\n");
 		return;
 	}
 
-	if (crtc->config->has_pch_encoder)
-		intel_pch_transcoder_set_m_n(crtc, &crtc->config->dp_m_n);
+	if (pipe_config->has_pch_encoder)
+		intel_pch_transcoder_set_m_n(crtc, &pipe_config->dp_m_n);
 	else
-		intel_cpu_transcoder_set_m_n(crtc, dp_m_n, dp_m2_n2);
+		intel_cpu_transcoder_set_m_n(crtc, pipe_config, dp_m_n, dp_m2_n2);
 }
 
 static void vlv_update_pll(struct intel_crtc *crtc,
@@ -6976,9 +6969,6 @@  void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe)
 	struct drm_crtc *crtc = intel_get_crtc_for_pipe(dev, pipe);
 	struct intel_crtc_state *state = to_intel_crtc_state(crtc->state);
 
-	/* Is state->cpu_transcoder correct to use? */
-	WARN_ON(crtc->state != &to_intel_crtc(crtc)->config->base);
-
 	/* Make sure the pipe isn't still relying on us */
 	assert_pipe_disabled(dev_priv, state->cpu_transcoder, pipe);
 
@@ -7103,14 +7093,15 @@  static void i8xx_update_pll(struct intel_crtc *crtc,
 	crtc_state->dpll_hw_state.dpll = dpll;
 }
 
-static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
+static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
+				   struct intel_crtc_state *pipe_config)
 {
 	struct drm_device *dev = intel_crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum pipe pipe = intel_crtc->pipe;
-	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
+	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
 	struct drm_display_mode *adjusted_mode =
-		&intel_crtc->config->base.adjusted_mode;
+		&pipe_config->base.adjusted_mode;
 	uint32_t crtc_vtotal, crtc_vblank_end;
 	int vsyncshift = 0;
 
@@ -7168,8 +7159,8 @@  static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
 	 * always be the user's requested size.
 	 */
 	I915_WRITE(PIPESRC(pipe),
-		   ((intel_crtc->config->pipe_src_w - 1) << 16) |
-		   (intel_crtc->config->pipe_src_h - 1));
+		   ((pipe_config->pipe_src_w - 1) << 16) |
+		    (pipe_config->pipe_src_h - 1));
 }
 
 static void intel_get_pipe_timings(struct intel_crtc *crtc,
@@ -7233,7 +7224,8 @@  void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 	mode->flags |= pipe_config->base.adjusted_mode.flags;
 }
 
-static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
+static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc,
+			      struct intel_crtc_state *pipe_config)
 {
 	struct drm_device *dev = intel_crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -7245,17 +7237,17 @@  static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
 	    (intel_crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
 		pipeconf |= I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE;
 
-	if (intel_crtc->config->double_wide)
+	if (pipe_config->double_wide)
 		pipeconf |= PIPECONF_DOUBLE_WIDE;
 
 	/* only g4x and later have fancy bpc/dither controls */
 	if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
 		/* Bspec claims that we can't use dithering for 30bpp pipes. */
-		if (intel_crtc->config->dither && intel_crtc->config->pipe_bpp != 30)
+		if (pipe_config->dither && pipe_config->pipe_bpp != 30)
 			pipeconf |= PIPECONF_DITHER_EN |
 				    PIPECONF_DITHER_TYPE_SP;
 
-		switch (intel_crtc->config->pipe_bpp) {
+		switch (pipe_config->pipe_bpp) {
 		case 18:
 			pipeconf |= PIPECONF_6BPC;
 			break;
@@ -7280,7 +7272,7 @@  static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
 		}
 	}
 
-	if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
+	if (pipe_config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
 		if (INTEL_INFO(dev)->gen < 4 ||
 		    intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_SDVO))
 			pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
@@ -7289,7 +7281,7 @@  static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
 	} else
 		pipeconf |= PIPECONF_PROGRESSIVE;
 
-	if (IS_VALLEYVIEW(dev) && intel_crtc->config->limited_color_range)
+	if (IS_VALLEYVIEW(dev) && pipe_config->limited_color_range)
 		pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
 
 	I915_WRITE(PIPECONF(intel_crtc->pipe), pipeconf);
@@ -8027,7 +8019,8 @@  static int ironlake_get_refclk(struct intel_crtc_state *crtc_state)
 	return 120000;
 }
 
-static void ironlake_set_pipeconf(struct drm_crtc *crtc)
+static void ironlake_set_pipeconf(struct drm_crtc *crtc,
+				  struct intel_crtc_state *pipe_config)
 {
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -8036,7 +8029,7 @@  static void ironlake_set_pipeconf(struct drm_crtc *crtc)
 
 	val = 0;
 
-	switch (intel_crtc->config->pipe_bpp) {
+	switch (pipe_config->pipe_bpp) {
 	case 18:
 		val |= PIPECONF_6BPC;
 		break;
@@ -8054,15 +8047,15 @@  static void ironlake_set_pipeconf(struct drm_crtc *crtc)
 		BUG();
 	}
 
-	if (intel_crtc->config->dither)
+	if (pipe_config->dither)
 		val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
 
-	if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
+	if (pipe_config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
 		val |= PIPECONF_INTERLACED_ILK;
 	else
 		val |= PIPECONF_PROGRESSIVE;
 
-	if (intel_crtc->config->limited_color_range)
+	if (pipe_config->limited_color_range)
 		val |= PIPECONF_COLOR_RANGE_SELECT;
 
 	I915_WRITE(PIPECONF(pipe), val);
@@ -8076,7 +8069,8 @@  static void ironlake_set_pipeconf(struct drm_crtc *crtc)
  * is supported, but eventually this should handle various
  * RGB<->YCbCr scenarios as well.
  */
-static void intel_set_pipe_csc(struct drm_crtc *crtc)
+static void intel_set_pipe_csc(struct drm_crtc *crtc,
+			       struct intel_crtc_state *pipe_config)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -8091,7 +8085,7 @@  static void intel_set_pipe_csc(struct drm_crtc *crtc)
 	 * consideration.
 	 */
 
-	if (intel_crtc->config->limited_color_range)
+	if (pipe_config->limited_color_range)
 		coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */
 
 	/*
@@ -8115,7 +8109,7 @@  static void intel_set_pipe_csc(struct drm_crtc *crtc)
 	if (INTEL_INFO(dev)->gen > 6) {
 		uint16_t postoff = 0;
 
-		if (intel_crtc->config->limited_color_range)
+		if (pipe_config->limited_color_range)
 			postoff = (16 * (1 << 12) / 255) & 0x1fff;
 
 		I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
@@ -8126,28 +8120,29 @@  static void intel_set_pipe_csc(struct drm_crtc *crtc)
 	} else {
 		uint32_t mode = CSC_MODE_YUV_TO_RGB;
 
-		if (intel_crtc->config->limited_color_range)
+		if (pipe_config->limited_color_range)
 			mode |= CSC_BLACK_SCREEN_OFFSET;
 
 		I915_WRITE(PIPE_CSC_MODE(pipe), mode);
 	}
 }
 
-static void haswell_set_pipeconf(struct drm_crtc *crtc)
+static void haswell_set_pipeconf(struct drm_crtc *crtc,
+				 struct intel_crtc_state *pipe_config)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	enum pipe pipe = intel_crtc->pipe;
-	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
+	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
 	uint32_t val;
 
 	val = 0;
 
-	if (IS_HASWELL(dev) && intel_crtc->config->dither)
+	if (IS_HASWELL(dev) && pipe_config->dither)
 		val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
 
-	if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
+	if (pipe_config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
 		val |= PIPECONF_INTERLACED_ILK;
 	else
 		val |= PIPECONF_PROGRESSIVE;
@@ -8161,7 +8156,7 @@  static void haswell_set_pipeconf(struct drm_crtc *crtc)
 	if (IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) {
 		val = 0;
 
-		switch (intel_crtc->config->pipe_bpp) {
+		switch (pipe_config->pipe_bpp) {
 		case 18:
 			val |= PIPEMISC_DITHER_6_BPC;
 			break;
@@ -8179,7 +8174,7 @@  static void haswell_set_pipeconf(struct drm_crtc *crtc)
 			BUG();
 		}
 
-		if (intel_crtc->config->dither)
+		if (pipe_config->dither)
 			val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
 
 		I915_WRITE(PIPEMISC(pipe), val);
@@ -8423,12 +8418,13 @@  static void intel_pch_transcoder_get_m_n(struct intel_crtc *crtc,
 }
 
 static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc,
-					 enum transcoder transcoder,
+					 struct intel_crtc_state *pipe_config,
 					 struct intel_link_m_n *m_n,
 					 struct intel_link_m_n *m2_n2)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum transcoder transcoder = pipe_config->cpu_transcoder;
 	enum pipe pipe = crtc->pipe;
 
 	if (INTEL_INFO(dev)->gen >= 5) {
@@ -8444,7 +8440,7 @@  static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc,
 		 * registers are not unnecessarily read).
 		 */
 		if (m2_n2 && INTEL_INFO(dev)->gen < 8 &&
-			crtc->config->has_drrs) {
+			pipe_config->has_drrs) {
 			m2_n2->link_m = I915_READ(PIPE_LINK_M2(transcoder));
 			m2_n2->link_n =	I915_READ(PIPE_LINK_N2(transcoder));
 			m2_n2->gmch_m =	I915_READ(PIPE_DATA_M2(transcoder))
@@ -8470,7 +8466,7 @@  void intel_dp_get_m_n(struct intel_crtc *crtc,
 	if (pipe_config->has_pch_encoder)
 		intel_pch_transcoder_get_m_n(crtc, &pipe_config->dp_m_n);
 	else
-		intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder,
+		intel_cpu_transcoder_get_m_n(crtc, pipe_config,
 					     &pipe_config->dp_m_n,
 					     &pipe_config->dp_m2_n2);
 }
@@ -8478,7 +8474,7 @@  void intel_dp_get_m_n(struct intel_crtc *crtc,
 static void ironlake_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,
+	intel_cpu_transcoder_get_m_n(crtc, pipe_config,
 				     &pipe_config->fdi_m_n, NULL);
 }
 
@@ -9331,6 +9327,8 @@  static void intel_crtc_update_cursor(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_crtc_state *pipe_config =
+		to_intel_crtc_state(crtc->state);
 	int pipe = intel_crtc->pipe;
 	int x = crtc->cursor_x;
 	int y = crtc->cursor_y;
@@ -9339,10 +9337,10 @@  static void intel_crtc_update_cursor(struct drm_crtc *crtc,
 	if (on)
 		base = intel_crtc->cursor_addr;
 
-	if (x >= intel_crtc->config->pipe_src_w)
+	if (x >= pipe_config->pipe_src_w)
 		base = 0;
 
-	if (y >= intel_crtc->config->pipe_src_h)
+	if (y >= pipe_config->pipe_src_h)
 		base = 0;
 
 	if (x < 0) {
@@ -9966,9 +9964,11 @@  struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
+	struct intel_crtc_state *pipe_config =
+		to_intel_crtc_state(crtc->state);
+	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
 	struct drm_display_mode *mode;
-	struct intel_crtc_state pipe_config;
+	struct intel_crtc_state fake_config;
 	int htot = I915_READ(HTOTAL(cpu_transcoder));
 	int hsync = I915_READ(HSYNC(cpu_transcoder));
 	int vtot = I915_READ(VTOTAL(cpu_transcoder));
@@ -9986,14 +9986,14 @@  struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 	 * Note, if LVDS ever uses a non-1 pixel multiplier, we'll need
 	 * to use a real value here instead.
 	 */
-	pipe_config.cpu_transcoder = (enum transcoder) pipe;
-	pipe_config.pixel_multiplier = 1;
-	pipe_config.dpll_hw_state.dpll = I915_READ(DPLL(pipe));
-	pipe_config.dpll_hw_state.fp0 = I915_READ(FP0(pipe));
-	pipe_config.dpll_hw_state.fp1 = I915_READ(FP1(pipe));
-	i9xx_crtc_clock_get(intel_crtc, &pipe_config);
-
-	mode->clock = pipe_config.port_clock / pipe_config.pixel_multiplier;
+	fake_config.cpu_transcoder = (enum transcoder) pipe;
+	fake_config.pixel_multiplier = 1;
+	fake_config.dpll_hw_state.dpll = I915_READ(DPLL(pipe));
+	fake_config.dpll_hw_state.fp0 = I915_READ(FP0(pipe));
+	fake_config.dpll_hw_state.fp1 = I915_READ(FP1(pipe));
+	i9xx_crtc_clock_get(intel_crtc, &fake_config);
+
+	mode->clock = fake_config.port_clock / fake_config.pixel_multiplier;
 	mode->hdisplay = (htot & 0xffff) + 1;
 	mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
 	mode->hsync_start = (hsync & 0xffff) + 1;
@@ -11839,12 +11839,13 @@  check_crtc_state(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *crtc;
 	struct intel_encoder *encoder;
-	struct intel_crtc_state pipe_config;
+	struct intel_crtc_state pipe_config, *sw_config;
 
 	for_each_intel_crtc(dev, crtc) {
 		bool enabled = false;
 		bool active = false;
 
+		sw_config = to_intel_crtc_state(crtc->base.state);
 		memset(&pipe_config, 0, sizeof(pipe_config));
 
 		DRM_DEBUG_KMS("[CRTC:%d]\n",
@@ -11887,11 +11888,11 @@  check_crtc_state(struct drm_device *dev)
 		     "(expected %i, found %i)\n", crtc->base.state->active, active);
 
 		if (active &&
-		    !intel_pipe_config_compare(dev, crtc->config, &pipe_config)) {
+		    !intel_pipe_config_compare(dev, sw_config, &pipe_config)) {
 			I915_STATE_WARN(1, "pipe state doesn't match!\n");
 			intel_dump_pipe_config(crtc, &pipe_config,
 					       "[hw state]");
-			intel_dump_pipe_config(crtc, crtc->config,
+			intel_dump_pipe_config(crtc, sw_config,
 					       "[sw state]");
 		}
 	}
@@ -11990,7 +11991,8 @@  static void update_scanline_offset(struct intel_crtc *crtc)
 	 * one to the value.
 	 */
 	if (IS_GEN2(dev)) {
-		const struct drm_display_mode *mode = &crtc->config->base.adjusted_mode;
+		const struct drm_display_mode *mode =
+			&crtc->base.state->adjusted_mode;
 		int vtotal;
 
 		vtotal = mode->crtc_vtotal;
@@ -13532,6 +13534,7 @@  static void intel_crtc_init(struct drm_device *dev, int pipe)
 	crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL);
 	if (!crtc_state)
 		goto fail;
+
 	intel_crtc->config = crtc_state;
 	intel_crtc->base.state = &crtc_state->base;
 	crtc_state->base.crtc = &intel_crtc->base;
@@ -14574,19 +14577,20 @@  intel_check_plane_mapping(struct intel_crtc *crtc)
 	return true;
 }
 
-static void intel_sanitize_crtc(struct intel_crtc *crtc)
+static void intel_sanitize_crtc(struct intel_crtc *crtc,
+				struct intel_crtc_state *pipe_config)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 reg;
 
 	/* Clear any frame start delays used for debugging left by the BIOS */
-	reg = PIPECONF(crtc->config->cpu_transcoder);
+	reg = PIPECONF(pipe_config->cpu_transcoder);
 	I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
 
 	/* restore vblank interrupts to correct state */
 	drm_crtc_vblank_reset(&crtc->base);
-	if (crtc->base.state->active) {
+	if (pipe_config->base.active) {
 		update_scanline_offset(crtc);
 		drm_crtc_vblank_on(&crtc->base);
 	}
@@ -14626,14 +14630,14 @@  static void intel_sanitize_crtc(struct intel_crtc *crtc)
 				connector->encoder->connectors_active = false;
 			}
 
-		WARN_ON(crtc->base.state->active);
-		crtc->base.state->enable = false;
-		crtc->base.state->active = false;
+		WARN_ON(pipe_config->base.active);
+		pipe_config->base.enable = false;
+		pipe_config->base.active = false;
 		crtc->base.enabled = false;
 	}
 
 	if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
-	    crtc->pipe == PIPE_A && !crtc->base.state->active) {
+	    crtc->pipe == PIPE_A && !pipe_config->base.active) {
 		/* BIOS forgot to enable pipe A, this mostly happens after
 		 * resume. Force-enable the pipe to fix this, the update_dpms
 		 * call below we restore the pipe to the right state, but leave
@@ -14645,7 +14649,7 @@  static void intel_sanitize_crtc(struct intel_crtc *crtc)
 	 * have active connectors/encoders. */
 	intel_crtc_update_dpms(&crtc->base);
 
-	if (crtc->base.state->active || HAS_GMCH_DISPLAY(dev)) {
+	if (pipe_config->base.active || HAS_GMCH_DISPLAY(dev)) {
 		/*
 		 * We start out with underrun reporting disabled to avoid races.
 		 * For correct bookkeeping mark this on active crtcs.
@@ -14763,17 +14767,19 @@  static void intel_modeset_readout_hw_state(struct drm_device *dev,
 	for_each_intel_crtc(dev, crtc) {
 		struct drm_plane *primary = crtc->base.primary;
 		struct intel_plane_state *plane_state;
+		struct intel_crtc_state *pipe_config =
+			to_intel_crtc_state(crtc->base.state);
 
-		memset(crtc->config, 0, sizeof(*crtc->config));
+		memset(pipe_config, 0, sizeof(*pipe_config));
 
-		crtc->config->quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE;
+		pipe_config->quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE;
 
 		if (crtc->base.state->active)
 			*crtc_mask |= drm_crtc_index(&crtc->base);
 
-		crtc->base.enabled = crtc->base.state->enable =
-		crtc->base.state->active =
-			dev_priv->display.get_pipe_config(crtc, crtc->config);
+		crtc->base.enabled = pipe_config->base.enable =
+		pipe_config->base.active =
+			dev_priv->display.get_pipe_config(crtc, pipe_config);
 
 		plane_state = to_intel_plane_state(primary->state);
 		plane_state->hw_enabled = plane_state->visible =
@@ -14818,7 +14824,8 @@  static void intel_modeset_readout_hw_state(struct drm_device *dev,
 		if (encoder->get_hw_state(encoder, &pipe)) {
 			crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
 			encoder->base.crtc = &crtc->base;
-			encoder->get_config(encoder, crtc->config);
+			encoder->get_config(encoder,
+				to_intel_crtc_state(crtc->base.state));
 		} else {
 			encoder->base.crtc = NULL;
 		}
@@ -14883,9 +14890,13 @@  void intel_modeset_setup_hw_state(struct drm_device *dev,
 	}
 
 	for_each_pipe(dev_priv, pipe) {
+		struct intel_crtc_state *pipe_config;
+
 		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
-		intel_sanitize_crtc(crtc);
-		intel_dump_pipe_config(crtc, crtc->config,
+		pipe_config = to_intel_crtc_state(crtc->base.state);
+
+		intel_sanitize_crtc(crtc, pipe_config);
+		intel_dump_pipe_config(crtc, pipe_config,
 				       "[setup_hw_state]");
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e6876faca7f0..abf8082be40c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -5309,10 +5309,10 @@  static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
 	if (INTEL_INFO(dev)->gen >= 8 && !IS_CHERRYVIEW(dev)) {
 		switch (index) {
 		case DRRS_HIGH_RR:
-			intel_dp_set_m_n(intel_crtc, M1_N1);
+			intel_dp_set_m_n(intel_crtc, pipe_config, M1_N1);
 			break;
 		case DRRS_LOW_RR:
-			intel_dp_set_m_n(intel_crtc, M2_N2);
+			intel_dp_set_m_n(intel_crtc, pipe_config, M2_N2);
 			break;
 		case DRRS_MAX_RR:
 		default:
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 7979a2f6838c..6767ed91faaf 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1102,7 +1102,9 @@  void bxt_enable_dc9(struct drm_i915_private *dev_priv);
 void bxt_disable_dc9(struct drm_i915_private *dev_priv);
 void intel_dp_get_m_n(struct intel_crtc *crtc,
 		      struct intel_crtc_state *pipe_config);
-void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n);
+void intel_dp_set_m_n(struct intel_crtc *crtc,
+		      struct intel_crtc_state *pipe_config,
+		      enum link_m_n_set m_n);
 int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
 void
 ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config,