]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/i915/display: program audio CDCLK-TS for keepalives
authorKai Vehmanen <kai.vehmanen@linux.intel.com>
Thu, 21 Oct 2021 10:59:15 +0000 (13:59 +0300)
committerUma Shankar <uma.shankar@intel.com>
Tue, 2 Nov 2021 10:15:52 +0000 (15:45 +0530)
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>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Acked-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Uma Shankar <uma.shankar@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211021105915.4128635-1-kai.vehmanen@linux.intel.com
drivers/gpu/drm/i915/display/intel_audio.c
drivers/gpu/drm/i915/display/intel_audio.h
drivers/gpu/drm/i915/display/intel_cdclk.c
drivers/gpu/drm/i915/i915_reg.h

index 03e8c05a74f63ff6b75aae57a95370bfda194c0b..a96523f1b052d91c3168fddb90087acf10de9fd0 100644 (file)
@@ -947,6 +947,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)
@@ -1330,6 +1364,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;
 }
 
index a3657c7a7ba2dcd63d207650a5335e0c56738a54..dcb259dd2da749599607938e963cc67743a02cc3 100644 (file)
@@ -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);
 
index 868dd43a7542f8ca9ab1a66c9271373759995c45..91c19e0a98d7b04ab2b3a826c53791de4fd03b5b 100644 (file)
@@ -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"
@@ -1975,6 +1976,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,
@@ -2003,6 +2006,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")) {
index e4f1d8275ad070f33ba54af0b9b0cbeb08105015..beeffbff6cf9d251d06f7f8cfc89724402d376be 100644 (file)
@@ -9782,6 +9782,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)))