diff mbox series

[v10,4/6] drm/i915/tgl: Do modeset to enable and configure DC3CO exitline

Message ID 20190930174137.15233-5-anshuman.gupta@intel.com (mailing list archive)
State New, archived
Headers show
Series DC3CO Support for TGL | expand

Commit Message

Gupta, Anshuman Sept. 30, 2019, 5:41 p.m. UTC
DC3CO enabling B.Specs sequence requires to enable end configure
exit scanlines to TRANS_EXITLINE register, programming this register
has to be part of modeset sequence as this can't be change when
transcoder or port is enabled.
When system boots with only eDP panel there may not be real
modeset as BIOS has already programmed the necessary registers,
therefore it needs to force a modeset to enable and configure
DC3CO exitline.

v1: Computing dc3co_exitline crtc state from a DP encoder
    compute config. [Imre]
    Enabling and disabling DC3CO PSR2 transcoder exitline from
    encoder pre_enable and post_disable hooks. [Imre]
    Computing dc3co_exitline instead of has_dc3co_exitline bool. [Imre]
v2: Code refactoring for symmetry and to avoid exported function. [Imre]
    Removing IS_TIGERLAKE check from compute_config, adding PIPE_A
    restriction and clearing dc3co_exitline state if crtc is not active
    or it is not PSR2 capable in dc3co exitline compute_config. [Imre]
    Using  IS_TGL check and  dc3co exitline get_config

Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Cc: Animesh Manna <animesh.manna@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c      | 104 +++++++++++++++++-
 drivers/gpu/drm/i915/display/intel_display.c  |   1 +
 .../drm/i915/display/intel_display_types.h    |   1 +
 drivers/gpu/drm/i915/i915_drv.h               |   1 +
 4 files changed, 105 insertions(+), 2 deletions(-)

Comments

