Skip to content

Commit 59ed1ea

Browse files
committed
ALSA: hda - Move codec suspend/resume to codec driver
This patch moves the suspend/resume mechanisms down to each codec driver level, as we have a proper codec driver bound on the bus now. Then we get the asynchronous PM gratis without fiddling much in the driver level. As a soft-landing transition, implement the common suspend/resume pm ops for hda_codec_driver and keep the each codec driver intact. Only the callers of suspend/resume in the controller side (azx_suspend() and azx_resume()) are removed. Another involved place is azx_bus_reset() calling the temporary suspend and resume as a hackish method of bus reset. The HD-audio core provide a helper function snd_hda_bus_reset() instead. Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent d8a766a commit 59ed1ea

File tree

6 files changed

+39
-86
lines changed

6 files changed

+39
-86
lines changed

sound/pci/hda/hda_bind.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/mutex.h>
99
#include <linux/module.h>
1010
#include <linux/export.h>
11+
#include <linux/pm.h>
1112
#include <sound/core.h>
1213
#include "hda_codec.h"
1314
#include "hda_local.h"
@@ -138,7 +139,7 @@ int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name,
138139
drv->driver.bus = &snd_hda_bus_type;
139140
drv->driver.probe = hda_codec_driver_probe;
140141
drv->driver.remove = hda_codec_driver_remove;
141-
/* TODO: PM and others */
142+
drv->driver.pm = &hda_codec_driver_pm;
142143
return driver_register(&drv->driver);
143144
}
144145
EXPORT_SYMBOL_GPL(__hda_codec_driver_register);

sound/pci/hda/hda_codec.c

Lines changed: 33 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
12501250
dev->groups = snd_hda_dev_attr_groups;
12511251
dev_set_name(dev, "hdaudioC%dD%d", bus->card->number, codec_addr);
12521252
dev_set_drvdata(dev, codec); /* for sysfs */
1253+
device_enable_async_suspend(dev);
12531254

12541255
codec->bus = bus;
12551256
codec->addr = codec_addr;
@@ -3970,8 +3971,31 @@ static void hda_call_codec_resume(struct hda_codec *codec)
39703971
codec->in_pm = 0;
39713972
snd_hda_power_down(codec); /* flag down before returning */
39723973
}
3974+
3975+
static int hda_codec_driver_suspend(struct device *dev)
3976+
{
3977+
struct hda_codec *codec = dev_to_hda_codec(dev);
3978+
int i;
3979+
3980+
cancel_delayed_work_sync(&codec->jackpoll_work);
3981+
for (i = 0; i < codec->num_pcms; i++)
3982+
snd_pcm_suspend_all(codec->pcm_info[i].pcm);
3983+
hda_call_codec_suspend(codec, false);
3984+
return 0;
3985+
}
3986+
3987+
static int hda_codec_driver_resume(struct device *dev)
3988+
{
3989+
hda_call_codec_resume(dev_to_hda_codec(dev));
3990+
return 0;
3991+
}
39733992
#endif /* CONFIG_PM */
39743993

3994+
/* referred in hda_bind.c */
3995+
const struct dev_pm_ops hda_codec_driver_pm = {
3996+
SET_SYSTEM_SLEEP_PM_OPS(hda_codec_driver_suspend,
3997+
hda_codec_driver_resume)
3998+
};
39753999

39764000
/**
39774001
* snd_hda_build_controls - build mixer controls
@@ -5505,77 +5529,26 @@ int snd_hda_add_imux_item(struct hda_codec *codec,
55055529
}
55065530
EXPORT_SYMBOL_GPL(snd_hda_add_imux_item);
55075531

5508-
5509-
#ifdef CONFIG_PM
5510-
/*
5511-
* power management
5512-
*/
5513-
5514-
5515-
static void hda_async_suspend(void *data, async_cookie_t cookie)
5516-
{
5517-
hda_call_codec_suspend(data, false);
5518-
}
5519-
5520-
static void hda_async_resume(void *data, async_cookie_t cookie)
5521-
{
5522-
hda_call_codec_resume(data);
5523-
}
5524-
55255532
/**
5526-
* snd_hda_suspend - suspend the codecs
5527-
* @bus: the HDA bus
5528-
*
5529-
* Returns 0 if successful.
5533+
* snd_hda_bus_reset - Reset the bus
5534+
* @bus: HD-audio bus
55305535
*/
5531-
int snd_hda_suspend(struct hda_bus *bus)
5536+
void snd_hda_bus_reset(struct hda_bus *bus)
55325537
{
55335538
struct hda_codec *codec;
5534-
ASYNC_DOMAIN_EXCLUSIVE(domain);
55355539

55365540
list_for_each_entry(codec, &bus->codec_list, list) {
5541+
/* FIXME: maybe a better way needed for forced reset */
55375542
cancel_delayed_work_sync(&codec->jackpoll_work);
5543+
#ifdef CONFIG_PM
55385544
if (hda_codec_is_power_on(codec)) {
5539-
if (bus->num_codecs > 1)
5540-
async_schedule_domain(hda_async_suspend, codec,
5541-
&domain);
5542-
else
5543-
hda_call_codec_suspend(codec, false);
5544-
}
5545-
}
5546-
5547-
if (bus->num_codecs > 1)
5548-
async_synchronize_full_domain(&domain);
5549-
5550-
return 0;
5551-
}
5552-
EXPORT_SYMBOL_GPL(snd_hda_suspend);
5553-
5554-
/**
5555-
* snd_hda_resume - resume the codecs
5556-
* @bus: the HDA bus
5557-
*
5558-
* Returns 0 if successful.
5559-
*/
5560-
int snd_hda_resume(struct hda_bus *bus)
5561-
{
5562-
struct hda_codec *codec;
5563-
ASYNC_DOMAIN_EXCLUSIVE(domain);
5564-
5565-
list_for_each_entry(codec, &bus->codec_list, list) {
5566-
if (bus->num_codecs > 1)
5567-
async_schedule_domain(hda_async_resume, codec, &domain);
5568-
else
5545+
hda_call_codec_suspend(codec, false);
55695546
hda_call_codec_resume(codec);
5547+
}
5548+
#endif
55705549
}
5571-
5572-
if (bus->num_codecs > 1)
5573-
async_synchronize_full_domain(&domain);
5574-
5575-
return 0;
55765550
}
5577-
EXPORT_SYMBOL_GPL(snd_hda_resume);
5578-
#endif /* CONFIG_PM */
5551+
EXPORT_SYMBOL_GPL(snd_hda_bus_reset);
55795552

