diff options
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 82 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 7 | 
3 files changed, 57 insertions, 36 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f69538508d8..2962a9ab44d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -284,6 +284,8 @@ struct drm_i915_error_state {  	struct intel_display_error_state *display;  }; +struct intel_crtc_config; +  struct drm_i915_display_funcs {  	bool (*fbc_enabled)(struct drm_device *dev);  	void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval); @@ -297,8 +299,6 @@ struct drm_i915_display_funcs {  				 struct drm_display_mode *mode);  	void (*modeset_global_resources)(struct drm_device *dev);  	int (*crtc_mode_set)(struct drm_crtc *crtc, -			     struct drm_display_mode *mode, -			     struct drm_display_mode *adjusted_mode,  			     int x, int y,  			     struct drm_framebuffer *old_fb);  	void (*crtc_enable)(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2db50e234c2..e22be581ed9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3971,15 +3971,16 @@ bool intel_connector_get_hw_state(struct intel_connector *connector)  	return encoder->get_hw_state(encoder, &pipe);  } -static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, -				  const struct drm_display_mode *mode, -				  struct drm_display_mode *adjusted_mode) +static bool intel_crtc_compute_config(struct drm_crtc *crtc, +				      struct intel_crtc_config *pipe_config)  {  	struct drm_device *dev = crtc->dev; +	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;  	if (HAS_PCH_SPLIT(dev)) {  		/* FDI link clock is fixed at 2.7G */ -		if (mode->clock * 3 > IRONLAKE_FDI_FREQ * 4) +		if (pipe_config->requested_mode.clock * 3 +		    > IRONLAKE_FDI_FREQ * 4)  			return false;  	} @@ -4665,14 +4666,15 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,  }  static int i9xx_crtc_mode_set(struct drm_crtc *crtc, -			      struct drm_display_mode *mode, -			      struct drm_display_mode *adjusted_mode,  			      int x, int y,  			      struct drm_framebuffer *fb)  {  	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 drm_display_mode *adjusted_mode = +		&intel_crtc->config.adjusted_mode; +	struct drm_display_mode *mode = &intel_crtc->config.requested_mode;  	int pipe = intel_crtc->pipe;  	int plane = intel_crtc->plane;  	int refclk, num_connectors = 0; @@ -5637,14 +5639,15 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,  }  static int ironlake_crtc_mode_set(struct drm_crtc *crtc, -				  struct drm_display_mode *mode, -				  struct drm_display_mode *adjusted_mode,  				  int x, int y,  				  struct drm_framebuffer *fb)  {  	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 drm_display_mode *adjusted_mode = +		&intel_crtc->config.adjusted_mode; +	struct drm_display_mode *mode = &intel_crtc->config.requested_mode;  	int pipe = intel_crtc->pipe;  	int plane = intel_crtc->plane;  	int num_connectors = 0; @@ -5803,14 +5806,15 @@ static void haswell_modeset_global_resources(struct drm_device *dev)  }  static int haswell_crtc_mode_set(struct drm_crtc *crtc, -				 struct drm_display_mode *mode, -				 struct drm_display_mode *adjusted_mode,  				 int x, int y,  				 struct drm_framebuffer *fb)  {  	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 drm_display_mode *adjusted_mode = +		&intel_crtc->config.adjusted_mode; +	struct drm_display_mode *mode = &intel_crtc->config.requested_mode;  	int pipe = intel_crtc->pipe;  	int plane = intel_crtc->plane;  	int num_connectors = 0; @@ -5887,8 +5891,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,  }  static int intel_crtc_mode_set(struct drm_crtc *crtc, -			       struct drm_display_mode *mode, -			       struct drm_display_mode *adjusted_mode,  			       int x, int y,  			       struct drm_framebuffer *fb)  { @@ -5897,6 +5899,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,  	struct drm_encoder_helper_funcs *encoder_funcs;  	struct intel_encoder *encoder;  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); +	struct drm_display_mode *adjusted_mode = +		&intel_crtc->config.adjusted_mode; +	struct drm_display_mode *mode = &intel_crtc->config.requested_mode;  	int pipe = intel_crtc->pipe;  	int ret; @@ -5907,8 +5912,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,  	drm_vblank_pre_modeset(dev, pipe); -	ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode, -					      x, y, fb); +	ret = dev_priv->display.crtc_mode_set(crtc, x, y, fb); +  	drm_vblank_post_modeset(dev, pipe);  	if (ret != 0) @@ -7530,19 +7535,22 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)  	}  } -static struct drm_display_mode * -intel_modeset_adjusted_mode(struct drm_crtc *crtc, -			    struct drm_display_mode *mode) +static struct intel_crtc_config * +intel_modeset_pipe_config(struct drm_crtc *crtc, +			  struct drm_display_mode *mode)  {  	struct drm_device *dev = crtc->dev; -	struct drm_display_mode *adjusted_mode;  	struct drm_encoder_helper_funcs *encoder_funcs;  	struct intel_encoder *encoder; +	struct intel_crtc_config *pipe_config; -	adjusted_mode = drm_mode_duplicate(dev, mode); -	if (!adjusted_mode) +	pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL); +	if (!pipe_config)  		return ERR_PTR(-ENOMEM); +	drm_mode_copy(&pipe_config->adjusted_mode, mode); +	drm_mode_copy(&pipe_config->requested_mode, mode); +  	/* Pass our mode to the connectors and the CRTC to give them a chance to  	 * adjust it according to limitations or connector properties, and also  	 * a chance to reject the mode entirely. @@ -7553,22 +7561,23 @@ intel_modeset_adjusted_mode(struct drm_crtc *crtc,  		if (&encoder->new_crtc->base != crtc)  			continue;  		encoder_funcs = encoder->base.helper_private; -		if (!(encoder_funcs->mode_fixup(&encoder->base, mode, -						adjusted_mode))) { +		if (!(encoder_funcs->mode_fixup(&encoder->base, +						&pipe_config->requested_mode, +						&pipe_config->adjusted_mode))) {  			DRM_DEBUG_KMS("Encoder fixup failed\n");  			goto fail;  		}  	} -	if (!(intel_crtc_mode_fixup(crtc, mode, adjusted_mode))) { +	if (!(intel_crtc_compute_config(crtc, pipe_config))) {  		DRM_DEBUG_KMS("CRTC fixup failed\n");  		goto fail;  	}  	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); -	return adjusted_mode; +	return pipe_config;  fail: -	drm_mode_destroy(dev, adjusted_mode); +	kfree(pipe_config);  	return ERR_PTR(-EINVAL);  } @@ -7834,7 +7843,8 @@ int intel_set_mode(struct drm_crtc *crtc,  {  	struct drm_device *dev = crtc->dev;  	drm_i915_private_t *dev_priv = dev->dev_private; -	struct drm_display_mode *adjusted_mode, *saved_mode, *saved_hwmode; +	struct drm_display_mode *saved_mode, *saved_hwmode; +	struct intel_crtc_config *pipe_config = NULL;  	struct intel_crtc *intel_crtc;  	unsigned disable_pipes, prepare_pipes, modeset_pipes;  	int ret = 0; @@ -7861,11 +7871,12 @@ int intel_set_mode(struct drm_crtc *crtc,  	 * Hence simply check whether any bit is set in modeset_pipes in all the  	 * pieces of code that are not yet converted to deal with mutliple crtcs  	 * changing their mode at the same time. */ -	adjusted_mode = NULL;  	if (modeset_pipes) { -		adjusted_mode = intel_modeset_adjusted_mode(crtc, mode); -		if (IS_ERR(adjusted_mode)) { -			ret = PTR_ERR(adjusted_mode); +		pipe_config = intel_modeset_pipe_config(crtc, mode); +		if (IS_ERR(pipe_config)) { +			ret = PTR_ERR(pipe_config); +			pipe_config = NULL; +  			goto out;  		}  	} @@ -7878,8 +7889,12 @@ int intel_set_mode(struct drm_crtc *crtc,  	/* crtc->mode is already used by the ->mode_set callbacks, hence we need  	 * to set it here already despite that we pass it down the callchain.  	 */ -	if (modeset_pipes) +	if (modeset_pipes) {  		crtc->mode = *mode; +		/* mode_set/enable/disable functions rely on a correct pipe +		 * config. */ +		to_intel_crtc(crtc)->config = *pipe_config; +	}  	/* Only after disabling all output pipelines that will be changed can we  	 * update the the output configuration. */ @@ -7893,7 +7908,6 @@ int intel_set_mode(struct drm_crtc *crtc,  	 */  	for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {  		ret = intel_crtc_mode_set(&intel_crtc->base, -					  mode, adjusted_mode,  					  x, y, fb);  		if (ret)  			goto done; @@ -7905,7 +7919,7 @@ int intel_set_mode(struct drm_crtc *crtc,  	if (modeset_pipes) {  		/* Store real post-adjustment hardware mode. */ -		crtc->hwmode = *adjusted_mode; +		crtc->hwmode = pipe_config->adjusted_mode;  		/* Calculate and store various constants which  		 * are later needed by vblank and swap-completion @@ -7916,7 +7930,6 @@ int intel_set_mode(struct drm_crtc *crtc,  	/* FIXME: add subpixel order */  done: -	drm_mode_destroy(dev, adjusted_mode);  	if (ret && crtc->enabled) {  		crtc->hwmode = *saved_hwmode;  		crtc->mode = *saved_mode; @@ -7925,6 +7938,7 @@ done:  	}  out: +	kfree(pipe_config);  	kfree(saved_mode);  	return ret;  } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 54bc2ea61fa..4cc66251fd3 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -200,6 +200,11 @@ struct intel_connector {  	struct edid *edid;  }; +struct intel_crtc_config { +	struct drm_display_mode requested_mode; +	struct drm_display_mode adjusted_mode; +}; +  struct intel_crtc {  	struct drm_crtc base;  	enum pipe pipe; @@ -233,6 +238,8 @@ struct intel_crtc {  	bool cursor_visible;  	unsigned int bpp; +	struct intel_crtc_config config; +  	/* We can share PLLs across outputs if the timings match */  	struct intel_pch_pll *pch_pll;  	uint32_t ddi_pll_sel;  |