Imre Deak Oct. 1, 2019, 9:17 a.m. UTC | #1
On Mon, Sep 30, 2019 at 11:11:35PM +0530, Anshuman Gupta wrote:
> DC3CO enabling B.Specs sequence requires to enable end configure
> exit scanlines to TRANS_EXITLINE register, programming this register
> has to be part of modeset sequence as this can't be change when
> transcoder or port is enabled.
> When system boots with only eDP panel there may not be real
> modeset as BIOS has already programmed the necessary registers,
> therefore it needs to force a modeset to enable and configure
> DC3CO exitline.
> 
> v1: Computing dc3co_exitline crtc state from a DP encoder
>     compute config. [Imre]
>     Enabling and disabling DC3CO PSR2 transcoder exitline from
>     encoder pre_enable and post_disable hooks. [Imre]
>     Computing dc3co_exitline instead of has_dc3co_exitline bool. [Imre]
> v2: Code refactoring for symmetry and to avoid exported function. [Imre]
>     Removing IS_TIGERLAKE check from compute_config, adding PIPE_A
>     restriction and clearing dc3co_exitline state if crtc is not active
>     or it is not PSR2 capable in dc3co exitline compute_config. [Imre]
>     Using  IS_TGL check and  dc3co exitline get_config
> 
> Cc: Jani Nikula <jani.nikula@intel.com>
> Cc: Imre Deak <imre.deak@intel.com>
> Cc: Animesh Manna <animesh.manna@intel.com>
> Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_ddi.c      | 104 +++++++++++++++++-
>  drivers/gpu/drm/i915/display/intel_display.c  |   1 +
>  .../drm/i915/display/intel_display_types.h    |   1 +
>  drivers/gpu/drm/i915/i915_drv.h               |   1 +
>  4 files changed, 105 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> index aa470c70a198..d779a33c70db 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -45,6 +45,7 @@
>  #include "intel_lspcon.h"
>  #include "intel_panel.h"
>  #include "intel_psr.h"
> +#include "intel_sprite.h"
>  #include "intel_tc.h"
>  #include "intel_vdsc.h"
>  
> @@ -3200,6 +3201,97 @@ static void intel_ddi_disable_fec_state(struct intel_encoder *encoder,
>  	POSTING_READ(intel_dp->regs.dp_tp_ctl);
>  }
>  
> +static u32 intel_get_frame_time_us(const struct intel_crtc_state *cstate)
> +{
> +	if (!cstate || !cstate->base.active)
> +		return 0;
> +
> +	return DIV_ROUND_UP(1000 * 1000,
> +			    drm_mode_vrefresh(&cstate->base.adjusted_mode));
> +}
> +
> +static void
> +tgl_clear_psr2_transcoder_exitline(const struct intel_crtc_state *cstate)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
> +	u32 val;
> +
> +	if (!cstate->dc3co_exitline)
> +		return;
> +
> +	val = I915_READ(EXITLINE(cstate->cpu_transcoder));
> +	val &= ~(EXITLINE_MASK | EXITLINE_ENABLE);
> +	I915_WRITE(EXITLINE(cstate->cpu_transcoder), val);
> +}
> +
> +static void
> +tgl_set_psr2_transcoder_exitline(const struct intel_crtc_state *cstate)
> +{
> +	u32 val, exit_scanlines;
> +	struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
> +
> +	if (!cstate->dc3co_exitline)
> +		return;
> +
> +	exit_scanlines = cstate->dc3co_exitline;
> +	exit_scanlines <<= EXITLINE_SHIFT;
> +	val = I915_READ(EXITLINE(cstate->cpu_transcoder));
> +	val &= ~(EXITLINE_MASK | EXITLINE_ENABLE);
> +	val |= exit_scanlines;
> +	val |= EXITLINE_ENABLE;
> +	I915_WRITE(EXITLINE(cstate->cpu_transcoder), val);
> +}
> +
> +static void tgl_dc3co_exitline_compute_config(struct intel_encoder *encoder,
> +					      struct intel_crtc_state *cstate)
> +{
> +	u32 exit_scanlines;
> +	struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
> +	u32 crtc_vdisplay = cstate->base.adjusted_mode.crtc_vdisplay;
> +
> +	dev_priv->psr.dc3co_frame_time_us = 0;

dev_priv->psr may be unrelated to this commit, so we can't update it
here; let's compute/set it in intel_psr_enable_locked().

> +	cstate->dc3co_exitline = 0;
> +
> +	if (!(dev_priv->csr.allowed_dc_mask & DC_STATE_EN_DC3CO))
> +		return;
> +
> +	/* B.Specs:49196 DC3CO only works with pipeA and DDIA.*/
> +	if (to_intel_crtc(cstate->base.crtc)->pipe != PIPE_A ||
> +	    encoder->port != PORT_A)
> +		return;
> +
> +	if (!cstate->has_psr2 || !cstate->base.active)
> +		return;
> +
> +	/*
> +	 * DC3CO Exit time 200us B.Spec 49196
> +	 * PSR2 transcoder Early Exit scanlines = ROUNDUP(200 / line time) + 1
> +	 */
> +	exit_scanlines =
> +		intel_usecs_to_scanlines(&cstate->base.adjusted_mode, 200) + 1;
> +
> +	if (WARN_ON(exit_scanlines > crtc_vdisplay))
> +		return;
> +
> +	cstate->dc3co_exitline = crtc_vdisplay - exit_scanlines;
> +	DRM_DEBUG_KMS("DC3CO exit scanlines %d\n", cstate->dc3co_exitline);
> +	dev_priv->psr.dc3co_frame_time_us = intel_get_frame_time_us(cstate);
> +}
> +
> +static void tgl_dc3co_exitline_get_config(struct intel_crtc_state *crtc_state)
> +{
> +	u32 val;
> +	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
> +
> +	if (INTEL_GEN(dev_priv) < 12)
> +		return;
> +
> +	val = I915_READ(EXITLINE(crtc_state->cpu_transcoder));
> +
> +	if (val & EXITLINE_ENABLE)
> +		crtc_state->dc3co_exitline = val & EXITLINE_MASK;
> +}
> +
>  static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder,
>  				  const struct intel_crtc_state *crtc_state,
>  				  const struct drm_connector_state *conn_state)
> @@ -3212,6 +3304,7 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder,
>  	int level = intel_ddi_dp_level(intel_dp);
>  	enum transcoder transcoder = crtc_state->cpu_transcoder;
>  
> +	tgl_set_psr2_transcoder_exitline(crtc_state);
>  	intel_dp_set_link_params(intel_dp, crtc_state->port_clock,
>  				 crtc_state->lane_count, is_mst);
>  
> @@ -3524,6 +3617,7 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder,
>  						  dig_port->ddi_io_power_domain);
>  
>  	intel_ddi_clk_disable(encoder);
> +	tgl_clear_psr2_transcoder_exitline(old_crtc_state);
>  }
>  
>  static void intel_ddi_post_disable_hdmi(struct intel_encoder *encoder,
> @@ -4070,6 +4164,9 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
>  		break;
>  	}
>  
> +	if (encoder->type == INTEL_OUTPUT_EDP)
> +		tgl_dc3co_exitline_get_config(pipe_config);
> +
>  	pipe_config->has_audio =
>  		intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder);
>  
> @@ -4147,10 +4244,13 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
>  	if (HAS_TRANSCODER_EDP(dev_priv) && port == PORT_A)
>  		pipe_config->cpu_transcoder = TRANSCODER_EDP;
>  
> -	if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI))
> +	if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI)) {
>  		ret = intel_hdmi_compute_config(encoder, pipe_config, conn_state);
> -	else
> +	} else {
>  		ret = intel_dp_compute_config(encoder, pipe_config, conn_state);
> +		tgl_dc3co_exitline_compute_config(encoder, pipe_config);
> +	}
> +
>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 8f125f1624bd..a467c7523e06 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -12820,6 +12820,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
>  
>  	PIPE_CONF_CHECK_I(pixel_multiplier);
>  	PIPE_CONF_CHECK_I(output_format);
> +	PIPE_CONF_CHECK_I(dc3co_exitline);
>  	PIPE_CONF_CHECK_BOOL(has_hdmi_sink);
>  	if ((INTEL_GEN(dev_priv) < 8 && !IS_HASWELL(dev_priv)) ||
>  	    IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 976669f01a8c..8aa38ace7845 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -870,6 +870,7 @@ struct intel_crtc_state {
>  
>  	bool has_psr;
>  	bool has_psr2;
> +	u32 dc3co_exitline;
>  
>  	/*
>  	 * Frequence the dpll for the port should run at. Differs from the
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index cddc98ea9965..7b2318c5c7a0 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -495,6 +495,7 @@ struct i915_psr {
>  	bool link_standby;
>  	bool colorimetry_support;
>  	bool psr2_enabled;
> +	u32 dc3co_frame_time_us;
>  	u8 sink_sync_latency;
>  	ktime_t last_entry_attempt;
>  	ktime_t last_exit;
> -- 
> 2.21.0
>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index aa470c70a198..d779a33c70db 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -45,6 +45,7 @@ 
 #include "intel_lspcon.h"
 #include "intel_panel.h"
 #include "intel_psr.h"
+#include "intel_sprite.h"
 #include "intel_tc.h"
 #include "intel_vdsc.h"
 
@@ -3200,6 +3201,97 @@  static void intel_ddi_disable_fec_state(struct intel_encoder *encoder,
 	POSTING_READ(intel_dp->regs.dp_tp_ctl);
 }
 
+static u32 intel_get_frame_time_us(const struct intel_crtc_state *cstate)
+{
+	if (!cstate || !cstate->base.active)
+		return 0;
+
+	return DIV_ROUND_UP(1000 * 1000,
+			    drm_mode_vrefresh(&cstate->base.adjusted_mode));
+}
+
+static void
+tgl_clear_psr2_transcoder_exitline(const struct intel_crtc_state *cstate)
+{
+	struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
+	u32 val;
+
+	if (!cstate->dc3co_exitline)
+		return;
+
+	val = I915_READ(EXITLINE(cstate->cpu_transcoder));
+	val &= ~(EXITLINE_MASK | EXITLINE_ENABLE);
+	I915_WRITE(EXITLINE(cstate->cpu_transcoder), val);
+}
+
+static void
+tgl_set_psr2_transcoder_exitline(const struct intel_crtc_state *cstate)
+{
+	u32 val, exit_scanlines;
+	struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
+
+	if (!cstate->dc3co_exitline)
+		return;
+
+	exit_scanlines = cstate->dc3co_exitline;
+	exit_scanlines <<= EXITLINE_SHIFT;
+	val = I915_READ(EXITLINE(cstate->cpu_transcoder));
+	val &= ~(EXITLINE_MASK | EXITLINE_ENABLE);
+	val |= exit_scanlines;
+	val |= EXITLINE_ENABLE;
+	I915_WRITE(EXITLINE(cstate->cpu_transcoder), val);
+}
+
+static void tgl_dc3co_exitline_compute_config(struct intel_encoder *encoder,
+					      struct intel_crtc_state *cstate)
+{
+	u32 exit_scanlines;
+	struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
+	u32 crtc_vdisplay = cstate->base.adjusted_mode.crtc_vdisplay;
+
+	dev_priv->psr.dc3co_frame_time_us = 0;
+	cstate->dc3co_exitline = 0;
+
+	if (!(dev_priv->csr.allowed_dc_mask & DC_STATE_EN_DC3CO))
+		return;
+
+	/* B.Specs:49196 DC3CO only works with pipeA and DDIA.*/
+	if (to_intel_crtc(cstate->base.crtc)->pipe != PIPE_A ||
+	    encoder->port != PORT_A)
+		return;
+
+	if (!cstate->has_psr2 || !cstate->base.active)
+		return;
+
+	/*
+	 * DC3CO Exit time 200us B.Spec 49196
+	 * PSR2 transcoder Early Exit scanlines = ROUNDUP(200 / line time) + 1
+	 */
+	exit_scanlines =
+		intel_usecs_to_scanlines(&cstate->base.adjusted_mode, 200) + 1;
+
+	if (WARN_ON(exit_scanlines > crtc_vdisplay))
+		return;
+
+	cstate->dc3co_exitline = crtc_vdisplay - exit_scanlines;
+	DRM_DEBUG_KMS("DC3CO exit scanlines %d\n", cstate->dc3co_exitline);
+	dev_priv->psr.dc3co_frame_time_us = intel_get_frame_time_us(cstate);
+}
+
+static void tgl_dc3co_exitline_get_config(struct intel_crtc_state *crtc_state)
+{
+	u32 val;
+	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+
+	if (INTEL_GEN(dev_priv) < 12)
+		return;
+
+	val = I915_READ(EXITLINE(crtc_state->cpu_transcoder));
+
+	if (val & EXITLINE_ENABLE)
+		crtc_state->dc3co_exitline = val & EXITLINE_MASK;
+}
+
 static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder,
 				  const struct intel_crtc_state *crtc_state,
 				  const struct drm_connector_state *conn_state)
