+#ifdef CONFIG_PM
+/*
+ * power management
+ */
+static unsigned char saved_regs[] = {
+ CM_REG_FUNCTRL1, CM_REG_CHFORMAT, CM_REG_LEGACY_CTRL, CM_REG_MISC_CTRL,
+ CM_REG_MIXER0, CM_REG_MIXER1, CM_REG_MIXER2, CM_REG_MIXER3, CM_REG_PLL,
+ CM_REG_CH0_FRAME1, CM_REG_CH0_FRAME2,
+ CM_REG_CH1_FRAME1, CM_REG_CH1_FRAME2, CM_REG_EXT_MISC,
+ CM_REG_INT_STATUS, CM_REG_INT_HLDCLR, CM_REG_FUNCTRL0,
+};
+
+static unsigned char saved_mixers[] = {
+ SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
+ SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1,
+ SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1,
+ SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1,
+ SB_DSP4_LINE_DEV, SB_DSP4_LINE_DEV + 1,
+ SB_DSP4_MIC_DEV, SB_DSP4_SPEAKER_DEV,
+ CM_REG_EXTENT_IND, SB_DSP4_OUTPUT_SW,
+ SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT,
+};
+
+static int snd_cmipci_suspend(struct pci_dev *pci, pm_message_t state)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct cmipci *cm = card->private_data;
+ int i;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+
+ snd_pcm_suspend_all(cm->pcm);
+ snd_pcm_suspend_all(cm->pcm2);
+ snd_pcm_suspend_all(cm->pcm_spdif);
+
+ /* save registers */
+ for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
+ cm->saved_regs[i] = snd_cmipci_read(cm, saved_regs[i]);
+ for (i = 0; i < ARRAY_SIZE(saved_mixers); i++)
+ cm->saved_mixers[i] = snd_cmipci_mixer_read(cm, saved_mixers[i]);
+
+ /* disable ints */
+ snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0);
+
+ pci_disable_device(pci);
+ pci_save_state(pci);
+ pci_set_power_state(pci, pci_choose_state(pci, state));
+ return 0;
+}
+
+static int snd_cmipci_resume(struct pci_dev *pci)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct cmipci *cm = card->private_data;
+ int i;
+
+ pci_set_power_state(pci, PCI_D0);
+ pci_restore_state(pci);
+ if (pci_enable_device(pci) < 0) {
+ printk(KERN_ERR "cmipci: pci_enable_device failed, "
+ "disabling device\n");
+ snd_card_disconnect(card);
+ return -EIO;
+ }
+ pci_set_master(pci);
+
+ /* reset / initialize to a sane state */
+ snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0);
+ snd_cmipci_ch_reset(cm, CM_CH_PLAY);
+ snd_cmipci_ch_reset(cm, CM_CH_CAPT);
+ snd_cmipci_mixer_write(cm, 0, 0);
+
+ /* restore registers */
+ for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
+ snd_cmipci_write(cm, saved_regs[i], cm->saved_regs[i]);
+ for (i = 0; i < ARRAY_SIZE(saved_mixers); i++)
+ snd_cmipci_mixer_write(cm, saved_mixers[i], cm->saved_mixers[i]);
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif /* CONFIG_PM */
+