aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/cs46xx
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/cs46xx')
-rw-r--r--sound/pci/cs46xx/cs46xx.c2
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c22
-rw-r--r--sound/pci/cs46xx/dsp_spos.c42
-rw-r--r--sound/pci/cs46xx/dsp_spos.h4
-rw-r--r--sound/pci/cs46xx/dsp_spos_scb_lib.c33
-rw-r--r--sound/pci/cs46xx/imgs/cwcdma.asp9
6 files changed, 79 insertions, 33 deletions
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 033aec430117..767fa7f06cd0 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -64,7 +64,7 @@ MODULE_PARM_DESC(thinkpad, "Force to enable Thinkpad's CLKRUN control.");
64module_param_array(mmap_valid, bool, NULL, 0444); 64module_param_array(mmap_valid, bool, NULL, 0444);
65MODULE_PARM_DESC(mmap_valid, "Support OSS mmap."); 65MODULE_PARM_DESC(mmap_valid, "Support OSS mmap.");
66 66
67static struct pci_device_id snd_cs46xx_ids[] = { 67static DEFINE_PCI_DEVICE_TABLE(snd_cs46xx_ids) = {
68 { PCI_VDEVICE(CIRRUS, 0x6001), 0, }, /* CS4280 */ 68 { PCI_VDEVICE(CIRRUS, 0x6001), 0, }, /* CS4280 */
69 { PCI_VDEVICE(CIRRUS, 0x6003), 0, }, /* CS4612 */ 69 { PCI_VDEVICE(CIRRUS, 0x6003), 0, }, /* CS4612 */
70 { PCI_VDEVICE(CIRRUS, 0x6004), 0, }, /* CS4615 */ 70 { PCI_VDEVICE(CIRRUS, 0x6004), 0, }, /* CS4615 */
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 1be96ead4244..3f99a5e8528c 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -2238,11 +2238,11 @@ static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97)
2238 2238
2239 /* set the desired CODEC mode */ 2239 /* set the desired CODEC mode */
2240 if (ac97->num == CS46XX_PRIMARY_CODEC_INDEX) { 2240 if (ac97->num == CS46XX_PRIMARY_CODEC_INDEX) {
2241 snd_printdd("cs46xx: CODOEC1 mode %04x\n",0x0); 2241 snd_printdd("cs46xx: CODEC1 mode %04x\n", 0x0);
2242 snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x0); 2242 snd_cs46xx_ac97_write(ac97, AC97_CSR_ACMODE, 0x0);
2243 } else if (ac97->num == CS46XX_SECONDARY_CODEC_INDEX) { 2243 } else if (ac97->num == CS46XX_SECONDARY_CODEC_INDEX) {
2244 snd_printdd("cs46xx: CODOEC2 mode %04x\n",0x3); 2244 snd_printdd("cs46xx: CODEC2 mode %04x\n", 0x3);
2245 snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x3); 2245 snd_cs46xx_ac97_write(ac97, AC97_CSR_ACMODE, 0x3);
2246 } else { 2246 } else {
2247 snd_BUG(); /* should never happen ... */ 2247 snd_BUG(); /* should never happen ... */
2248 } 2248 }
@@ -2266,7 +2266,7 @@ static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97)
2266 return; 2266 return;
2267 2267
2268 /* test if we can write to the record gain volume register */ 2268 /* test if we can write to the record gain volume register */
2269 snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05); 2269 snd_ac97_write(ac97, AC97_REC_GAIN, 0x8a05);
2270 if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05) 2270 if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05)
2271 return; 2271 return;
2272 2272
@@ -3597,7 +3597,7 @@ static struct cs_card_type __devinitdata cards[] = {
3597#ifdef CONFIG_PM 3597#ifdef CONFIG_PM
3598static unsigned int saved_regs[] = { 3598static unsigned int saved_regs[] = {
3599 BA0_ACOSV, 3599 BA0_ACOSV,
3600 BA0_ASER_FADDR, 3600 /*BA0_ASER_FADDR,*/
3601 BA0_ASER_MASTER, 3601 BA0_ASER_MASTER,
3602 BA1_PVOL, 3602 BA1_PVOL,
3603 BA1_CVOL, 3603 BA1_CVOL,
@@ -3644,6 +3644,7 @@ int snd_cs46xx_resume(struct pci_dev *pci)
3644#ifdef CONFIG_SND_CS46XX_NEW_DSP 3644#ifdef CONFIG_SND_CS46XX_NEW_DSP
3645 int i; 3645 int i;
3646#endif 3646#endif
3647 unsigned int tmp;
3647 3648
3648 pci_set_power_state(pci, PCI_D0); 3649 pci_set_power_state(pci, PCI_D0);
3649 pci_restore_state(pci); 3650 pci_restore_state(pci);
@@ -3685,6 +3686,15 @@ int snd_cs46xx_resume(struct pci_dev *pci)
3685 snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); 3686 snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
3686 snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); 3687 snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
3687 3688
3689 /*
3690 * Stop capture DMA.
3691 */
3692 tmp = snd_cs46xx_peek(chip, BA1_CCTL);
3693 chip->capt.ctl = tmp & 0x0000ffff;
3694 snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000);
3695
3696 mdelay(5);
3697
3688 /* reset playback/capture */ 3698 /* reset playback/capture */
3689 snd_cs46xx_set_play_sample_rate(chip, 8000); 3699 snd_cs46xx_set_play_sample_rate(chip, 8000);
3690 snd_cs46xx_set_capture_sample_rate(chip, 8000); 3700 snd_cs46xx_set_capture_sample_rate(chip, 8000);
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index f4f0c8f5dad7..3e5ca8fb519f 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -298,6 +298,9 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip)
298 if (ins->scbs[i].deleted) continue; 298 if (ins->scbs[i].deleted) continue;
299 299
300 cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); 300 cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) );
301#ifdef CONFIG_PM
302 kfree(ins->scbs[i].data);
303#endif
301 } 304 }
302 305
303 kfree(ins->code.data); 306 kfree(ins->code.data);
@@ -974,13 +977,11 @@ static struct dsp_scb_descriptor * _map_scb (struct snd_cs46xx *chip, char * nam
974 977
975 index = find_free_scb_index (ins); 978 index = find_free_scb_index (ins);
976 979
980 memset(&ins->scbs[index], 0, sizeof(ins->scbs[index]));
977 strcpy(ins->scbs[index].scb_name, name); 981 strcpy(ins->scbs[index].scb_name, name);
978 ins->scbs[index].address = dest; 982 ins->scbs[index].address = dest;
979 ins->scbs[index].index = index; 983 ins->scbs[index].index = index;
980 ins->scbs[index].proc_info = NULL;
981 ins->scbs[index].ref_count = 1; 984 ins->scbs[index].ref_count = 1;
982 ins->scbs[index].deleted = 0;
983 spin_lock_init(&ins->scbs[index].lock);
984 985
985 desc = (ins->scbs + index); 986 desc = (ins->scbs + index);
986 ins->scbs[index].scb_symbol = add_symbol (chip, name, dest, SYMBOL_PARAMETER); 987 ins->scbs[index].scb_symbol = add_symbol (chip, name, dest, SYMBOL_PARAMETER);
@@ -1022,17 +1023,29 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size)
1022 return desc; 1023 return desc;
1023} 1024}
1024 1025
1026#define SCB_BYTES (0x10 * 4)
1027
1025struct dsp_scb_descriptor * 1028struct dsp_scb_descriptor *
1026cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest) 1029cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest)
1027{ 1030{
1028 struct dsp_scb_descriptor * desc; 1031 struct dsp_scb_descriptor * desc;
1029 1032
1033#ifdef CONFIG_PM
1034 /* copy the data for resume */
1035 scb_data = kmemdup(scb_data, SCB_BYTES, GFP_KERNEL);
1036 if (!scb_data)
1037 return NULL;
1038#endif
1039
1030 desc = _map_scb (chip,name,dest); 1040 desc = _map_scb (chip,name,dest);
1031 if (desc) { 1041 if (desc) {
1032 desc->data = scb_data; 1042 desc->data = scb_data;
1033 _dsp_create_scb(chip,scb_data,dest); 1043 _dsp_create_scb(chip,scb_data,dest);
1034 } else { 1044 } else {
1035 snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); 1045 snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n");
1046#ifdef CONFIG_PM
1047 kfree(scb_data);
1048#endif
1036 } 1049 }
1037 1050
1038 return desc; 1051 return desc;
@@ -1988,7 +2001,28 @@ int cs46xx_dsp_resume(struct snd_cs46xx * chip)
1988 continue; 2001 continue;
1989 _dsp_create_scb(chip, s->data, s->address); 2002 _dsp_create_scb(chip, s->data, s->address);
1990 } 2003 }
1991 2004 for (i = 0; i < ins->nscb; i++) {
2005 struct dsp_scb_descriptor *s = &ins->scbs[i];
2006 if (s->deleted)
2007 continue;
2008 if (s->updated)
2009 cs46xx_dsp_spos_update_scb(chip, s);
2010 if (s->volume_set)
2011 cs46xx_dsp_scb_set_volume(chip, s,
2012 s->volume[0], s->volume[1]);
2013 }
2014 if (ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) {
2015 cs46xx_dsp_enable_spdif_hw(chip);
2016 snd_cs46xx_poke(chip, (ins->ref_snoop_scb->address + 2) << 2,
2017 (OUTPUT_SNOOP_BUFFER + 0x10) << 0x10);
2018 if (ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN)
2019 cs46xx_poke_via_dsp(chip, SP_SPDOUT_CSUV,
2020 ins->spdif_csuv_stream);
2021 }
2022 if (chip->dsp_spos_instance->spdif_status_in) {
2023 cs46xx_poke_via_dsp(chip, SP_ASER_COUNTDOWN, 0x80000005);
2024 cs46xx_poke_via_dsp(chip, SP_SPDIN_CONTROL, 0x800003ff);
2025 }
1992 return 0; 2026 return 0;
1993} 2027}
1994#endif 2028#endif
diff --git a/sound/pci/cs46xx/dsp_spos.h b/sound/pci/cs46xx/dsp_spos.h
index f9e169d33c03..ca47a8114c7f 100644
--- a/sound/pci/cs46xx/dsp_spos.h
+++ b/sound/pci/cs46xx/dsp_spos.h
@@ -212,6 +212,7 @@ static inline void cs46xx_dsp_spos_update_scb (struct snd_cs46xx * chip,
212 (scb->address + SCBsubListPtr) << 2, 212 (scb->address + SCBsubListPtr) << 2,
213 (scb->sub_list_ptr->address << 0x10) | 213 (scb->sub_list_ptr->address << 0x10) |
214 (scb->next_scb_ptr->address)); 214 (scb->next_scb_ptr->address));
215 scb->updated = 1;
215} 216}
216 217
217static inline void cs46xx_dsp_scb_set_volume (struct snd_cs46xx * chip, 218static inline void cs46xx_dsp_scb_set_volume (struct snd_cs46xx * chip,
@@ -222,6 +223,9 @@ static inline void cs46xx_dsp_scb_set_volume (struct snd_cs46xx * chip,
222 223
223 snd_cs46xx_poke(chip, (scb->address + SCBVolumeCtrl) << 2, val); 224 snd_cs46xx_poke(chip, (scb->address + SCBVolumeCtrl) << 2, val);
224 snd_cs46xx_poke(chip, (scb->address + SCBVolumeCtrl + 1) << 2, val); 225 snd_cs46xx_poke(chip, (scb->address + SCBVolumeCtrl + 1) << 2, val);
226 scb->volume_set = 1;
227 scb->volume[0] = left;
228 scb->volume[1] = right;
225} 229}
226#endif /* __DSP_SPOS_H__ */ 230#endif /* __DSP_SPOS_H__ */
227#endif /* CONFIG_SND_CS46XX_NEW_DSP */ 231#endif /* CONFIG_SND_CS46XX_NEW_DSP */
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
index dd7c41b037b4..00b148a10239 100644
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c
@@ -115,7 +115,6 @@ static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry,
115static void _dsp_unlink_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb) 115static void _dsp_unlink_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb)
116{ 116{
117 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 117 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
118 unsigned long flags;
119 118
120 if ( scb->parent_scb_ptr ) { 119 if ( scb->parent_scb_ptr ) {
121 /* unlink parent SCB */ 120 /* unlink parent SCB */
@@ -153,8 +152,6 @@ static void _dsp_unlink_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor
153 scb->next_scb_ptr = ins->the_null_scb; 152 scb->next_scb_ptr = ins->the_null_scb;
154 } 153 }
155 154
156 spin_lock_irqsave(&chip->reg_lock, flags);
157
158 /* update parent first entry in DSP RAM */ 155 /* update parent first entry in DSP RAM */
159 cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr); 156 cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr);
160 157
@@ -162,7 +159,6 @@ static void _dsp_unlink_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor
162 cs46xx_dsp_spos_update_scb(chip,scb); 159 cs46xx_dsp_spos_update_scb(chip,scb);
163 160
164 scb->parent_scb_ptr = NULL; 161 scb->parent_scb_ptr = NULL;
165 spin_unlock_irqrestore(&chip->reg_lock, flags);
166 } 162 }
167} 163}
168 164
@@ -197,9 +193,9 @@ void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor *
197 goto _end; 193 goto _end;
198#endif 194#endif
199 195
200 spin_lock_irqsave(&scb->lock, flags); 196 spin_lock_irqsave(&chip->reg_lock, flags);
201 _dsp_unlink_scb (chip,scb); 197 _dsp_unlink_scb (chip,scb);
202 spin_unlock_irqrestore(&scb->lock, flags); 198 spin_unlock_irqrestore(&chip->reg_lock, flags);
203 199
204 cs46xx_dsp_proc_free_scb_desc(scb); 200 cs46xx_dsp_proc_free_scb_desc(scb);
205 if (snd_BUG_ON(!scb->scb_symbol)) 201 if (snd_BUG_ON(!scb->scb_symbol))
@@ -207,6 +203,10 @@ void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor *
207 remove_symbol (chip,scb->scb_symbol); 203 remove_symbol (chip,scb->scb_symbol);
208 204
209 ins->scbs[scb->index].deleted = 1; 205 ins->scbs[scb->index].deleted = 1;
206#ifdef CONFIG_PM
207 kfree(ins->scbs[scb->index].data);
208 ins->scbs[scb->index].data = NULL;
209#endif
210 210
211 if (scb->index < ins->scb_highest_frag_index) 211 if (scb->index < ins->scb_highest_frag_index)
212 ins->scb_highest_frag_index = scb->index; 212 ins->scb_highest_frag_index = scb->index;
@@ -1508,20 +1508,17 @@ int cs46xx_dsp_pcm_unlink (struct snd_cs46xx * chip,
1508 chip->dsp_spos_instance->npcm_channels <= 0)) 1508 chip->dsp_spos_instance->npcm_channels <= 0))
1509 return -EIO; 1509 return -EIO;
1510 1510
1511 spin_lock(&pcm_channel->src_scb->lock); 1511 spin_lock_irqsave(&chip->reg_lock, flags);
1512
1513 if (pcm_channel->unlinked) { 1512 if (pcm_channel->unlinked) {
1514 spin_unlock(&pcm_channel->src_scb->lock); 1513 spin_unlock_irqrestore(&chip->reg_lock, flags);
1515 return -EIO; 1514 return -EIO;
1516 } 1515 }
1517 1516
1518 spin_lock_irqsave(&chip->reg_lock, flags);
1519 pcm_channel->unlinked = 1; 1517 pcm_channel->unlinked = 1;
1520 spin_unlock_irqrestore(&chip->reg_lock, flags);
1521 1518
1522 _dsp_unlink_scb (chip,pcm_channel->pcm_reader_scb); 1519 _dsp_unlink_scb (chip,pcm_channel->pcm_reader_scb);
1520 spin_unlock_irqrestore(&chip->reg_lock, flags);
1523 1521
1524 spin_unlock(&pcm_channel->src_scb->lock);
1525 return 0; 1522 return 0;
1526} 1523}
1527 1524
@@ -1533,10 +1530,10 @@ int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip,
1533 struct dsp_scb_descriptor * src_scb = pcm_channel->src_scb; 1530 struct dsp_scb_descriptor * src_scb = pcm_channel->src_scb;
1534 unsigned long flags; 1531 unsigned long flags;
1535 1532
1536 spin_lock(&pcm_channel->src_scb->lock); 1533 spin_lock_irqsave(&chip->reg_lock, flags);
1537 1534
1538 if (pcm_channel->unlinked == 0) { 1535 if (pcm_channel->unlinked == 0) {
1539 spin_unlock(&pcm_channel->src_scb->lock); 1536 spin_unlock_irqrestore(&chip->reg_lock, flags);
1540 return -EIO; 1537 return -EIO;
1541 } 1538 }
1542 1539
@@ -1552,8 +1549,6 @@ int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip,
1552 snd_BUG_ON(pcm_channel->pcm_reader_scb->parent_scb_ptr); 1549 snd_BUG_ON(pcm_channel->pcm_reader_scb->parent_scb_ptr);
1553 pcm_channel->pcm_reader_scb->parent_scb_ptr = parent_scb; 1550 pcm_channel->pcm_reader_scb->parent_scb_ptr = parent_scb;
1554 1551
1555 spin_lock_irqsave(&chip->reg_lock, flags);
1556
1557 /* update SCB entry in DSP RAM */ 1552 /* update SCB entry in DSP RAM */
1558 cs46xx_dsp_spos_update_scb(chip,pcm_channel->pcm_reader_scb); 1553 cs46xx_dsp_spos_update_scb(chip,pcm_channel->pcm_reader_scb);
1559 1554
@@ -1562,8 +1557,6 @@ int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip,
1562 1557
1563 pcm_channel->unlinked = 0; 1558 pcm_channel->unlinked = 0;
1564 spin_unlock_irqrestore(&chip->reg_lock, flags); 1559 spin_unlock_irqrestore(&chip->reg_lock, flags);
1565
1566 spin_unlock(&pcm_channel->src_scb->lock);
1567 return 0; 1560 return 0;
1568} 1561}
1569 1562
@@ -1596,13 +1589,17 @@ cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * s
1596 1589
1597int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src) 1590int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src)
1598{ 1591{
1592 unsigned long flags;
1593
1599 if (snd_BUG_ON(!src->parent_scb_ptr)) 1594 if (snd_BUG_ON(!src->parent_scb_ptr))
1600 return -EINVAL; 1595 return -EINVAL;
1601 1596
1602 /* mute SCB */ 1597 /* mute SCB */
1603 cs46xx_dsp_scb_set_volume (chip,src,0,0); 1598 cs46xx_dsp_scb_set_volume (chip,src,0,0);
1604 1599
1600 spin_lock_irqsave(&chip->reg_lock, flags);
1605 _dsp_unlink_scb (chip,src); 1601 _dsp_unlink_scb (chip,src);
1602 spin_unlock_irqrestore(&chip->reg_lock, flags);
1606 1603
1607 return 0; 1604 return 0;
1608} 1605}
diff --git a/sound/pci/cs46xx/imgs/cwcdma.asp b/sound/pci/cs46xx/imgs/cwcdma.asp
index 09d24c76f034..a65e1193c89a 100644
--- a/sound/pci/cs46xx/imgs/cwcdma.asp
+++ b/sound/pci/cs46xx/imgs/cwcdma.asp
@@ -26,10 +26,11 @@
26// 26//
27// 27//
28// The purpose of this code is very simple: make it possible to tranfser 28// The purpose of this code is very simple: make it possible to tranfser
29// the samples 'as they are' with no alteration from a PCMreader SCB (DMA from host) 29// the samples 'as they are' with no alteration from a PCMreader
30// to any other SCB. This is useful for AC3 throug SPDIF. SRC (source rate converters) 30// SCB (DMA from host) to any other SCB. This is useful for AC3 through SPDIF.
31// task always alters the samples in some how, however it's from 48khz -> 48khz. The 31// SRC (source rate converters) task always alters the samples in somehow,
32// alterations are not audible, but AC3 wont work. 32// however it's from 48khz -> 48khz.
33// The alterations are not audible, but AC3 wont work.
33// 34//
34// ... 35// ...
35// | 36// |