aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-08-28 12:14:29 -0400
committerTakashi Iwai <tiwai@suse.de>2012-08-30 10:48:49 -0400
commit68467f51c1b578ad98593bf5dee4337bd8d7798d (patch)
tree52bd817b23e2274425bc6c8cc1776405bea8f7ea /sound
parent48ee7cb8b4867093c75eb5102f2359c9799b3341 (diff)
ALSA: hda - Fix runtime PM leftover refcounts
When the HD-audio is removed, it leaves the refcounts when codecs are powered up (usually yes) in the destructor. For fixing the unbalance, and cleaning up the code mess, this patch changes the following: - change pm_notify callback to take the explicit power on/off state, - check of D3 stop-clock and keep_link_on flags is moved to the caller side, - call pm_notify callback in snd_hda_codec_new() and snd_hda_codec_free() so that the refcounts are proprely updated. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_codec.c21
-rw-r--r--sound/pci/hda/hda_codec.h2
-rw-r--r--sound/pci/hda/hda_intel.c19
3 files changed, 20 insertions, 22 deletions
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);
98static void hda_power_work(struct work_struct *work); 98static void hda_power_work(struct work_struct *work);
99static void hda_keep_power_on(struct hda_codec *codec); 99static void hda_keep_power_on(struct hda_codec *codec);
100#define hda_codec_is_power_on(codec) ((codec)->power_on) 100#define hda_codec_is_power_on(codec) ((codec)->power_on)
101static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up)
102{
103 if (bus->ops.pm_notify)
104 bus->ops.pm_notify(bus, power_up);
105}
101#else 106#else
102static inline void hda_keep_power_on(struct hda_codec *codec) {} 107static inline void hda_keep_power_on(struct hda_codec *codec) {}
103#define hda_codec_is_power_on(codec) 1 108#define hda_codec_is_power_on(codec) 1
109#define hda_call_pm_notify(bus, state) {}
104#endif 110#endif
105 111
106/** 112/**
@@ -1199,6 +1205,10 @@ static void snd_hda_codec_free(struct hda_codec *codec)
1199 codec->bus->caddr_tbl[codec->addr] = NULL; 1205 codec->bus->caddr_tbl[codec->addr] = NULL;
1200 if (codec->patch_ops.free) 1206 if (codec->patch_ops.free)
1201 codec->patch_ops.free(codec); 1207 codec->patch_ops.free(codec);
1208#ifdef CONFIG_SND_HDA_POWER_SAVE
1209 if (codec->power_on)
1210 hda_call_pm_notify(codec->bus, false);
1211#endif
1202 module_put(codec->owner); 1212 module_put(codec->owner);
1203 free_hda_cache(&codec->amp_cache); 1213 free_hda_cache(&codec->amp_cache);
1204 free_hda_cache(&codec->cmd_cache); 1214 free_hda_cache(&codec->cmd_cache);
@@ -1271,6 +1281,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
1271 * phase. 1281 * phase.
1272 */ 1282 */
1273 hda_keep_power_on(codec); 1283 hda_keep_power_on(codec);
1284 hda_call_pm_notify(bus, true);
1274#endif 1285#endif
1275 1286
1276 if (codec->bus->modelname) { 1287 if (codec->bus->modelname) {
@@ -3576,7 +3587,7 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3576 } 3587 }
3577 3588
3578#ifdef CONFIG_SND_HDA_POWER_SAVE 3589#ifdef CONFIG_SND_HDA_POWER_SAVE
3579 if ((power_state == AC_PWRST_D3) 3590 if (!codec->bus->power_keep_link_on && power_state == AC_PWRST_D3
3580 && codec->d3_stop_clk && (state & AC_PWRST_CLK_STOP_OK)) 3591 && codec->d3_stop_clk && (state & AC_PWRST_CLK_STOP_OK))
3581 codec->d3_stop_clk_ok = 1; 3592 codec->d3_stop_clk_ok = 1;
3582#endif 3593#endif
@@ -4430,8 +4441,8 @@ static void hda_power_work(struct work_struct *work)
4430 spin_unlock(&codec->power_lock); 4441 spin_unlock(&codec->power_lock);
4431 4442
4432 hda_call_codec_suspend(codec); 4443 hda_call_codec_suspend(codec);
4433 if (bus->ops.pm_notify) 4444 if (codec->d3_stop_clk_ok)
4434 bus->ops.pm_notify(bus, codec); 4445 hda_call_pm_notify(bus, false);
4435} 4446}
4436 4447
4437static void hda_keep_power_on(struct hda_codec *codec) 4448static 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)
4488 codec->power_transition = 1; /* avoid reentrance */ 4499 codec->power_transition = 1; /* avoid reentrance */
4489 spin_unlock(&codec->power_lock); 4500 spin_unlock(&codec->power_lock);
4490 4501
4491 if (bus->ops.pm_notify) 4502 if (codec->d3_stop_clk_ok) /* flag set at suspend */
4492 bus->ops.pm_notify(bus, codec); 4503 hda_call_pm_notify(bus, true);
4493 hda_call_codec_resume(codec); 4504 hda_call_codec_resume(codec);
4494 4505
4495 spin_lock(&codec->power_lock); 4506 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 {
616 void (*bus_reset)(struct hda_bus *bus); 616 void (*bus_reset)(struct hda_bus *bus);
617#ifdef CONFIG_SND_HDA_POWER_SAVE 617#ifdef CONFIG_SND_HDA_POWER_SAVE
618 /* notify power-up/down from codec to controller */ 618 /* notify power-up/down from codec to controller */
619 void (*pm_notify)(struct hda_bus *bus, struct hda_codec *codec); 619 void (*pm_notify)(struct hda_bus *bus, bool power_up);
620#endif 620#endif
621}; 621};
622 622
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,
1033} 1033}
1034 1034
1035#ifdef CONFIG_SND_HDA_POWER_SAVE 1035#ifdef CONFIG_SND_HDA_POWER_SAVE
1036static void azx_power_notify(struct hda_bus *bus, struct hda_codec *codec); 1036static void azx_power_notify(struct hda_bus *bus, bool power_up);
1037#endif 1037#endif
1038 1038
1039/* reset codec link */ 1039/* reset codec link */
@@ -2406,14 +2406,11 @@ static void azx_stop_chip(struct azx *chip)
2406 2406
2407#ifdef CONFIG_SND_HDA_POWER_SAVE 2407#ifdef CONFIG_SND_HDA_POWER_SAVE
2408/* power-up/down the controller */ 2408/* power-up/down the controller */
2409static void azx_power_notify(struct hda_bus *bus, struct hda_codec *codec) 2409static void azx_power_notify(struct hda_bus *bus, bool power_up)
2410{ 2410{
2411 struct azx *chip = bus->private_data; 2411 struct azx *chip = bus->private_data;
2412 2412
2413 if (bus->power_keep_link_on || !codec->d3_stop_clk_ok) 2413 if (power_up)
2414 return;
2415
2416 if (codec->power_on)
2417 pm_runtime_get_sync(&chip->pci->dev); 2414 pm_runtime_get_sync(&chip->pci->dev);
2418 else 2415 else
2419 pm_runtime_put_sync(&chip->pci->dev); 2416 pm_runtime_put_sync(&chip->pci->dev);
@@ -3273,15 +3270,6 @@ static void azx_firmware_cb(const struct firmware *fw, void *context)
3273} 3270}
3274#endif 3271#endif
3275 3272
3276static void rpm_get_all_codecs(struct azx *chip)
3277{
3278 struct hda_codec *codec;
3279
3280 list_for_each_entry(codec, &chip->bus->codec_list, list) {
3281 pm_runtime_get_noresume(&chip->pci->dev);
3282 }
3283}
3284
3285static int __devinit azx_probe(struct pci_dev *pci, 3273static int __devinit azx_probe(struct pci_dev *pci,
3286 const struct pci_device_id *pci_id) 3274 const struct pci_device_id *pci_id)
3287{ 3275{
@@ -3388,7 +3376,6 @@ static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip)
3388 goto out_free; 3376 goto out_free;
3389 3377
3390 chip->running = 1; 3378 chip->running = 1;
3391 rpm_get_all_codecs(chip); /* all codecs are active */
3392 power_down_all_codecs(chip); 3379 power_down_all_codecs(chip);
3393 azx_notifier_register(chip); 3380 azx_notifier_register(chip);
3394 azx_add_card_list(chip); 3381 azx_add_card_list(chip);