Commit 4c25b932 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Takashi Iwai

ALSA: virtuoso: work around missing reset in the Xonar DS Windows driver

For the WM8776 chip, this driver uses a different sample format and
more features than the Windows driver.  When rebooting from Linux into
Windows, the latter driver does not reset the chip but assumes all its
registers have their default settings, so we get garbled sound or, if
the output happened to be muted before rebooting, no sound.

To make that driver happy, hook our driver's cleanup function into the
shutdown notifier and ensure that the chip gets reset.
Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
Reported-and-tested-by: Nathan Schagen
Cc: <stable@kernel.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent a2acad82
...@@ -155,6 +155,7 @@ void oxygen_pci_remove(struct pci_dev *pci); ...@@ -155,6 +155,7 @@ void oxygen_pci_remove(struct pci_dev *pci);
int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state);
int oxygen_pci_resume(struct pci_dev *pci); int oxygen_pci_resume(struct pci_dev *pci);
#endif #endif
void oxygen_pci_shutdown(struct pci_dev *pci);
/* oxygen_mixer.c */ /* oxygen_mixer.c */
......
...@@ -519,16 +519,21 @@ static void oxygen_init(struct oxygen *chip) ...@@ -519,16 +519,21 @@ static void oxygen_init(struct oxygen *chip)
} }
} }
static void oxygen_card_free(struct snd_card *card) static void oxygen_shutdown(struct oxygen *chip)
{ {
struct oxygen *chip = card->private_data;
spin_lock_irq(&chip->reg_lock); spin_lock_irq(&chip->reg_lock);
chip->interrupt_mask = 0; chip->interrupt_mask = 0;
chip->pcm_running = 0; chip->pcm_running = 0;
oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
spin_unlock_irq(&chip->reg_lock); spin_unlock_irq(&chip->reg_lock);
}
static void oxygen_card_free(struct snd_card *card)
{
struct oxygen *chip = card->private_data;
oxygen_shutdown(chip);
if (chip->irq >= 0) if (chip->irq >= 0)
free_irq(chip->irq, chip); free_irq(chip->irq, chip);
flush_scheduled_work(); flush_scheduled_work();
...@@ -778,3 +783,13 @@ int oxygen_pci_resume(struct pci_dev *pci) ...@@ -778,3 +783,13 @@ int oxygen_pci_resume(struct pci_dev *pci)
} }
EXPORT_SYMBOL(oxygen_pci_resume); EXPORT_SYMBOL(oxygen_pci_resume);
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
void oxygen_pci_shutdown(struct pci_dev *pci)
{
struct snd_card *card = pci_get_drvdata(pci);
struct oxygen *chip = card->private_data;
oxygen_shutdown(chip);
chip->model.cleanup(chip);
}
EXPORT_SYMBOL(oxygen_pci_shutdown);
...@@ -95,6 +95,7 @@ static struct pci_driver xonar_driver = { ...@@ -95,6 +95,7 @@ static struct pci_driver xonar_driver = {
.suspend = oxygen_pci_suspend, .suspend = oxygen_pci_suspend,
.resume = oxygen_pci_resume, .resume = oxygen_pci_resume,
#endif #endif
.shutdown = oxygen_pci_shutdown,
}; };
static int __init alsa_card_xonar_init(void) static int __init alsa_card_xonar_init(void)
......
...@@ -193,6 +193,7 @@ static void xonar_ds_init(struct oxygen *chip) ...@@ -193,6 +193,7 @@ static void xonar_ds_init(struct oxygen *chip)
static void xonar_ds_cleanup(struct oxygen *chip) static void xonar_ds_cleanup(struct oxygen *chip)
{ {
xonar_disable_output(chip); xonar_disable_output(chip);
wm8776_write(chip, WM8776_RESET, 0);
} }
static void xonar_ds_suspend(struct oxygen *chip) static void xonar_ds_suspend(struct oxygen *chip)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment