diff mbox

[v2,09/20] drm/i915: Fill in more crtc state, v2.

Message ID 1436252911-5703-10-git-send-email-maarten.lankhorst@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Maarten Lankhorst July 7, 2015, 7:08 a.m. UTC
Perform a full readout of the state by making sure the mode is set
up correctly atomically.

Also there was a small memory leak by doing the memset, fix this
by calling __drm_atomic_helper_crtc_destroy_state first.

Changes since v1:
- Moved after reworking primary plane and updating mode members.
- Force a modeset calculation by changing mode->type from what the
  final mode will be.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 35 ++++++++++++++++-------------------
 drivers/gpu/drm/i915/intel_fbdev.c   |  9 ++-------
 2 files changed, 18 insertions(+), 26 deletions(-)

Comments

Daniel Vetter July 7, 2015, 10:28 a.m. UTC | #1
On Tue, Jul 07, 2015 at 09:08:20AM +0200, Maarten Lankhorst wrote:
> Perform a full readout of the state by making sure the mode is set
> up correctly atomically.
> 
> Also there was a small memory leak by doing the memset, fix this
> by calling __drm_atomic_helper_crtc_destroy_state first.
> 
> Changes since v1:
> - Moved after reworking primary plane and updating mode members.
> - Force a modeset calculation by changing mode->type from what the
>   final mode will be.
> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>

tbh I don't really like mode_from_pipe_config since it goes in reverse.
With the adjust mode of config_compare we can compare different final hw
states and make a call whether they match enough for modeset avoidance or
not. mode_from_pipe_config otoh is a lie on panels where we can do
upscaling, hence I'd like to remove it to avoid confusion.
-Daniel

> ---
>  drivers/gpu/drm/i915/intel_display.c | 35 ++++++++++++++++-------------------
>  drivers/gpu/drm/i915/intel_fbdev.c   |  9 ++-------
>  2 files changed, 18 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index ee543e1515f1..dc4bdb91ad4d 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -15191,6 +15191,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc->base.state);
>  	struct intel_encoder *encoder;
>  	u32 reg;
>  	bool enable;
> @@ -15202,6 +15203,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
>  	/* restore vblank interrupts to correct state */
>  	drm_crtc_vblank_reset(&crtc->base);
>  	if (crtc->active) {
> +		drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
>  		update_scanline_offset(crtc);
>  		drm_crtc_vblank_on(&crtc->base);
>  	}
> @@ -15254,9 +15256,8 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
>  			      crtc->base.state->enable ? "enabled" : "disabled",
>  			      crtc->active ? "enabled" : "disabled");
>  
> -		crtc->base.state->enable = crtc->active;
> -		crtc->base.state->active = crtc->active;
> -		crtc->base.enabled = crtc->active;
> +		crtc->base.enabled = crtc->base.state->active = crtc->active;
> +		WARN_ON(drm_atomic_set_mode_for_crtc(&pipe_config->base, NULL) < 0);
>  
>  		/* Because we only establish the connector -> encoder ->
>  		 * crtc links if something is active, this means the
> @@ -15412,6 +15413,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
>  	int i;
>  
>  	for_each_intel_crtc(dev, crtc) {
> +		__drm_atomic_helper_crtc_destroy_state(&crtc->base, crtc->base.state);
>  		memset(crtc->config, 0, sizeof(*crtc->config));
>  		crtc->config->base.crtc = &crtc->base;
>  
> @@ -15420,11 +15422,21 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
>  		crtc->active = dev_priv->display.get_pipe_config(crtc,
>  								 crtc->config);
>  
> -		crtc->base.state->enable = crtc->active;
>  		crtc->base.state->active = crtc->active;
>  		crtc->base.enabled = crtc->active;
>  		crtc->base.hwmode = crtc->config->base.adjusted_mode;
>  
> +		if (crtc->base.enabled) {
> +			memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
> +			intel_mode_from_pipe_config(&crtc->base.mode, crtc->config);
> +			WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode) < 0);
> +
> +			/* make sure a initial modeset happens by making sure
> +			 * mode->type will be different from the final mode
> +			 */
> +			crtc->base.state->mode.type = 0;
> +		}
> +
>  		readout_plane_state(crtc, to_intel_crtc_state(crtc->base.state));
>  
>  		DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
> @@ -15501,21 +15513,6 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
>  
>  	intel_modeset_readout_hw_state(dev);
>  
> -	/*
> -	 * Now that we have the config, copy it to each CRTC struct
> -	 * Note that this could go away if we move to using crtc_config
> -	 * checking everywhere.
> -	 */
> -	for_each_intel_crtc(dev, crtc) {
> -		if (crtc->active && i915.fastboot) {
> -			intel_mode_from_pipe_config(&crtc->base.mode,
> -						    crtc->config);
> -			DRM_DEBUG_KMS("[CRTC:%d] found active mode: ",
> -				      crtc->base.base.id);
> -			drm_mode_debug_printmodeline(&crtc->base.mode);
> -		}
> -	}
> -
>  	/* HW state is read out, now we need to sanitize this mess. */
>  	for_each_intel_encoder(dev, encoder) {
>  		intel_sanitize_encoder(encoder);
> diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
> index 3d5bb56477ab..52d20cea182c 100644
> --- a/drivers/gpu/drm/i915/intel_fbdev.c
> +++ b/drivers/gpu/drm/i915/intel_fbdev.c
> @@ -486,16 +486,11 @@ retry:
>  			 * config, not the input mode, which is what crtc->mode
>  			 * usually contains. But since our current fastboot
>  			 * code puts a mode derived from the post-pfit timings
> -			 * into crtc->mode this works out correctly. We don't
> -			 * use hwmode anywhere right now, so use it for this
> -			 * since the fb helper layer wants a pointer to
> -			 * something we own.
> +			 * into crtc->mode this works out correctly.
>  			 */
>  			DRM_DEBUG_KMS("looking for current mode on connector %s\n",
>  				      connector->name);
> -			intel_mode_from_pipe_config(&encoder->crtc->hwmode,
> -						    to_intel_crtc(encoder->crtc)->config);
> -			modes[i] = &encoder->crtc->hwmode;
> +			modes[i] = &encoder->crtc->mode;
>  		}
>  		crtcs[i] = new_crtc;
>  
> -- 
> 2.1.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Maarten Lankhorst July 13, 2015, 9:32 a.m. UTC | #2
Op 07-07-15 om 12:28 schreef Daniel Vetter:
> On Tue, Jul 07, 2015 at 09:08:20AM +0200, Maarten Lankhorst wrote:
>> Perform a full readout of the state by making sure the mode is set
>> up correctly atomically.
>>
>> Also there was a small memory leak by doing the memset, fix this
>> by calling __drm_atomic_helper_crtc_destroy_state first.
>>
>> Changes since v1:
>> - Moved after reworking primary plane and updating mode members.
>> - Force a modeset calculation by changing mode->type from what the
>>   final mode will be.
>>
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> tbh I don't really like mode_from_pipe_config since it goes in reverse.
> With the adjust mode of config_compare we can compare different final hw
> states and make a call whether they match enough for modeset avoidance or
> not. mode_from_pipe_config otoh is a lie on panels where we can do
> upscaling, hence I'd like to remove it to avoid confusion.
What do you want the initial mode to be then?

