drm/i915/audio: add codec wakeup override enabled/disable callback
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>
This commit is contained in:
parent
bd5b2d4407
commit
632f3ab95f
3 changed files with 31 additions and 0 deletions
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue