diff mbox series

[v2] drm/i915/display: program audio CDCLK-TS for keepalives

Message ID 20210913164004.3999218-1-kai.vehmanen@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series [v2] drm/i915/display: program audio CDCLK-TS for keepalives | expand

Commit Message

Kai Vehmanen Sept. 13, 2021, 4:40 p.m. UTC
XE_LPD display adds support for display audio codec keepalive feature.
This feature works also when display codec is in D3 state and the audio
link is off (BCLK off). To enable this functionality, display driver
must update the AUD_TS_CDCLK_M/N registers whenever CDCLK is changed.
Actual timestamps are generated only when the audio codec driver
specifically enables the KeepAlive (KAE) feature.

This patch adds new hooks to intel_set_cdclk() in order to inform
display audio driver when CDCLK change is started and when it is
complete.

Bspec: 53679
Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_audio.c | 37 ++++++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_audio.h |  2 ++
 drivers/gpu/drm/i915/display/intel_cdclk.c |  5 +++
 drivers/gpu/drm/i915/i915_reg.h            |  4 +++
 4 files changed, 48 insertions(+)

Changes V1->V2:
 - addressed review comments Jani Nikula (Sep 10)
 - added an initial call to intel_audio_cdclk_change_post() so 
   that AUD_CDCLK initial configuration is always performance

Comments

Shankar, Uma Sept. 15, 2021, 7:55 p.m. UTC | #1
> -----Original Message-----
> From: Kai Vehmanen <kai.vehmanen@linux.intel.com>
> Sent: Monday, September 13, 2021 10:10 PM
> To: intel-gfx@lists.freedesktop.org
> Cc: Shankar, Uma <uma.shankar@intel.com>; ville.syrjala@linux.intel.com; Nikula,
> Jani <jani.nikula@intel.com>; Kai Vehmanen <kai.vehmanen@linux.intel.com>
> Subject: [PATCH v2] drm/i915/display: program audio CDCLK-TS for keepalives
> 
> XE_LPD display adds support for display audio codec keepalive feature.
> This feature works also when display codec is in D3 state and the audio link is off
> (BCLK off). To enable this functionality, display driver must update the
> AUD_TS_CDCLK_M/N registers whenever CDCLK is changed.
> Actual timestamps are generated only when the audio codec driver specifically
> enables the KeepAlive (KAE) feature.
> 
> This patch adds new hooks to intel_set_cdclk() in order to inform display audio driver
> when CDCLK change is started and when it is complete.

Looks Good to me.
Reviewed-by: Uma Shankar <uma.shankar@intel.com>