You need to fill in some mode to satisfy drm_atomic_crtc_check.

~Maarten
Daniel Vetter July 13, 2015, 9:48 a.m. UTC | #3
On Mon, Jul 13, 2015 at 11:32:09AM +0200, Maarten Lankhorst wrote:
> Op 07-07-15 om 12:28 schreef Daniel Vetter:
> > On Tue, Jul 07, 2015 at 09:08:20AM +0200, Maarten Lankhorst wrote:
> >> Perform a full readout of the state by making sure the mode is set
> >> up correctly atomically.
> >>
> >> Also there was a small memory leak by doing the memset, fix this
> >> by calling __drm_atomic_helper_crtc_destroy_state first.
> >>
> >> Changes since v1:
> >> - Moved after reworking primary plane and updating mode members.
> >> - Force a modeset calculation by changing mode->type from what the
> >>   final mode will be.
> >>
> >> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > tbh I don't really like mode_from_pipe_config since it goes in reverse.
> > With the adjust mode of config_compare we can compare different final hw
> > states and make a call whether they match enough for modeset avoidance or
> > not. mode_from_pipe_config otoh is a lie on panels where we can do
> > upscaling, hence I'd like to remove it to avoid confusion.
> What do you want the initial mode to be then?
> 
> You need to fill in some mode to satisfy drm_atomic_crtc_check.

All zeros? That would make it clear that we have a mode, and that we also
have no idea really what it is ...

