diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 1b35115f7195..90b34e830415 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -98,9 +98,15 @@ EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset); static void hda_power_work(struct work_struct *work); static void hda_keep_power_on(struct hda_codec *codec); #define hda_codec_is_power_on(codec) ((codec)->power_on) +static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up) +{ + if (bus->ops.pm_notify) + bus->ops.pm_notify(bus, power_up); +} #else static inline void hda_keep_power_on(struct hda_codec *codec) {} #define hda_codec_is_power_on(codec) 1 +#define hda_call_pm_notify(bus, state) {} #endif /** @@ -1199,6 +1205,10 @@ static void snd_hda_codec_free(struct hda_codec *codec) codec->bus->caddr_tbl[codec->addr] = NULL; if (codec->patch_ops.free) codec->patch_ops.free(codec); +#ifdef CONFIG_SND_HDA_POWER_SAVE + if (codec->power_on) + hda_call_pm_notify(codec->bus, false); +#endif module_put(codec->owner); free_hda_cache(&codec->amp_cache); free_hda_cache(&codec->cmd_cache); @@ -1271,6 +1281,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, * phase. */ hda_keep_power_on(codec); + hda_call_pm_notify(bus, true); #endif if (codec->bus->modelname) { @@ -3576,7 +3587,7 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, } #ifdef CONFIG_SND_HDA_POWER_SAVE - if ((power_state == AC_PWRST_D3) + if (!codec->bus->power_keep_link_on && power_state == AC_PWRST_D3 && codec->d3_stop_clk && (state & AC_PWRST_CLK_STOP_OK)) codec->d3_stop_clk_ok = 1; #endif @@ -4430,8 +4441,8 @@ static void hda_power_work(struct work_struct *work) spin_unlock(&codec->power_lock); hda_call_codec_suspend(codec); - if (bus->ops.pm_notify) - bus->ops.pm_notify(bus, codec); + if (codec->d3_stop_clk_ok) + hda_call_pm_notify(bus, false); } static void hda_keep_power_on(struct hda_codec *codec) @@ -4488,8 +4499,8 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) codec->power_transition = 1; /* avoid reentrance */ spin_unlock(&codec->power_lock); - if (bus->ops.pm_notify) - bus->ops.pm_notify(bus, codec); + if (codec->d3_stop_clk_ok) /* flag set at suspend */ + hda_call_pm_notify(bus, true); hda_call_codec_resume(codec); spin_lock(&codec->power_lock); diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 72477ccb20f9..2e5a22fec0be 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -616,7 +616,7 @@ struct hda_bus_ops { void (*bus_reset)(struct hda_bus *bus); #ifdef CONFIG_SND_HDA_POWER_SAVE /* notify power-up/down from codec to controller */ - void (*pm_notify)(struct hda_bus *bus, struct hda_codec *codec); + void (*pm_notify)(struct hda_bus *bus, bool power_up); #endif }; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1c9c779dda55..1b6e856e7ab1 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1033,7 +1033,7 @@ static unsigned int azx_get_response(struct hda_bus *bus, } #ifdef CONFIG_SND_HDA_POWER_SAVE -static void azx_power_notify(struct hda_bus *bus, struct hda_codec *codec); +static void azx_power_notify(struct hda_bus *bus, bool power_up); #endif /* reset codec link */ @@ -2406,14 +2406,11 @@ static void azx_stop_chip(struct azx *chip) #ifdef CONFIG_SND_HDA_POWER_SAVE /* power-up/down the controller */ -static void azx_power_notify(struct hda_bus *bus, struct hda_codec *codec) +static void azx_power_notify(struct hda_bus *bus, bool power_up) { struct azx *chip = bus->private_data; - if (bus->power_keep_link_on || !codec->d3_stop_clk_ok) - return; - - if (codec->power_on) + if (power_up) pm_runtime_get_sync(&chip->pci->dev); else pm_runtime_put_sync(&chip->pci->dev); @@ -3273,15 +3270,6 @@ static void azx_firmware_cb(const struct firmware *fw, void *context) } #endif -static void rpm_get_all_codecs(struct azx *chip) -{ - struct hda_codec *codec; - - list_for_each_entry(codec, &chip->bus->codec_list, list) { - pm_runtime_get_noresume(&chip->pci->dev); - } -} - static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -3388,7 +3376,6 @@ static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip) goto out_free; chip->running = 1; - rpm_get_all_codecs(chip); /* all codecs are active */ power_down_all_codecs(chip); azx_notifier_register(chip); azx_add_card_list(chip);