diff options
| author | Cássio Gabriel <cassiogabrielcontato@gmail.com> | 2026-04-09 02:07:46 -0300 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2026-04-09 12:02:39 +0200 |
| commit | efca489a86fc6a5364215fdf03c2fad3b864d03a (patch) | |
| tree | 82b507b5fca51b5fe267b1294d9eb05279de320b | |
| parent | 49690509ebdcbfa7618dd5a5ff3c89f7af9a5b43 (diff) | |
ALSA: msnd: add ISA and PnP system sleep callbacks
The msnd drivers do not implement system sleep callbacks today, so
they have no defined way to recover DSP state after suspend.
Add common card suspend/resume helpers, rerun the DSP
initialization path on resume, restore the cached capture-source
state, and rearm the shared IRQ for already-open users.
Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
Link: https://patch.msgid.link/20260409-msnd-pm-support-v1-2-2abef720d0e7@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
| -rw-r--r-- | sound/isa/msnd/msnd.h | 2 | ||||
| -rw-r--r-- | sound/isa/msnd/msnd_pinnacle.c | 95 |
2 files changed, 95 insertions, 2 deletions
diff --git a/sound/isa/msnd/msnd.h b/sound/isa/msnd/msnd.h index b25beca25c0d..56a700e6a5cb 100644 --- a/sound/isa/msnd/msnd.h +++ b/sound/isa/msnd/msnd.h @@ -253,6 +253,8 @@ struct snd_msnd { spinlock_t mixer_lock; int nresets; unsigned recsrc; + u8 pm_recsrc; + bool pm_mpu_input; #define LEVEL_ENTRIES 32 int left_levels[LEVEL_ENTRIES]; int right_levels[LEVEL_ENTRIES]; diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index c4eec391cd29..5b729bb02ef6 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -513,6 +513,19 @@ static void snd_msnd_mpu401_close(struct snd_mpu401 *mpu) snd_msnd_disable_irq(mpu->private_data); } +#ifdef CONFIG_PM +static u8 snd_msnd_pm_recsrc(struct snd_msnd *chip) +{ + /* Convert recsrc to the Capture Source selector: 0=Analog, 1=MASS, 2=SPDIF. */ + if (chip->recsrc & BIT(4)) + return 1; + if ((chip->recsrc & BIT(17)) && + test_bit(F_HAVEDIGITAL, &chip->flags)) + return 2; + return 0; +} +#endif + static long mpu_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; @@ -1001,10 +1014,73 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx) return 0; } +#ifdef CONFIG_PM +static int snd_msnd_card_suspend(struct snd_card *card) +{ + struct snd_msnd *chip = card->private_data; + struct snd_mpu401 *mpu; + int err; + + mpu = chip->rmidi ? chip->rmidi->private_data : NULL; + chip->pm_recsrc = snd_msnd_pm_recsrc(chip); + chip->pm_mpu_input = mpu && test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); + if (chip->pm_mpu_input) + snd_msnd_send_dsp_cmd(chip, HDEX_MIDI_IN_STOP); + + err = snd_msnd_force_irq(chip, false); + if (err < 0) { + if (chip->pm_mpu_input) + snd_msnd_send_dsp_cmd(chip, HDEX_MIDI_IN_START); + return err; + } + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + return 0; +} + +static int snd_msnd_card_resume(struct snd_card *card) +{ + struct snd_msnd *chip = card->private_data; + int err; + + err = snd_msnd_initialize(card); + if (err < 0) + return err; + + snd_msnd_calibrate_adc(chip, chip->play_sample_rate); + snd_msndmix_force_recsrc(chip, chip->pm_recsrc); + + err = snd_msnd_force_irq(chip, true); + if (err < 0) + return err; + + if (chip->pm_mpu_input) + snd_msnd_send_dsp_cmd(chip, HDEX_MIDI_IN_START); + + chip->nresets = 0; + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; +} + +static int snd_msnd_isa_suspend(struct device *dev, unsigned int idx, + pm_message_t state) +{ + return snd_msnd_card_suspend(dev_get_drvdata(dev)); +} + +static int snd_msnd_isa_resume(struct device *dev, unsigned int idx) +{ + return snd_msnd_card_resume(dev_get_drvdata(dev)); +} +#endif + static struct isa_driver snd_msnd_driver = { .match = snd_msnd_isa_match, .probe = snd_msnd_isa_probe, - /* FIXME: suspend, resume */ +#ifdef CONFIG_PM + .suspend = snd_msnd_isa_suspend, + .resume = snd_msnd_isa_resume, +#endif .driver = { .name = DEV_NAME }, @@ -1111,6 +1187,18 @@ static int snd_msnd_pnp_detect(struct pnp_card_link *pcard, return 0; } +#ifdef CONFIG_PM +static int snd_msnd_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state) +{ + return snd_msnd_card_suspend(pnp_get_card_drvdata(pcard)); +} + +static int snd_msnd_pnp_resume(struct pnp_card_link *pcard) +{ + return snd_msnd_card_resume(pnp_get_card_drvdata(pcard)); +} +#endif + static int isa_registered; static int pnp_registered; @@ -1127,6 +1215,10 @@ static struct pnp_card_driver msnd_pnpc_driver = { .name = "msnd_pinnacle", .id_table = msnd_pnpids, .probe = snd_msnd_pnp_detect, +#ifdef CONFIG_PM + .suspend = snd_msnd_pnp_suspend, + .resume = snd_msnd_pnp_resume, +#endif }; #endif /* CONFIG_PNP */ @@ -1161,4 +1253,3 @@ static void __exit snd_msnd_exit(void) module_init(snd_msnd_init); module_exit(snd_msnd_exit); - |