> Bspec: 53679
> Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_audio.c | 37 ++++++++++++++++++++++
> drivers/gpu/drm/i915/display/intel_audio.h |  2 ++
> drivers/gpu/drm/i915/display/intel_cdclk.c |  5 +++
>  drivers/gpu/drm/i915/i915_reg.h            |  4 +++
>  4 files changed, 48 insertions(+)
> 
> Changes V1->V2:
>  - addressed review comments Jani Nikula (Sep 10)
>  - added an initial call to intel_audio_cdclk_change_post() so
>    that AUD_CDCLK initial configuration is always performance
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_audio.c
> b/drivers/gpu/drm/i915/display/intel_audio.c
> index 532237588511..ff74dc4dc121 100644
> --- a/drivers/gpu/drm/i915/display/intel_audio.c
> +++ b/drivers/gpu/drm/i915/display/intel_audio.c
> @@ -936,6 +936,40 @@ void intel_init_audio_hooks(struct drm_i915_private
> *dev_priv)
>  	}
>  }
> 
> +struct aud_ts_cdclk_m_n {
> +	u8 m;
> +	u16 n;
> +};
> +
> +void intel_audio_cdclk_change_pre(struct drm_i915_private *i915) {
> +	if (DISPLAY_VER(i915) >= 13)
> +		intel_de_rmw(i915, AUD_TS_CDCLK_M, AUD_TS_CDCLK_M_EN, 0);
> }
> +
> +static void get_aud_ts_cdclk_m_n(int refclk, int cdclk, struct
> +aud_ts_cdclk_m_n *aud_ts) {
> +	if (refclk == 24000)
> +		aud_ts->m = 12;
> +	else
> +		aud_ts->m = 15;
> +
> +	aud_ts->n = cdclk * aud_ts->m / 24000; }
> +
> +void intel_audio_cdclk_change_post(struct drm_i915_private *i915) {
> +	struct aud_ts_cdclk_m_n aud_ts;
> +
> +	if (DISPLAY_VER(i915) >= 13) {
> +		get_aud_ts_cdclk_m_n(i915->cdclk.hw.ref, i915->cdclk.hw.cdclk,
> +&aud_ts);
> +
> +		intel_de_write(i915, AUD_TS_CDCLK_N, aud_ts.n);
> +		intel_de_write(i915, AUD_TS_CDCLK_M, aud_ts.m |
> AUD_TS_CDCLK_M_EN);
> +		drm_dbg_kms(&i915->drm, "aud_ts_cdclk set to M=%u, N=%u\n",
> aud_ts.m, aud_ts.n);
> +	}
> +}
> +
>  static int glk_force_audio_cdclk_commit(struct intel_atomic_state *state,
>  					struct intel_crtc *crtc,
>  					bool enable)
> @@ -1318,6 +1352,9 @@ static void i915_audio_component_init(struct
> drm_i915_private *dev_priv)
>  		dev_priv->audio_freq_cntrl = aud_freq;
>  	}
> 
> +	/* init with current cdclk */
> +	intel_audio_cdclk_change_post(dev_priv);
> +
>  	dev_priv->audio_component_registered = true;  }
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_audio.h
> b/drivers/gpu/drm/i915/display/intel_audio.h
> index a3657c7a7ba2..dcb259dd2da7 100644
> --- a/drivers/gpu/drm/i915/display/intel_audio.h
> +++ b/drivers/gpu/drm/i915/display/intel_audio.h
> @@ -18,6 +18,8 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
> void intel_audio_codec_disable(struct intel_encoder *encoder,
>  			       const struct intel_crtc_state *old_crtc_state,
>  			       const struct drm_connector_state *old_conn_state);
> +void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv);
> +void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv);
>  void intel_audio_init(struct drm_i915_private *dev_priv);  void
> intel_audio_deinit(struct drm_i915_private *dev_priv);
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c
> b/drivers/gpu/drm/i915/display/intel_cdclk.c
> index 9aec17b33819..a1365f31142d 100644
> --- a/drivers/gpu/drm/i915/display/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
> @@ -24,6 +24,7 @@
>  #include <linux/time.h>
> 
>  #include "intel_atomic.h"
> +#include "intel_audio.h"
>  #include "intel_bw.h"
>  #include "intel_cdclk.h"
>  #include "intel_de.h"
> @@ -1943,6 +1944,8 @@ static void intel_set_cdclk(struct drm_i915_private
> *dev_priv,
>  		intel_psr_pause(intel_dp);
>  	}
> 
> +	intel_audio_cdclk_change_pre(dev_priv);
> +
>  	/*
>  	 * Lock aux/gmbus while we change cdclk in case those
>  	 * functions use cdclk. Not all platforms/ports do, @@ -1971,6 +1974,8 @@
> static void intel_set_cdclk(struct drm_i915_private *dev_priv,
>  		intel_psr_resume(intel_dp);
>  	}
> 
> +	intel_audio_cdclk_change_post(dev_priv);
> +
>  	if (drm_WARN(&dev_priv->drm,
>  		     intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config),
>  		     "cdclk state doesn't match!\n")) { diff --git
> a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index
> bd63760207b0..795775c9e2eb 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -9734,6 +9734,10 @@ enum {
>  #define AUD_PIN_BUF_CTL		_MMIO(0x48414)
>  #define   AUD_PIN_BUF_ENABLE		REG_BIT(31)
> 
> +#define AUD_TS_CDCLK_M			_MMIO(0x65ea0)
> +#define   AUD_TS_CDCLK_M_EN		REG_BIT(31)
> +#define AUD_TS_CDCLK_N			_MMIO(0x65ea4)
> +
>  /* Display Audio Config Reg */
>  #define AUD_CONFIG_BE			_MMIO(0x65ef0)
>  #define HBLANK_EARLY_ENABLE_ICL(pipe)		(0x1 << (20 - (pipe)))
> --
> 2.32.0
Ville Syrjälä Oct. 6, 2021, 1:49 p.m. UTC | #2
On Mon, Sep 13, 2021 at 07:40:04PM +0300, Kai Vehmanen wrote:
> XE_LPD display adds support for display audio codec keepalive feature.
> This feature works also when display codec is in D3 state and the audio
> link is off (BCLK off). To enable this functionality, display driver
> must update the AUD_TS_CDCLK_M/N registers whenever CDCLK is changed.
> Actual timestamps are generated only when the audio codec driver
> specifically enables the KeepAlive (KAE) feature.
> 
> This patch adds new hooks to intel_set_cdclk() in order to inform
> display audio driver when CDCLK change is started and when it is
> complete.
> 
> Bspec: 53679
> Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_audio.c | 37 ++++++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_audio.h |  2 ++
>  drivers/gpu/drm/i915/display/intel_cdclk.c |  5 +++
>  drivers/gpu/drm/i915/i915_reg.h            |  4 +++
>  4 files changed, 48 insertions(+)
> 
> Changes V1->V2:
>  - addressed review comments Jani Nikula (Sep 10)
>  - added an initial call to intel_audio_cdclk_change_post() so 
>    that AUD_CDCLK initial configuration is always performance
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c
> index 532237588511..ff74dc4dc121 100644
> --- a/drivers/gpu/drm/i915/display/intel_audio.c
> +++ b/drivers/gpu/drm/i915/display/intel_audio.c
> @@ -936,6 +936,40 @@ void intel_init_audio_hooks(struct drm_i915_private *dev_priv)
>  	}
>  }
>  
> +struct aud_ts_cdclk_m_n {
> +	u8 m;
> +	u16 n;
> +};
> +
> +void intel_audio_cdclk_change_pre(struct drm_i915_private *i915)
> +{
> +	if (DISPLAY_VER(i915) >= 13)
> +		intel_de_rmw(i915, AUD_TS_CDCLK_M, AUD_TS_CDCLK_M_EN, 0);
> +}
> +
> +static void get_aud_ts_cdclk_m_n(int refclk, int cdclk, struct aud_ts_cdclk_m_n *aud_ts)
> +{
> +	if (refclk == 24000)
> +		aud_ts->m = 12;

Wasn't there a single exception to this rule? Ie. should this be 
if (refclk == 24000 && cdclk != something) ?

> +	else
> +		aud_ts->m = 15;
> +
> +	aud_ts->n = cdclk * aud_ts->m / 24000;
> +}
> +
> +void intel_audio_cdclk_change_post(struct drm_i915_private *i915)
> +{
> +	struct aud_ts_cdclk_m_n aud_ts;
> +
> +	if (DISPLAY_VER(i915) >= 13) {
> +		get_aud_ts_cdclk_m_n(i915->cdclk.hw.ref, i915->cdclk.hw.cdclk, &aud_ts);
> +
> +		intel_de_write(i915, AUD_TS_CDCLK_N, aud_ts.n);
> +		intel_de_write(i915, AUD_TS_CDCLK_M, aud_ts.m | AUD_TS_CDCLK_M_EN);
> +		drm_dbg_kms(&i915->drm, "aud_ts_cdclk set to M=%u, N=%u\n", aud_ts.m, aud_ts.n);
> +	}
> +}
> +
>  static int glk_force_audio_cdclk_commit(struct intel_atomic_state *state,
>  					struct intel_crtc *crtc,
>  					bool enable)
> @@ -1318,6 +1352,9 @@ static void i915_audio_component_init(struct drm_i915_private *dev_priv)
>  		dev_priv->audio_freq_cntrl = aud_freq;
>  	}
>  
> +	/* init with current cdclk */
> +	intel_audio_cdclk_change_post(dev_priv);
> +
>  	dev_priv->audio_component_registered = true;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_audio.h b/drivers/gpu/drm/i915/display/intel_audio.h
> index a3657c7a7ba2..dcb259dd2da7 100644
> --- a/drivers/gpu/drm/i915/display/intel_audio.h
> +++ b/drivers/gpu/drm/i915/display/intel_audio.h
> @@ -18,6 +18,8 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
>  void intel_audio_codec_disable(struct intel_encoder *encoder,
>  			       const struct intel_crtc_state *old_crtc_state,
>  			       const struct drm_connector_state *old_conn_state);
> +void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv);
> +void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv);
>  void intel_audio_init(struct drm_i915_private *dev_priv);
>  void intel_audio_deinit(struct drm_i915_private *dev_priv);
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
> index 9aec17b33819..a1365f31142d 100644
> --- a/drivers/gpu/drm/i915/display/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
> @@ -24,6 +24,7 @@
>  #include <linux/time.h>
>  
>  #include "intel_atomic.h"
> +#include "intel_audio.h"
>  #include "intel_bw.h"
>  #include "intel_cdclk.h"
>  #include "intel_de.h"
> @@ -1943,6 +1944,8 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
>  		intel_psr_pause(intel_dp);
>  	}
>  
> +	intel_audio_cdclk_change_pre(dev_priv);
> +
>  	/*
>  	 * Lock aux/gmbus while we change cdclk in case those
>  	 * functions use cdclk. Not all platforms/ports do,
> @@ -1971,6 +1974,8 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
>  		intel_psr_resume(intel_dp);
>  	}
>  
> +	intel_audio_cdclk_change_post(dev_priv);
> +
>  	if (drm_WARN(&dev_priv->drm,
>  		     intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config),
>  		     "cdclk state doesn't match!\n")) {
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index bd63760207b0..795775c9e2eb 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -9734,6 +9734,10 @@ enum {
>  #define AUD_PIN_BUF_CTL		_MMIO(0x48414)
>  #define   AUD_PIN_BUF_ENABLE		REG_BIT(31)
>  
> +#define AUD_TS_CDCLK_M			_MMIO(0x65ea0)
> +#define   AUD_TS_CDCLK_M_EN		REG_BIT(31)
> +#define AUD_TS_CDCLK_N			_MMIO(0x65ea4)
> +
>  /* Display Audio Config Reg */
>  #define AUD_CONFIG_BE			_MMIO(0x65ef0)
>  #define HBLANK_EARLY_ENABLE_ICL(pipe)		(0x1 << (20 - (pipe)))
> -- 
> 2.32.0
Kai Vehmanen Oct. 6, 2021, 3:45 p.m. UTC | #3
Hi,

