drm/i915: save AUD_FREQ_CNTRL state at audio domain suspend
authorKai Vehmanen <kai.vehmanen@linux.intel.com>
Fri, 20 Sep 2019 08:39:18 +0000 (11:39 +0300)
committerJani Nikula <jani.nikula@intel.com>
Mon, 23 Sep 2019 07:39:06 +0000 (10:39 +0300)
When audio power domain is suspended, the display driver must
save state of AUD_FREQ_CNTRL on Tiger Lake and Ice Lake
systems. The initial value of the register is set by BIOS and
is read by driver during the audio component init sequence.

Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190920083918.27057-1-kai.vehmanen@linux.intel.com
drivers/gpu/drm/i915/display/intel_audio.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_reg.h

index aac089c..54638d9 100644 (file)
@@ -852,10 +852,17 @@ static unsigned long i915_audio_component_get_power(struct device *kdev)
 
        ret = intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
 
-       /* Force CDCLK to 2*BCLK as long as we need audio to be powered. */
-       if (dev_priv->audio_power_refcount++ == 0)
+       if (dev_priv->audio_power_refcount++ == 0) {
+               if (IS_TIGERLAKE(dev_priv) || IS_ICELAKE(dev_priv)) {
+                       I915_WRITE(AUD_FREQ_CNTRL, dev_priv->audio_freq_cntrl);
+                       DRM_DEBUG_KMS("restored AUD_FREQ_CNTRL to 0x%x\n",
+                                     dev_priv->audio_freq_cntrl);
+               }
+
+               /* Force CDCLK to 2*BCLK as long as we need audio powered. */
                if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv))
                        glk_force_audio_cdclk(dev_priv, true);
+       }
 
        return ret;
 }
@@ -1116,6 +1123,12 @@ static void i915_audio_component_init(struct drm_i915_private *dev_priv)
                return;
        }
 
+       if (IS_TIGERLAKE(dev_priv) || IS_ICELAKE(dev_priv)) {
+               dev_priv->audio_freq_cntrl = I915_READ(AUD_FREQ_CNTRL);
+               DRM_DEBUG_KMS("init value of AUD_FREQ_CNTRL of 0x%x\n",
+                             dev_priv->audio_freq_cntrl);
+       }
+
        dev_priv->audio_component_registered = true;
 }
 
index 07f1e89..fcf7423 100644 (file)
@@ -1541,6 +1541,7 @@ struct drm_i915_private {
         */
        struct mutex av_mutex;
        int audio_power_refcount;
+       u32 audio_freq_cntrl;
 
        struct {
                struct mutex mutex;
index 8649a30..6ecb64c 100644 (file)
@@ -9127,6 +9127,8 @@ enum {
 #define HSW_AUD_CHICKENBIT                     _MMIO(0x65f10)
 #define   SKL_AUD_CODEC_WAKE_SIGNAL            (1 << 15)
 
+#define AUD_FREQ_CNTRL                 _MMIO(0x65900)
+
 /*
  * HSW - ICL power wells
  *