drm/i915/audio: add codec wakeup override enabled/disable callback
authorLu, Han <han.lu@intel.com>
Tue, 5 May 2015 01:05:47 +0000 (09:05 +0800)
committerTakashi Iwai <tiwai@suse.de>
Tue, 5 May 2015 12:44:19 +0000 (14:44 +0200)
Add support for enabling codec wakeup override signal to allow
re-enumeration of the controller on SKL after resume from low power state.

In SKL, HDMI/DP codec and PCH HD Audio Controller are in different power
wells, so it's necessary to reset display audio codecs when power well on,
otherwise display audio codecs will disappear when resume from low power
state.
Reset steps when power on:
    enable codec wakeup -> azx_init_chip() -> disable codec wakeup

v3 by Jani: Simplify to only support toggling the appropriate chicken bit.

v4 by Han: add explanation and specify the hw swquence.

Signed-off-by: Lu, Han <han.lu@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_audio.c
include/drm/i915_component.h

index 3da1af46625c73a5a24c996b56e94c6f0b637526..7d88f4f515941207f2e8ba3704b6263007ba1f89 100644 (file)
@@ -6477,6 +6477,9 @@ enum skl_disp_power_wells {
 #define   AUDIO_CP_READY(trans)                ((1 << 1) << ((trans) * 4))
 #define   AUDIO_ELD_VALID(trans)       ((1 << 0) << ((trans) * 4))
 
+#define HSW_AUD_CHICKENBIT                     0x65f10
+#define   SKL_AUD_CODEC_WAKE_SIGNAL            (1 << 15)
+
 /* HSW Power Wells */
 #define HSW_PWR_WELL_BIOS                      0x45400 /* CTL1 */
 #define HSW_PWR_WELL_DRIVER                    0x45404 /* CTL2 */
index 2396cc702d18b3f48c08e5d6b7025770e60c65bf..ef342571ae6ae936b32d5f1a569358f9915fba2e 100644 (file)
@@ -475,6 +475,32 @@ static void i915_audio_component_put_power(struct device *dev)
        intel_display_power_put(dev_to_i915(dev), POWER_DOMAIN_AUDIO);
 }
 
+static void i915_audio_component_codec_wake_override(struct device *dev,
+                                                    bool enable)
+{
+       struct drm_i915_private *dev_priv = dev_to_i915(dev);
+       u32 tmp;
+
+       if (!IS_SKYLAKE(dev_priv))
+               return;
+
+       /*
+        * Enable/disable generating the codec wake signal, overriding the
+        * internal logic to generate the codec wake to controller.
+        */
+       tmp = I915_READ(HSW_AUD_CHICKENBIT);
+       tmp &= ~SKL_AUD_CODEC_WAKE_SIGNAL;
+       I915_WRITE(HSW_AUD_CHICKENBIT, tmp);
+       usleep_range(1000, 1500);
+
+       if (enable) {
+               tmp = I915_READ(HSW_AUD_CHICKENBIT);
+               tmp |= SKL_AUD_CODEC_WAKE_SIGNAL;
+               I915_WRITE(HSW_AUD_CHICKENBIT, tmp);
+               usleep_range(1000, 1500);
+       }
+}
+
 /* Get CDCLK in kHz  */
 static int i915_audio_component_get_cdclk_freq(struct device *dev)
 {
@@ -495,6 +521,7 @@ static const struct i915_audio_component_ops i915_audio_component_ops = {
        .owner          = THIS_MODULE,
        .get_power      = i915_audio_component_get_power,
        .put_power      = i915_audio_component_put_power,
+       .codec_wake_override = i915_audio_component_codec_wake_override,
        .get_cdclk_freq = i915_audio_component_get_cdclk_freq,
 };
 
index 3e2f22e5bf3c075679da1f0364f507b0f5287d9e..c9a8b64aa33b14bfcff5a13c4d0bee28a362ea75 100644 (file)
@@ -31,6 +31,7 @@ struct i915_audio_component {
                struct module *owner;
                void (*get_power)(struct device *);
                void (*put_power)(struct device *);
+               void (*codec_wake_override)(struct device *, bool enable);
                int (*get_cdclk_freq)(struct device *);
        } *ops;
 };