On Wed, 6 Oct 2021, Ville Syrjälä wrote:

> On Mon, Sep 13, 2021 at 07:40:04PM +0300, Kai Vehmanen wrote:
> > XE_LPD display adds support for display audio codec keepalive feature.
> > This feature works also when display codec is in D3 state and the audio
> > link is off (BCLK off). To enable this functionality, display driver
> > must update the AUD_TS_CDCLK_M/N registers whenever CDCLK is changed.
> > Actual timestamps are generated only when the audio codec driver
> > specifically enables the KeepAlive (KAE) feature.
[...]
> > +	if (refclk == 24000)
> > +		aud_ts->m = 12;
> 
> Wasn't there a single exception to this rule? Ie. should this be 
> if (refclk == 24000 && cdclk != something) ?

ack. I had a discussion with hw folks on this and concluded we can go
with the simple formula.

Br, Kai
Ville Syrjälä Oct. 6, 2021, 4:56 p.m. UTC | #4
On Wed, Oct 06, 2021 at 06:45:31PM +0300, Kai Vehmanen wrote:
> Hi,
> 
> On Wed, 6 Oct 2021, Ville Syrjälä wrote:
> 
> > On Mon, Sep 13, 2021 at 07:40:04PM +0300, Kai Vehmanen wrote:
> > > XE_LPD display adds support for display audio codec keepalive feature.
> > > This feature works also when display codec is in D3 state and the audio
> > > link is off (BCLK off). To enable this functionality, display driver
> > > must update the AUD_TS_CDCLK_M/N registers whenever CDCLK is changed.
> > > Actual timestamps are generated only when the audio codec driver
> > > specifically enables the KeepAlive (KAE) feature.
> [...]
> > > +	if (refclk == 24000)
> > > +		aud_ts->m = 12;
> > 
> > Wasn't there a single exception to this rule? Ie. should this be 
> > if (refclk == 24000 && cdclk != something) ?
> 
> ack. I had a discussion with hw folks on this and concluded we can go
> with the simple formula.

