diff mbox

[01/36] drm/i915: introduce struct intel_crtc_config

Message ID 1361407828-2419-2-git-send-email-daniel.vetter@ffwll.ch (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Vetter Feb. 21, 2013, 12:49 a.m. UTC
Currently only containing the requested and the adjusted mode. And
only crtc callbacks are converted somewhat to it, encoders will be
done on a as-needed basis (simply too much churn in one patch
otherwise).

Future patches will add tons more useful stuff to this struct,
starting with the very simple.

v2: Store the pipe_config in the intel_crtc, so that the ->mode-set,
->enable and also ->disable have easy access to it.

v3: Store the pipe config in the right crtc ...

v4: Rebased.

v5: Fixup an BUG when trying to kfree an ERR_PTR.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_drv.h      |  4 +-
 drivers/gpu/drm/i915/intel_display.c | 84 +++++++++++++++++++++---------------
 drivers/gpu/drm/i915/intel_drv.h     |  7 +++
 3 files changed, 59 insertions(+), 36 deletions(-)

Comments

Ville Syrjälä Feb. 21, 2013, 2:38 p.m. UTC | #1
On Thu, Feb 21, 2013 at 01:49:53AM +0100, Daniel Vetter wrote:
> Currently only containing the requested and the adjusted mode. And
> only crtc callbacks are converted somewhat to it, encoders will be
> done on a as-needed basis (simply too much churn in one patch
> otherwise).
> 
> Future patches will add tons more useful stuff to this struct,
> starting with the very simple.

Just a few bikesheds below. Otherwise the direction where this is going
looks very nice.

> v2: Store the pipe_config in the intel_crtc, so that the ->mode-set,
> ->enable and also ->disable have easy access to it.
> 
> v3: Store the pipe config in the right crtc ...
> 
> v4: Rebased.
> 
> v5: Fixup an BUG when trying to kfree an ERR_PTR.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/i915_drv.h      |  4 +-
>  drivers/gpu/drm/i915/intel_display.c | 84 +++++++++++++++++++++---------------
>  drivers/gpu/drm/i915/intel_drv.h     |  7 +++
>  3 files changed, 59 insertions(+), 36 deletions(-)
> 
<snip>
> @@ -7382,19 +7386,24 @@ 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);
>  
> +	pipe_config->adjusted_mode = *mode;
> +	pipe_config->adjusted_mode.base.id = 0;
> +	pipe_config->requested_mode = *mode;
> +	pipe_config->requested_mode.base.id = 0;

drm_mode_copy() perhaps?

> +
>  	/* 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.
> @@ -7405,22 +7414,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);
>  }
>  
> @@ -7686,7 +7696,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;
>  	struct intel_crtc *intel_crtc;
>  	unsigned disable_pipes, prepare_pipes, modeset_pipes;
>  	int ret = 0;
> @@ -7713,11 +7724,13 @@ 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;
> +	pipe_config = NULL;

The NULL assignment could be moved to where pipe_config is declared.

>  	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;
>  		}
>  	}
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0f1d15b..1196d0e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -271,6 +271,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);
@@ -284,8 +286,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 6fe4d07..d2f5e7fd 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3881,15 +3881,15 @@  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;
 	}
 
@@ -4579,14 +4579,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;
@@ -5484,14 +5485,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;
@@ -5650,14 +5652,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;
@@ -5732,8 +5735,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)
 {
@@ -5742,6 +5743,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;
 
@@ -5752,8 +5756,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)
@@ -7382,19 +7386,24 @@  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);
 
+	pipe_config->adjusted_mode = *mode;
+	pipe_config->adjusted_mode.base.id = 0;
+	pipe_config->requested_mode = *mode;
+	pipe_config->requested_mode.base.id = 0;
+
 	/* 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.
@@ -7405,22 +7414,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);
 }
 
@@ -7686,7 +7696,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;
 	struct intel_crtc *intel_crtc;
 	unsigned disable_pipes, prepare_pipes, modeset_pipes;
 	int ret = 0;
@@ -7713,11 +7724,13 @@  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;
+	pipe_config = 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;
 		}
 	}
@@ -7730,8 +7743,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. */
@@ -7745,7 +7762,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;
@@ -7757,7 +7773,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
@@ -7768,7 +7784,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;
@@ -7777,6 +7792,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 13afb37..898fdfe 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -199,6 +199,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;
@@ -232,6 +237,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;