55805553
/*
55815554
* generic arrays

sound/pci/hda/hda_codec.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -567,14 +567,12 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
567567

568568
int snd_hda_lock_devices(struct hda_bus *bus);
569569
void snd_hda_unlock_devices(struct hda_bus *bus);
570+
void snd_hda_bus_reset(struct hda_bus *bus);
570571

571572
/*
572573
* power management
573574
*/
574-
#ifdef CONFIG_PM
575-
int snd_hda_suspend(struct hda_bus *bus);
576-
int snd_hda_resume(struct hda_bus *bus);
577-
#endif
575+
extern const struct dev_pm_ops hda_codec_driver_pm;
578576

579577
static inline
580578
int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid)

sound/pci/hda/hda_controller.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,15 +1780,8 @@ static void azx_bus_reset(struct hda_bus *bus)
17801780
bus->in_reset = 1;
17811781
azx_stop_chip(chip);
17821782
azx_init_chip(chip, true);
1783-
#ifdef CONFIG_PM
1784-
if (chip->initialized) {
1785-
struct azx_pcm *p;
1786-
list_for_each_entry(p, &chip->pcm_list, list)
1787-
snd_pcm_suspend_all(p->pcm);
1788-
snd_hda_suspend(chip->bus);
1789-
snd_hda_resume(chip->bus);
1790-
}
1791-
#endif
1783+
if (chip->initialized)
1784+
snd_hda_bus_reset(chip->bus);
17921785
bus->in_reset = 0;
17931786
}
17941787

sound/pci/hda/hda_intel.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,6 @@ static int azx_suspend(struct device *dev)
772772
struct snd_card *card = dev_get_drvdata(dev);
773773
struct azx *chip;
774774
struct hda_intel *hda;
775-
struct azx_pcm *p;
776775

777776
if (!card)
778777
return 0;
@@ -784,10 +783,6 @@ static int azx_suspend(struct device *dev)
784783

785784
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
786785
azx_clear_irq_pending(chip);
787-
list_for_each_entry(p, &chip->pcm_list, list)
788-
snd_pcm_suspend_all(p->pcm);
789-
if (chip->initialized)
790-
snd_hda_suspend(chip->bus);
791786
azx_stop_chip(chip);
792787
azx_enter_link_reset(chip);
793788
if (chip->irq >= 0) {
@@ -830,7 +825,6 @@ static int azx_resume(struct device *dev)
830825

831826
azx_init_chip(chip, true);
832827

833-
snd_hda_resume(chip->bus);
834828
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
835829
return 0;
836830
}

sound/pci/hda/hda_tegra.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -249,14 +249,9 @@ static int hda_tegra_suspend(struct device *dev)
249249
{
250250
struct snd_card *card = dev_get_drvdata(dev);
251251
struct azx *chip = card->private_data;
252-
struct azx_pcm *p;
253252
struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
254253

255254
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
256-
list_for_each_entry(p, &chip->pcm_list, list)
257-
snd_pcm_suspend_all(p->pcm);
258-
if (chip->initialized)
259-
snd_hda_suspend(chip->bus);
260255

261256
azx_stop_chip(chip);
262257
azx_enter_link_reset(chip);
@@ -277,7 +272,6 @@ static int hda_tegra_resume(struct device *dev)
277272

278273
azx_init_chip(chip, 1);
279274

280-
snd_hda_resume(chip->bus);
281275
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
282276

283277
return 0;

0 commit comments

Comments
 (0)