@@ -3212,6 +3304,7 @@  static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder,
 	int level = intel_ddi_dp_level(intel_dp);
 	enum transcoder transcoder = crtc_state->cpu_transcoder;
 
+	tgl_set_psr2_transcoder_exitline(crtc_state);
 	intel_dp_set_link_params(intel_dp, crtc_state->port_clock,
 				 crtc_state->lane_count, is_mst);
 
@@ -3524,6 +3617,7 @@  static void intel_ddi_post_disable_dp(struct intel_encoder *encoder,
 						  dig_port->ddi_io_power_domain);
 
 	intel_ddi_clk_disable(encoder);
+	tgl_clear_psr2_transcoder_exitline(old_crtc_state);
 }
 
 static void intel_ddi_post_disable_hdmi(struct intel_encoder *encoder,
@@ -4070,6 +4164,9 @@  void intel_ddi_get_config(struct intel_encoder *encoder,
 		break;
 	}
 
+	if (encoder->type == INTEL_OUTPUT_EDP)
+		tgl_dc3co_exitline_get_config(pipe_config);
+
 	pipe_config->has_audio =
 		intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder);
 
@@ -4147,10 +4244,13 @@  static int intel_ddi_compute_config(struct intel_encoder *encoder,
 	if (HAS_TRANSCODER_EDP(dev_priv) && port == PORT_A)
 		pipe_config->cpu_transcoder = TRANSCODER_EDP;
 
-	if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI))
+	if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI)) {
 		ret = intel_hdmi_compute_config(encoder, pipe_config, conn_state);
-	else
+	} else {
 		ret = intel_dp_compute_config(encoder, pipe_config, conn_state);
+		tgl_dc3co_exitline_compute_config(encoder, pipe_config);
+	}
+
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 8f125f1624bd..a467c7523e06 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -12820,6 +12820,7 @@  intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 
 	PIPE_CONF_CHECK_I(pixel_multiplier);
 	PIPE_CONF_CHECK_I(output_format);
+	PIPE_CONF_CHECK_I(dc3co_exitline);
 	PIPE_CONF_CHECK_BOOL(has_hdmi_sink);
 	if ((INTEL_GEN(dev_priv) < 8 && !IS_HASWELL(dev_priv)) ||
 	    IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 976669f01a8c..8aa38ace7845 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -870,6 +870,7 @@  struct intel_crtc_state {
 
 	bool has_psr;
 	bool has_psr2;
+	u32 dc3co_exitline;
 
 	/*
 	 * Frequence the dpll for the port should run at. Differs from the
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index cddc98ea9965..7b2318c5c7a0 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -495,6 +495,7 @@  struct i915_psr {
 	bool link_standby;
 	bool colorimetry_support;
 	bool psr2_enabled;
+	u32 dc3co_frame_time_us;
 	u8 sink_sync_latency;
 	ktime_t last_entry_attempt;
 	ktime_t last_exit;