[alsa-devel] [PATCH 1/2] snd-ice1712: add suspend support for ICE1712 chip
Add suspend/resume support for ICE1712 chip. Card-specific subdrivers need to enable it and provide callbacks that suspend/resume the codecs.
Signed-off-by: Ondrej Zary linux@rainbow-software.org --- sound/pci/ice1712/ice1712.c | 85 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 8 deletions(-)
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 28ec872..dbb0f96 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -2428,6 +2428,13 @@ static int snd_ice1712_chip_init(struct snd_ice1712 *ice) snd_ice1712_write(ice, ICE1712_IREG_CONSUMER_POWERDOWN, 0); } snd_ice1712_set_pro_rate(ice, 48000, 1); + /* unmask used interrupts */ + outb(((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) == 0 ? + ICE1712_IRQ_MPU2 : 0) | + ((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_NO_CON_AC97) ? + ICE1712_IRQ_PBKDS | ICE1712_IRQ_CONCAP | ICE1712_IRQ_CONPBK : 0), + ICEREG(ice, IRQMASK)); + outb(0x00, ICEMT(ice, IRQ));
return 0; } @@ -2589,6 +2596,7 @@ static int snd_ice1712_create(struct snd_card *card, ice->pci = pci; ice->irq = -1; pci_set_master(pci); + /* disable legacy emulation */ pci_write_config_word(ice->pci, 0x40, 0x807f); pci_write_config_word(ice->pci, 0x42, 0x0006); snd_ice1712_proc_init(ice); @@ -2625,14 +2633,6 @@ static int snd_ice1712_create(struct snd_card *card, return -EIO; }
- /* unmask used interrupts */ - outb(((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) == 0 ? - ICE1712_IRQ_MPU2 : 0) | - ((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_NO_CON_AC97) ? - ICE1712_IRQ_PBKDS | ICE1712_IRQ_CONCAP | ICE1712_IRQ_CONPBK : 0), - ICEREG(ice, IRQMASK)); - outb(0x00, ICEMT(ice, IRQ)); - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops); if (err < 0) { snd_ice1712_free(ice); @@ -2809,11 +2809,80 @@ static void snd_ice1712_remove(struct pci_dev *pci) snd_card_free(card); }
+#ifdef CONFIG_PM_SLEEP +static int snd_ice1712_suspend(struct device *dev) +{ + struct pci_dev *pci = to_pci_dev(dev); + struct snd_card *card = dev_get_drvdata(dev); + struct snd_ice1712 *ice = card->private_data; + + if (!ice->pm_suspend_enabled) + return 0; + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + + snd_pcm_suspend_all(ice->pcm); + snd_pcm_suspend_all(ice->pcm_pro); + snd_pcm_suspend_all(ice->pcm_ds); + snd_ac97_suspend(ice->ac97); + + if (ice->pm_suspend) + ice->pm_suspend(ice); + + pci_disable_device(pci); + pci_save_state(pci); + pci_set_power_state(pci, PCI_D3hot); + return 0; +} + +static int snd_ice1712_resume(struct device *dev) +{ + struct pci_dev *pci = to_pci_dev(dev); + struct snd_card *card = dev_get_drvdata(dev); + struct snd_ice1712 *ice = card->private_data; + + if (!ice->pm_suspend_enabled) + return 0; + + pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + + if (pci_enable_device(pci) < 0) { + snd_card_disconnect(card); + return -EIO; + } + + pci_set_master(pci); + + if (snd_ice1712_chip_init(ice) < 0) { + snd_card_disconnect(card); + return -EIO; + } + + if (ice->pm_resume) + ice->pm_resume(ice); + + if (ice->ac97) + snd_ac97_resume(ice->ac97); + + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; +} + +static SIMPLE_DEV_PM_OPS(snd_ice1712_pm, snd_ice1712_suspend, snd_ice1712_resume); +#define SND_VT1712_PM_OPS &snd_ice1712_pm +#else +#define SND_VT1712_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ + static struct pci_driver ice1712_driver = { .name = KBUILD_MODNAME, .id_table = snd_ice1712_ids, .probe = snd_ice1712_probe, .remove = snd_ice1712_remove, + .driver = { + .pm = SND_VT1712_PM_OPS, + }, };
module_pci_driver(ice1712_driver);
Add suspend support for M-Audio cards based on ICE1712 chip. Tested with M-Audio Audiophile 24/96. S/PDIF will probably not work.
Signed-off-by: Ondrej Zary linux@rainbow-software.org --- sound/pci/ice1712/delta.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index 9e28cc1..c19ae72 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c @@ -575,6 +575,30 @@ static struct snd_ak4xxx_private akm_vx442_priv = { .mask_flags = 0, };
+#ifdef CONFIG_PM_SLEEP +static int snd_ice1712_delta_resume(struct snd_ice1712 *ice) +{ + unsigned char akm_backup[AK4XXX_IMAGE_SIZE]; + /* init codec and restore registers */ + if (ice->akm_codecs) { + memcpy(akm_backup, ice->akm->images, sizeof(akm_backup)); + snd_akm4xxx_init(ice->akm); + memcpy(ice->akm->images, akm_backup, sizeof(akm_backup)); + snd_akm4xxx_reset(ice->akm, 0); + } + + return 0; +} + +static int snd_ice1712_delta_suspend(struct snd_ice1712 *ice) +{ + if (ice->akm_codecs) /* reset & mute codec */ + snd_akm4xxx_reset(ice->akm, 1); + + return 0; +} +#endif + static int snd_ice1712_delta_init(struct snd_ice1712 *ice) { int err; @@ -621,7 +645,11 @@ static int snd_ice1712_delta_init(struct snd_ice1712 *ice) ice->num_total_adcs = 4; break; } - +#ifdef CONFIG_PM_SLEEP + ice->pm_resume = snd_ice1712_delta_resume; + ice->pm_suspend = snd_ice1712_delta_suspend; + ice->pm_suspend_enabled = 1; +#endif /* initialize the SPI clock to high */ tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); tmp |= ICE1712_DELTA_AP_CCLK;
At Sun, 30 Mar 2014 23:37:30 +0200, Ondrej Zary wrote:
Add suspend/resume support for ICE1712 chip. Card-specific subdrivers need to enable it and provide callbacks that suspend/resume the codecs.
Signed-off-by: Ondrej Zary linux@rainbow-software.org
Thanks, applied both patches.
Takashi
sound/pci/ice1712/ice1712.c | 85 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 8 deletions(-)
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 28ec872..dbb0f96 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -2428,6 +2428,13 @@ static int snd_ice1712_chip_init(struct snd_ice1712 *ice) snd_ice1712_write(ice, ICE1712_IREG_CONSUMER_POWERDOWN, 0); } snd_ice1712_set_pro_rate(ice, 48000, 1);
/* unmask used interrupts */
outb(((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) == 0 ?
ICE1712_IRQ_MPU2 : 0) |
((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_NO_CON_AC97) ?
ICE1712_IRQ_PBKDS | ICE1712_IRQ_CONCAP | ICE1712_IRQ_CONPBK : 0),
ICEREG(ice, IRQMASK));
outb(0x00, ICEMT(ice, IRQ));
return 0;
} @@ -2589,6 +2596,7 @@ static int snd_ice1712_create(struct snd_card *card, ice->pci = pci; ice->irq = -1; pci_set_master(pci);
- /* disable legacy emulation */ pci_write_config_word(ice->pci, 0x40, 0x807f); pci_write_config_word(ice->pci, 0x42, 0x0006); snd_ice1712_proc_init(ice);
@@ -2625,14 +2633,6 @@ static int snd_ice1712_create(struct snd_card *card, return -EIO; }
- /* unmask used interrupts */
- outb(((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) == 0 ?
ICE1712_IRQ_MPU2 : 0) |
((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_NO_CON_AC97) ?
ICE1712_IRQ_PBKDS | ICE1712_IRQ_CONCAP | ICE1712_IRQ_CONPBK : 0),
ICEREG(ice, IRQMASK));
- outb(0x00, ICEMT(ice, IRQ));
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops); if (err < 0) { snd_ice1712_free(ice);
@@ -2809,11 +2809,80 @@ static void snd_ice1712_remove(struct pci_dev *pci) snd_card_free(card); }
+#ifdef CONFIG_PM_SLEEP +static int snd_ice1712_suspend(struct device *dev) +{
- struct pci_dev *pci = to_pci_dev(dev);
- struct snd_card *card = dev_get_drvdata(dev);
- struct snd_ice1712 *ice = card->private_data;
- if (!ice->pm_suspend_enabled)
return 0;
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(ice->pcm);
- snd_pcm_suspend_all(ice->pcm_pro);
- snd_pcm_suspend_all(ice->pcm_ds);
- snd_ac97_suspend(ice->ac97);
- if (ice->pm_suspend)
ice->pm_suspend(ice);
- pci_disable_device(pci);
- pci_save_state(pci);
- pci_set_power_state(pci, PCI_D3hot);
- return 0;
+}
+static int snd_ice1712_resume(struct device *dev) +{
- struct pci_dev *pci = to_pci_dev(dev);
- struct snd_card *card = dev_get_drvdata(dev);
- struct snd_ice1712 *ice = card->private_data;
- if (!ice->pm_suspend_enabled)
return 0;
- pci_set_power_state(pci, PCI_D0);
- pci_restore_state(pci);
- if (pci_enable_device(pci) < 0) {
snd_card_disconnect(card);
return -EIO;
- }
- pci_set_master(pci);
- if (snd_ice1712_chip_init(ice) < 0) {
snd_card_disconnect(card);
return -EIO;
- }
- if (ice->pm_resume)
ice->pm_resume(ice);
- if (ice->ac97)
snd_ac97_resume(ice->ac97);
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
- return 0;
+}
+static SIMPLE_DEV_PM_OPS(snd_ice1712_pm, snd_ice1712_suspend, snd_ice1712_resume); +#define SND_VT1712_PM_OPS &snd_ice1712_pm +#else +#define SND_VT1712_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */
static struct pci_driver ice1712_driver = { .name = KBUILD_MODNAME, .id_table = snd_ice1712_ids, .probe = snd_ice1712_probe, .remove = snd_ice1712_remove,
- .driver = {
.pm = SND_VT1712_PM_OPS,
- },
};
module_pci_driver(ice1712_driver);
Ondrej Zary
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
participants (2)
-
Ondrej Zary
-
Takashi Iwai