diff options
Diffstat (limited to 'sound/pci/cs46xx/cs46xx_lib.c')
-rw-r--r-- | sound/pci/cs46xx/cs46xx_lib.c | 77 |
1 files changed, 62 insertions, 15 deletions
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index bef1f6d1859c..71d7aab9d869 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -2897,6 +2897,10 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip) | |||
2897 | } | 2897 | } |
2898 | #endif | 2898 | #endif |
2899 | 2899 | ||
2900 | #ifdef CONFIG_PM | ||
2901 | kfree(chip->saved_regs); | ||
2902 | #endif | ||
2903 | |||
2900 | pci_disable_device(chip->pci); | 2904 | pci_disable_device(chip->pci); |
2901 | kfree(chip); | 2905 | kfree(chip); |
2902 | return 0; | 2906 | return 0; |
@@ -3140,6 +3144,23 @@ static int snd_cs46xx_chip_init(struct snd_cs46xx *chip) | |||
3140 | /* | 3144 | /* |
3141 | * start and load DSP | 3145 | * start and load DSP |
3142 | */ | 3146 | */ |
3147 | |||
3148 | static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip) | ||
3149 | { | ||
3150 | unsigned int tmp; | ||
3151 | |||
3152 | snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM); | ||
3153 | |||
3154 | tmp = snd_cs46xx_peek(chip, BA1_PFIE); | ||
3155 | tmp &= ~0x0000f03f; | ||
3156 | snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt enable */ | ||
3157 | |||
3158 | tmp = snd_cs46xx_peek(chip, BA1_CIE); | ||
3159 | tmp &= ~0x0000003f; | ||
3160 | tmp |= 0x00000001; | ||
3161 | snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt enable */ | ||
3162 | } | ||
3163 | |||
3143 | int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip) | 3164 | int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip) |
3144 | { | 3165 | { |
3145 | unsigned int tmp; | 3166 | unsigned int tmp; |
@@ -3214,19 +3235,7 @@ int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip) | |||
3214 | 3235 | ||
3215 | snd_cs46xx_proc_start(chip); | 3236 | snd_cs46xx_proc_start(chip); |
3216 | 3237 | ||
3217 | /* | 3238 | cs46xx_enable_stream_irqs(chip); |
3218 | * Enable interrupts on the part. | ||
3219 | */ | ||
3220 | snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM); | ||
3221 | |||
3222 | tmp = snd_cs46xx_peek(chip, BA1_PFIE); | ||
3223 | tmp &= ~0x0000f03f; | ||
3224 | snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt enable */ | ||
3225 | |||
3226 | tmp = snd_cs46xx_peek(chip, BA1_CIE); | ||
3227 | tmp &= ~0x0000003f; | ||
3228 | tmp |= 0x00000001; | ||
3229 | snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt enable */ | ||
3230 | 3239 | ||
3231 | #ifndef CONFIG_SND_CS46XX_NEW_DSP | 3240 | #ifndef CONFIG_SND_CS46XX_NEW_DSP |
3232 | /* set the attenuation to 0dB */ | 3241 | /* set the attenuation to 0dB */ |
@@ -3665,11 +3674,19 @@ static struct cs_card_type __devinitdata cards[] = { | |||
3665 | * APM support | 3674 | * APM support |
3666 | */ | 3675 | */ |
3667 | #ifdef CONFIG_PM | 3676 | #ifdef CONFIG_PM |
3677 | static unsigned int saved_regs[] = { | ||
3678 | BA0_ACOSV, | ||
3679 | BA0_ASER_FADDR, | ||
3680 | BA0_ASER_MASTER, | ||
3681 | BA1_PVOL, | ||
3682 | BA1_CVOL, | ||
3683 | }; | ||
3684 | |||
3668 | int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) | 3685 | int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) |
3669 | { | 3686 | { |
3670 | struct snd_card *card = pci_get_drvdata(pci); | 3687 | struct snd_card *card = pci_get_drvdata(pci); |
3671 | struct snd_cs46xx *chip = card->private_data; | 3688 | struct snd_cs46xx *chip = card->private_data; |
3672 | int amp_saved; | 3689 | int i, amp_saved; |
3673 | 3690 | ||
3674 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 3691 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
3675 | chip->in_suspend = 1; | 3692 | chip->in_suspend = 1; |
@@ -3680,6 +3697,10 @@ int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) | |||
3680 | snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); | 3697 | snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); |
3681 | snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); | 3698 | snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); |
3682 | 3699 | ||
3700 | /* save some registers */ | ||
3701 | for (i = 0; i < ARRAY_SIZE(saved_regs); i++) | ||
3702 | chip->saved_regs[i] = snd_cs46xx_peekBA0(chip, saved_regs[i]); | ||
3703 | |||
3683 | amp_saved = chip->amplifier; | 3704 | amp_saved = chip->amplifier; |
3684 | /* turn off amp */ | 3705 | /* turn off amp */ |
3685 | chip->amplifier_ctrl(chip, -chip->amplifier); | 3706 | chip->amplifier_ctrl(chip, -chip->amplifier); |
@@ -3698,7 +3719,7 @@ int snd_cs46xx_resume(struct pci_dev *pci) | |||
3698 | { | 3719 | { |
3699 | struct snd_card *card = pci_get_drvdata(pci); | 3720 | struct snd_card *card = pci_get_drvdata(pci); |
3700 | struct snd_cs46xx *chip = card->private_data; | 3721 | struct snd_cs46xx *chip = card->private_data; |
3701 | int amp_saved; | 3722 | int i, amp_saved; |
3702 | 3723 | ||
3703 | pci_set_power_state(pci, PCI_D0); | 3724 | pci_set_power_state(pci, PCI_D0); |
3704 | pci_restore_state(pci); | 3725 | pci_restore_state(pci); |
@@ -3716,6 +3737,16 @@ int snd_cs46xx_resume(struct pci_dev *pci) | |||
3716 | 3737 | ||
3717 | snd_cs46xx_chip_init(chip); | 3738 | snd_cs46xx_chip_init(chip); |
3718 | 3739 | ||
3740 | snd_cs46xx_reset(chip); | ||
3741 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | ||
3742 | cs46xx_dsp_resume(chip); | ||
3743 | /* restore some registers */ | ||
3744 | for (i = 0; i < ARRAY_SIZE(saved_regs); i++) | ||
3745 | snd_cs46xx_pokeBA0(chip, saved_regs[i], chip->saved_regs[i]); | ||
3746 | #else | ||
3747 | snd_cs46xx_download_image(chip); | ||
3748 | #endif | ||
3749 | |||
3719 | #if 0 | 3750 | #if 0 |
3720 | snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE, | 3751 | snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE, |
3721 | chip->ac97_general_purpose); | 3752 | chip->ac97_general_purpose); |
@@ -3730,6 +3761,13 @@ int snd_cs46xx_resume(struct pci_dev *pci) | |||
3730 | snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); | 3761 | snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); |
3731 | snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); | 3762 | snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); |
3732 | 3763 | ||
3764 | /* reset playback/capture */ | ||
3765 | snd_cs46xx_set_play_sample_rate(chip, 8000); | ||
3766 | snd_cs46xx_set_capture_sample_rate(chip, 8000); | ||
3767 | snd_cs46xx_proc_start(chip); | ||
3768 | |||
3769 | cs46xx_enable_stream_irqs(chip); | ||
3770 | |||
3733 | if (amp_saved) | 3771 | if (amp_saved) |
3734 | chip->amplifier_ctrl(chip, 1); /* turn amp on */ | 3772 | chip->amplifier_ctrl(chip, 1); /* turn amp on */ |
3735 | else | 3773 | else |
@@ -3896,6 +3934,15 @@ int __devinit snd_cs46xx_create(struct snd_card *card, | |||
3896 | 3934 | ||
3897 | snd_cs46xx_proc_init(card, chip); | 3935 | snd_cs46xx_proc_init(card, chip); |
3898 | 3936 | ||
3937 | #ifdef CONFIG_PM | ||
3938 | chip->saved_regs = kmalloc(sizeof(*chip->saved_regs) * | ||
3939 | ARRAY_SIZE(saved_regs), GFP_KERNEL); | ||
3940 | if (!chip->saved_regs) { | ||
3941 | snd_cs46xx_free(chip); | ||
3942 | return -ENOMEM; | ||
3943 | } | ||
3944 | #endif | ||
3945 | |||
3899 | chip->active_ctrl(chip, -1); /* disable CLKRUN */ | 3946 | chip->active_ctrl(chip, -1); /* disable CLKRUN */ |
3900 | 3947 | ||
3901 | snd_card_set_dev(card, &pci->dev); | 3948 | snd_card_set_dev(card, &pci->dev); |