Otoh I think you've convinced me now that we indeed do need a real mode
object here to avoid other troubles (i.e. the entire discussion around
initial fbcon modesets). Given that I'd guess even the slightly wrong
fill_in_modes here with the change to set DRIVER_MODE would be ok. As long
as we can guarantee that we'll get a full modeset eventually we should be
fine I hope.
-Daniel
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ee543e1515f1..dc4bdb91ad4d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15191,6 +15191,7 @@  static void intel_sanitize_crtc(struct intel_crtc *crtc)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc->base.state);
 	struct intel_encoder *encoder;
 	u32 reg;
 	bool enable;
@@ -15202,6 +15203,7 @@  static void intel_sanitize_crtc(struct intel_crtc *crtc)
 	/* restore vblank interrupts to correct state */
 	drm_crtc_vblank_reset(&crtc->base);
 	if (crtc->active) {
+		drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
 		update_scanline_offset(crtc);
 		drm_crtc_vblank_on(&crtc->base);
 	}
@@ -15254,9 +15256,8 @@  static void intel_sanitize_crtc(struct intel_crtc *crtc)
 			      crtc->base.state->enable ? "enabled" : "disabled",
 			      crtc->active ? "enabled" : "disabled");
 
-		crtc->base.state->enable = crtc->active;
-		crtc->base.state->active = crtc->active;
-		crtc->base.enabled = crtc->active;
+		crtc->base.enabled = crtc->base.state->active = crtc->active;
+		WARN_ON(drm_atomic_set_mode_for_crtc(&pipe_config->base, NULL) < 0);
 
 		/* Because we only establish the connector -> encoder ->
 		 * crtc links if something is active, this means the
@@ -15412,6 +15413,7 @@  static void intel_modeset_readout_hw_state(struct drm_device *dev)
 	int i;
 
 	for_each_intel_crtc(dev, crtc) {
+		__drm_atomic_helper_crtc_destroy_state(&crtc->base, crtc->base.state);
 		memset(crtc->config, 0, sizeof(*crtc->config));
 		crtc->config->base.crtc = &crtc->base;
 
@@ -15420,11 +15422,21 @@  static void intel_modeset_readout_hw_state(struct drm_device *dev)
 		crtc->active = dev_priv->display.get_pipe_config(crtc,
 								 crtc->config);
 
-		crtc->base.state->enable = crtc->active;
 		crtc->base.state->active = crtc->active;
 		crtc->base.enabled = crtc->active;
 		crtc->base.hwmode = crtc->config->base.adjusted_mode;
 
+		if (crtc->base.enabled) {
+			memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
+			intel_mode_from_pipe_config(&crtc->base.mode, crtc->config);
+			WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode) < 0);
+
+			/* make sure a initial modeset happens by making sure
+			 * mode->type will be different from the final mode
+			 */
+			crtc->base.state->mode.type = 0;
+		}
+
 		readout_plane_state(crtc, to_intel_crtc_state(crtc->base.state));
 
 		DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
@@ -15501,21 +15513,6 @@  void intel_modeset_setup_hw_state(struct drm_device *dev,
 
 	intel_modeset_readout_hw_state(dev);
 
-	/*
-	 * Now that we have the config, copy it to each CRTC struct
-	 * Note that this could go away if we move to using crtc_config
-	 * checking everywhere.
-	 */
-	for_each_intel_crtc(dev, crtc) {
-		if (crtc->active && i915.fastboot) {
-			intel_mode_from_pipe_config(&crtc->base.mode,
-						    crtc->config);
-			DRM_DEBUG_KMS("[CRTC:%d] found active mode: ",
-				      crtc->base.base.id);
-			drm_mode_debug_printmodeline(&crtc->base.mode);
-		}
-	}
-
 	/* HW state is read out, now we need to sanitize this mess. */
 	for_each_intel_encoder(dev, encoder) {
 		intel_sanitize_encoder(encoder);
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 3d5bb56477ab..52d20cea182c 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -486,16 +486,11 @@  retry:
 			 * config, not the input mode, which is what crtc->mode
 			 * usually contains. But since our current fastboot
 			 * code puts a mode derived from the post-pfit timings
-			 * into crtc->mode this works out correctly. We don't
-			 * use hwmode anywhere right now, so use it for this
-			 * since the fb helper layer wants a pointer to
-			 * something we own.
+			 * into crtc->mode this works out correctly.
 			 */
 			DRM_DEBUG_KMS("looking for current mode on connector %s\n",
 				      connector->name);
-			intel_mode_from_pipe_config(&encoder->crtc->hwmode,
-						    to_intel_crtc(encoder->crtc)->config);
-			modes[i] = &encoder->crtc->hwmode;
+			modes[i] = &encoder->crtc->mode;
 		}
 		crtcs[i] = new_crtc;