diff options
author | Takashi Iwai <tiwai@suse.de> | 2007-07-19 05:23:21 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2007-07-20 05:11:57 -0400 |
commit | 89f157d9e6bf08b65f93dcb1dca1de037079885f (patch) | |
tree | cd828ea196a97f13216bb1af2da68901a079f6c5 /sound | |
parent | 87d483630a4bd5af2beb2155c7ae8c408729a1a6 (diff) |
[ALSA] cs46xx - Fix PM resume
Fixed PM resume of cs46xx devices. It now restores properly the DSP
image and kick-off the DSP.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/cs46xx/cs46xx_lib.c | 77 | ||||
-rw-r--r-- | sound/pci/cs46xx/cs46xx_lib.h | 3 | ||||
-rw-r--r-- | sound/pci/cs46xx/dsp_spos.c | 170 |
3 files changed, 191 insertions, 59 deletions
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index bef1f6d1859..71d7aab9d86 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); |
diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h index f75750c2bd2..20dcd72f06c 100644 --- a/sound/pci/cs46xx/cs46xx_lib.h +++ b/sound/pci/cs46xx/cs46xx_lib.h | |||
@@ -86,6 +86,9 @@ static inline unsigned int snd_cs46xx_peekBA0(struct snd_cs46xx *chip, unsigned | |||
86 | struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip); | 86 | struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip); |
87 | void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip); | 87 | void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip); |
88 | int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module); | 88 | int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module); |
89 | #ifdef CONFIG_PM | ||
90 | int cs46xx_dsp_resume(struct snd_cs46xx * chip); | ||
91 | #endif | ||
89 | struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, | 92 | struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, |
90 | int symbol_type); | 93 | int symbol_type); |
91 | #ifdef CONFIG_PROC_FS | 94 | #ifdef CONFIG_PROC_FS |
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index 336e77e2600..590b35d91df 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c | |||
@@ -306,13 +306,59 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) | |||
306 | mutex_unlock(&chip->spos_mutex); | 306 | mutex_unlock(&chip->spos_mutex); |
307 | } | 307 | } |
308 | 308 | ||
309 | static int dsp_load_parameter(struct snd_cs46xx *chip, | ||
310 | struct dsp_segment_desc *parameter) | ||
311 | { | ||
312 | u32 doffset, dsize; | ||
313 | |||
314 | if (!parameter) { | ||
315 | snd_printdd("dsp_spos: module got no parameter segment\n"); | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET); | ||
320 | dsize = parameter->size * 4; | ||
321 | |||
322 | snd_printdd("dsp_spos: " | ||
323 | "downloading parameter data to chip (%08x-%08x)\n", | ||
324 | doffset,doffset + dsize); | ||
325 | if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) { | ||
326 | snd_printk(KERN_ERR "dsp_spos: " | ||
327 | "failed to download parameter data to DSP\n"); | ||
328 | return -EINVAL; | ||
329 | } | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | static int dsp_load_sample(struct snd_cs46xx *chip, | ||
334 | struct dsp_segment_desc *sample) | ||
335 | { | ||
336 | u32 doffset, dsize; | ||
337 | |||
338 | if (!sample) { | ||
339 | snd_printdd("dsp_spos: module got no sample segment\n"); | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | doffset = (sample->offset * 4 + DSP_SAMPLE_BYTE_OFFSET); | ||
344 | dsize = sample->size * 4; | ||
345 | |||
346 | snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n", | ||
347 | doffset,doffset + dsize); | ||
348 | |||
349 | if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) { | ||
350 | snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n"); | ||
351 | return -EINVAL; | ||
352 | } | ||
353 | return 0; | ||
354 | } | ||
355 | |||
309 | int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module) | 356 | int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module) |
310 | { | 357 | { |
311 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | 358 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; |
312 | struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM); | 359 | struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM); |
313 | struct dsp_segment_desc * parameter = get_segment_desc (module,SEGTYPE_SP_PARAMETER); | ||
314 | struct dsp_segment_desc * sample = get_segment_desc (module,SEGTYPE_SP_SAMPLE); | ||
315 | u32 doffset, dsize; | 360 | u32 doffset, dsize; |
361 | int err; | ||
316 | 362 | ||
317 | if (ins->nmodules == DSP_MAX_MODULES - 1) { | 363 | if (ins->nmodules == DSP_MAX_MODULES - 1) { |
318 | snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n"); | 364 | snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n"); |
@@ -326,49 +372,20 @@ int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * m | |||
326 | snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE); | 372 | snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE); |
327 | } | 373 | } |
328 | 374 | ||
329 | if (parameter == NULL) { | 375 | err = dsp_load_parameter(chip, get_segment_desc(module, |
330 | snd_printdd("dsp_spos: module got no parameter segment\n"); | 376 | SEGTYPE_SP_PARAMETER)); |
331 | } else { | 377 | if (err < 0) |
332 | if (ins->nmodules > 0) { | 378 | return err; |
333 | snd_printk(KERN_WARNING "dsp_spos: WARNING current parameter data may be overwriten!\n"); | ||
334 | } | ||
335 | |||
336 | doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET); | ||
337 | dsize = parameter->size * 4; | ||
338 | |||
339 | snd_printdd("dsp_spos: downloading parameter data to chip (%08x-%08x)\n", | ||
340 | doffset,doffset + dsize); | ||
341 | |||
342 | if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) { | ||
343 | snd_printk(KERN_ERR "dsp_spos: failed to download parameter data to DSP\n"); | ||
344 | return -EINVAL; | ||
345 | } | ||
346 | } | ||
347 | 379 | ||
348 | if (ins->nmodules == 0) { | 380 | if (ins->nmodules == 0) { |
349 | snd_printdd("dsp_spos: clearing sample area\n"); | 381 | snd_printdd("dsp_spos: clearing sample area\n"); |
350 | snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE); | 382 | snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE); |
351 | } | 383 | } |
352 | 384 | ||
353 | if (sample == NULL) { | 385 | err = dsp_load_sample(chip, get_segment_desc(module, |
354 | snd_printdd("dsp_spos: module got no sample segment\n"); | 386 | SEGTYPE_SP_SAMPLE)); |
355 | } else { | 387 | if (err < 0) |
356 | if (ins->nmodules > 0) { | 388 | return err; |
357 | snd_printk(KERN_WARNING "dsp_spos: WARNING current sample data may be overwriten\n"); | ||
358 | } | ||
359 | |||
360 | doffset = (sample->offset * 4 + DSP_SAMPLE_BYTE_OFFSET); | ||
361 | dsize = sample->size * 4; | ||
362 | |||
363 | snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n", | ||
364 | doffset,doffset + dsize); | ||
365 | |||
366 | if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) { | ||
367 | snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n"); | ||
368 | return -EINVAL; | ||
369 | } | ||
370 | } | ||
371 | |||
372 | 389 | ||
373 | if (ins->nmodules == 0) { | 390 | if (ins->nmodules == 0) { |
374 | snd_printdd("dsp_spos: clearing code area\n"); | 391 | snd_printdd("dsp_spos: clearing code area\n"); |
@@ -986,7 +1003,10 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size) | |||
986 | return NULL; | 1003 | return NULL; |
987 | } | 1004 | } |
988 | 1005 | ||
989 | strcpy(ins->tasks[ins->ntask].task_name,name); | 1006 | if (name) |
1007 | strcpy(ins->tasks[ins->ntask].task_name, name); | ||
1008 | else | ||
1009 | strcpy(ins->tasks[ins->ntask].task_name, "(NULL)"); | ||
990 | ins->tasks[ins->ntask].address = dest; | 1010 | ins->tasks[ins->ntask].address = dest; |
991 | ins->tasks[ins->ntask].size = size; | 1011 | ins->tasks[ins->ntask].size = size; |
992 | 1012 | ||
@@ -995,7 +1015,8 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size) | |||
995 | desc = (ins->tasks + ins->ntask); | 1015 | desc = (ins->tasks + ins->ntask); |
996 | ins->ntask++; | 1016 | ins->ntask++; |
997 | 1017 | ||
998 | add_symbol (chip,name,dest,SYMBOL_PARAMETER); | 1018 | if (name) |
1019 | add_symbol (chip,name,dest,SYMBOL_PARAMETER); | ||
999 | return desc; | 1020 | return desc; |
1000 | } | 1021 | } |
1001 | 1022 | ||
@@ -1006,6 +1027,7 @@ cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 | |||
1006 | 1027 | ||
1007 | desc = _map_scb (chip,name,dest); | 1028 | desc = _map_scb (chip,name,dest); |
1008 | if (desc) { | 1029 | if (desc) { |
1030 | desc->data = scb_data; | ||
1009 | _dsp_create_scb(chip,scb_data,dest); | 1031 | _dsp_create_scb(chip,scb_data,dest); |
1010 | } else { | 1032 | } else { |
1011 | snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); | 1033 | snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); |
@@ -1023,6 +1045,7 @@ cs46xx_dsp_create_task_tree (struct snd_cs46xx *chip, char * name, u32 * task_da | |||
1023 | 1045 | ||
1024 | desc = _map_task_tree (chip,name,dest,size); | 1046 | desc = _map_task_tree (chip,name,dest,size); |
1025 | if (desc) { | 1047 | if (desc) { |
1048 | desc->data = task_data; | ||
1026 | _dsp_create_task_tree(chip,task_data,dest,size); | 1049 | _dsp_create_task_tree(chip,task_data,dest,size); |
1027 | } else { | 1050 | } else { |
1028 | snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n"); | 1051 | snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n"); |
@@ -1320,8 +1343,10 @@ int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip) | |||
1320 | 0x0000ffff | 1343 | 0x0000ffff |
1321 | }; | 1344 | }; |
1322 | 1345 | ||
1323 | /* dirty hack ... */ | 1346 | if (!cs46xx_dsp_create_task_tree(chip, NULL, |
1324 | _dsp_create_task_tree (chip,(u32 *)&mix2_ostream_spb,WRITE_BACK_SPB,2); | 1347 | (u32 *)&mix2_ostream_spb, |
1348 | WRITE_BACK_SPB, 2)) | ||
1349 | goto _fail_end; | ||
1325 | } | 1350 | } |
1326 | 1351 | ||
1327 | /* input sample converter */ | 1352 | /* input sample converter */ |
@@ -1622,7 +1647,6 @@ static int cs46xx_dsp_async_init (struct snd_cs46xx *chip, | |||
1622 | return 0; | 1647 | return 0; |
1623 | } | 1648 | } |
1624 | 1649 | ||
1625 | |||
1626 | static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip) | 1650 | static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip) |
1627 | { | 1651 | { |
1628 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | 1652 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; |
@@ -1894,3 +1918,61 @@ int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right) | |||
1894 | 1918 | ||
1895 | return 0; | 1919 | return 0; |
1896 | } | 1920 | } |
1921 | |||
1922 | #ifdef CONFIG_PM | ||
1923 | int cs46xx_dsp_resume(struct snd_cs46xx * chip) | ||
1924 | { | ||
1925 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | ||
1926 | int i, err; | ||
1927 | |||
1928 | /* clear parameter, sample and code areas */ | ||
1929 | snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, | ||
1930 | DSP_PARAMETER_BYTE_SIZE); | ||
1931 | snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, | ||
1932 | DSP_SAMPLE_BYTE_SIZE); | ||
1933 | snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE); | ||
1934 | |||
1935 | for (i = 0; i < ins->nmodules; i++) { | ||
1936 | struct dsp_module_desc *module = &ins->modules[i]; | ||
1937 | struct dsp_segment_desc *seg; | ||
1938 | u32 doffset, dsize; | ||
1939 | |||
1940 | seg = get_segment_desc(module, SEGTYPE_SP_PARAMETER); | ||
1941 | err = dsp_load_parameter(chip, seg); | ||
1942 | if (err < 0) | ||
1943 | return err; | ||
1944 | |||
1945 | seg = get_segment_desc(module, SEGTYPE_SP_SAMPLE); | ||
1946 | err = dsp_load_sample(chip, seg); | ||
1947 | if (err < 0) | ||
1948 | return err; | ||
1949 | |||
1950 | seg = get_segment_desc(module, SEGTYPE_SP_PROGRAM); | ||
1951 | if (!seg) | ||
1952 | continue; | ||
1953 | |||
1954 | doffset = seg->offset * 4 + module->load_address * 4 | ||
1955 | + DSP_CODE_BYTE_OFFSET; | ||
1956 | dsize = seg->size * 4; | ||
1957 | err = snd_cs46xx_download(chip, | ||
1958 | ins->code.data + module->load_address, | ||
1959 | doffset, dsize); | ||
1960 | if (err < 0) | ||
1961 | return err; | ||
1962 | } | ||
1963 | |||
1964 | for (i = 0; i < ins->ntask; i++) { | ||
1965 | struct dsp_task_descriptor *t = &ins->tasks[i]; | ||
1966 | _dsp_create_task_tree(chip, t->data, t->address, t->size); | ||
1967 | } | ||
1968 | |||
1969 | for (i = 0; i < ins->nscb; i++) { | ||
1970 | struct dsp_scb_descriptor *s = &ins->scbs[i]; | ||
1971 | if (s->deleted) | ||
1972 | continue; | ||
1973 | _dsp_create_scb(chip, s->data, s->address); | ||
1974 | } | ||
1975 | |||
1976 | return 0; | ||
1977 | } | ||
1978 | #endif | ||