OK. Seems fine by me.

Acked-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c
index 532237588511..ff74dc4dc121 100644
--- a/drivers/gpu/drm/i915/display/intel_audio.c
+++ b/drivers/gpu/drm/i915/display/intel_audio.c
@@ -936,6 +936,40 @@  void intel_init_audio_hooks(struct drm_i915_private *dev_priv)
 	}
 }
 
+struct aud_ts_cdclk_m_n {
+	u8 m;
+	u16 n;
+};
+
+void intel_audio_cdclk_change_pre(struct drm_i915_private *i915)
+{
+	if (DISPLAY_VER(i915) >= 13)
+		intel_de_rmw(i915, AUD_TS_CDCLK_M, AUD_TS_CDCLK_M_EN, 0);
+}
+
+static void get_aud_ts_cdclk_m_n(int refclk, int cdclk, struct aud_ts_cdclk_m_n *aud_ts)
+{
+	if (refclk == 24000)
+		aud_ts->m = 12;
+	else
+		aud_ts->m = 15;
+
+	aud_ts->n = cdclk * aud_ts->m / 24000;
+}
+
+void intel_audio_cdclk_change_post(struct drm_i915_private *i915)
+{
+	struct aud_ts_cdclk_m_n aud_ts;
+
+	if (DISPLAY_VER(i915) >= 13) {
+		get_aud_ts_cdclk_m_n(i915->cdclk.hw.ref, i915->cdclk.hw.cdclk, &aud_ts);
+
+		intel_de_write(i915, AUD_TS_CDCLK_N, aud_ts.n);
+		intel_de_write(i915, AUD_TS_CDCLK_M, aud_ts.m | AUD_TS_CDCLK_M_EN);
+		drm_dbg_kms(&i915->drm, "aud_ts_cdclk set to M=%u, N=%u\n", aud_ts.m, aud_ts.n);
+	}
+}
+
 static int glk_force_audio_cdclk_commit(struct intel_atomic_state *state,
 					struct intel_crtc *crtc,
 					bool enable)
@@ -1318,6 +1352,9 @@  static void i915_audio_component_init(struct drm_i915_private *dev_priv)
 		dev_priv->audio_freq_cntrl = aud_freq;
 	}
 
+	/* init with current cdclk */
+	intel_audio_cdclk_change_post(dev_priv);
+
 	dev_priv->audio_component_registered = true;
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_audio.h b/drivers/gpu/drm/i915/display/intel_audio.h
index a3657c7a7ba2..dcb259dd2da7 100644
--- a/drivers/gpu/drm/i915/display/intel_audio.h
+++ b/drivers/gpu/drm/i915/display/intel_audio.h
@@ -18,6 +18,8 @@  void intel_audio_codec_enable(struct intel_encoder *encoder,
 void intel_audio_codec_disable(struct intel_encoder *encoder,
 			       const struct intel_crtc_state *old_crtc_state,
 			       const struct drm_connector_state *old_conn_state);
+void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv);
+void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv);
 void intel_audio_init(struct drm_i915_private *dev_priv);
 void intel_audio_deinit(struct drm_i915_private *dev_priv);
 
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 9aec17b33819..a1365f31142d 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -24,6 +24,7 @@ 
 #include <linux/time.h>
 
 #include "intel_atomic.h"
+#include "intel_audio.h"
 #include "intel_bw.h"
 #include "intel_cdclk.h"
 #include "intel_de.h"
@@ -1943,6 +1944,8 @@  static void intel_set_cdclk(struct drm_i915_private *dev_priv,
 		intel_psr_pause(intel_dp);
 	}
 
+	intel_audio_cdclk_change_pre(dev_priv);
+
 	/*
 	 * Lock aux/gmbus while we change cdclk in case those
 	 * functions use cdclk. Not all platforms/ports do,
@@ -1971,6 +1974,8 @@  static void intel_set_cdclk(struct drm_i915_private *dev_priv,
 		intel_psr_resume(intel_dp);
 	}
 
+	intel_audio_cdclk_change_post(dev_priv);
+
 	if (drm_WARN(&dev_priv->drm,
 		     intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config),
 		     "cdclk state doesn't match!\n")) {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index bd63760207b0..795775c9e2eb 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -9734,6 +9734,10 @@  enum {
 #define AUD_PIN_BUF_CTL		_MMIO(0x48414)
 #define   AUD_PIN_BUF_ENABLE		REG_BIT(31)
 
+#define AUD_TS_CDCLK_M			_MMIO(0x65ea0)
+#define   AUD_TS_CDCLK_M_EN		REG_BIT(31)
+#define AUD_TS_CDCLK_N			_MMIO(0x65ea4)
+
 /* Display Audio Config Reg */
 #define AUD_CONFIG_BE			_MMIO(0x65ef0)
 #define HBLANK_EARLY_ENABLE_ICL(pipe)		(0x1 << (20 - (pipe)))