Changeset 34 for GPL/trunk/alsa-kernel/pci/cs46xx
- Timestamp:
- Dec 11, 2005, 5:57:39 PM (20 years ago)
- Location:
- GPL/trunk/alsa-kernel/pci/cs46xx
- Files:
-
- 12 edited
-
cs46xx.c (modified) (8 diffs)
-
cs46xx_lib.c (modified) (35 diffs)
-
cs46xx_lib.h (modified) (3 diffs)
-
dsp_spos.c (modified) (1 diff)
-
dsp_spos.h (modified) (5 diffs)
-
dsp_spos_scb_lib.c (modified) (68 diffs)
-
imgs/cwc4630.h (modified) (2 diffs)
-
imgs/cwcasync.h (modified) (2 diffs)
-
imgs/cwcbinhack.h (modified) (2 diffs)
-
imgs/cwcdma.h (modified) (3 diffs)
-
imgs/cwcemb80.h (modified) (3 diffs)
-
imgs/cwcsnoop.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
GPL/trunk/alsa-kernel/pci/cs46xx/cs46xx.c
r33 r34 30 30 #include <linux/time.h> 31 31 #include <linux/init.h> 32 #include <linux/moduleparam.h> 32 33 #include <sound/core.h> 33 34 #include <sound/cs46xx.h> 34 #define SNDRV_GET_ID35 35 #include <sound/initval.h> 36 36 … … 38 38 MODULE_DESCRIPTION("Cirrus Logic Sound Fusion CS46XX"); 39 39 MODULE_LICENSE("GPL"); 40 MODULE_CLASSES("{sound}"); 41 MODULE_DEVICES("{{Cirrus Logic,Sound Fusion (CS4280)}," 40 MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)}," 42 41 "{Cirrus Logic,Sound Fusion (CS4610)}," 43 42 "{Cirrus Logic,Sound Fusion (CS4612)}," … … 50 49 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 51 50 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 52 #ifdef TARGET_OS253 51 static int external_amp[SNDRV_CARDS] = {0}; 54 52 static int thinkpad[SNDRV_CARDS] = {1,0,0,0,0,0,0,0}; 55 53 static int mmap_valid[SNDRV_CARDS] = {0}; 56 #else57 static int external_amp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};58 static int thinkpad[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};59 static int mmap_valid[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};60 #endif61 54 62 MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");55 //module_param_array(index, int, NULL, 0444); 63 56 MODULE_PARM_DESC(index, "Index value for the CS46xx soundcard."); 64 MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC); 65 MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s"); 57 //module_param_array(id, charp, NULL, 0444); 66 58 MODULE_PARM_DESC(id, "ID string for the CS46xx soundcard."); 67 MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC); 68 MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); 59 //module_param_array(enable, bool, NULL, 0444); 69 60 MODULE_PARM_DESC(enable, "Enable CS46xx soundcard."); 70 MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC); 71 MODULE_PARM(external_amp, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); 61 //module_param_array(external_amp, bool, NULL, 0444); 72 62 MODULE_PARM_DESC(external_amp, "Force to enable external amplifer."); 73 MODULE_PARM_SYNTAX(external_amp, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC); 74 MODULE_PARM(thinkpad, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); 63 //module_param_array(thinkpad, bool, NULL, 0444); 75 64 MODULE_PARM_DESC(thinkpad, "Force to enable Thinkpad's CLKRUN control."); 76 MODULE_PARM_SYNTAX(thinkpad, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC); 77 MODULE_PARM(mmap_valid, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); 65 //module_param_array(mmap_valid, bool, NULL, 0444); 78 66 MODULE_PARM_DESC(mmap_valid, "Support OSS mmap."); 79 MODULE_PARM_SYNTAX(mmap_valid, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);80 67 81 68 static struct pci_device_id snd_cs46xx_ids[] = { … … 92 79 { 93 80 static int dev; 94 s nd_card_t*card;95 cs46xx_t*chip;81 struct snd_card *card; 82 struct snd_cs46xx *chip; 96 83 int err; 97 84 … … 112 99 return err; 113 100 } 101 card->private_data = chip; 114 102 chip->accept_valid = mmap_valid[dev]; 115 103 if ((err = snd_cs46xx_pcm(chip, 0, NULL)) < 0) { … … 127 115 } 128 116 #endif 129 if ((err = snd_cs46xx_mixer(chip )) < 0) {117 if ((err = snd_cs46xx_mixer(chip, 2)) < 0) { 130 118 snd_card_free(card); 131 119 return err; … … 164 152 } 165 153 166 pci_set_drvdata(pci, card);154 pci_set_drvdata(pci, card); 167 155 dev++; 168 156 return 0; 169 157 } 170 158 171 172 159 static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci) 173 160 { 174 snd_card_free(pci_get_drvdata(pci));175 pci_set_drvdata(pci, NULL);161 snd_card_free(pci_get_drvdata(pci)); 162 pci_set_drvdata(pci, NULL); 176 163 } 177 164 178 165 static struct pci_driver driver = { 179 0, 0, 0, 180 "Sound Fusion CS46xx", 181 snd_cs46xx_ids, 182 snd_card_cs46xx_probe, 183 snd_card_cs46xx_remove, 184 SND_PCI_PM_CALLBACKS 166 .name = "Sound Fusion CS46xx", 167 .id_table = snd_cs46xx_ids, 168 .probe = snd_card_cs46xx_probe, 169 .remove = snd_card_cs46xx_remove, 170 #ifdef CONFIG_PM 171 .suspend = snd_cs46xx_suspend, 172 .resume = snd_cs46xx_resume, 173 #endif 185 174 }; 186 175 187 176 static int __init alsa_card_cs46xx_init(void) 188 177 { 189 int err; 190 191 if ((err = pci_module_init(&driver)) < 0) { 192 #ifdef MODULE 193 // printk(KERN_ERR "Sound Fusion CS46xx soundcard not found or device busy\n"); 194 #endif 195 return err; 196 } 197 return 0; 178 return pci_register_driver(&driver); 198 179 } 199 180 … … 205 186 module_init(alsa_card_cs46xx_init) 206 187 module_exit(alsa_card_cs46xx_exit) 207 208 #ifndef MODULE209 210 /* format is: snd-cs46xx=snd_enable,snd_index,snd_id */211 212 static int __init alsa_card_cs46xx_setup(char *str)213 {214 static unsigned __initdata nr_dev = 0;215 216 if (nr_dev >= SNDRV_CARDS)217 return 0;218 (void)(get_option(&str,&enable[nr_dev]) == 2 &&219 get_option(&str,&index[nr_dev]) == 2 &&220 get_id(&str,&id[nr_dev]) == 2);221 nr_dev++;222 return 1;223 }224 225 __setup("snd-cs46xx=", alsa_card_cs46xx_setup);226 227 #endif /* ifndef MODULE */ -
GPL/trunk/alsa-kernel/pci/cs46xx/cs46xx_lib.c
r33 r34 8 8 * - Sometimes the SPDIF input DSP tasks get's unsynchronized 9 9 * and the SPDIF get somewhat "distorcionated", or/and left right channel 10 * are swapped. To get around this problem when it happens, mute and unmute 10 * are swapped. To get around this problem when it happens, mute and unmute 11 11 * the SPDIF input mixer controll. 12 12 * - On the Hercules Game Theater XP the amplifier are sometimes turned … … 23 23 * multi channel PCM. But known to work. 24 24 * 25 * FINALLY: A credit to the developers Tom and Jordan 25 * FINALLY: A credit to the developers Tom and Jordan 26 26 * at Cirrus for have helping me out with the DSP, however we 27 27 * still don't have sufficient documentation and technical 28 28 * references to be able to implement all fancy feutures 29 * supported by the cs46xx DSP's. 29 * supported by the cs46xx DSP's. 30 30 * Benny <benny@hostmobility.com> 31 * 31 * 32 32 * This program is free software; you can redistribute it and/or modify 33 33 * it under the terms of the GNU General Public License as published by … … 45 45 * 46 46 */ 47 47 48 #include <sound/driver.h> 48 #include <asm/io.h>49 49 #include <linux/delay.h> 50 50 #include <linux/pci.h> 51 51 #include <linux/pm.h> 52 52 #include <linux/init.h> 53 #include <linux/interrupt.h> 53 54 #include <linux/slab.h> 55 //#include <linux/gameport.h> 56 54 57 #include <sound/core.h> 55 58 #include <sound/control.h> 56 59 #include <sound/info.h> 60 #include <sound/pcm.h> 61 #include <sound/pcm_params.h> 57 62 #include <sound/cs46xx.h> 58 #ifndef LINUX_2_2 59 #include < linux/gameport.h>60 #endif 63 64 #include <asm/io.h> 65 61 66 #include "cs46xx_lib.h" 62 67 #include "dsp_spos.h" 63 #include <sound/pcm_params.h> 64 65 static void amp_voyetra(cs46xx_t *chip, int change); 66 67 static unsigned short snd_cs46xx_codec_read(cs46xx_t *chip, 68 unsigned short reg, 69 int codec_index) 70 { 71 int count; 72 unsigned short result,tmp; 73 u32 offset = 0; 74 snd_assert ( (codec_index == CS46XX_PRIMARY_CODEC_INDEX) || 75 (codec_index == CS46XX_SECONDARY_CODEC_INDEX), 76 return -EINVAL); 77 78 chip->active_ctrl(chip, 1); 79 80 if (codec_index == CS46XX_SECONDARY_CODEC_INDEX) 81 offset = CS46XX_SECONDARY_CODEC_OFFSET; 82 83 /* 84 * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address 85 * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 86 * 3. Write ACCTL = Control Register = 460h for initiating the write7---55 87 * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h 88 * 5. if DCV not cleared, break and return error 89 * 6. Read ACSTS = Status Register = 464h, check VSTS bit 90 */ 91 92 snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset); 93 94 tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL); 95 if ((tmp & ACCTL_VFRM) == 0) { 96 snd_printk(KERN_WARNING "cs46xx: ACCTL_VFRM not set 0x%x\n",tmp); 97 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, (tmp & (~ACCTL_ESYN)) | ACCTL_VFRM ); 98 msleep(50); 99 tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL + offset); 100 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, tmp | ACCTL_ESYN | ACCTL_VFRM ); 101 102 } 103 104 /* 105 * Setup the AC97 control registers on the CS461x to send the 106 * appropriate command to the AC97 to perform the read. 107 * ACCAD = Command Address Register = 46Ch 108 * ACCDA = Command Data Register = 470h 109 * ACCTL = Control Register = 460h 110 * set DCV - will clear when process completed 111 * set CRW - Read command 112 * set VFRM - valid frame enabled 113 * set ESYN - ASYNC generation enabled 114 * set RSTN - ARST# inactive, AC97 codec not reset 115 */ 116 117 snd_cs46xx_pokeBA0(chip, BA0_ACCAD, reg); 118 snd_cs46xx_pokeBA0(chip, BA0_ACCDA, 0); 119 if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) { 120 snd_cs46xx_pokeBA0(chip, BA0_ACCTL,/* clear ACCTL_DCV */ ACCTL_CRW | 121 ACCTL_VFRM | ACCTL_ESYN | 122 ACCTL_RSTN); 123 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | 124 ACCTL_VFRM | ACCTL_ESYN | 125 ACCTL_RSTN); 126 } else { 127 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC | 128 ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN | 129 ACCTL_RSTN); 130 } 131 132 /* 133 * Wait for the read to occur. 134 */ 135 for (count = 0; count < 1000; count++) { 136 /* 137 * First, we want to wait for a short time. 68 69 static void amp_voyetra(struct snd_cs46xx *chip, int change); 70 71 #ifdef CONFIG_SND_CS46XX_NEW_DSP 72 static struct snd_pcm_ops snd_cs46xx_playback_rear_ops; 73 static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops; 74 static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops; 75 static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops; 76 static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops; 77 static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops; 78 #endif 79 80 static struct snd_pcm_ops snd_cs46xx_playback_ops; 81 static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops; 82 static struct snd_pcm_ops snd_cs46xx_capture_ops; 83 static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops; 84 85 static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, 86 unsigned short reg, 87 int codec_index) 88 { 89 int count; 90 unsigned short result,tmp; 91 u32 offset = 0; 92 snd_assert ( (codec_index == CS46XX_PRIMARY_CODEC_INDEX) || 93 (codec_index == CS46XX_SECONDARY_CODEC_INDEX), 94 return -EINVAL); 95 96 chip->active_ctrl(chip, 1); 97 98 if (codec_index == CS46XX_SECONDARY_CODEC_INDEX) 99 offset = CS46XX_SECONDARY_CODEC_OFFSET; 100 101 /* 102 * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address 103 * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 104 * 3. Write ACCTL = Control Register = 460h for initiating the write7---55 105 * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h 106 * 5. if DCV not cleared, break and return error 107 * 6. Read ACSTS = Status Register = 464h, check VSTS bit 108 */ 109 110 snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset); 111 112 tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL); 113 if ((tmp & ACCTL_VFRM) == 0) { 114 snd_printk(KERN_WARNING "cs46xx: ACCTL_VFRM not set 0x%x\n",tmp); 115 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, (tmp & (~ACCTL_ESYN)) | ACCTL_VFRM ); 116 msleep(50); 117 tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL + offset); 118 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, tmp | ACCTL_ESYN | ACCTL_VFRM ); 119 120 } 121 122 /* 123 * Setup the AC97 control registers on the CS461x to send the 124 * appropriate command to the AC97 to perform the read. 125 * ACCAD = Command Address Register = 46Ch 126 * ACCDA = Command Data Register = 470h 127 * ACCTL = Control Register = 460h 128 * set DCV - will clear when process completed 129 * set CRW - Read command 130 * set VFRM - valid frame enabled 131 * set ESYN - ASYNC generation enabled 132 * set RSTN - ARST# inactive, AC97 codec not reset 133 */ 134 135 snd_cs46xx_pokeBA0(chip, BA0_ACCAD, reg); 136 snd_cs46xx_pokeBA0(chip, BA0_ACCDA, 0); 137 if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) { 138 snd_cs46xx_pokeBA0(chip, BA0_ACCTL,/* clear ACCTL_DCV */ ACCTL_CRW | 139 ACCTL_VFRM | ACCTL_ESYN | 140 ACCTL_RSTN); 141 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | 142 ACCTL_VFRM | ACCTL_ESYN | 143 ACCTL_RSTN); 144 } else { 145 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC | 146 ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN | 147 ACCTL_RSTN); 148 } 149 150 /* 151 * Wait for the read to occur. 152 */ 153 for (count = 0; count < 1000; count++) { 154 /* 155 * First, we want to wait for a short time. 156 */ 157 udelay(10); 158 /* 159 * Now, check to see if the read has completed. 160 * ACCTL = 460h, DCV should be reset by now and 460h = 17h 161 */ 162 if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) 163 goto ok1; 164 } 165 166 snd_printk(KERN_ERR "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); 167 result = 0xffff; 168 goto end; 169 170 ok1: 171 /* 172 * Wait for the valid status bit to go active. 173 */ 174 for (count = 0; count < 100; count++) { 175 /* 176 * Read the AC97 status register. 177 * ACSTS = Status Register = 464h 178 * VSTS - Valid Status 179 */ 180 if (snd_cs46xx_peekBA0(chip, BA0_ACSTS + offset) & ACSTS_VSTS) 181 goto ok2; 182 udelay(10); 183 } 184 185 snd_printk(KERN_ERR "AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n", codec_index, reg); 186 result = 0xffff; 187 goto end; 188 189 ok2: 190 /* 191 * Read the data returned from the AC97 register. 192 * ACSDA = Status Data Register = 474h 193 */ 194 #if 0 195 printk("e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg, 196 snd_cs46xx_peekBA0(chip, BA0_ACSDA), 197 snd_cs46xx_peekBA0(chip, BA0_ACCAD)); 198 #endif 199 200 //snd_cs46xx_peekBA0(chip, BA0_ACCAD); 201 result = snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset); 202 end: 203 chip->active_ctrl(chip, -1); 204 return result; 205 } 206 207 static unsigned short snd_cs46xx_ac97_read(struct snd_ac97 * ac97, 208 unsigned short reg) 209 { 210 struct snd_cs46xx *chip = ac97->private_data; 211 unsigned short val; 212 int codec_index = ac97->num; 213 214 snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX || 215 codec_index == CS46XX_SECONDARY_CODEC_INDEX, 216 return 0xffff); 217 218 val = snd_cs46xx_codec_read(chip, reg, codec_index); 219 220 return val; 221 } 222 223 224 static void snd_cs46xx_codec_write(struct snd_cs46xx *chip, 225 unsigned short reg, 226 unsigned short val, 227 int codec_index) 228 { 229 int count; 230 231 snd_assert ((codec_index == CS46XX_PRIMARY_CODEC_INDEX) || 232 (codec_index == CS46XX_SECONDARY_CODEC_INDEX), 233 return); 234 235 chip->active_ctrl(chip, 1); 236 237 /* 238 * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address 239 * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 240 * 3. Write ACCTL = Control Register = 460h for initiating the write 241 * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h 242 * 5. if DCV not cleared, break and return error 243 */ 244 245 /* 246 * Setup the AC97 control registers on the CS461x to send the 247 * appropriate command to the AC97 to perform the read. 248 * ACCAD = Command Address Register = 46Ch 249 * ACCDA = Command Data Register = 470h 250 * ACCTL = Control Register = 460h 251 * set DCV - will clear when process completed 252 * reset CRW - Write command 253 * set VFRM - valid frame enabled 254 * set ESYN - ASYNC generation enabled 255 * set RSTN - ARST# inactive, AC97 codec not reset 138 256 */ 139 udelay(10); 140 /* 141 * Now, check to see if the read has completed. 142 * ACCTL = 460h, DCV should be reset by now and 460h = 17h 143 */ 144 if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) 145 goto ok1; 146 } 147 148 snd_printk("AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); 149 result = 0xffff; 150 goto end; 151 152 ok1: 153 /* 154 * Wait for the valid status bit to go active. 155 */ 156 for (count = 0; count < 100; count++) { 157 /* 158 * Read the AC97 status register. 159 * ACSTS = Status Register = 464h 160 * VSTS - Valid Status 161 */ 162 if (snd_cs46xx_peekBA0(chip, BA0_ACSTS + offset) & ACSTS_VSTS) 163 goto ok2; 164 udelay(10); 165 } 166 167 snd_printk("AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n", codec_index, reg); 168 result = 0xffff; 169 goto end; 170 171 ok2: 172 /* 173 * Read the data returned from the AC97 register. 174 * ACSDA = Status Data Register = 474h 175 */ 176 #if 0 177 printk("e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg, 178 snd_cs46xx_peekBA0(chip, BA0_ACSDA), 179 snd_cs46xx_peekBA0(chip, BA0_ACCAD)); 180 #endif 181 182 //snd_cs46xx_peekBA0(chip, BA0_ACCAD); 183 result = snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset); 184 end: 185 chip->active_ctrl(chip, -1); 186 return result; 187 } 188 189 static unsigned short snd_cs46xx_ac97_read(ac97_t * ac97, 190 unsigned short reg) 191 { 192 cs46xx_t *chip = ac97->private_data; 193 unsigned short val; 194 int codec_index = ac97->num; 195 196 snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX || 197 codec_index == CS46XX_SECONDARY_CODEC_INDEX, 198 return 0xffff); 199 200 val = snd_cs46xx_codec_read(chip, reg, codec_index); 201 202 /* HACK: voyetra uses EAPD bit in the reverse way. 203 * we flip the bit to show the mixer status correctly 204 */ 205 if (reg == AC97_POWERDOWN && chip->amplifier_ctrl == amp_voyetra) 206 val ^= 0x8000; 207 208 return val; 209 } 210 211 212 static void snd_cs46xx_codec_write(cs46xx_t *chip, 213 unsigned short reg, 214 unsigned short val, 215 int codec_index) 216 { 217 int count; 218 219 snd_assert ((codec_index == CS46XX_PRIMARY_CODEC_INDEX) || 220 (codec_index == CS46XX_SECONDARY_CODEC_INDEX), 221 return); 222 223 chip->active_ctrl(chip, 1); 224 225 /* 226 * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address 227 * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 228 * 3. Write ACCTL = Control Register = 460h for initiating the write 229 * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h 230 * 5. if DCV not cleared, break and return error 231 */ 232 233 /* 234 * Setup the AC97 control registers on the CS461x to send the 235 * appropriate command to the AC97 to perform the read. 236 * ACCAD = Command Address Register = 46Ch 237 * ACCDA = Command Data Register = 470h 238 * ACCTL = Control Register = 460h 239 * set DCV - will clear when process completed 240 * reset CRW - Write command 241 * set VFRM - valid frame enabled 242 * set ESYN - ASYNC generation enabled 243 * set RSTN - ARST# inactive, AC97 codec not reset 244 */ 245 snd_cs46xx_pokeBA0(chip, BA0_ACCAD , reg); 246 snd_cs46xx_pokeBA0(chip, BA0_ACCDA , val); 247 snd_cs46xx_peekBA0(chip, BA0_ACCTL); 248 249 if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) { 250 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, /* clear ACCTL_DCV */ ACCTL_VFRM | 251 ACCTL_ESYN | ACCTL_RSTN); 252 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | 253 ACCTL_ESYN | ACCTL_RSTN); 254 } else { 255 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC | 256 ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); 257 } 258 259 for (count = 0; count < 4000; count++) { 260 /* 261 * First, we want to wait for a short time. 262 */ 263 udelay(10); 264 /* 265 * Now, check to see if the write has completed. 266 * ACCTL = 460h, DCV should be reset by now and 460h = 07h 267 */ 268 if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) { 269 goto end; 270 } 271 } 272 snd_printk("AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val); 273 end: 274 chip->active_ctrl(chip, -1); 275 } 276 277 static void snd_cs46xx_ac97_write(ac97_t *ac97, 278 unsigned short reg, 279 unsigned short val) 280 { 281 cs46xx_t *chip = ac97->private_data; 282 int codec_index = ac97->num; 283 284 snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX || 285 codec_index == CS46XX_SECONDARY_CODEC_INDEX, 286 return); 287 /* HACK: voyetra uses EAPD bit in the reverse way. 288 * we flip the bit to show the mixer status correctly 289 */ 290 if (reg == AC97_POWERDOWN && chip->amplifier_ctrl == amp_voyetra) 291 val ^= 0x8000; 292 293 snd_cs46xx_codec_write(chip, reg, val, codec_index); 257 snd_cs46xx_pokeBA0(chip, BA0_ACCAD , reg); 258 snd_cs46xx_pokeBA0(chip, BA0_ACCDA , val); 259 snd_cs46xx_peekBA0(chip, BA0_ACCTL); 260 261 if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) { 262 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, /* clear ACCTL_DCV */ ACCTL_VFRM | 263 ACCTL_ESYN | ACCTL_RSTN); 264 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | 265 ACCTL_ESYN | ACCTL_RSTN); 266 } else { 267 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC | 268 ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); 269 } 270 271 for (count = 0; count < 4000; count++) { 272 /* 273 * First, we want to wait for a short time. 274 */ 275 udelay(10); 276 /* 277 * Now, check to see if the write has completed. 278 * ACCTL = 460h, DCV should be reset by now and 460h = 07h 279 */ 280 if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) { 281 goto end; 282 } 283 } 284 snd_printk(KERN_ERR "AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val); 285 end: 286 chip->active_ctrl(chip, -1); 287 } 288 289 static void snd_cs46xx_ac97_write(struct snd_ac97 *ac97, 290 unsigned short reg, 291 unsigned short val) 292 { 293 struct snd_cs46xx *chip = ac97->private_data; 294 int codec_index = ac97->num; 295 296 snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX || 297 codec_index == CS46XX_SECONDARY_CODEC_INDEX, 298 return); 299 300 snd_cs46xx_codec_write(chip, reg, val, codec_index); 294 301 } 295 302 … … 299 306 */ 300 307 301 int snd_cs46xx_download( cs46xx_t*chip,302 u32 *src,308 int snd_cs46xx_download(struct snd_cs46xx *chip, 309 u32 *src, 303 310 unsigned long offset, 304 311 unsigned long len) 305 312 { 306 unsigned longdst;307 unsigned int bank = offset >> 16;308 offset = offset & 0xffff;309 310 snd_assert(!(offset & 3) && !(len & 3), return -EINVAL);311 dst = (unsigned long)chip->region.idx[bank+1].remap_addr + offset;312 len /= sizeof(u32);313 314 /* writel already converts 32-bit value to right endianess */315 while (len-- > 0) {316 writel(*src++, dst);317 dst += sizeof(u32);318 }319 return 0;313 void __iomem *dst; 314 unsigned int bank = offset >> 16; 315 offset = offset & 0xffff; 316 317 snd_assert(!(offset & 3) && !(len & 3), return -EINVAL); 318 dst = (char*)chip->region.idx[bank+1].remap_addr + offset; 319 len /= sizeof(u32); 320 321 /* writel already converts 32-bit value to right endianess */ 322 while (len-- > 0) { 323 writel(*src++, dst); 324 (char*)dst += sizeof(u32); 325 } 326 return 0; 320 327 } 321 328 … … 328 335 #include "imgs/cwcdma.h" 329 336 330 int snd_cs46xx_clear_BA1( cs46xx_t*chip,337 int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip, 331 338 unsigned long offset, 332 unsigned long len) 333 { 334 unsigned longdst;335 unsigned int bank = offset >> 16;336 offset = offset & 0xffff;337 338 snd_assert(!(offset & 3) && !(len & 3), return -EINVAL);339 dst = chip->region.idx[bank+1].remap_addr + offset;340 len /= sizeof(u32);341 342 /* writel already converts 32-bit value to right endianess */343 while (len-- > 0) {344 writel(0, dst);345 dst += sizeof(u32);346 }347 return 0;339 unsigned long len) 340 { 341 void __iomem *dst; 342 unsigned int bank = offset >> 16; 343 offset = offset & 0xffff; 344 345 snd_assert(!(offset & 3) && !(len & 3), return -EINVAL); 346 dst = chip->region.idx[bank+1].remap_addr + offset; 347 len /= sizeof(u32); 348 349 /* writel already converts 32-bit value to right endianess */ 350 while (len-- > 0) { 351 writel(0, dst); 352 dst += sizeof(u32); 353 } 354 return 0; 348 355 } 349 356 … … 352 359 #include "cs46xx_image.h" 353 360 354 int snd_cs46xx_download_image( cs46xx_t*chip)355 { 356 int idx, err;357 unsigned long offset = 0;358 359 for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) {360 if ((err = snd_cs46xx_download(chip,361 &BA1Struct.map[offset],362 BA1Struct.memory[idx].offset,363 BA1Struct.memory[idx].size)) < 0)364 return err;365 offset += BA1Struct.memory[idx].size >> 2;366 } 367 return 0;361 int snd_cs46xx_download_image(struct snd_cs46xx *chip) 362 { 363 int idx, err; 364 unsigned long offset = 0; 365 366 for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) { 367 if ((err = snd_cs46xx_download(chip, 368 &BA1Struct.map[offset], 369 BA1Struct.memory[idx].offset, 370 BA1Struct.memory[idx].size)) < 0) 371 return err; 372 offset += BA1Struct.memory[idx].size >> 2; 373 } 374 return 0; 368 375 } 369 376 #endif /* CONFIG_SND_CS46XX_NEW_DSP */ … … 373 380 */ 374 381 375 static void snd_cs46xx_reset(cs46xx_t *chip) 376 { 377 int idx; 378 379 /* 380 * Write the reset bit of the SP control register. 381 */ 382 snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RSTSP); 383 384 /* 385 * Write the control register. 386 */ 387 snd_cs46xx_poke(chip, BA1_SPCR, SPCR_DRQEN); 388 389 /* 390 * Clear the trap registers. 391 */ 392 for (idx = 0; idx < 8; idx++) { 393 snd_cs46xx_poke(chip, BA1_DREG, DREG_REGID_TRAP_SELECT + idx); 394 snd_cs46xx_poke(chip, BA1_TWPR, 0xFFFF); 395 } 396 snd_cs46xx_poke(chip, BA1_DREG, 0); 397 398 /* 399 * Set the frame timer to reflect the number of cycles per frame. 400 */ 401 snd_cs46xx_poke(chip, BA1_FRMT, 0xadf); 402 } 403 404 static int cs46xx_wait_for_fifo(cs46xx_t * chip,int retry_timeout) 405 { 406 u32 i, status = 0; 407 /* 408 * Make sure the previous FIFO write operation has completed. 409 */ 410 for(i = 0; i < 50; i++){ 411 status = snd_cs46xx_peekBA0(chip, BA0_SERBST); 412 413 if( !(status & SERBST_WBSY) ) 414 break; 415 416 mdelay(retry_timeout); 417 } 418 419 if(status & SERBST_WBSY) { 420 snd_printk( KERN_ERR "cs46xx: failure waiting for FIFO command to complete\n"); 421 422 return -EINVAL; 423 } 424 425 return 0; 426 } 427 428 static void snd_cs46xx_clear_serial_FIFOs(cs46xx_t *chip) 429 { 430 int idx, powerdown = 0; 431 unsigned int tmp; 432 433 /* 434 * See if the devices are powered down. If so, we must power them up first 435 * or they will not respond. 436 */ 437 tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1); 438 if (!(tmp & CLKCR1_SWCE)) { 439 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE); 440 powerdown = 1; 441 } 442 443 /* 444 * We want to clear out the serial port FIFOs so we don't end up playing 445 * whatever random garbage happens to be in them. We fill the sample FIFOS 446 * with zero (silence). 447 */ 448 snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0); 449 450 /* 451 * Fill all 256 sample FIFO locations. 452 */ 453 for (idx = 0; idx < 0xFF; idx++) { 454 /* 455 * Make sure the previous FIFO write operation has completed. 456 */ 457 if (cs46xx_wait_for_fifo(chip,1)) { 458 snd_printdd ("failed waiting for FIFO at addr (%02X)\n",idx); 459 if (powerdown) 460 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); 461 462 break; 463 } 464 /* 465 * Write the serial port FIFO index. 466 */ 467 snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx); 468 /* 469 * Tell the serial port to load the new value into the FIFO location. 470 */ 471 snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC); 472 } 473 /* 474 * Now, if we powered up the devices, then power them back down again. 475 * This is kinda ugly, but should never happen. 476 */ 477 if (powerdown) 478 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); 479 } 480 481 static void snd_cs46xx_proc_start(cs46xx_t *chip) 482 { 483 int cnt; 484 485 /* 486 * Set the frame timer to reflect the number of cycles per frame. 487 */ 488 snd_cs46xx_poke(chip, BA1_FRMT, 0xadf); 489 /* 490 * Turn on the run, run at frame, and DMA enable bits in the local copy of 491 * the SP control register. 492 */ 493 snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN); 494 /* 495 * Wait until the run at frame bit resets itself in the SP control 496 * register. 497 */ 498 for (cnt = 0; cnt < 25; cnt++) { 499 udelay(50); 500 if (!(snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR)) 501 break; 502 } 503 504 if (snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR) 505 snd_printk("SPCR_RUNFR never reset\n"); 506 } 507 508 static void snd_cs46xx_proc_stop(cs46xx_t *chip) 509 { 510 /* 511 * Turn off the run, run at frame, and DMA enable bits in the local copy of 512 * the SP control register. 513 */ 514 snd_cs46xx_poke(chip, BA1_SPCR, 0); 382 static void snd_cs46xx_reset(struct snd_cs46xx *chip) 383 { 384 int idx; 385 386 /* 387 * Write the reset bit of the SP control register. 388 */ 389 snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RSTSP); 390 391 /* 392 * Write the control register. 393 */ 394 snd_cs46xx_poke(chip, BA1_SPCR, SPCR_DRQEN); 395 396 /* 397 * Clear the trap registers. 398 */ 399 for (idx = 0; idx < 8; idx++) { 400 snd_cs46xx_poke(chip, BA1_DREG, DREG_REGID_TRAP_SELECT + idx); 401 snd_cs46xx_poke(chip, BA1_TWPR, 0xFFFF); 402 } 403 snd_cs46xx_poke(chip, BA1_DREG, 0); 404 405 /* 406 * Set the frame timer to reflect the number of cycles per frame. 407 */ 408 snd_cs46xx_poke(chip, BA1_FRMT, 0xadf); 409 } 410 411 static int cs46xx_wait_for_fifo(struct snd_cs46xx * chip,int retry_timeout) 412 { 413 u32 i, status = 0; 414 /* 415 * Make sure the previous FIFO write operation has completed. 416 */ 417 for(i = 0; i < 50; i++){ 418 status = snd_cs46xx_peekBA0(chip, BA0_SERBST); 419 420 if( !(status & SERBST_WBSY) ) 421 break; 422 423 mdelay(retry_timeout); 424 } 425 426 if(status & SERBST_WBSY) { 427 snd_printk( KERN_ERR "cs46xx: failure waiting for FIFO command to complete\n"); 428 429 return -EINVAL; 430 } 431 432 return 0; 433 } 434 435 static void snd_cs46xx_clear_serial_FIFOs(struct snd_cs46xx *chip) 436 { 437 int idx, powerdown = 0; 438 unsigned int tmp; 439 440 /* 441 * See if the devices are powered down. If so, we must power them up first 442 * or they will not respond. 443 */ 444 tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1); 445 if (!(tmp & CLKCR1_SWCE)) { 446 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE); 447 powerdown = 1; 448 } 449 450 /* 451 * We want to clear out the serial port FIFOs so we don't end up playing 452 * whatever random garbage happens to be in them. We fill the sample FIFOS 453 * with zero (silence). 454 */ 455 snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0); 456 457 /* 458 * Fill all 256 sample FIFO locations. 459 */ 460 for (idx = 0; idx < 0xFF; idx++) { 461 /* 462 * Make sure the previous FIFO write operation has completed. 463 */ 464 if (cs46xx_wait_for_fifo(chip,1)) { 465 snd_printdd ("failed waiting for FIFO at addr (%02X)\n",idx); 466 467 if (powerdown) 468 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); 469 470 break; 471 } 472 /* 473 * Write the serial port FIFO index. 474 */ 475 snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx); 476 /* 477 * Tell the serial port to load the new value into the FIFO location. 478 */ 479 snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC); 480 } 481 /* 482 * Now, if we powered up the devices, then power them back down again. 483 * This is kinda ugly, but should never happen. 484 */ 485 if (powerdown) 486 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); 487 } 488 489 static void snd_cs46xx_proc_start(struct snd_cs46xx *chip) 490 { 491 int cnt; 492 493 /* 494 * Set the frame timer to reflect the number of cycles per frame. 495 */ 496 snd_cs46xx_poke(chip, BA1_FRMT, 0xadf); 497 /* 498 * Turn on the run, run at frame, and DMA enable bits in the local copy of 499 * the SP control register. 500 */ 501 snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN); 502 /* 503 * Wait until the run at frame bit resets itself in the SP control 504 * register. 505 */ 506 for (cnt = 0; cnt < 25; cnt++) { 507 udelay(50); 508 if (!(snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR)) 509 break; 510 } 511 512 if (snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR) 513 snd_printk(KERN_ERR "SPCR_RUNFR never reset\n"); 514 } 515 516 static void snd_cs46xx_proc_stop(struct snd_cs46xx *chip) 517 { 518 /* 519 * Turn off the run, run at frame, and DMA enable bits in the local copy of 520 * the SP control register. 521 */ 522 snd_cs46xx_poke(chip, BA1_SPCR, 0); 515 523 } 516 524 … … 521 529 #define GOF_PER_SEC 200 522 530 523 static void snd_cs46xx_set_play_sample_rate( cs46xx_t*chip, unsigned int rate)524 { 525 unsigned long flags;526 unsigned int tmp1, tmp2;527 unsigned int phiIncr;528 unsigned int correctionPerGOF, correctionPerSec;529 530 /*531 * Compute the values used to drive the actual sample rate conversion.532 * The following formulas are being computed, using inline assembly533 * since we need to use 64 bit arithmetic to compute the values:534 *535 * phiIncr = floor((Fs,in * 2^26) / Fs,out)536 * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /537 * GOF_PER_SEC)538 * ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M539 * GOF_PER_SEC * correctionPerGOF540 *541 * i.e.542 *543 * phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out)544 * correctionPerGOF:correctionPerSec =545 * dividend:remainder(ulOther / GOF_PER_SEC)546 */547 tmp1 = rate << 16;548 phiIncr = tmp1 / 48000;549 tmp1 -= phiIncr * 48000;550 tmp1 <<= 10;551 phiIncr <<= 10;552 tmp2 = tmp1 / 48000;553 phiIncr += tmp2;554 tmp1 -= tmp2 * 48000;555 correctionPerGOF = tmp1 / GOF_PER_SEC;556 tmp1 -= correctionPerGOF * GOF_PER_SEC;557 correctionPerSec = tmp1;558 559 /*560 * Fill in the SampleRateConverter control block.561 */562 spin_lock_irqsave(&chip->reg_lock, flags);563 snd_cs46xx_poke(chip, BA1_PSRC,564 ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));565 snd_cs46xx_poke(chip, BA1_PPI, phiIncr);566 spin_unlock_irqrestore(&chip->reg_lock, flags);567 } 568 569 static void snd_cs46xx_set_capture_sample_rate( cs46xx_t*chip, unsigned int rate)570 { 571 unsigned long flags;572 unsigned int phiIncr, coeffIncr, tmp1, tmp2;573 unsigned int correctionPerGOF, correctionPerSec, initialDelay;574 unsigned int frameGroupLength, cnt;575 576 /*577 * We can only decimate by up to a factor of 1/9th the hardware rate.578 * Correct the value if an attempt is made to stray outside that limit.579 */580 if ((rate * 9) < 48000)581 rate = 48000 / 9;582 583 /*584 * We can not capture at at rate greater than the Input Rate (48000).585 * Return an error if an attempt is made to stray outside that limit.586 */587 if (rate > 48000)588 rate = 48000;589 590 /*591 * Compute the values used to drive the actual sample rate conversion.592 * The following formulas are being computed, using inline assembly593 * since we need to use 64 bit arithmetic to compute the values:594 *595 * coeffIncr = -floor((Fs,out * 2^23) / Fs,in)596 * phiIncr = floor((Fs,in * 2^26) / Fs,out)597 * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /598 * GOF_PER_SEC)599 * correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -600 * GOF_PER_SEC * correctionPerGOF601 * initialDelay = ceil((24 * Fs,in) / Fs,out)602 *603 * i.e.604 *605 * coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))606 * phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)607 * correctionPerGOF:correctionPerSec =608 * dividend:remainder(ulOther / GOF_PER_SEC)609 * initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)610 */611 612 tmp1 = rate << 16;613 coeffIncr = tmp1 / 48000;614 tmp1 -= coeffIncr * 48000;615 tmp1 <<= 7;616 coeffIncr <<= 7;617 coeffIncr += tmp1 / 48000;618 coeffIncr ^= 0xFFFFFFFF;619 coeffIncr++;620 tmp1 = 48000 << 16;621 phiIncr = tmp1 / rate;622 tmp1 -= phiIncr * rate;623 tmp1 <<= 10;624 phiIncr <<= 10;625 tmp2 = tmp1 / rate;626 phiIncr += tmp2;627 tmp1 -= tmp2 * rate;628 correctionPerGOF = tmp1 / GOF_PER_SEC;629 tmp1 -= correctionPerGOF * GOF_PER_SEC;630 correctionPerSec = tmp1;631 initialDelay = ((48000 * 24) + rate - 1) / rate;632 633 /*634 * Fill in the VariDecimate control block.635 */636 spin_lock_irqsave(&chip->reg_lock, flags);637 snd_cs46xx_poke(chip, BA1_CSRC,638 ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));639 snd_cs46xx_poke(chip, BA1_CCI, coeffIncr);640 snd_cs46xx_poke(chip, BA1_CD,641 (((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);642 snd_cs46xx_poke(chip, BA1_CPI, phiIncr);643 spin_unlock_irqrestore(&chip->reg_lock, flags);644 645 /*646 * Figure out the frame group length for the write back task. Basically,647 * this is just the factors of 24000 (2^6*3*5^3) that are not present in648 * the output sample rate.649 */650 frameGroupLength = 1;651 for (cnt = 2; cnt <= 64; cnt *= 2) {652 if (((rate / cnt) * cnt) != rate)653 frameGroupLength *= 2;654 }655 if (((rate / 3) * 3) != rate) {656 frameGroupLength *= 3;657 }658 for (cnt = 5; cnt <= 125; cnt *= 5) {659 if (((rate / cnt) * cnt) != rate) 660 frameGroupLength *= 5;661 }662 663 /*664 * Fill in the WriteBack control block.665 */666 spin_lock_irqsave(&chip->reg_lock, flags);667 snd_cs46xx_poke(chip, BA1_CFG1, frameGroupLength);668 snd_cs46xx_poke(chip, BA1_CFG2, (0x00800000 | frameGroupLength));669 snd_cs46xx_poke(chip, BA1_CCST, 0x0000FFFF);670 snd_cs46xx_poke(chip, BA1_CSPB, ((65536 * rate) / 24000));671 snd_cs46xx_poke(chip, (BA1_CSPB + 4), 0x0000FFFF);672 spin_unlock_irqrestore(&chip->reg_lock, flags);531 static void snd_cs46xx_set_play_sample_rate(struct snd_cs46xx *chip, unsigned int rate) 532 { 533 unsigned long flags; 534 unsigned int tmp1, tmp2; 535 unsigned int phiIncr; 536 unsigned int correctionPerGOF, correctionPerSec; 537 538 /* 539 * Compute the values used to drive the actual sample rate conversion. 540 * The following formulas are being computed, using inline assembly 541 * since we need to use 64 bit arithmetic to compute the values: 542 * 543 * phiIncr = floor((Fs,in * 2^26) / Fs,out) 544 * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) / 545 * GOF_PER_SEC) 546 * ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M 547 * GOF_PER_SEC * correctionPerGOF 548 * 549 * i.e. 550 * 551 * phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out) 552 * correctionPerGOF:correctionPerSec = 553 * dividend:remainder(ulOther / GOF_PER_SEC) 554 */ 555 tmp1 = rate << 16; 556 phiIncr = tmp1 / 48000; 557 tmp1 -= phiIncr * 48000; 558 tmp1 <<= 10; 559 phiIncr <<= 10; 560 tmp2 = tmp1 / 48000; 561 phiIncr += tmp2; 562 tmp1 -= tmp2 * 48000; 563 correctionPerGOF = tmp1 / GOF_PER_SEC; 564 tmp1 -= correctionPerGOF * GOF_PER_SEC; 565 correctionPerSec = tmp1; 566 567 /* 568 * Fill in the SampleRateConverter control block. 569 */ 570 spin_lock_irqsave(&chip->reg_lock, flags); 571 snd_cs46xx_poke(chip, BA1_PSRC, 572 ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF)); 573 snd_cs46xx_poke(chip, BA1_PPI, phiIncr); 574 spin_unlock_irqrestore(&chip->reg_lock, flags); 575 } 576 577 static void snd_cs46xx_set_capture_sample_rate(struct snd_cs46xx *chip, unsigned int rate) 578 { 579 unsigned long flags; 580 unsigned int phiIncr, coeffIncr, tmp1, tmp2; 581 unsigned int correctionPerGOF, correctionPerSec, initialDelay; 582 unsigned int frameGroupLength, cnt; 583 584 /* 585 * We can only decimate by up to a factor of 1/9th the hardware rate. 586 * Correct the value if an attempt is made to stray outside that limit. 587 */ 588 if ((rate * 9) < 48000) 589 rate = 48000 / 9; 590 591 /* 592 * We can not capture at at rate greater than the Input Rate (48000). 593 * Return an error if an attempt is made to stray outside that limit. 594 */ 595 if (rate > 48000) 596 rate = 48000; 597 598 /* 599 * Compute the values used to drive the actual sample rate conversion. 600 * The following formulas are being computed, using inline assembly 601 * since we need to use 64 bit arithmetic to compute the values: 602 * 603 * coeffIncr = -floor((Fs,out * 2^23) / Fs,in) 604 * phiIncr = floor((Fs,in * 2^26) / Fs,out) 605 * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) / 606 * GOF_PER_SEC) 607 * correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr - 608 * GOF_PER_SEC * correctionPerGOF 609 * initialDelay = ceil((24 * Fs,in) / Fs,out) 610 * 611 * i.e. 612 * 613 * coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in)) 614 * phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out) 615 * correctionPerGOF:correctionPerSec = 616 * dividend:remainder(ulOther / GOF_PER_SEC) 617 * initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out) 618 */ 619 620 tmp1 = rate << 16; 621 coeffIncr = tmp1 / 48000; 622 tmp1 -= coeffIncr * 48000; 623 tmp1 <<= 7; 624 coeffIncr <<= 7; 625 coeffIncr += tmp1 / 48000; 626 coeffIncr ^= 0xFFFFFFFF; 627 coeffIncr++; 628 tmp1 = 48000 << 16; 629 phiIncr = tmp1 / rate; 630 tmp1 -= phiIncr * rate; 631 tmp1 <<= 10; 632 phiIncr <<= 10; 633 tmp2 = tmp1 / rate; 634 phiIncr += tmp2; 635 tmp1 -= tmp2 * rate; 636 correctionPerGOF = tmp1 / GOF_PER_SEC; 637 tmp1 -= correctionPerGOF * GOF_PER_SEC; 638 correctionPerSec = tmp1; 639 initialDelay = ((48000 * 24) + rate - 1) / rate; 640 641 /* 642 * Fill in the VariDecimate control block. 643 */ 644 spin_lock_irqsave(&chip->reg_lock, flags); 645 snd_cs46xx_poke(chip, BA1_CSRC, 646 ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF)); 647 snd_cs46xx_poke(chip, BA1_CCI, coeffIncr); 648 snd_cs46xx_poke(chip, BA1_CD, 649 (((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80); 650 snd_cs46xx_poke(chip, BA1_CPI, phiIncr); 651 spin_unlock_irqrestore(&chip->reg_lock, flags); 652 653 /* 654 * Figure out the frame group length for the write back task. Basically, 655 * this is just the factors of 24000 (2^6*3*5^3) that are not present in 656 * the output sample rate. 657 */ 658 frameGroupLength = 1; 659 for (cnt = 2; cnt <= 64; cnt *= 2) { 660 if (((rate / cnt) * cnt) != rate) 661 frameGroupLength *= 2; 662 } 663 if (((rate / 3) * 3) != rate) { 664 frameGroupLength *= 3; 665 } 666 for (cnt = 5; cnt <= 125; cnt *= 5) { 667 if (((rate / cnt) * cnt) != rate) 668 frameGroupLength *= 5; 669 } 670 671 /* 672 * Fill in the WriteBack control block. 673 */ 674 spin_lock_irqsave(&chip->reg_lock, flags); 675 snd_cs46xx_poke(chip, BA1_CFG1, frameGroupLength); 676 snd_cs46xx_poke(chip, BA1_CFG2, (0x00800000 | frameGroupLength)); 677 snd_cs46xx_poke(chip, BA1_CCST, 0x0000FFFF); 678 snd_cs46xx_poke(chip, BA1_CSPB, ((65536 * rate) / 24000)); 679 snd_cs46xx_poke(chip, (BA1_CSPB + 4), 0x0000FFFF); 680 spin_unlock_irqrestore(&chip->reg_lock, flags); 673 681 } 674 682 … … 677 685 */ 678 686 679 static void snd_cs46xx_pb_trans_copy(s nd_pcm_substream_t*substream,680 snd_pcm_indirect_t *rec, size_t bytes)681 { 682 snd_pcm_runtime_t*runtime = substream->runtime;683 cs46xx_pcm_t* cpcm = runtime->private_data;684 memcpy(cpcm->hw_buf.area + rec->hw_data, runtime->dma_area + rec->sw_data, bytes);685 } 686 687 static int snd_cs46xx_playback_transfer(s nd_pcm_substream_t*substream)688 { 689 snd_pcm_runtime_t*runtime = substream->runtime;690 cs46xx_pcm_t* cpcm = runtime->private_data;691 snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy);692 return 0;693 } 694 695 static void snd_cs46xx_cp_trans_copy(s nd_pcm_substream_t*substream,696 snd_pcm_indirect_t *rec, size_t bytes)697 { 698 cs46xx_t*chip = snd_pcm_substream_chip(substream);699 snd_pcm_runtime_t*runtime = substream->runtime;700 memcpy(runtime->dma_area + rec->sw_data,701 chip->capt.hw_buf.area + rec->hw_data, bytes);702 } 703 704 static int snd_cs46xx_capture_transfer(s nd_pcm_substream_t*substream)705 { 706 cs46xx_t*chip = snd_pcm_substream_chip(substream);707 snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy);708 return 0;709 } 710 711 static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(s nd_pcm_substream_t *substream)712 { 713 cs46xx_t*chip = snd_pcm_substream_chip(substream);714 size_t ptr;715 cs46xx_pcm_t*cpcm = substream->runtime->private_data;716 snd_assert (cpcm->pcm_channel,return -ENXIO);717 718 #ifdef CONFIG_SND_CS46XX_NEW_DSP 719 ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2);687 static void snd_cs46xx_pb_trans_copy(struct snd_pcm_substream *substream, 688 struct snd_pcm_indirect *rec, size_t bytes) 689 { 690 struct snd_pcm_runtime *runtime = substream->runtime; 691 struct snd_cs46xx_pcm * cpcm = runtime->private_data; 692 memcpy(cpcm->hw_buf.area + rec->hw_data, runtime->dma_area + rec->sw_data, bytes); 693 } 694 695 static int snd_cs46xx_playback_transfer(struct snd_pcm_substream *substream) 696 { 697 struct snd_pcm_runtime *runtime = substream->runtime; 698 struct snd_cs46xx_pcm * cpcm = runtime->private_data; 699 snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy); 700 return 0; 701 } 702 703 static void snd_cs46xx_cp_trans_copy(struct snd_pcm_substream *substream, 704 struct snd_pcm_indirect *rec, size_t bytes) 705 { 706 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 707 struct snd_pcm_runtime *runtime = substream->runtime; 708 memcpy(runtime->dma_area + rec->sw_data, 709 chip->capt.hw_buf.area + rec->hw_data, bytes); 710 } 711 712 static int snd_cs46xx_capture_transfer(struct snd_pcm_substream *substream) 713 { 714 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 715 snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy); 716 return 0; 717 } 718 719 static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(struct snd_pcm_substream *substream) 720 { 721 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 722 size_t ptr; 723 struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data; 724 snd_assert (cpcm->pcm_channel,return -ENXIO); 725 726 #ifdef CONFIG_SND_CS46XX_NEW_DSP 727 ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2); 720 728 #else 721 ptr = snd_cs46xx_peek(chip, BA1_PBA);722 #endif 723 ptr -= cpcm->hw_buf.addr;724 return ptr >> cpcm->shift;725 } 726 727 static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(s nd_pcm_substream_t *substream)728 { 729 cs46xx_t*chip = snd_pcm_substream_chip(substream);730 size_t ptr;731 cs46xx_pcm_t*cpcm = substream->runtime->private_data;732 733 #ifdef CONFIG_SND_CS46XX_NEW_DSP 734 snd_assert (cpcm->pcm_channel,return -ENXIO);735 ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2);729 ptr = snd_cs46xx_peek(chip, BA1_PBA); 730 #endif 731 ptr -= cpcm->hw_buf.addr; 732 return ptr >> cpcm->shift; 733 } 734 735 static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(struct snd_pcm_substream *substream) 736 { 737 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 738 size_t ptr; 739 struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data; 740 741 #ifdef CONFIG_SND_CS46XX_NEW_DSP 742 snd_assert (cpcm->pcm_channel,return -ENXIO); 743 ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2); 736 744 #else 737 ptr = snd_cs46xx_peek(chip, BA1_PBA);738 #endif 739 ptr -= cpcm->hw_buf.addr;740 return snd_pcm_indirect_playback_pointer(substream, &cpcm->pcm_rec, ptr);741 } 742 743 static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(s nd_pcm_substream_t *substream)744 { 745 cs46xx_t*chip = snd_pcm_substream_chip(substream);746 size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;747 return ptr >> chip->capt.shift;748 } 749 750 static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(s nd_pcm_substream_t *substream)751 { 752 cs46xx_t*chip = snd_pcm_substream_chip(substream);753 size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;754 return snd_pcm_indirect_capture_pointer(substream, &chip->capt.pcm_rec, ptr);755 } 756 757 static int snd_cs46xx_playback_trigger(s nd_pcm_substream_t *substream,758 int cmd)759 { 760 cs46xx_t*chip = snd_pcm_substream_chip(substream);761 /*snd_pcm_runtime_t*runtime = substream->runtime;*/762 int result = 0;763 764 #ifdef CONFIG_SND_CS46XX_NEW_DSP 765 cs46xx_pcm_t*cpcm = substream->runtime->private_data;766 if (! cpcm->pcm_channel) {767 return -ENXIO;768 }769 #endif 770 switch (cmd) {771 case SNDRV_PCM_TRIGGER_START:772 case SNDRV_PCM_TRIGGER_RESUME:773 #ifdef CONFIG_SND_CS46XX_NEW_DSP 774 /* magic value to unmute PCM stream playback volume */775 snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 776 SCBVolumeCtrl) << 2, 0x80008000);777 778 if (cpcm->pcm_channel->unlinked)779 cs46xx_dsp_pcm_link(chip,cpcm->pcm_channel);780 781 if (substream->runtime->periods != CS46XX_FRAGS)782 snd_cs46xx_playback_transfer(substream);745 ptr = snd_cs46xx_peek(chip, BA1_PBA); 746 #endif 747 ptr -= cpcm->hw_buf.addr; 748 return snd_pcm_indirect_playback_pointer(substream, &cpcm->pcm_rec, ptr); 749 } 750 751 static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(struct snd_pcm_substream *substream) 752 { 753 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 754 size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr; 755 return ptr >> chip->capt.shift; 756 } 757 758 static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(struct snd_pcm_substream *substream) 759 { 760 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 761 size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr; 762 return snd_pcm_indirect_capture_pointer(substream, &chip->capt.pcm_rec, ptr); 763 } 764 765 static int snd_cs46xx_playback_trigger(struct snd_pcm_substream *substream, 766 int cmd) 767 { 768 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 769 /*struct snd_pcm_runtime *runtime = substream->runtime;*/ 770 int result = 0; 771 772 #ifdef CONFIG_SND_CS46XX_NEW_DSP 773 struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data; 774 if (! cpcm->pcm_channel) { 775 return -ENXIO; 776 } 777 #endif 778 switch (cmd) { 779 case SNDRV_PCM_TRIGGER_START: 780 case SNDRV_PCM_TRIGGER_RESUME: 781 #ifdef CONFIG_SND_CS46XX_NEW_DSP 782 /* magic value to unmute PCM stream playback volume */ 783 snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 784 SCBVolumeCtrl) << 2, 0x80008000); 785 786 if (cpcm->pcm_channel->unlinked) 787 cs46xx_dsp_pcm_link(chip,cpcm->pcm_channel); 788 789 if (substream->runtime->periods != CS46XX_FRAGS) 790 snd_cs46xx_playback_transfer(substream); 783 791 #else 784 spin_lock(&chip->reg_lock);785 if (substream->runtime->periods != CS46XX_FRAGS)786 snd_cs46xx_playback_transfer(substream);787 { unsigned int tmp;788 tmp = snd_cs46xx_peek(chip, BA1_PCTL);789 tmp &= 0x0000ffff;790 snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp);791 }792 spin_unlock(&chip->reg_lock);793 #endif 794 break;795 case SNDRV_PCM_TRIGGER_STOP:796 case SNDRV_PCM_TRIGGER_SUSPEND:797 #ifdef CONFIG_SND_CS46XX_NEW_DSP 798 /* magic mute channel */799 snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 800 SCBVolumeCtrl) << 2, 0xffffffff);801 802 if (!cpcm->pcm_channel->unlinked)803 cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel);792 spin_lock(&chip->reg_lock); 793 if (substream->runtime->periods != CS46XX_FRAGS) 794 snd_cs46xx_playback_transfer(substream); 795 { unsigned int tmp; 796 tmp = snd_cs46xx_peek(chip, BA1_PCTL); 797 tmp &= 0x0000ffff; 798 snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp); 799 } 800 spin_unlock(&chip->reg_lock); 801 #endif 802 break; 803 case SNDRV_PCM_TRIGGER_STOP: 804 case SNDRV_PCM_TRIGGER_SUSPEND: 805 #ifdef CONFIG_SND_CS46XX_NEW_DSP 806 /* magic mute channel */ 807 snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 808 SCBVolumeCtrl) << 2, 0xffffffff); 809 810 if (!cpcm->pcm_channel->unlinked) 811 cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel); 804 812 #else 805 spin_lock(&chip->reg_lock);806 { unsigned int tmp;807 tmp = snd_cs46xx_peek(chip, BA1_PCTL);808 tmp &= 0x0000ffff;809 snd_cs46xx_poke(chip, BA1_PCTL, tmp);810 }811 spin_unlock(&chip->reg_lock);812 #endif 813 break;814 default:815 result = -EINVAL;816 break;817 }818 819 return result;820 } 821 822 static int snd_cs46xx_capture_trigger(s nd_pcm_substream_t *substream,823 int cmd)824 { 825 cs46xx_t*chip = snd_pcm_substream_chip(substream);826 unsigned int tmp;827 int result = 0;828 829 spin_lock(&chip->reg_lock);830 switch (cmd) {831 case SNDRV_PCM_TRIGGER_START:832 case SNDRV_PCM_TRIGGER_RESUME:833 tmp = snd_cs46xx_peek(chip, BA1_CCTL);834 tmp &= 0xffff0000;835 snd_cs46xx_poke(chip, BA1_CCTL, chip->capt.ctl | tmp);836 break;837 case SNDRV_PCM_TRIGGER_STOP:838 case SNDRV_PCM_TRIGGER_SUSPEND:839 tmp = snd_cs46xx_peek(chip, BA1_CCTL);840 tmp &= 0xffff0000;841 snd_cs46xx_poke(chip, BA1_CCTL, tmp);842 break;843 default:844 result = -EINVAL;845 break;846 }847 spin_unlock(&chip->reg_lock);848 849 return result;850 } 851 852 #ifdef CONFIG_SND_CS46XX_NEW_DSP 853 static int _cs46xx_adjust_sample_rate ( cs46xx_t *chip, cs46xx_pcm_t*cpcm,854 int sample_rate) 855 { 856 857 /* If PCMReaderSCB and SrcTaskSCB not created yet ... */858 if ( cpcm->pcm_channel == NULL) {859 cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, 860 cpcm, cpcm->hw_addr,cpcm->pcm_channel_id);861 if (cpcm->pcm_channel == NULL) {862 snd_printk(KERN_ERR "cs46xx: failed to create virtual PCM channel\n");863 return -ENOMEM;864 }865 cpcm->pcm_channel->sample_rate = sample_rate;866 } else867 /* if sample rate is changed */868 if ((int)cpcm->pcm_channel->sample_rate != sample_rate) {869 int unlinked = cpcm->pcm_channel->unlinked;870 cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel);871 872 if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm, 873 cpcm->hw_addr,874 cpcm->pcm_channel_id)) == NULL) {875 snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n");876 return -ENOMEM;877 }878 879 if (!unlinked) cs46xx_dsp_pcm_link (chip,cpcm->pcm_channel);880 cpcm->pcm_channel->sample_rate = sample_rate;881 }882 883 return 0;884 } 885 #endif 886 887 888 static int snd_cs46xx_playback_hw_params(s nd_pcm_substream_t *substream,889 snd_pcm_hw_params_t *hw_params)890 { 891 snd_pcm_runtime_t*runtime = substream->runtime;892 cs46xx_pcm_t*cpcm;893 int err;894 #ifdef CONFIG_SND_CS46XX_NEW_DSP 895 cs46xx_t*chip = snd_pcm_substream_chip(substream);896 int sample_rate = params_rate(hw_params);897 int period_size = params_period_bytes(hw_params);898 #endif 899 cpcm = runtime->private_data;900 901 #ifdef CONFIG_SND_CS46XX_NEW_DSP 902 snd_assert (sample_rate != 0, return -ENXIO);903 904 down (&chip->spos_mutex);905 906 if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) {907 up (&chip->spos_mutex);908 return -ENXIO;909 }910 911 //snd_assert (cpcm->pcm_channel != NULL);912 if (!cpcm->pcm_channel) {913 up (&chip->spos_mutex);914 return -ENXIO;915 }916 917 918 if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size)) {919 up (&chip->spos_mutex);920 return -EINVAL;921 }922 923 snd_printdd ("period_size (%d), periods (%d) buffer_size(%d)\n",924 period_size, params_periods(hw_params),925 params_buffer_bytes(hw_params));926 #endif 927 928 if (params_periods(hw_params) == CS46XX_FRAGS) {929 if (runtime->dma_area != cpcm->hw_buf.area)930 snd_pcm_lib_free_pages(substream);931 runtime->dma_area = cpcm->hw_buf.area;932 runtime->dma_addr = cpcm->hw_buf.addr;933 runtime->dma_bytes = cpcm->hw_buf.bytes;934 935 936 #ifdef CONFIG_SND_CS46XX_NEW_DSP 937 if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {938 substream->ops = &snd_cs46xx_playback_ops;939 } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {940 substream->ops = &snd_cs46xx_playback_rear_ops;941 } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) {942 substream->ops = &snd_cs46xx_playback_clfe_ops;943 } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) {944 substream->ops = &snd_cs46xx_playback_iec958_ops;945 } else {946 //snd_assert(0);947 }813 spin_lock(&chip->reg_lock); 814 { unsigned int tmp; 815 tmp = snd_cs46xx_peek(chip, BA1_PCTL); 816 tmp &= 0x0000ffff; 817 snd_cs46xx_poke(chip, BA1_PCTL, tmp); 818 } 819 spin_unlock(&chip->reg_lock); 820 #endif 821 break; 822 default: 823 result = -EINVAL; 824 break; 825 } 826 827 return result; 828 } 829 830 static int snd_cs46xx_capture_trigger(struct snd_pcm_substream *substream, 831 int cmd) 832 { 833 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 834 unsigned int tmp; 835 int result = 0; 836 837 spin_lock(&chip->reg_lock); 838 switch (cmd) { 839 case SNDRV_PCM_TRIGGER_START: 840 case SNDRV_PCM_TRIGGER_RESUME: 841 tmp = snd_cs46xx_peek(chip, BA1_CCTL); 842 tmp &= 0xffff0000; 843 snd_cs46xx_poke(chip, BA1_CCTL, chip->capt.ctl | tmp); 844 break; 845 case SNDRV_PCM_TRIGGER_STOP: 846 case SNDRV_PCM_TRIGGER_SUSPEND: 847 tmp = snd_cs46xx_peek(chip, BA1_CCTL); 848 tmp &= 0xffff0000; 849 snd_cs46xx_poke(chip, BA1_CCTL, tmp); 850 break; 851 default: 852 result = -EINVAL; 853 break; 854 } 855 spin_unlock(&chip->reg_lock); 856 857 return result; 858 } 859 860 #ifdef CONFIG_SND_CS46XX_NEW_DSP 861 static int _cs46xx_adjust_sample_rate (struct snd_cs46xx *chip, struct snd_cs46xx_pcm *cpcm, 862 int sample_rate) 863 { 864 865 /* If PCMReaderSCB and SrcTaskSCB not created yet ... */ 866 if ( cpcm->pcm_channel == NULL) { 867 cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, 868 cpcm, cpcm->hw_buf.addr,cpcm->pcm_channel_id); 869 if (cpcm->pcm_channel == NULL) { 870 snd_printk(KERN_ERR "cs46xx: failed to create virtual PCM channel\n"); 871 return -ENOMEM; 872 } 873 cpcm->pcm_channel->sample_rate = sample_rate; 874 } else 875 /* if sample rate is changed */ 876 if ((int)cpcm->pcm_channel->sample_rate != sample_rate) { 877 int unlinked = cpcm->pcm_channel->unlinked; 878 cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel); 879 880 if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm, 881 cpcm->hw_buf.addr, 882 cpcm->pcm_channel_id)) == NULL) { 883 snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n"); 884 return -ENOMEM; 885 } 886 887 if (!unlinked) cs46xx_dsp_pcm_link (chip,cpcm->pcm_channel); 888 cpcm->pcm_channel->sample_rate = sample_rate; 889 } 890 891 return 0; 892 } 893 #endif 894 895 896 static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, 897 struct snd_pcm_hw_params *hw_params) 898 { 899 struct snd_pcm_runtime *runtime = substream->runtime; 900 struct snd_cs46xx_pcm *cpcm; 901 int err; 902 #ifdef CONFIG_SND_CS46XX_NEW_DSP 903 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 904 int sample_rate = params_rate(hw_params); 905 int period_size = params_period_bytes(hw_params); 906 #endif 907 cpcm = runtime->private_data; 908 909 #ifdef CONFIG_SND_CS46XX_NEW_DSP 910 snd_assert (sample_rate != 0, return -ENXIO); 911 912 down (&chip->spos_mutex); 913 914 if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) { 915 up (&chip->spos_mutex); 916 return -ENXIO; 917 } 918 919 snd_assert (cpcm->pcm_channel != NULL); 920 if (!cpcm->pcm_channel) { 921 up (&chip->spos_mutex); 922 return -ENXIO; 923 } 924 925 926 if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size)) { 927 up (&chip->spos_mutex); 928 return -EINVAL; 929 } 930 931 snd_printdd ("period_size (%d), periods (%d) buffer_size(%d)\n", 932 period_size, params_periods(hw_params), 933 params_buffer_bytes(hw_params)); 934 #endif 935 936 if (params_periods(hw_params) == CS46XX_FRAGS) { 937 if (runtime->dma_area != cpcm->hw_buf.area) 938 snd_pcm_lib_free_pages(substream); 939 runtime->dma_area = cpcm->hw_buf.area; 940 runtime->dma_addr = cpcm->hw_buf.addr; 941 runtime->dma_bytes = cpcm->hw_buf.bytes; 942 943 944 #ifdef CONFIG_SND_CS46XX_NEW_DSP 945 if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) { 946 substream->ops = &snd_cs46xx_playback_ops; 947 } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) { 948 substream->ops = &snd_cs46xx_playback_rear_ops; 949 } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) { 950 substream->ops = &snd_cs46xx_playback_clfe_ops; 951 } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) { 952 substream->ops = &snd_cs46xx_playback_iec958_ops; 953 } else { 954 snd_assert(0); 955 } 948 956 #else 949 substream->ops = &snd_cs46xx_playback_ops;950 #endif 951 952 } else {953 if (runtime->dma_area == cpcm->hw_buf.area) {954 runtime->dma_area = NULL;955 runtime->dma_addr = 0;956 runtime->dma_bytes = 0;957 }958 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) {959 #ifdef CONFIG_SND_CS46XX_NEW_DSP 960 up (&chip->spos_mutex);961 #endif 962 return err;963 }964 965 #ifdef CONFIG_SND_CS46XX_NEW_DSP 966 if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {967 substream->ops = &snd_cs46xx_playback_indirect_ops;968 } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {969 substream->ops = &snd_cs46xx_playback_indirect_rear_ops;970 } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) {971 substream->ops = &snd_cs46xx_playback_indirect_clfe_ops;972 } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) {973 substream->ops = &snd_cs46xx_playback_indirect_iec958_ops;974 } else {975 //snd_assert(0);976 }957 substream->ops = &snd_cs46xx_playback_ops; 958 #endif 959 960 } else { 961 if (runtime->dma_area == cpcm->hw_buf.area) { 962 runtime->dma_area = NULL; 963 runtime->dma_addr = 0; 964 runtime->dma_bytes = 0; 965 } 966 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) { 967 #ifdef CONFIG_SND_CS46XX_NEW_DSP 968 up (&chip->spos_mutex); 969 #endif 970 return err; 971 } 972 973 #ifdef CONFIG_SND_CS46XX_NEW_DSP 974 if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) { 975 substream->ops = &snd_cs46xx_playback_indirect_ops; 976 } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) { 977 substream->ops = &snd_cs46xx_playback_indirect_rear_ops; 978 } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) { 979 substream->ops = &snd_cs46xx_playback_indirect_clfe_ops; 980 } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) { 981 substream->ops = &snd_cs46xx_playback_indirect_iec958_ops; 982 } else { 983 snd_assert(0); 984 } 977 985 #else 978 substream->ops = &snd_cs46xx_playback_indirect_ops;979 #endif 980 981 }982 983 #ifdef CONFIG_SND_CS46XX_NEW_DSP 984 up (&chip->spos_mutex);985 #endif 986 987 return 0;988 } 989 990 static int snd_cs46xx_playback_hw_free(s nd_pcm_substream_t *substream)991 { 992 /*cs46xx_t*chip = snd_pcm_substream_chip(substream);*/993 snd_pcm_runtime_t*runtime = substream->runtime;994 cs46xx_pcm_t*cpcm;995 996 cpcm = runtime->private_data;997 998 /* if play_back open fails, then this function999 is called and cpcm can actually be NULL here */1000 if (!cpcm) return -ENXIO;1001 1002 if (runtime->dma_area != cpcm->hw_buf.area)1003 snd_pcm_lib_free_pages(substream);1004 1005 runtime->dma_area = NULL;1006 runtime->dma_addr = 0;1007 runtime->dma_bytes = 0;1008 1009 return 0;1010 } 1011 1012 static int snd_cs46xx_playback_prepare(s nd_pcm_substream_t *substream)1013 { 1014 unsigned int tmp;1015 unsigned int pfie;1016 cs46xx_t*chip = snd_pcm_substream_chip(substream);1017 snd_pcm_runtime_t*runtime = substream->runtime;1018 cs46xx_pcm_t*cpcm;1019 1020 cpcm = runtime->private_data;986 substream->ops = &snd_cs46xx_playback_indirect_ops; 987 #endif 988 989 } 990 991 #ifdef CONFIG_SND_CS46XX_NEW_DSP 992 up (&chip->spos_mutex); 993 #endif 994 995 return 0; 996 } 997 998 static int snd_cs46xx_playback_hw_free(struct snd_pcm_substream *substream) 999 { 1000 /*struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);*/ 1001 struct snd_pcm_runtime *runtime = substream->runtime; 1002 struct snd_cs46xx_pcm *cpcm; 1003 1004 cpcm = runtime->private_data; 1005 1006 /* if play_back open fails, then this function 1007 is called and cpcm can actually be NULL here */ 1008 if (!cpcm) return -ENXIO; 1009 1010 if (runtime->dma_area != cpcm->hw_buf.area) 1011 snd_pcm_lib_free_pages(substream); 1012 1013 runtime->dma_area = NULL; 1014 runtime->dma_addr = 0; 1015 runtime->dma_bytes = 0; 1016 1017 return 0; 1018 } 1019 1020 static int snd_cs46xx_playback_prepare(struct snd_pcm_substream *substream) 1021 { 1022 unsigned int tmp; 1023 unsigned int pfie; 1024 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 1025 struct snd_pcm_runtime *runtime = substream->runtime; 1026 struct snd_cs46xx_pcm *cpcm; 1027 1028 cpcm = runtime->private_data; 1021 1029 1022 1030 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1023 1031 snd_assert (cpcm->pcm_channel != NULL, return -ENXIO); 1024 1032 1025 pfie = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2 );1026 pfie &= ~0x0000f03f;1033 pfie = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2 ); 1034 pfie &= ~0x0000f03f; 1027 1035 #else 1028 /* old dsp */1029 pfie = snd_cs46xx_peek(chip, BA1_PFIE);1030 pfie &= ~0x0000f03f;1031 #endif 1032 1033 cpcm->shift = 2;1034 /* if to convert from stereo to mono */1035 if (runtime->channels == 1) {1036 cpcm->shift--;1037 pfie |= 0x00002000;1038 }1039 /* if to convert from 8 bit to 16 bit */1040 if (snd_pcm_format_width(runtime->format) == 8) {1041 cpcm->shift--;1042 pfie |= 0x00001000;1043 }1044 /* if to convert to unsigned */1045 if (snd_pcm_format_unsigned(runtime->format))1046 pfie |= 0x00008000;1047 1048 /* Never convert byte order when sample stream is 8 bit */1049 if (snd_pcm_format_width(runtime->format) != 8) {1050 /* convert from big endian to little endian */1051 if (snd_pcm_format_big_endian(runtime->format))1052 pfie |= 0x00004000;1053 }1054 1055 memset(&cpcm->pcm_rec, 0, sizeof(cpcm->pcm_rec));1056 cpcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);1057 cpcm->pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;1058 1059 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1060 1061 tmp = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2);1062 tmp &= ~0x000003ff;1063 tmp |= (4 << cpcm->shift) - 1;1064 /* playback transaction count register */1065 snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2, tmp);1066 1067 /* playback format && interrupt enable */1068 snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2, pfie | cpcm->pcm_channel->pcm_slot);1036 /* old dsp */ 1037 pfie = snd_cs46xx_peek(chip, BA1_PFIE); 1038 pfie &= ~0x0000f03f; 1039 #endif 1040 1041 cpcm->shift = 2; 1042 /* if to convert from stereo to mono */ 1043 if (runtime->channels == 1) { 1044 cpcm->shift--; 1045 pfie |= 0x00002000; 1046 } 1047 /* if to convert from 8 bit to 16 bit */ 1048 if (snd_pcm_format_width(runtime->format) == 8) { 1049 cpcm->shift--; 1050 pfie |= 0x00001000; 1051 } 1052 /* if to convert to unsigned */ 1053 if (snd_pcm_format_unsigned(runtime->format)) 1054 pfie |= 0x00008000; 1055 1056 /* Never convert byte order when sample stream is 8 bit */ 1057 if (snd_pcm_format_width(runtime->format) != 8) { 1058 /* convert from big endian to little endian */ 1059 if (snd_pcm_format_big_endian(runtime->format)) 1060 pfie |= 0x00004000; 1061 } 1062 1063 memset(&cpcm->pcm_rec, 0, sizeof(cpcm->pcm_rec)); 1064 cpcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); 1065 cpcm->pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift; 1066 1067 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1068 1069 tmp = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2); 1070 tmp &= ~0x000003ff; 1071 tmp |= (4 << cpcm->shift) - 1; 1072 /* playback transaction count register */ 1073 snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2, tmp); 1074 1075 /* playback format && interrupt enable */ 1076 snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2, pfie | cpcm->pcm_channel->pcm_slot); 1069 1077 #else 1070 snd_cs46xx_poke(chip, BA1_PBA, cpcm->hw_buf.addr);1071 tmp = snd_cs46xx_peek(chip, BA1_PDTC);1072 tmp &= ~0x000003ff;1073 tmp |= (4 << cpcm->shift) - 1;1074 snd_cs46xx_poke(chip, BA1_PDTC, tmp);1075 snd_cs46xx_poke(chip, BA1_PFIE, pfie);1076 snd_cs46xx_set_play_sample_rate(chip, runtime->rate);1077 #endif 1078 1079 return 0;1080 } 1081 1082 static int snd_cs46xx_capture_hw_params(s nd_pcm_substream_t *substream,1083 snd_pcm_hw_params_t *hw_params)1084 { 1085 cs46xx_t*chip = snd_pcm_substream_chip(substream);1086 snd_pcm_runtime_t*runtime = substream->runtime;1087 int err;1088 1089 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1090 cs46xx_dsp_pcm_ostream_set_period (chip, params_period_bytes(hw_params));1091 #endif 1092 if (runtime->periods == CS46XX_FRAGS) {1093 if (runtime->dma_area != chip->capt.hw_buf.area)1094 snd_pcm_lib_free_pages(substream);1095 runtime->dma_area = chip->capt.hw_buf.area;1096 runtime->dma_addr = chip->capt.hw_buf.addr;1097 runtime->dma_bytes = chip->capt.hw_buf.bytes;1098 substream->ops = &snd_cs46xx_capture_ops;1099 } else {1100 if (runtime->dma_area == chip->capt.hw_buf.area) {1101 runtime->dma_area = NULL;1102 runtime->dma_addr = 0;1103 runtime->dma_bytes = 0;1104 }1105 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)1106 return err;1107 substream->ops = &snd_cs46xx_capture_indirect_ops;1108 }1109 1110 return 0;1111 } 1112 1113 static int snd_cs46xx_capture_hw_free(s nd_pcm_substream_t *substream)1114 { 1115 cs46xx_t*chip = snd_pcm_substream_chip(substream);1116 snd_pcm_runtime_t*runtime = substream->runtime;1117 1118 if (runtime->dma_area != chip->capt.hw_buf.area)1119 snd_pcm_lib_free_pages(substream);1120 runtime->dma_area = NULL;1121 runtime->dma_addr = 0;1122 runtime->dma_bytes = 0;1123 1124 return 0;1125 } 1126 1127 static int snd_cs46xx_capture_prepare(s nd_pcm_substream_t *substream)1128 { 1129 cs46xx_t*chip = snd_pcm_substream_chip(substream);1130 snd_pcm_runtime_t*runtime = substream->runtime;1131 1132 snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_buf.addr);1133 chip->capt.shift = 2;1134 memset(&chip->capt.pcm_rec, 0, sizeof(chip->capt.pcm_rec));1135 chip->capt.pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);1136 chip->capt.pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << 2;1137 snd_cs46xx_set_capture_sample_rate(chip, runtime->rate);1138 1139 return 0;1078 snd_cs46xx_poke(chip, BA1_PBA, cpcm->hw_buf.addr); 1079 tmp = snd_cs46xx_peek(chip, BA1_PDTC); 1080 tmp &= ~0x000003ff; 1081 tmp |= (4 << cpcm->shift) - 1; 1082 snd_cs46xx_poke(chip, BA1_PDTC, tmp); 1083 snd_cs46xx_poke(chip, BA1_PFIE, pfie); 1084 snd_cs46xx_set_play_sample_rate(chip, runtime->rate); 1085 #endif 1086 1087 return 0; 1088 } 1089 1090 static int snd_cs46xx_capture_hw_params(struct snd_pcm_substream *substream, 1091 struct snd_pcm_hw_params *hw_params) 1092 { 1093 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 1094 struct snd_pcm_runtime *runtime = substream->runtime; 1095 int err; 1096 1097 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1098 cs46xx_dsp_pcm_ostream_set_period (chip, params_period_bytes(hw_params)); 1099 #endif 1100 if (runtime->periods == CS46XX_FRAGS) { 1101 if (runtime->dma_area != chip->capt.hw_buf.area) 1102 snd_pcm_lib_free_pages(substream); 1103 runtime->dma_area = chip->capt.hw_buf.area; 1104 runtime->dma_addr = chip->capt.hw_buf.addr; 1105 runtime->dma_bytes = chip->capt.hw_buf.bytes; 1106 substream->ops = &snd_cs46xx_capture_ops; 1107 } else { 1108 if (runtime->dma_area == chip->capt.hw_buf.area) { 1109 runtime->dma_area = NULL; 1110 runtime->dma_addr = 0; 1111 runtime->dma_bytes = 0; 1112 } 1113 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) 1114 return err; 1115 substream->ops = &snd_cs46xx_capture_indirect_ops; 1116 } 1117 1118 return 0; 1119 } 1120 1121 static int snd_cs46xx_capture_hw_free(struct snd_pcm_substream *substream) 1122 { 1123 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 1124 struct snd_pcm_runtime *runtime = substream->runtime; 1125 1126 if (runtime->dma_area != chip->capt.hw_buf.area) 1127 snd_pcm_lib_free_pages(substream); 1128 runtime->dma_area = NULL; 1129 runtime->dma_addr = 0; 1130 runtime->dma_bytes = 0; 1131 1132 return 0; 1133 } 1134 1135 static int snd_cs46xx_capture_prepare(struct snd_pcm_substream *substream) 1136 { 1137 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 1138 struct snd_pcm_runtime *runtime = substream->runtime; 1139 1140 snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_buf.addr); 1141 chip->capt.shift = 2; 1142 memset(&chip->capt.pcm_rec, 0, sizeof(chip->capt.pcm_rec)); 1143 chip->capt.pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); 1144 chip->capt.pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << 2; 1145 snd_cs46xx_set_capture_sample_rate(chip, runtime->rate); 1146 1147 return 0; 1140 1148 } 1141 1149 1142 1150 static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *regs) 1143 1151 { 1144 cs46xx_t *chip = dev_id; 1145 u32 status1; 1146 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1147 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1148 u32 status2; 1149 int i; 1150 cs46xx_pcm_t *cpcm = NULL; 1151 #endif 1152 #ifdef TARGET_OS2 1153 int fOurIrq = FALSE; 1154 #endif 1155 1156 /* 1157 * Read the Interrupt Status Register to clear the interrupt 1158 */ 1159 status1 = snd_cs46xx_peekBA0(chip, BA0_HISR); 1160 if ((status1 & 0x7fffffff) == 0) { 1161 snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV); 1162 return IRQ_NONE; 1163 } 1164 1165 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1166 status2 = snd_cs46xx_peekBA0(chip, BA0_HSR0); 1167 1168 for (i = 0; i < DSP_MAX_PCM_CHANNELS; ++i) { 1169 if (i <= 15) { 1170 if ( status1 & (1 << i) ) { 1171 if (i == CS46XX_DSP_CAPTURE_CHANNEL) { 1172 if (chip->capt.substream) 1173 snd_pcm_period_elapsed(chip->capt.substream); 1174 } else { 1175 if (ins->pcm_channels[i].active && 1176 ins->pcm_channels[i].private_data && 1177 !ins->pcm_channels[i].unlinked) { 1178 cpcm = ins->pcm_channels[i].private_data; 1179 snd_pcm_period_elapsed(cpcm->substream); 1180 } 1181 } 1182 } 1183 } else { 1184 if ( status2 & (1 << (i - 16))) { 1185 if (ins->pcm_channels[i].active && 1186 ins->pcm_channels[i].private_data && 1187 !ins->pcm_channels[i].unlinked) { 1188 cpcm = ins->pcm_channels[i].private_data; 1189 snd_pcm_period_elapsed(cpcm->substream); 1190 } 1191 } 1192 } 1193 } 1152 struct snd_cs46xx *chip = dev_id; 1153 u32 status1; 1154 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1155 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1156 u32 status2; 1157 int i; 1158 struct snd_cs46xx_pcm *cpcm = NULL; 1159 #endif 1160 1161 /* 1162 * Read the Interrupt Status Register to clear the interrupt 1163 */ 1164 status1 = snd_cs46xx_peekBA0(chip, BA0_HISR); 1165 if ((status1 & 0x7fffffff) == 0) { 1166 snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV); 1167 return IRQ_NONE; 1168 } 1169 1170 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1171 status2 = snd_cs46xx_peekBA0(chip, BA0_HSR0); 1172 1173 for (i = 0; i < DSP_MAX_PCM_CHANNELS; ++i) { 1174 if (i <= 15) { 1175 if ( status1 & (1 << i) ) { 1176 if (i == CS46XX_DSP_CAPTURE_CHANNEL) { 1177 if (chip->capt.substream) 1178 snd_pcm_period_elapsed(chip->capt.substream); 1179 } else { 1180 if (ins->pcm_channels[i].active && 1181 ins->pcm_channels[i].private_data && 1182 !ins->pcm_channels[i].unlinked) { 1183 cpcm = ins->pcm_channels[i].private_data; 1184 snd_pcm_period_elapsed(cpcm->substream); 1185 } 1186 } 1187 } 1188 } else { 1189 if ( status2 & (1 << (i - 16))) { 1190 if (ins->pcm_channels[i].active && 1191 ins->pcm_channels[i].private_data && 1192 !ins->pcm_channels[i].unlinked) { 1193 cpcm = ins->pcm_channels[i].private_data; 1194 snd_pcm_period_elapsed(cpcm->substream); 1195 } 1196 } 1197 } 1198 } 1194 1199 1195 1200 #else 1196 #ifdef TARGET_OS2 1197 if (status1 & (HISR_VC0|HISR_VC1)) 1198 { 1199 fOurIrq = TRUE; 1200 } 1201 #endif 1202 1203 /* old dsp */ 1204 if ((status1 & HISR_VC0) && chip->playback_pcm) { 1205 if (chip->playback_pcm->substream) 1206 snd_pcm_period_elapsed(chip->playback_pcm->substream); 1207 } 1208 if ((status1 & HISR_VC1) && chip->pcm) { 1209 if (chip->capt.substream) 1210 snd_pcm_period_elapsed(chip->capt.substream); 1211 } 1212 #endif 1213 1214 if ((status1 & HISR_MIDI) && chip->rmidi) { 1215 unsigned char c; 1216 1217 #ifdef TARGET_OS2 1218 fOurIrq = TRUE; 1219 #endif 1220 spin_lock(&chip->reg_lock); 1221 while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_RBE) == 0) { 1222 c = snd_cs46xx_peekBA0(chip, BA0_MIDRP); 1223 if ((chip->midcr & MIDCR_RIE) == 0) 1224 continue; 1225 spin_unlock(&chip->reg_lock); 1226 snd_rawmidi_receive(chip->midi_input, &c, 1); 1227 spin_lock(&chip->reg_lock); 1228 } 1229 while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) { 1230 if ((chip->midcr & MIDCR_TIE) == 0) 1231 break; 1232 if (snd_rawmidi_transmit(chip->midi_output, &c, 1) != 1) { 1233 chip->midcr &= ~MIDCR_TIE; 1234 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); 1235 break; 1236 } 1237 snd_cs46xx_pokeBA0(chip, BA0_MIDWP, c); 1238 } 1239 spin_unlock(&chip->reg_lock); 1240 } 1241 /* 1242 * EOI to the PCI part....reenables interrupts 1243 */ 1244 snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV); 1245 #ifdef TARGET_OS2 1246 if (fOurIrq) { 1247 eoi_irq(irq); 1248 } 1249 #endif //TARGET_OS2 1250 return IRQ_HANDLED; 1251 1252 } 1253 1254 static snd_pcm_hardware_t snd_cs46xx_playback = 1255 { 1256 /* info: */ (SNDRV_PCM_INFO_MMAP | 1257 SNDRV_PCM_INFO_INTERLEAVED | 1258 SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/ 1259 /*SNDRV_PCM_INFO_RESUME*/), 1260 /* formats: */ (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | 1261 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | 1262 SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE), 1263 /* rates: */ SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, 1264 /* rate_min: */ 5500, 1265 /* rate_max: */ 48000, 1266 /* channels_min: */ 1, 1267 /* channels_max: */ 2, 1268 /* buffer_bytes_max: */ (256 * 1024), 1269 /* period_bytes_min: */ CS46XX_MIN_PERIOD_SIZE, 1270 /* period_bytes_max: */ CS46XX_MAX_PERIOD_SIZE, 1271 /* periods_min: */ CS46XX_FRAGS, 1272 /* periods_max: */ 1024, 1273 /* fifo_size: */ 0, 1201 /* old dsp */ 1202 if ((status1 & HISR_VC0) && chip->playback_pcm) { 1203 if (chip->playback_pcm->substream) 1204 snd_pcm_period_elapsed(chip->playback_pcm->substream); 1205 } 1206 if ((status1 & HISR_VC1) && chip->pcm) { 1207 if (chip->capt.substream) 1208 snd_pcm_period_elapsed(chip->capt.substream); 1209 } 1210 #endif 1211 1212 if ((status1 & HISR_MIDI) && chip->rmidi) { 1213 unsigned char c; 1214 1215 spin_lock(&chip->reg_lock); 1216 while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_RBE) == 0) { 1217 c = snd_cs46xx_peekBA0(chip, BA0_MIDRP); 1218 if ((chip->midcr & MIDCR_RIE) == 0) 1219 continue; 1220 snd_rawmidi_receive(chip->midi_input, &c, 1); 1221 } 1222 while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) { 1223 if ((chip->midcr & MIDCR_TIE) == 0) 1224 break; 1225 if (snd_rawmidi_transmit(chip->midi_output, &c, 1) != 1) { 1226 chip->midcr &= ~MIDCR_TIE; 1227 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); 1228 break; 1229 } 1230 snd_cs46xx_pokeBA0(chip, BA0_MIDWP, c); 1231 } 1232 spin_unlock(&chip->reg_lock); 1233 } 1234 /* 1235 * EOI to the PCI part....reenables interrupts 1236 */ 1237 snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV); 1238 1239 return IRQ_HANDLED; 1240 } 1241 1242 static struct snd_pcm_hardware snd_cs46xx_playback = 1243 { 1244 .info = (SNDRV_PCM_INFO_MMAP | 1245 SNDRV_PCM_INFO_INTERLEAVED | 1246 SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/ 1247 /*SNDRV_PCM_INFO_RESUME*/), 1248 .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | 1249 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | 1250 SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE), 1251 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, 1252 .rate_min = 5500, 1253 .rate_max = 48000, 1254 .channels_min = 1, 1255 .channels_max = 2, 1256 .buffer_bytes_max = (256 * 1024), 1257 .period_bytes_min = CS46XX_MIN_PERIOD_SIZE, 1258 .period_bytes_max = CS46XX_MAX_PERIOD_SIZE, 1259 .periods_min = CS46XX_FRAGS, 1260 .periods_max = 1024, 1261 .fifo_size = 0, 1274 1262 }; 1275 1263 1276 static s nd_pcm_hardware_tsnd_cs46xx_capture =1277 { 1278 /* info: */(SNDRV_PCM_INFO_MMAP |1279 SNDRV_PCM_INFO_INTERLEAVED |1280 SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/1281 /*SNDRV_PCM_INFO_RESUME*/),1282 /* formats: */SNDRV_PCM_FMTBIT_S16_LE,1283 /* rates: */SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,1284 /* rate_min: */5500,1285 /* rate_max: */48000,1286 /* channels_min: */2,1287 /* channels_max: */2,1288 /* buffer_bytes_max: */(256 * 1024),1289 /* period_bytes_min: */CS46XX_MIN_PERIOD_SIZE,1290 /* period_bytes_max: */CS46XX_MAX_PERIOD_SIZE,1291 /* periods_min: */CS46XX_FRAGS,1292 /* periods_max: */1024,1293 /* fifo_size: */0,1264 static struct snd_pcm_hardware snd_cs46xx_capture = 1265 { 1266 .info = (SNDRV_PCM_INFO_MMAP | 1267 SNDRV_PCM_INFO_INTERLEAVED | 1268 SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/ 1269 /*SNDRV_PCM_INFO_RESUME*/), 1270 .formats = SNDRV_PCM_FMTBIT_S16_LE, 1271 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, 1272 .rate_min = 5500, 1273 .rate_max = 48000, 1274 .channels_min = 2, 1275 .channels_max = 2, 1276 .buffer_bytes_max = (256 * 1024), 1277 .period_bytes_min = CS46XX_MIN_PERIOD_SIZE, 1278 .period_bytes_max = CS46XX_MAX_PERIOD_SIZE, 1279 .periods_min = CS46XX_FRAGS, 1280 .periods_max = 1024, 1281 .fifo_size = 0, 1294 1282 }; 1295 1283 … … 1298 1286 static unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 }; 1299 1287 1300 #define PERIOD_SIZES sizeof(period_sizes) / sizeof(period_sizes[0]) 1301 1302 static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = { 1303 /*.count = */PERIOD_SIZES, 1304 /*.list = */period_sizes, 1305 /*.mask = */0 1288 static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { 1289 .count = ARRAY_SIZE(period_sizes), 1290 .list = period_sizes, 1291 .mask = 0 1306 1292 }; 1307 1293 1308 1294 #endif 1309 1295 1310 static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime) 1311 { 1312 cs46xx_pcm_t * cpcm = runtime->private_data; 1313 kfree(cpcm); 1314 } 1315 1316 static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id) 1317 { 1318 cs46xx_t *chip = snd_pcm_substream_chip(substream); 1319 cs46xx_pcm_t * cpcm; 1320 snd_pcm_runtime_t *runtime = substream->runtime; 1321 1322 cpcm = kcalloc(1, sizeof(*cpcm), GFP_KERNEL); 1323 if (cpcm == NULL) 1324 return -ENOMEM; 1325 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 1326 PAGE_SIZE, &cpcm->hw_buf) < 0) { 1327 kfree(cpcm); 1328 return -ENOMEM; 1329 } 1330 1331 runtime->hw = snd_cs46xx_playback; 1332 runtime->private_data = cpcm; 1333 runtime->private_free = snd_cs46xx_pcm_free_substream; 1334 1335 cpcm->substream = substream; 1336 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1337 down (&chip->spos_mutex); 1338 cpcm->pcm_channel = NULL; 1339 cpcm->pcm_channel_id = pcm_channel_id; 1340 1341 1342 snd_pcm_hw_constraint_list(runtime, 0, 1343 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 1344 &hw_constraints_period_sizes); 1345 1346 up (&chip->spos_mutex); 1296 static void snd_cs46xx_pcm_free_substream(struct snd_pcm_runtime *runtime) 1297 { 1298 kfree(runtime->private_data); 1299 } 1300 1301 static int _cs46xx_playback_open_channel (struct snd_pcm_substream *substream,int pcm_channel_id) 1302 { 1303 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 1304 struct snd_cs46xx_pcm * cpcm; 1305 struct snd_pcm_runtime *runtime = substream->runtime; 1306 1307 cpcm = (struct snd_cs46xx_pcm * )kzalloc(sizeof(*cpcm), GFP_KERNEL); 1308 if (cpcm == NULL) 1309 return -ENOMEM; 1310 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 1311 PAGE_SIZE, &cpcm->hw_buf) < 0) { 1312 kfree(cpcm); 1313 return -ENOMEM; 1314 } 1315 1316 runtime->hw = snd_cs46xx_playback; 1317 runtime->private_data = cpcm; 1318 runtime->private_free = snd_cs46xx_pcm_free_substream; 1319 1320 cpcm->substream = substream; 1321 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1322 down (&chip->spos_mutex); 1323 cpcm->pcm_channel = NULL; 1324 cpcm->pcm_channel_id = pcm_channel_id; 1325 1326 1327 snd_pcm_hw_constraint_list(runtime, 0, 1328 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 1329 &hw_constraints_period_sizes); 1330 1331 up (&chip->spos_mutex); 1347 1332 #else 1348 chip->playback_pcm = cpcm; /* HACK */1349 #endif 1350 1351 if (chip->accept_valid)1352 substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;1353 chip->active_ctrl(chip, 1);1354 1355 return 0;1356 } 1357 1358 static int snd_cs46xx_playback_open(s nd_pcm_substream_t *substream)1359 { 1360 snd_printdd("open front channel\n");1361 return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL);1362 } 1363 1364 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1365 static int snd_cs46xx_playback_open_rear(s nd_pcm_substream_t *substream)1366 { 1367 snd_printdd("open rear channel\n");1368 1369 return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL);1370 } 1371 1372 static int snd_cs46xx_playback_open_clfe(s nd_pcm_substream_t *substream)1373 { 1374 snd_printdd("open center - LFE channel\n");1375 1376 return _cs46xx_playback_open_channel(substream,DSP_PCM_CENTER_LFE_CHANNEL);1377 } 1378 1379 static int snd_cs46xx_playback_open_iec958(s nd_pcm_substream_t *substream)1380 { 1381 cs46xx_t*chip = snd_pcm_substream_chip(substream);1382 1383 snd_printdd("open raw iec958 channel\n");1384 1385 down (&chip->spos_mutex);1386 cs46xx_iec958_pre_open (chip);1387 up (&chip->spos_mutex);1388 1389 return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL);1390 } 1391 1392 static int snd_cs46xx_playback_close(s nd_pcm_substream_t *substream);1393 1394 static int snd_cs46xx_playback_close_iec958(s nd_pcm_substream_t *substream)1395 { 1396 int err;1397 cs46xx_t*chip = snd_pcm_substream_chip(substream);1398 1399 snd_printdd("close raw iec958 channel\n");1400 1401 err = snd_cs46xx_playback_close(substream);1402 1403 down (&chip->spos_mutex);1404 cs46xx_iec958_post_close (chip);1405 up (&chip->spos_mutex);1406 1407 return err;1408 } 1409 #endif 1410 1411 static int snd_cs46xx_capture_open(s nd_pcm_substream_t *substream)1412 { 1413 cs46xx_t*chip = snd_pcm_substream_chip(substream);1414 1415 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),1416 PAGE_SIZE, &chip->capt.hw_buf) < 0)1417 return -ENOMEM;1418 chip->capt.substream = substream;1419 substream->runtime->hw = snd_cs46xx_capture;1420 1421 if (chip->accept_valid)1422 substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;1423 1424 chip->active_ctrl(chip, 1);1425 1426 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1427 snd_pcm_hw_constraint_list(substream->runtime, 0,1428 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 1429 &hw_constraints_period_sizes);1430 #endif 1431 return 0;1432 } 1433 1434 static int snd_cs46xx_playback_close(s nd_pcm_substream_t *substream)1435 { 1436 cs46xx_t*chip = snd_pcm_substream_chip(substream);1437 snd_pcm_runtime_t*runtime = substream->runtime;1438 cs46xx_pcm_t* cpcm;1439 1440 cpcm = runtime->private_data;1441 1442 /* when playback_open fails, then cpcm can be NULL */1443 if (!cpcm) return -ENXIO;1444 1445 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1446 down (&chip->spos_mutex);1447 if (cpcm->pcm_channel) {1448 cs46xx_dsp_destroy_pcm_channel(chip,cpcm->pcm_channel);1449 cpcm->pcm_channel = NULL;1450 }1451 up (&chip->spos_mutex);1333 chip->playback_pcm = cpcm; /* HACK */ 1334 #endif 1335 1336 if (chip->accept_valid) 1337 substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID; 1338 chip->active_ctrl(chip, 1); 1339 1340 return 0; 1341 } 1342 1343 static int snd_cs46xx_playback_open(struct snd_pcm_substream *substream) 1344 { 1345 snd_printdd("open front channel\n"); 1346 return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL); 1347 } 1348 1349 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1350 static int snd_cs46xx_playback_open_rear(struct snd_pcm_substream *substream) 1351 { 1352 snd_printdd("open rear channel\n"); 1353 1354 return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL); 1355 } 1356 1357 static int snd_cs46xx_playback_open_clfe(struct snd_pcm_substream *substream) 1358 { 1359 snd_printdd("open center - LFE channel\n"); 1360 1361 return _cs46xx_playback_open_channel(substream,DSP_PCM_CENTER_LFE_CHANNEL); 1362 } 1363 1364 static int snd_cs46xx_playback_open_iec958(struct snd_pcm_substream *substream) 1365 { 1366 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 1367 1368 snd_printdd("open raw iec958 channel\n"); 1369 1370 down (&chip->spos_mutex); 1371 cs46xx_iec958_pre_open (chip); 1372 up (&chip->spos_mutex); 1373 1374 return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL); 1375 } 1376 1377 static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream); 1378 1379 static int snd_cs46xx_playback_close_iec958(struct snd_pcm_substream *substream) 1380 { 1381 int err; 1382 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 1383 1384 snd_printdd("close raw iec958 channel\n"); 1385 1386 err = snd_cs46xx_playback_close(substream); 1387 1388 down (&chip->spos_mutex); 1389 cs46xx_iec958_post_close (chip); 1390 up (&chip->spos_mutex); 1391 1392 return err; 1393 } 1394 #endif 1395 1396 static int snd_cs46xx_capture_open(struct snd_pcm_substream *substream) 1397 { 1398 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 1399 1400 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 1401 PAGE_SIZE, &chip->capt.hw_buf) < 0) 1402 return -ENOMEM; 1403 chip->capt.substream = substream; 1404 substream->runtime->hw = snd_cs46xx_capture; 1405 1406 if (chip->accept_valid) 1407 substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID; 1408 1409 chip->active_ctrl(chip, 1); 1410 1411 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1412 snd_pcm_hw_constraint_list(substream->runtime, 0, 1413 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 1414 &hw_constraints_period_sizes); 1415 #endif 1416 return 0; 1417 } 1418 1419 static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream) 1420 { 1421 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 1422 struct snd_pcm_runtime *runtime = substream->runtime; 1423 struct snd_cs46xx_pcm * cpcm; 1424 1425 cpcm = runtime->private_data; 1426 1427 /* when playback_open fails, then cpcm can be NULL */ 1428 if (!cpcm) return -ENXIO; 1429 1430 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1431 down (&chip->spos_mutex); 1432 if (cpcm->pcm_channel) { 1433 cs46xx_dsp_destroy_pcm_channel(chip,cpcm->pcm_channel); 1434 cpcm->pcm_channel = NULL; 1435 } 1436 up (&chip->spos_mutex); 1452 1437 #else 1453 chip->playback_pcm = NULL; 1454 #endif 1455 1456 cpcm->substream = NULL; 1457 snd_dma_free_pages(&cpcm->hw_buf); 1458 chip->active_ctrl(chip, -1); 1459 1460 return 0; 1461 } 1462 1463 static int snd_cs46xx_capture_close(snd_pcm_substream_t * substream) 1464 { 1465 cs46xx_t *chip = snd_pcm_substream_chip(substream); 1466 1467 chip->capt.substream = NULL; 1468 snd_dma_free_pages(&chip->capt.hw_buf); 1469 chip->active_ctrl(chip, -1); 1470 1471 return 0; 1472 } 1473 1474 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1475 snd_pcm_ops_t snd_cs46xx_playback_rear_ops = { 1476 /* .open = */ snd_cs46xx_playback_open_rear, 1477 /* .close = */ snd_cs46xx_playback_close, 1478 /* .ioctl = */ snd_pcm_lib_ioctl, 1479 /* .hw_params = */ snd_cs46xx_playback_hw_params, 1480 /* .hw_free = */ snd_cs46xx_playback_hw_free, 1481 /* .prepare = */ snd_cs46xx_playback_prepare, 1482 /* .trigger = */ snd_cs46xx_playback_trigger, 1483 /* .pointer = */ snd_cs46xx_playback_direct_pointer, 1484 0,0,0,0 1438 chip->playback_pcm = NULL; 1439 #endif 1440 1441 cpcm->substream = NULL; 1442 snd_dma_free_pages(&cpcm->hw_buf); 1443 chip->active_ctrl(chip, -1); 1444 1445 return 0; 1446 } 1447 1448 static int snd_cs46xx_capture_close(struct snd_pcm_substream *substream) 1449 { 1450 struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); 1451 1452 chip->capt.substream = NULL; 1453 snd_dma_free_pages(&chip->capt.hw_buf); 1454 chip->active_ctrl(chip, -1); 1455 1456 return 0; 1457 } 1458 1459 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1460 static struct snd_pcm_ops snd_cs46xx_playback_rear_ops = { 1461 .open = snd_cs46xx_playback_open_rear, 1462 .close = snd_cs46xx_playback_close, 1463 .ioctl = snd_pcm_lib_ioctl, 1464 .hw_params = snd_cs46xx_playback_hw_params, 1465 .hw_free = snd_cs46xx_playback_hw_free, 1466 .prepare = snd_cs46xx_playback_prepare, 1467 .trigger = snd_cs46xx_playback_trigger, 1468 .pointer = snd_cs46xx_playback_direct_pointer, 1485 1469 }; 1486 snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops = { 1487 /* .open = */ snd_cs46xx_playback_open_rear, 1488 /* .close = */ snd_cs46xx_playback_close,1489 /* .ioctl = */ snd_pcm_lib_ioctl,1490 /* .hw_params = */ snd_cs46xx_playback_hw_params,1491 /* .hw_free = */ snd_cs46xx_playback_hw_free,1492 /* .prepare = */ snd_cs46xx_playback_prepare,1493 /* .trigger = */ snd_cs46xx_playback_trigger,1494 /* .pointer = */ snd_cs46xx_playback_indirect_pointer,1495 0,0,0,1496 /* .ack = */snd_cs46xx_playback_transfer,1470 1471 static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = { 1472 .open = snd_cs46xx_playback_open_rear, 1473 .close = snd_cs46xx_playback_close, 1474 .ioctl = snd_pcm_lib_ioctl, 1475 .hw_params = snd_cs46xx_playback_hw_params, 1476 .hw_free = snd_cs46xx_playback_hw_free, 1477 .prepare = snd_cs46xx_playback_prepare, 1478 .trigger = snd_cs46xx_playback_trigger, 1479 .pointer = snd_cs46xx_playback_indirect_pointer, 1480 .ack = snd_cs46xx_playback_transfer, 1497 1481 }; 1498 1482 1499 snd_pcm_ops_t snd_cs46xx_playback_clfe_ops = { 1500 /* .open = */ snd_cs46xx_playback_open_clfe, 1501 /* .close = */ snd_cs46xx_playback_close, 1502 /* .ioctl = */ snd_pcm_lib_ioctl, 1503 /* .hw_params = */ snd_cs46xx_playback_hw_params, 1504 /* .hw_free = */ snd_cs46xx_playback_hw_free, 1505 /* .prepare = */ snd_cs46xx_playback_prepare, 1506 /* .trigger = */ snd_cs46xx_playback_trigger, 1507 /* .pointer = */ snd_cs46xx_playback_direct_pointer, 1508 0,0,0,0 1483 static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = { 1484 .open = snd_cs46xx_playback_open_clfe, 1485 .close = snd_cs46xx_playback_close, 1486 .ioctl = snd_pcm_lib_ioctl, 1487 .hw_params = snd_cs46xx_playback_hw_params, 1488 .hw_free = snd_cs46xx_playback_hw_free, 1489 .prepare = snd_cs46xx_playback_prepare, 1490 .trigger = snd_cs46xx_playback_trigger, 1491 .pointer = snd_cs46xx_playback_direct_pointer, 1509 1492 }; 1510 1493 1511 snd_pcm_ops_t snd_cs46xx_playback_indirect_clfe_ops = { 1512 /* .open = */ snd_cs46xx_playback_open_clfe, 1513 /* .close = */ snd_cs46xx_playback_close, 1514 /* .ioctl = */ snd_pcm_lib_ioctl, 1515 /* .hw_params = */ snd_cs46xx_playback_hw_params, 1516 /* .hw_free = */ snd_cs46xx_playback_hw_free, 1517 /* .prepare = */ snd_cs46xx_playback_prepare, 1518 /* .trigger = */ snd_cs46xx_playback_trigger, 1519 /* .pointer = */ snd_cs46xx_playback_indirect_pointer, 1520 0,0,0, 1521 /* .ack = */ snd_cs46xx_playback_transfer, 1494 static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = { 1495 .open = snd_cs46xx_playback_open_clfe, 1496 .close = snd_cs46xx_playback_close, 1497 .ioctl = snd_pcm_lib_ioctl, 1498 .hw_params = snd_cs46xx_playback_hw_params, 1499 .hw_free = snd_cs46xx_playback_hw_free, 1500 .prepare = snd_cs46xx_playback_prepare, 1501 .trigger = snd_cs46xx_playback_trigger, 1502 .pointer = snd_cs46xx_playback_indirect_pointer, 1503 .ack = snd_cs46xx_playback_transfer, 1522 1504 }; 1523 1505 1524 snd_pcm_ops_t snd_cs46xx_playback_iec958_ops = { 1525 /* .open = */ snd_cs46xx_playback_open_iec958, 1526 /* .close = */ snd_cs46xx_playback_close_iec958, 1527 /* .ioctl = */ snd_pcm_lib_ioctl, 1528 /* .hw_params = */ snd_cs46xx_playback_hw_params, 1529 /* .hw_free = */ snd_cs46xx_playback_hw_free, 1530 /* .prepare = */ snd_cs46xx_playback_prepare, 1531 /* .trigger = */ snd_cs46xx_playback_trigger, 1532 /* .pointer = */ snd_cs46xx_playback_direct_pointer, 1533 0,0,0,0 1506 static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = { 1507 .open = snd_cs46xx_playback_open_iec958, 1508 .close = snd_cs46xx_playback_close_iec958, 1509 .ioctl = snd_pcm_lib_ioctl, 1510 .hw_params = snd_cs46xx_playback_hw_params, 1511 .hw_free = snd_cs46xx_playback_hw_free, 1512 .prepare = snd_cs46xx_playback_prepare, 1513 .trigger = snd_cs46xx_playback_trigger, 1514 .pointer = snd_cs46xx_playback_direct_pointer, 1534 1515 }; 1535 1516 1536 snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops = { 1537 /* .open = */ snd_cs46xx_playback_open_iec958, 1538 /* .close = */ snd_cs46xx_playback_close_iec958, 1539 /* .ioctl = */ snd_pcm_lib_ioctl, 1540 /* .hw_params = */ snd_cs46xx_playback_hw_params, 1541 /* .hw_free = */ snd_cs46xx_playback_hw_free, 1542 /* .prepare = */ snd_cs46xx_playback_prepare, 1543 /* .trigger = */ snd_cs46xx_playback_trigger, 1544 /* .pointer = */ snd_cs46xx_playback_indirect_pointer, 1545 0,0,0, 1546 /* .ack = */ snd_cs46xx_playback_transfer, 1517 static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = { 1518 .open = snd_cs46xx_playback_open_iec958, 1519 .close = snd_cs46xx_playback_close_iec958, 1520 .ioctl = snd_pcm_lib_ioctl, 1521 .hw_params = snd_cs46xx_playback_hw_params, 1522 .hw_free = snd_cs46xx_playback_hw_free, 1523 .prepare = snd_cs46xx_playback_prepare, 1524 .trigger = snd_cs46xx_playback_trigger, 1525 .pointer = snd_cs46xx_playback_indirect_pointer, 1526 .ack = snd_cs46xx_playback_transfer, 1547 1527 }; 1548 1528 1549 1529 #endif 1550 1530 1551 snd_pcm_ops_t snd_cs46xx_playback_ops = { 1552 snd_cs46xx_playback_open, 1553 snd_cs46xx_playback_close, 1554 snd_pcm_lib_ioctl, 1555 snd_cs46xx_playback_hw_params, 1556 snd_cs46xx_playback_hw_free, 1557 snd_cs46xx_playback_prepare, 1558 snd_cs46xx_playback_trigger, 1559 snd_cs46xx_playback_direct_pointer, 1560 0,0,0,0 1531 static struct snd_pcm_ops snd_cs46xx_playback_ops = { 1532 .open = snd_cs46xx_playback_open, 1533 .close = snd_cs46xx_playback_close, 1534 .ioctl = snd_pcm_lib_ioctl, 1535 .hw_params = snd_cs46xx_playback_hw_params, 1536 .hw_free = snd_cs46xx_playback_hw_free, 1537 .prepare = snd_cs46xx_playback_prepare, 1538 .trigger = snd_cs46xx_playback_trigger, 1539 .pointer = snd_cs46xx_playback_direct_pointer, 1561 1540 }; 1562 1541 1563 s nd_pcm_ops_tsnd_cs46xx_playback_indirect_ops = {1564 snd_cs46xx_playback_open,1565 snd_cs46xx_playback_close,1566 snd_pcm_lib_ioctl,1567 snd_cs46xx_playback_hw_params,1568 snd_cs46xx_playback_hw_free,1569 snd_cs46xx_playback_prepare,1570 snd_cs46xx_playback_trigger,1571 snd_cs46xx_playback_indirect_pointer,0,0,0,1572 snd_cs46xx_playback_transfer 1542 static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = { 1543 .open = snd_cs46xx_playback_open, 1544 .close = snd_cs46xx_playback_close, 1545 .ioctl = snd_pcm_lib_ioctl, 1546 .hw_params = snd_cs46xx_playback_hw_params, 1547 .hw_free = snd_cs46xx_playback_hw_free, 1548 .prepare = snd_cs46xx_playback_prepare, 1549 .trigger = snd_cs46xx_playback_trigger, 1550 .pointer = snd_cs46xx_playback_indirect_pointer, 1551 .ack = snd_cs46xx_playback_transfer, 1573 1552 }; 1574 1553 1575 snd_pcm_ops_t snd_cs46xx_capture_ops = { 1576 snd_cs46xx_capture_open, 1577 snd_cs46xx_capture_close, 1578 snd_pcm_lib_ioctl, 1579 snd_cs46xx_capture_hw_params, 1580 snd_cs46xx_capture_hw_free, 1581 snd_cs46xx_capture_prepare, 1582 snd_cs46xx_capture_trigger, 1583 snd_cs46xx_capture_direct_pointer, 1584 0,0,0,0 1554 static struct snd_pcm_ops snd_cs46xx_capture_ops = { 1555 .open = snd_cs46xx_capture_open, 1556 .close = snd_cs46xx_capture_close, 1557 .ioctl = snd_pcm_lib_ioctl, 1558 .hw_params = snd_cs46xx_capture_hw_params, 1559 .hw_free = snd_cs46xx_capture_hw_free, 1560 .prepare = snd_cs46xx_capture_prepare, 1561 .trigger = snd_cs46xx_capture_trigger, 1562 .pointer = snd_cs46xx_capture_direct_pointer, 1585 1563 }; 1586 1564 1587 s nd_pcm_ops_tsnd_cs46xx_capture_indirect_ops = {1588 snd_cs46xx_capture_open,1589 snd_cs46xx_capture_close,1590 snd_pcm_lib_ioctl,1591 snd_cs46xx_capture_hw_params,1592 snd_cs46xx_capture_hw_free,1593 snd_cs46xx_capture_prepare,1594 snd_cs46xx_capture_trigger,1595 snd_cs46xx_capture_indirect_pointer,0,0,0,1596 snd_cs46xx_capture_transfer 1565 static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = { 1566 .open = snd_cs46xx_capture_open, 1567 .close = snd_cs46xx_capture_close, 1568 .ioctl = snd_pcm_lib_ioctl, 1569 .hw_params = snd_cs46xx_capture_hw_params, 1570 .hw_free = snd_cs46xx_capture_hw_free, 1571 .prepare = snd_cs46xx_capture_prepare, 1572 .trigger = snd_cs46xx_capture_trigger, 1573 .pointer = snd_cs46xx_capture_indirect_pointer, 1574 .ack = snd_cs46xx_capture_transfer, 1597 1575 }; 1598 1576 1599 1600 static void snd_cs46xx_pcm_free(snd_pcm_t *pcm) 1601 { 1602 cs46xx_t *chip = pcm->private_data; 1603 chip->pcm = NULL; 1604 snd_pcm_lib_preallocate_free_for_all(pcm); 1605 } 1606 1607 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1608 static void snd_cs46xx_pcm_rear_free(snd_pcm_t *pcm) 1609 { 1610 cs46xx_t *chip = pcm->private_data; 1611 chip->pcm_rear = NULL; 1612 snd_pcm_lib_preallocate_free_for_all(pcm); 1613 } 1614 1615 static void snd_cs46xx_pcm_center_lfe_free(snd_pcm_t *pcm) 1616 { 1617 cs46xx_t *chip = pcm->private_data; 1618 chip->pcm_center_lfe = NULL; 1619 snd_pcm_lib_preallocate_free_for_all(pcm); 1620 } 1621 1622 static void snd_cs46xx_pcm_iec958_free(snd_pcm_t *pcm) 1623 { 1624 cs46xx_t *chip = pcm->private_data; 1625 chip->pcm_iec958 = NULL; 1626 snd_pcm_lib_preallocate_free_for_all(pcm); 1627 } 1628 1577 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1629 1578 #define MAX_PLAYBACK_CHANNELS (DSP_MAX_PCM_CHANNELS - 1) 1630 1579 #else … … 1632 1581 #endif 1633 1582 1634 int __devinit snd_cs46xx_pcm( cs46xx_t *chip, int device, snd_pcm_t** rpcm)1635 { 1636 s nd_pcm_t*pcm;1583 int __devinit snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm) 1584 { 1585 struct snd_pcm *pcm; 1637 1586 int err; 1638 1587 … … 1643 1592 1644 1593 pcm->private_data = chip; 1645 pcm->private_free = snd_cs46xx_pcm_free;1646 1594 1647 1595 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_ops); … … 1664 1612 1665 1613 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1666 int __devinit snd_cs46xx_pcm_rear( cs46xx_t *chip, int device, snd_pcm_t** rpcm)1667 { 1668 s nd_pcm_t*pcm;1614 int __devinit snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm) 1615 { 1616 struct snd_pcm *pcm; 1669 1617 int err; 1670 1618 … … 1676 1624 1677 1625 pcm->private_data = chip; 1678 pcm->private_free = snd_cs46xx_pcm_rear_free;1679 1626 1680 1627 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_rear_ops); … … 1694 1641 } 1695 1642 1696 int __devinit snd_cs46xx_pcm_center_lfe( cs46xx_t *chip, int device, snd_pcm_t** rpcm)1697 { 1698 s nd_pcm_t*pcm;1643 int __devinit snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm) 1644 { 1645 struct snd_pcm *pcm; 1699 1646 int err; 1700 1647 … … 1706 1653 1707 1654 pcm->private_data = chip; 1708 pcm->private_free = snd_cs46xx_pcm_center_lfe_free;1709 1655 1710 1656 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_clfe_ops); … … 1724 1670 } 1725 1671 1726 int __devinit snd_cs46xx_pcm_iec958( cs46xx_t *chip, int device, snd_pcm_t** rpcm)1727 { 1728 s nd_pcm_t*pcm;1672 int __devinit snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm) 1673 { 1674 struct snd_pcm *pcm; 1729 1675 int err; 1730 1676 … … 1736 1682 1737 1683 pcm->private_data = chip; 1738 pcm->private_free = snd_cs46xx_pcm_iec958_free;1739 1684 1740 1685 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_iec958_ops); … … 1753 1698 return 0; 1754 1699 } 1755 1756 1700 #endif 1757 1701 … … 1759 1703 * Mixer routines 1760 1704 */ 1761 static void snd_cs46xx_mixer_free_ac97_bus( ac97_bus_t*bus)1762 { 1763 cs46xx_t*chip = bus->private_data;1764 1765 chip->ac97_bus = NULL;1766 } 1767 1768 static void snd_cs46xx_mixer_free_ac97( ac97_t*ac97)1769 { 1770 cs46xx_t*chip = ac97->private_data;1771 1772 snd_assert ((ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) ||1773 (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]),1774 return);1775 1776 if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) {1777 chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = NULL;1778 chip->eapd_switch = NULL;1779 }1780 else1781 chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = NULL;1782 } 1783 1784 static int snd_cs46xx_vol_info(s nd_kcontrol_t *kcontrol,1785 snd_ctl_elem_info_t*uinfo)1786 { 1787 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;1788 uinfo->count = 2;1789 uinfo->value.integer.min = 0;1790 uinfo->value.integer.max = 0x7fff;1791 return 0;1792 } 1793 1794 static int snd_cs46xx_vol_get(s nd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)1795 { 1796 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);1797 int reg = kcontrol->private_value;1798 unsigned int val = snd_cs46xx_peek(chip, reg);1799 ucontrol->value.integer.value[0] = 0xffff - (val >> 16);1800 ucontrol->value.integer.value[1] = 0xffff - (val & 0xffff);1801 return 0;1802 } 1803 1804 static int snd_cs46xx_vol_put(s nd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)1805 { 1806 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);1807 int reg = kcontrol->private_value;1808 unsigned int val = ((0xffff - ucontrol->value.integer.value[0]) << 16 | 1809 (0xffff - ucontrol->value.integer.value[1]));1810 unsigned int old = snd_cs46xx_peek(chip, reg);1811 int change = (old != val);1812 1813 if (change) {1814 snd_cs46xx_poke(chip, reg, val);1815 }1816 1817 return change;1818 } 1819 1820 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1821 1822 static int snd_cs46xx_vol_dac_get(s nd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)1823 { 1824 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);1825 1826 ucontrol->value.integer.value[0] = chip->dsp_spos_instance->dac_volume_left;1827 ucontrol->value.integer.value[1] = chip->dsp_spos_instance->dac_volume_right;1828 1829 return 0;1830 } 1831 1832 static int snd_cs46xx_vol_dac_put(s nd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)1833 { 1834 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);1835 int change = 0;1836 1837 if (chip->dsp_spos_instance->dac_volume_right != ucontrol->value.integer.value[0] ||1838 chip->dsp_spos_instance->dac_volume_left != ucontrol->value.integer.value[1]) {1839 cs46xx_dsp_set_dac_volume(chip,1840 ucontrol->value.integer.value[0],1841 ucontrol->value.integer.value[1]);1842 change = 1;1843 }1844 1845 return change;1705 static void snd_cs46xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus) 1706 { 1707 struct snd_cs46xx *chip = bus->private_data; 1708 1709 chip->ac97_bus = NULL; 1710 } 1711 1712 static void snd_cs46xx_mixer_free_ac97(struct snd_ac97 *ac97) 1713 { 1714 struct snd_cs46xx *chip = ac97->private_data; 1715 1716 snd_assert ((ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) || 1717 (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]), 1718 return); 1719 1720 if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) { 1721 chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = NULL; 1722 chip->eapd_switch = NULL; 1723 } 1724 else 1725 chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = NULL; 1726 } 1727 1728 static int snd_cs46xx_vol_info(struct snd_kcontrol *kcontrol, 1729 struct snd_ctl_elem_info *uinfo) 1730 { 1731 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1732 uinfo->count = 2; 1733 uinfo->value.integer.min = 0; 1734 uinfo->value.integer.max = 0x7fff; 1735 return 0; 1736 } 1737 1738 static int snd_cs46xx_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1739 { 1740 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1741 int reg = kcontrol->private_value; 1742 unsigned int val = snd_cs46xx_peek(chip, reg); 1743 ucontrol->value.integer.value[0] = 0xffff - (val >> 16); 1744 ucontrol->value.integer.value[1] = 0xffff - (val & 0xffff); 1745 return 0; 1746 } 1747 1748 static int snd_cs46xx_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1749 { 1750 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1751 int reg = kcontrol->private_value; 1752 unsigned int val = ((0xffff - ucontrol->value.integer.value[0]) << 16 | 1753 (0xffff - ucontrol->value.integer.value[1])); 1754 unsigned int old = snd_cs46xx_peek(chip, reg); 1755 int change = (old != val); 1756 1757 if (change) { 1758 snd_cs46xx_poke(chip, reg, val); 1759 } 1760 1761 return change; 1762 } 1763 1764 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1765 1766 static int snd_cs46xx_vol_dac_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1767 { 1768 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1769 1770 ucontrol->value.integer.value[0] = chip->dsp_spos_instance->dac_volume_left; 1771 ucontrol->value.integer.value[1] = chip->dsp_spos_instance->dac_volume_right; 1772 1773 return 0; 1774 } 1775 1776 static int snd_cs46xx_vol_dac_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1777 { 1778 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1779 int change = 0; 1780 1781 if (chip->dsp_spos_instance->dac_volume_right != ucontrol->value.integer.value[0] || 1782 chip->dsp_spos_instance->dac_volume_left != ucontrol->value.integer.value[1]) { 1783 cs46xx_dsp_set_dac_volume(chip, 1784 ucontrol->value.integer.value[0], 1785 ucontrol->value.integer.value[1]); 1786 change = 1; 1787 } 1788 1789 return change; 1846 1790 } 1847 1791 1848 1792 #if 0 1849 static int snd_cs46xx_vol_iec958_get(s nd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)1850 { 1851 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);1852 1853 ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_input_volume_left;1854 ucontrol->value.integer.value[1] = chip->dsp_spos_instance->spdif_input_volume_right;1855 return 0;1856 } 1857 1858 static int snd_cs46xx_vol_iec958_put(s nd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)1859 { 1860 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);1861 int change = 0;1862 1863 if (chip->dsp_spos_instance->spdif_input_volume_left != ucontrol->value.integer.value[0] ||1864 chip->dsp_spos_instance->spdif_input_volume_right!= ucontrol->value.integer.value[1]) {1865 cs46xx_dsp_set_iec958_volume (chip,1866 ucontrol->value.integer.value[0],1867 ucontrol->value.integer.value[1]);1868 change = 1;1869 }1870 1871 return change;1872 } 1873 #endif 1874 1875 static int snd_mixer_boolean_info(s nd_kcontrol_t *kcontrol,1876 snd_ctl_elem_info_t*uinfo)1877 { 1878 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;1879 uinfo->count = 1;1880 uinfo->value.integer.min = 0;1881 uinfo->value.integer.max = 1;1882 return 0;1883 } 1884 1885 static int snd_cs46xx_iec958_get(s nd_kcontrol_t *kcontrol,1886 s nd_ctl_elem_value_t*ucontrol)1887 { 1888 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);1889 int reg = kcontrol->private_value;1890 1891 if (reg == CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT)1892 ucontrol->value.integer.value[0] = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);1893 else1894 ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_status_in;1895 1896 return 0;1897 } 1898 1899 static int snd_cs46xx_iec958_put(s nd_kcontrol_t *kcontrol,1900 snd_ctl_elem_value_t*ucontrol)1901 { 1902 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);1903 int change, res;1904 1905 switch (kcontrol->private_value) {1906 case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT:1907 down (&chip->spos_mutex);1908 change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);1909 if (ucontrol->value.integer.value[0] && !change) 1910 cs46xx_dsp_enable_spdif_out(chip);1911 else if (change && !ucontrol->value.integer.value[0])1912 cs46xx_dsp_disable_spdif_out(chip);1913 1914 res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED));1915 up (&chip->spos_mutex);1916 break;1917 case CS46XX_MIXER_SPDIF_INPUT_ELEMENT:1918 change = chip->dsp_spos_instance->spdif_status_in;1919 if (ucontrol->value.integer.value[0] && !change) {1920 cs46xx_dsp_enable_spdif_in(chip);1921 /* restore volume */1922 }1923 else if (change && !ucontrol->value.integer.value[0])1924 cs46xx_dsp_disable_spdif_in(chip);1925 1926 res = (change != chip->dsp_spos_instance->spdif_status_in);1927 break;1928 default:1929 res = -EINVAL;1930 snd_assert(0, (void)0);1931 }1932 1933 return res;1934 } 1935 1936 static int snd_cs46xx_adc_capture_get(s nd_kcontrol_t *kcontrol,1937 s nd_ctl_elem_value_t*ucontrol)1938 { 1939 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);1940 dsp_spos_instance_t* ins = chip->dsp_spos_instance;1941 1942 if (ins->adc_input != NULL) 1943 ucontrol->value.integer.value[0] = 1;1944 else 1945 ucontrol->value.integer.value[0] = 0;1946 1947 return 0;1948 } 1949 1950 1951 static int snd_cs46xx_adc_capture_put(snd_kcontrol_t *kcontrol, 1952 snd_ctl_elem_value_t *ucontrol) 1953 { 1954 cs46xx_t *chip = snd_kcontrol_chip(kcontrol);1955 dsp_spos_instance_t * ins = chip->dsp_spos_instance;1956 int change = 0; 1957 1958 if (ucontrol->value.integer.value[0] && !ins->adc_input) { 1959 cs46xx_dsp_enable_adc_capture(chip);1960 change = 1; 1961 } else if (!ucontrol->value.integer.value[0] && ins->adc_input) { 1962 cs46xx_dsp_disable_adc_capture(chip);1963 change = 1; 1964 } 1965 return change; 1966 } 1967 1968 static int snd_cs46xx_pcm_capture_get(snd_kcontrol_t *kcontrol, 1969 snd_ctl_elem_value_t *ucontrol) 1970 { 1971 cs46xx_t *chip = snd_kcontrol_chip(kcontrol);1972 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1973 1974 if (ins->pcm_input != NULL) 1975 ucontrol->value.integer.value[0] = 1; 1976 else 1977 ucontrol->value.integer.value[0] = 0; 1978 1979 return 0; 1980 } 1981 1982 static int snd_cs46xx_pcm_capture_put(s nd_kcontrol_t *kcontrol,1983 s nd_ctl_elem_value_t*ucontrol)1984 { 1985 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);1986 dsp_spos_instance_t* ins = chip->dsp_spos_instance;1987 int change = 0;1988 1989 if (ucontrol->value.integer.value[0] && !ins->pcm_input) {1990 cs46xx_dsp_enable_pcm_capture(chip);1991 change = 1;1992 } else if (!ucontrol->value.integer.value[0] && ins->pcm_input) {1993 cs46xx_dsp_disable_pcm_capture(chip);1994 change = 1;1995 }1996 1997 return change;1998 } 1999 2000 static int snd_herc_spdif_select_get(s nd_kcontrol_t *kcontrol,2001 s nd_ctl_elem_value_t*ucontrol)2002 { 2003 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);2004 2005 int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);2006 2007 if (val1 & EGPIODR_GPOE0)2008 ucontrol->value.integer.value[0] = 1;2009 else2010 ucontrol->value.integer.value[0] = 0;2011 2012 return 0;1793 static int snd_cs46xx_vol_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1794 { 1795 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1796 1797 ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_input_volume_left; 1798 ucontrol->value.integer.value[1] = chip->dsp_spos_instance->spdif_input_volume_right; 1799 return 0; 1800 } 1801 1802 static int snd_cs46xx_vol_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1803 { 1804 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1805 int change = 0; 1806 1807 if (chip->dsp_spos_instance->spdif_input_volume_left != ucontrol->value.integer.value[0] || 1808 chip->dsp_spos_instance->spdif_input_volume_right!= ucontrol->value.integer.value[1]) { 1809 cs46xx_dsp_set_iec958_volume (chip, 1810 ucontrol->value.integer.value[0], 1811 ucontrol->value.integer.value[1]); 1812 change = 1; 1813 } 1814 1815 return change; 1816 } 1817 #endif 1818 1819 static int snd_mixer_boolean_info(struct snd_kcontrol *kcontrol, 1820 struct snd_ctl_elem_info *uinfo) 1821 { 1822 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1823 uinfo->count = 1; 1824 uinfo->value.integer.min = 0; 1825 uinfo->value.integer.max = 1; 1826 return 0; 1827 } 1828 1829 static int snd_cs46xx_iec958_get(struct snd_kcontrol *kcontrol, 1830 struct snd_ctl_elem_value *ucontrol) 1831 { 1832 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1833 int reg = kcontrol->private_value; 1834 1835 if (reg == CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT) 1836 ucontrol->value.integer.value[0] = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED); 1837 else 1838 ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_status_in; 1839 1840 return 0; 1841 } 1842 1843 static int snd_cs46xx_iec958_put(struct snd_kcontrol *kcontrol, 1844 struct snd_ctl_elem_value *ucontrol) 1845 { 1846 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1847 int change, res; 1848 1849 switch (kcontrol->private_value) { 1850 case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT: 1851 down (&chip->spos_mutex); 1852 change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED); 1853 if (ucontrol->value.integer.value[0] && !change) 1854 cs46xx_dsp_enable_spdif_out(chip); 1855 else if (change && !ucontrol->value.integer.value[0]) 1856 cs46xx_dsp_disable_spdif_out(chip); 1857 1858 res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED)); 1859 up (&chip->spos_mutex); 1860 break; 1861 case CS46XX_MIXER_SPDIF_INPUT_ELEMENT: 1862 change = chip->dsp_spos_instance->spdif_status_in; 1863 if (ucontrol->value.integer.value[0] && !change) { 1864 cs46xx_dsp_enable_spdif_in(chip); 1865 /* restore volume */ 1866 } 1867 else if (change && !ucontrol->value.integer.value[0]) 1868 cs46xx_dsp_disable_spdif_in(chip); 1869 1870 res = (change != chip->dsp_spos_instance->spdif_status_in); 1871 break; 1872 default: 1873 res = -EINVAL; 1874 snd_assert(0, (void)0); 1875 } 1876 1877 return res; 1878 } 1879 1880 static int snd_cs46xx_adc_capture_get(struct snd_kcontrol *kcontrol, 1881 struct snd_ctl_elem_value *ucontrol) 1882 { 1883 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1884 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1885 1886 if (ins->adc_input != NULL) 1887 ucontrol->value.integer.value[0] = 1; 1888 else 1889 ucontrol->value.integer.value[0] = 0; 1890 1891 return 0; 1892 } 1893 1894 static int snd_cs46xx_adc_capture_put(struct snd_kcontrol *kcontrol, 1895 struct snd_ctl_elem_value *ucontrol) 1896 { 1897 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1898 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1899 int change = 0; 1900 1901 if (ucontrol->value.integer.value[0] && !ins->adc_input) { 1902 cs46xx_dsp_enable_adc_capture(chip); 1903 change = 1; 1904 } else if (!ucontrol->value.integer.value[0] && ins->adc_input) { 1905 cs46xx_dsp_disable_adc_capture(chip); 1906 change = 1; 1907 } 1908 return change; 1909 } 1910 1911 static int snd_cs46xx_pcm_capture_get(struct snd_kcontrol *kcontrol, 1912 struct snd_ctl_elem_value *ucontrol) 1913 { 1914 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1915 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1916 1917 if (ins->pcm_input != NULL) 1918 ucontrol->value.integer.value[0] = 1; 1919 else 1920 ucontrol->value.integer.value[0] = 0; 1921 1922 return 0; 1923 } 1924 1925 1926 static int snd_cs46xx_pcm_capture_put(struct snd_kcontrol *kcontrol, 1927 struct snd_ctl_elem_value *ucontrol) 1928 { 1929 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1930 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1931 int change = 0; 1932 1933 if (ucontrol->value.integer.value[0] && !ins->pcm_input) { 1934 cs46xx_dsp_enable_pcm_capture(chip); 1935 change = 1; 1936 } else if (!ucontrol->value.integer.value[0] && ins->pcm_input) { 1937 cs46xx_dsp_disable_pcm_capture(chip); 1938 change = 1; 1939 } 1940 1941 return change; 1942 } 1943 1944 static int snd_herc_spdif_select_get(struct snd_kcontrol *kcontrol, 1945 struct snd_ctl_elem_value *ucontrol) 1946 { 1947 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1948 1949 int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR); 1950 1951 if (val1 & EGPIODR_GPOE0) 1952 ucontrol->value.integer.value[0] = 1; 1953 else 1954 ucontrol->value.integer.value[0] = 0; 1955 1956 return 0; 2013 1957 } 2014 1958 2015 1959 /* 2016 1960 * Game Theatre XP card - EGPIO[0] is used to select SPDIF input optical or coaxial. 2017 */ 2018 static int snd_herc_spdif_select_put(s nd_kcontrol_t *kcontrol,2019 snd_ctl_elem_value_t*ucontrol)2020 { 2021 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);2022 int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);2023 int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);2024 2025 if (ucontrol->value.integer.value[0]) {2026 /* optical is default */2027 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, 2028 EGPIODR_GPOE0 | val1); /* enable EGPIO0 output */2029 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, 2030 EGPIOPTR_GPPT0 | val2); /* open-drain on output */2031 } else {2032 /* coaxial */2033 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, val1 & ~EGPIODR_GPOE0); /* disable */2034 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT0); /* disable */2035 }2036 2037 /* checking diff from the EGPIO direction register 2038 should be enough */2039 return (val1 != (int)snd_cs46xx_peekBA0(chip, BA0_EGPIODR));2040 } 2041 2042 2043 static int snd_cs46xx_spdif_info(s nd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)2044 { 2045 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;2046 uinfo->count = 1;2047 return 0;2048 } 2049 2050 static int snd_cs46xx_spdif_default_get(s nd_kcontrol_t *kcontrol,2051 snd_ctl_elem_value_t *ucontrol)2052 { 2053 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);2054 dsp_spos_instance_t* ins = chip->dsp_spos_instance;2055 2056 down (&chip->spos_mutex);2057 ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff);2058 ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff);2059 ucontrol->value.iec958.status[2] = 0;2060 ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff);2061 up (&chip->spos_mutex);2062 2063 return 0;2064 } 2065 2066 static int snd_cs46xx_spdif_default_put(s nd_kcontrol_t *kcontrol,2067 snd_ctl_elem_value_t *ucontrol)2068 { 2069 cs46xx_t* chip = snd_kcontrol_chip(kcontrol);2070 dsp_spos_instance_t* ins = chip->dsp_spos_instance;2071 unsigned int val;2072 int change;2073 2074 down (&chip->spos_mutex);2075 val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |2076 ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) |2077 ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) |2078 /* left and right validity bit */2079 (1 << 13) | (1 << 12);2080 2081 2082 change = (unsigned int)ins->spdif_csuv_default != val;2083 ins->spdif_csuv_default = val;2084 2085 if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) )2086 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);2087 2088 up (&chip->spos_mutex);2089 2090 return change;2091 } 2092 2093 static int snd_cs46xx_spdif_mask_get(s nd_kcontrol_t *kcontrol,2094 snd_ctl_elem_value_t *ucontrol)2095 { 2096 ucontrol->value.iec958.status[0] = 0xff;2097 ucontrol->value.iec958.status[1] = 0xff;2098 ucontrol->value.iec958.status[2] = 0x00;2099 ucontrol->value.iec958.status[3] = 0xff;2100 return 0;2101 } 2102 2103 static int snd_cs46xx_spdif_stream_get(s nd_kcontrol_t *kcontrol,2104 snd_ctl_elem_value_t *ucontrol)2105 { 2106 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);2107 dsp_spos_instance_t* ins = chip->dsp_spos_instance;2108 2109 down (&chip->spos_mutex);2110 ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff);2111 ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff);2112 ucontrol->value.iec958.status[2] = 0;2113 ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff);2114 up (&chip->spos_mutex);2115 2116 return 0;2117 } 2118 2119 static int snd_cs46xx_spdif_stream_put(s nd_kcontrol_t *kcontrol,2120 snd_ctl_elem_value_t *ucontrol)2121 { 2122 cs46xx_t* chip = snd_kcontrol_chip(kcontrol);2123 dsp_spos_instance_t* ins = chip->dsp_spos_instance;2124 unsigned int val;2125 int change;2126 2127 down (&chip->spos_mutex);2128 val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |2129 ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) |2130 ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) |2131 /* left and right validity bit */2132 (1 << 13) | (1 << 12);2133 2134 2135 change = ins->spdif_csuv_stream != val;2136 ins->spdif_csuv_stream = val;2137 2138 if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN )2139 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);2140 2141 up (&chip->spos_mutex);2142 2143 return change;1961 */ 1962 static int snd_herc_spdif_select_put(struct snd_kcontrol *kcontrol, 1963 struct snd_ctl_elem_value *ucontrol) 1964 { 1965 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1966 int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR); 1967 int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR); 1968 1969 if (ucontrol->value.integer.value[0]) { 1970 /* optical is default */ 1971 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, 1972 EGPIODR_GPOE0 | val1); /* enable EGPIO0 output */ 1973 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, 1974 EGPIOPTR_GPPT0 | val2); /* open-drain on output */ 1975 } else { 1976 /* coaxial */ 1977 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, val1 & ~EGPIODR_GPOE0); /* disable */ 1978 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT0); /* disable */ 1979 } 1980 1981 /* checking diff from the EGPIO direction register 1982 should be enough */ 1983 return (val1 != (int)snd_cs46xx_peekBA0(chip, BA0_EGPIODR)); 1984 } 1985 1986 1987 static int snd_cs46xx_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 1988 { 1989 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 1990 uinfo->count = 1; 1991 return 0; 1992 } 1993 1994 static int snd_cs46xx_spdif_default_get(struct snd_kcontrol *kcontrol, 1995 struct snd_ctl_elem_value *ucontrol) 1996 { 1997 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 1998 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1999 2000 down (&chip->spos_mutex); 2001 ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff); 2002 ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff); 2003 ucontrol->value.iec958.status[2] = 0; 2004 ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff); 2005 up (&chip->spos_mutex); 2006 2007 return 0; 2008 } 2009 2010 static int snd_cs46xx_spdif_default_put(struct snd_kcontrol *kcontrol, 2011 struct snd_ctl_elem_value *ucontrol) 2012 { 2013 struct snd_cs46xx * chip = snd_kcontrol_chip(kcontrol); 2014 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 2015 unsigned int val; 2016 int change; 2017 2018 down (&chip->spos_mutex); 2019 val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | 2020 ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) | 2021 ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | 2022 /* left and right validity bit */ 2023 (1 << 13) | (1 << 12); 2024 2025 2026 change = (unsigned int)ins->spdif_csuv_default != val; 2027 ins->spdif_csuv_default = val; 2028 2029 if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) ) 2030 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); 2031 2032 up (&chip->spos_mutex); 2033 2034 return change; 2035 } 2036 2037 static int snd_cs46xx_spdif_mask_get(struct snd_kcontrol *kcontrol, 2038 struct snd_ctl_elem_value *ucontrol) 2039 { 2040 ucontrol->value.iec958.status[0] = 0xff; 2041 ucontrol->value.iec958.status[1] = 0xff; 2042 ucontrol->value.iec958.status[2] = 0x00; 2043 ucontrol->value.iec958.status[3] = 0xff; 2044 return 0; 2045 } 2046 2047 static int snd_cs46xx_spdif_stream_get(struct snd_kcontrol *kcontrol, 2048 struct snd_ctl_elem_value *ucontrol) 2049 { 2050 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 2051 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 2052 2053 down (&chip->spos_mutex); 2054 ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff); 2055 ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff); 2056 ucontrol->value.iec958.status[2] = 0; 2057 ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff); 2058 up (&chip->spos_mutex); 2059 2060 return 0; 2061 } 2062 2063 static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol, 2064 struct snd_ctl_elem_value *ucontrol) 2065 { 2066 struct snd_cs46xx * chip = snd_kcontrol_chip(kcontrol); 2067 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 2068 unsigned int val; 2069 int change; 2070 2071 down (&chip->spos_mutex); 2072 val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | 2073 ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) | 2074 ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | 2075 /* left and right validity bit */ 2076 (1 << 13) | (1 << 12); 2077 2078 2079 change = ins->spdif_csuv_stream != val; 2080 ins->spdif_csuv_stream = val; 2081 2082 if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN ) 2083 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); 2084 2085 up (&chip->spos_mutex); 2086 2087 return change; 2144 2088 } 2145 2089 … … 2148 2092 2149 2093 #ifdef CONFIG_SND_CS46XX_DEBUG_GPIO 2150 static int snd_cs46xx_egpio_select_info(s nd_kcontrol_t *kcontrol,2151 s nd_ctl_elem_info_t*uinfo)2152 { 2153 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;2154 uinfo->count = 1;2155 uinfo->value.integer.min = 0;2156 uinfo->value.integer.max = 8;2157 return 0;2158 } 2159 2160 static int snd_cs46xx_egpio_select_get(s nd_kcontrol_t *kcontrol,2161 s nd_ctl_elem_value_t*ucontrol)2162 { 2163 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);2164 ucontrol->value.integer.value[0] = chip->current_gpio;2165 2166 return 0;2167 } 2168 2169 static int snd_cs46xx_egpio_select_put(s nd_kcontrol_t *kcontrol,2170 s nd_ctl_elem_value_t*ucontrol)2171 { 2172 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);2173 int change = (chip->current_gpio != ucontrol->value.integer.value[0]);2174 chip->current_gpio = ucontrol->value.integer.value[0];2175 2176 return change;2177 } 2178 2179 2180 static int snd_cs46xx_egpio_get(s nd_kcontrol_t *kcontrol,2181 snd_ctl_elem_value_t*ucontrol)2182 { 2183 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);2184 int reg = kcontrol->private_value;2185 2186 snd_printdd ("put: reg = %04x, gpio %02x\n",reg,chip->current_gpio);2187 ucontrol->value.integer.value[0] = 2188 (snd_cs46xx_peekBA0(chip, reg) & (1 << chip->current_gpio)) ? 1 : 0;2189 2190 return 0;2191 } 2192 2193 static int snd_cs46xx_egpio_put(s nd_kcontrol_t *kcontrol,2194 snd_ctl_elem_value_t*ucontrol)2195 { 2196 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);2197 int reg = kcontrol->private_value;2198 int val = snd_cs46xx_peekBA0(chip, reg);2199 int oldval = val;2200 snd_printdd ("put: reg = %04x, gpio %02x\n",reg,chip->current_gpio);2201 2202 if (ucontrol->value.integer.value[0])2203 val |= (1 << chip->current_gpio);2204 else2205 val &= ~(1 << chip->current_gpio);2206 2207 snd_cs46xx_pokeBA0(chip, reg,val);2208 snd_printdd ("put: val %08x oldval %08x\n",val,oldval);2209 2210 return (oldval != val);2094 static int snd_cs46xx_egpio_select_info(struct snd_kcontrol *kcontrol, 2095 struct snd_ctl_elem_info *uinfo) 2096 { 2097 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 2098 uinfo->count = 1; 2099 uinfo->value.integer.min = 0; 2100 uinfo->value.integer.max = 8; 2101 return 0; 2102 } 2103 2104 static int snd_cs46xx_egpio_select_get(struct snd_kcontrol *kcontrol, 2105 struct snd_ctl_elem_value *ucontrol) 2106 { 2107 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 2108 ucontrol->value.integer.value[0] = chip->current_gpio; 2109 2110 return 0; 2111 } 2112 2113 static int snd_cs46xx_egpio_select_put(struct snd_kcontrol *kcontrol, 2114 struct snd_ctl_elem_value *ucontrol) 2115 { 2116 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 2117 int change = (chip->current_gpio != ucontrol->value.integer.value[0]); 2118 chip->current_gpio = ucontrol->value.integer.value[0]; 2119 2120 return change; 2121 } 2122 2123 2124 static int snd_cs46xx_egpio_get(struct snd_kcontrol *kcontrol, 2125 struct snd_ctl_elem_value *ucontrol) 2126 { 2127 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 2128 int reg = kcontrol->private_value; 2129 2130 snd_printdd ("put: reg = %04x, gpio %02x\n",reg,chip->current_gpio); 2131 ucontrol->value.integer.value[0] = 2132 (snd_cs46xx_peekBA0(chip, reg) & (1 << chip->current_gpio)) ? 1 : 0; 2133 2134 return 0; 2135 } 2136 2137 static int snd_cs46xx_egpio_put(struct snd_kcontrol *kcontrol, 2138 struct snd_ctl_elem_value *ucontrol) 2139 { 2140 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 2141 int reg = kcontrol->private_value; 2142 int val = snd_cs46xx_peekBA0(chip, reg); 2143 int oldval = val; 2144 snd_printdd ("put: reg = %04x, gpio %02x\n",reg,chip->current_gpio); 2145 2146 if (ucontrol->value.integer.value[0]) 2147 val |= (1 << chip->current_gpio); 2148 else 2149 val &= ~(1 << chip->current_gpio); 2150 2151 snd_cs46xx_pokeBA0(chip, reg,val); 2152 snd_printdd ("put: val %08x oldval %08x\n",val,oldval); 2153 2154 return (oldval != val); 2211 2155 } 2212 2156 #endif /* CONFIG_SND_CS46XX_DEBUG_GPIO */ 2213 2157 2214 static s nd_kcontrol_new_tsnd_cs46xx_controls[] __devinitdata = {2215 {2216 SNDRV_CTL_ELEM_IFACE_MIXER,0,0,2217 "DAC Volume",0,0,0,2218 snd_cs46xx_vol_info,2158 static struct snd_kcontrol_new snd_cs46xx_controls[] __devinitdata = { 2159 { 2160 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2161 .name = "DAC Volume", 2162 .info = snd_cs46xx_vol_info, 2219 2163 #ifndef CONFIG_SND_CS46XX_NEW_DSP 2220 snd_cs46xx_vol_get,2221 snd_cs46xx_vol_put,2222 BA1_PVOL,2164 .get = snd_cs46xx_vol_get, 2165 .put = snd_cs46xx_vol_put, 2166 .private_value = BA1_PVOL, 2223 2167 #else 2224 snd_cs46xx_vol_dac_get,2225 snd_cs46xx_vol_dac_put,2226 0 2227 #endif 2228 }, 2229 {2230 SNDRV_CTL_ELEM_IFACE_MIXER,0,0,2231 "ADC Volume",0,0,0,2232 snd_cs46xx_vol_info,2233 snd_cs46xx_vol_get,2234 snd_cs46xx_vol_put,2168 .get = snd_cs46xx_vol_dac_get, 2169 .put = snd_cs46xx_vol_dac_put, 2170 #endif 2171 }, 2172 2173 { 2174 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2175 .name = "ADC Volume", 2176 .info = snd_cs46xx_vol_info, 2177 .get = snd_cs46xx_vol_get, 2178 .put = snd_cs46xx_vol_put, 2235 2179 #ifndef CONFIG_SND_CS46XX_NEW_DSP 2236 BA1_CVOL,2180 .private_value = BA1_CVOL, 2237 2181 #else 2238 (VARIDECIMATE_SCB_ADDR + 0xE) << 2,2239 #endif 2240 },2241 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2242 {2243 /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,2244 /* .name = */"ADC Capture Switch",0,0,0,2245 /* .info = */snd_mixer_boolean_info,2246 /* .get = */snd_cs46xx_adc_capture_get,2247 /* .put = */snd_cs46xx_adc_capture_put,0 2248 },2249 {2250 /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,2251 /* .name = */"DAC Capture Switch",0,0,0,2252 /* .info = */snd_mixer_boolean_info,2253 /* .get = */snd_cs46xx_pcm_capture_get,2254 /* .put = */snd_cs46xx_pcm_capture_put,0 2255 },2256 {2257 /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,2258 /* .name = */"IEC958 Output Switch",0,0,0,2259 /* .info = */snd_mixer_boolean_info,2260 /* .get = */snd_cs46xx_iec958_get,2261 /* .put = */snd_cs46xx_iec958_put,2262 /* .private_value = */CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT,2263 },2264 {2265 /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,2266 /* .name = */"IEC958 Input Switch",0,0,0,2267 /* .info = */snd_mixer_boolean_info,2268 /* .get = */snd_cs46xx_iec958_get,2269 /* .put = */snd_cs46xx_iec958_put,2270 /* .private_value = */CS46XX_MIXER_SPDIF_INPUT_ELEMENT,2271 },2182 .private_value = (VARIDECIMATE_SCB_ADDR + 0xE) << 2, 2183 #endif 2184 }, 2185 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2186 { 2187 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2188 .name = "ADC Capture Switch", 2189 .info = snd_mixer_boolean_info, 2190 .get = snd_cs46xx_adc_capture_get, 2191 .put = snd_cs46xx_adc_capture_put 2192 }, 2193 { 2194 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2195 .name = "DAC Capture Switch", 2196 .info = snd_mixer_boolean_info, 2197 .get = snd_cs46xx_pcm_capture_get, 2198 .put = snd_cs46xx_pcm_capture_put 2199 }, 2200 { 2201 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2202 .name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH), 2203 .info = snd_mixer_boolean_info, 2204 .get = snd_cs46xx_iec958_get, 2205 .put = snd_cs46xx_iec958_put, 2206 .private_value = CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT, 2207 }, 2208 { 2209 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2210 .name = SNDRV_CTL_NAME_IEC958("Input ",NONE,SWITCH), 2211 .info = snd_mixer_boolean_info, 2212 .get = snd_cs46xx_iec958_get, 2213 .put = snd_cs46xx_iec958_put, 2214 .private_value = CS46XX_MIXER_SPDIF_INPUT_ELEMENT, 2215 }, 2272 2216 #if 0 2273 /* Input IEC958 volume does not work for the moment. (Benny) */ 2274 { 2275 /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0, 2276 /* .name = */"IEC958 Input Volume",0,0,0, 2277 /* .info = */snd_cs46xx_vol_info, 2278 /* .get = */snd_cs46xx_vol_iec958_get, 2279 /* .put = */snd_cs46xx_vol_iec958_put, 2280 /* .private_value = */(ASYNCRX_SCB_ADDR + 0xE) << 2, 2281 }, 2282 #endif 2283 { 2284 /* .iface = */SNDRV_CTL_ELEM_IFACE_PCM,0,0, 2285 /* .name = */SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),0,0,0, 2286 /* .info = */ snd_cs46xx_spdif_info, 2287 /* .get = */ snd_cs46xx_spdif_default_get, 2288 /* .put = */snd_cs46xx_spdif_default_put,0 2289 }, 2290 { 2291 /* .iface = */SNDRV_CTL_ELEM_IFACE_PCM,0,0, 2292 /* .name = */ SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),0, 2293 SNDRV_CTL_ELEM_ACCESS_READ,0, 2294 /* .info = */ snd_cs46xx_spdif_info, 2295 /* .get = */ snd_cs46xx_spdif_mask_get,NULL,0 2296 }, 2297 { 2298 /* .iface = */SNDRV_CTL_ELEM_IFACE_PCM,0,0, 2299 /* .name = */ SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),0,0,0, 2300 /* .info = */ snd_cs46xx_spdif_info, 2301 /* .get = */ snd_cs46xx_spdif_stream_get, 2302 /* .put = */ snd_cs46xx_spdif_stream_put,0 2303 }, 2217 /* Input IEC958 volume does not work for the moment. (Benny) */ 2218 { 2219 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2220 .name = SNDRV_CTL_NAME_IEC958("Input ",NONE,VOLUME), 2221 .info = snd_cs46xx_vol_info, 2222 .get = snd_cs46xx_vol_iec958_get, 2223 .put = snd_cs46xx_vol_iec958_put, 2224 .private_value = (ASYNCRX_SCB_ADDR + 0xE) << 2, 2225 }, 2226 #endif 2227 { 2228 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 2229 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), 2230 .info = snd_cs46xx_spdif_info, 2231 .get = snd_cs46xx_spdif_default_get, 2232 .put = snd_cs46xx_spdif_default_put, 2233 }, 2234 { 2235 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 2236 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), 2237 .info = snd_cs46xx_spdif_info, 2238 .get = snd_cs46xx_spdif_mask_get, 2239 .access = SNDRV_CTL_ELEM_ACCESS_READ 2240 }, 2241 { 2242 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 2243 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), 2244 .info = snd_cs46xx_spdif_info, 2245 .get = snd_cs46xx_spdif_stream_get, 2246 .put = snd_cs46xx_spdif_stream_put 2247 }, 2248 2304 2249 #endif 2305 2250 #ifdef CONFIG_SND_CS46XX_DEBUG_GPIO 2306 {2307 /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,2308 /* .name = */"EGPIO select",0,0,0,2309 /* .info = */snd_cs46xx_egpio_select_info,2310 /* .get = */snd_cs46xx_egpio_select_get,2311 /* .put = */snd_cs46xx_egpio_select_put,2312 /* .private_value = */0,2313 },2314 {2315 /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,2316 /* .name = */"EGPIO Input/Output",0,0,0,2317 /* .info = */snd_mixer_boolean_info,2318 /* .get = */snd_cs46xx_egpio_get,2319 /* .put = */snd_cs46xx_egpio_put,2320 /* .private_value = */BA0_EGPIODR,2321 },2322 {2323 /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,2324 /* .name = */"EGPIO CMOS/Open drain",0,0,0,2325 /* .info = */snd_mixer_boolean_info,2326 /* .get = */snd_cs46xx_egpio_get,2327 /* .put = */snd_cs46xx_egpio_put,2328 /* .private_value = */BA0_EGPIOPTR,2329 },2330 {2331 /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,2332 /* .name = */"EGPIO On/Off",0,0,0,2333 /* .info = */snd_mixer_boolean_info,2334 /* .get = */snd_cs46xx_egpio_get,2335 /* .put = */snd_cs46xx_egpio_put,2336 /* .private_value = */BA0_EGPIOSR 2337 },2251 { 2252 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2253 .name = "EGPIO select", 2254 .info = snd_cs46xx_egpio_select_info, 2255 .get = snd_cs46xx_egpio_select_get, 2256 .put = snd_cs46xx_egpio_select_put, 2257 .private_value = 0, 2258 }, 2259 { 2260 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2261 .name = "EGPIO Input/Output", 2262 .info = snd_mixer_boolean_info, 2263 .get = snd_cs46xx_egpio_get, 2264 .put = snd_cs46xx_egpio_put, 2265 .private_value = BA0_EGPIODR, 2266 }, 2267 { 2268 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2269 .name = "EGPIO CMOS/Open drain", 2270 .info = snd_mixer_boolean_info, 2271 .get = snd_cs46xx_egpio_get, 2272 .put = snd_cs46xx_egpio_put, 2273 .private_value = BA0_EGPIOPTR, 2274 }, 2275 { 2276 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2277 .name = "EGPIO On/Off", 2278 .info = snd_mixer_boolean_info, 2279 .get = snd_cs46xx_egpio_get, 2280 .put = snd_cs46xx_egpio_put, 2281 .private_value = BA0_EGPIOSR, 2282 }, 2338 2283 #endif 2339 2284 }; … … 2341 2286 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2342 2287 /* set primary cs4294 codec into Extended Audio Mode */ 2343 static int snd_cs46xx_front_dup_get(s nd_kcontrol_t *kcontrol,2344 snd_ctl_elem_value_t*ucontrol)2345 { 2346 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);2347 unsigned short val;2348 val = snd_ac97_read(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], AC97_CSR_ACMODE);2349 ucontrol->value.integer.value[0] = (val & 0x200) ? 0 : 1;2350 return 0;2351 } 2352 2353 static int snd_cs46xx_front_dup_put(s nd_kcontrol_t *kcontrol,2354 snd_ctl_elem_value_t*ucontrol)2355 { 2356 cs46xx_t*chip = snd_kcontrol_chip(kcontrol);2357 return snd_ac97_update_bits(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX],2358 AC97_CSR_ACMODE, 0x200,2359 ucontrol->value.integer.value[0] ? 0 : 0x200);2360 } 2361 2362 static s nd_kcontrol_new_tsnd_cs46xx_front_dup_ctl = {2363 /*.iface = */SNDRV_CTL_ELEM_IFACE_MIXER, 0,0,2364 /*.name = */"Duplicate Front",0,0,0,2365 /*.info = */snd_mixer_boolean_info,2366 /*.get = */snd_cs46xx_front_dup_get,2367 /*.put = */snd_cs46xx_front_dup_put,0 2288 static int snd_cs46xx_front_dup_get(struct snd_kcontrol *kcontrol, 2289 struct snd_ctl_elem_value *ucontrol) 2290 { 2291 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 2292 unsigned short val; 2293 val = snd_ac97_read(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], AC97_CSR_ACMODE); 2294 ucontrol->value.integer.value[0] = (val & 0x200) ? 0 : 1; 2295 return 0; 2296 } 2297 2298 static int snd_cs46xx_front_dup_put(struct snd_kcontrol *kcontrol, 2299 struct snd_ctl_elem_value *ucontrol) 2300 { 2301 struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); 2302 return snd_ac97_update_bits(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], 2303 AC97_CSR_ACMODE, 0x200, 2304 ucontrol->value.integer.value[0] ? 0 : 0x200); 2305 } 2306 2307 static struct snd_kcontrol_new snd_cs46xx_front_dup_ctl = { 2308 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2309 .name = "Duplicate Front", 2310 .info = snd_mixer_boolean_info, 2311 .get = snd_cs46xx_front_dup_get, 2312 .put = snd_cs46xx_front_dup_put, 2368 2313 }; 2369 2314 #endif 2370 2315 2371 2316 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2372 /* Only available on the Hercules Game Theater XP soundcard */2373 static s nd_kcontrol_new_tsnd_hercules_controls[] __devinitdata = {2374 {2375 /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,2376 /* .name = */"Optical/Coaxial SPDIF Input Switch",0,0,0,2377 /* .info = */snd_mixer_boolean_info,2378 /* .get = */snd_herc_spdif_select_get,2379 /* .put = */snd_herc_spdif_select_put,0,2380 } 2317 /* Only available on the Hercules Game Theater XP soundcard */ 2318 static struct snd_kcontrol_new snd_hercules_controls[] __devinitdata = { 2319 { 2320 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2321 .name = "Optical/Coaxial SPDIF Input Switch", 2322 .info = snd_mixer_boolean_info, 2323 .get = snd_herc_spdif_select_get, 2324 .put = snd_herc_spdif_select_put, 2325 }, 2381 2326 }; 2382 2327 2383 2328 2384 static void snd_cs46xx_codec_reset (ac97_t * ac97) 2385 { 2386 unsigned long end_time; 2387 int err; 2388 2389 /* reset to defaults */ 2390 snd_ac97_write(ac97, AC97_RESET, 0); 2391 2392 /* set the desired CODEC mode */ 2393 if (ac97->num == CS46XX_PRIMARY_CODEC_INDEX) { 2394 snd_printdd("cs46xx: CODOEC1 mode %04x\n",0x0); 2395 snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x0); 2396 } else if (ac97->num == CS46XX_SECONDARY_CODEC_INDEX) { 2397 snd_printdd("cs46xx: CODOEC2 mode %04x\n",0x3); 2398 snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x3); 2399 } else { 2400 // snd_assert(0); /* should never happen ... */ 2401 } 2402 2403 udelay(50); 2404 2405 /* it's necessary to wait awhile until registers are accessible after RESET */ 2406 /* because the PCM or MASTER volume registers can be modified, */ 2407 /* the REC_GAIN register is used for tests */ 2408 end_time = jiffies + HZ; 2409 do { 2410 unsigned short ext_mid; 2411 2412 /* use preliminary reads to settle the communication */ 2413 snd_ac97_read(ac97, AC97_RESET); 2414 snd_ac97_read(ac97, AC97_VENDOR_ID1); 2415 snd_ac97_read(ac97, AC97_VENDOR_ID2); 2416 /* modem? */ 2417 ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID); 2418 if (ext_mid != 0xffff && (ext_mid & 1) != 0) 2419 return; 2420 2421 /* test if we can write to the record gain volume register */ 2422 snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05); 2423 if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05) 2424 return; 2425 2426 msleep(10); 2427 } while (time_after_eq(end_time, jiffies)); 2428 2429 snd_printk("CS46xx secondary codec dont respond!\n"); 2430 } 2431 #endif 2432 2433 static int __devinit cs46xx_detect_codec(cs46xx_t *chip, int codec) 2434 { 2435 int idx, err; 2436 ac97_template_t ac97; 2437 2438 memset(&ac97, 0, sizeof(ac97)); 2439 ac97.private_data = chip; 2440 ac97.private_free = snd_cs46xx_mixer_free_ac97; 2441 ac97.num = codec; 2442 if (chip->amplifier_ctrl == amp_voyetra) 2443 ac97.scaps = AC97_SCAP_INV_EAPD; 2444 2445 if (codec == CS46XX_SECONDARY_CODEC_INDEX) { 2446 snd_cs46xx_codec_write(chip, AC97_RESET, 0, codec); 2447 udelay(10); 2448 if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) { 2449 snd_printdd("snd_cs46xx: seconadry codec not present\n"); 2450 return -ENXIO; 2451 } 2452 } 2453 2454 snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000, codec); 2455 for (idx = 0; idx < 100; ++idx) { 2456 if (snd_cs46xx_codec_read(chip, AC97_MASTER, codec) == 0x8000) { 2457 err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]); 2458 return err; 2459 } 2460 msleep(10); 2461 } 2462 snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec); 2463 return -ENXIO; 2464 } 2465 2466 int __devinit snd_cs46xx_mixer(cs46xx_t *chip) 2467 { 2468 snd_card_t *card = chip->card; 2469 snd_ctl_elem_id_t id; 2470 int err; 2471 unsigned int idx; 2472 static ac97_bus_ops_t ops = { 2473 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2474 snd_cs46xx_codec_reset, 2475 #else 2476 0, 2477 #endif 2478 snd_cs46xx_ac97_write, 2479 snd_cs46xx_ac97_read,0,0 2480 }; 2481 /* detect primary codec */ 2482 chip->nr_ac97_codecs = 0; 2483 snd_printdd("snd_cs46xx: detecting primary codec\n"); 2484 if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0) 2485 return err; 2486 chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus; 2487 2488 if (cs46xx_detect_codec(chip, CS46XX_PRIMARY_CODEC_INDEX) < 0) 2489 return -ENXIO; 2490 chip->nr_ac97_codecs = 1; 2491 2492 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2493 snd_printdd("snd_cs46xx: detecting seconadry codec\n"); 2494 /* try detect a secondary codec */ 2495 if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX)) 2496 chip->nr_ac97_codecs = 2; 2329 static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97) 2330 { 2331 unsigned long end_time; 2332 int err; 2333 2334 /* reset to defaults */ 2335 snd_ac97_write(ac97, AC97_RESET, 0); 2336 2337 /* set the desired CODEC mode */ 2338 if (ac97->num == CS46XX_PRIMARY_CODEC_INDEX) { 2339 snd_printdd("cs46xx: CODOEC1 mode %04x\n",0x0); 2340 snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x0); 2341 } else if (ac97->num == CS46XX_SECONDARY_CODEC_INDEX) { 2342 snd_printdd("cs46xx: CODOEC2 mode %04x\n",0x3); 2343 snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x3); 2344 } else { 2345 snd_assert(0); /* should never happen ... */ 2346 } 2347 2348 udelay(50); 2349 2350 /* it's necessary to wait awhile until registers are accessible after RESET */ 2351 /* because the PCM or MASTER volume registers can be modified, */ 2352 /* the REC_GAIN register is used for tests */ 2353 end_time = jiffies + HZ; 2354 do { 2355 unsigned short ext_mid; 2356 2357 /* use preliminary reads to settle the communication */ 2358 snd_ac97_read(ac97, AC97_RESET); 2359 snd_ac97_read(ac97, AC97_VENDOR_ID1); 2360 snd_ac97_read(ac97, AC97_VENDOR_ID2); 2361 /* modem? */ 2362 ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID); 2363 if (ext_mid != 0xffff && (ext_mid & 1) != 0) 2364 return; 2365 2366 /* test if we can write to the record gain volume register */ 2367 snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05); 2368 if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05) 2369 return; 2370 2371 msleep(10); 2372 } while (time_after_eq(end_time, jiffies)); 2373 2374 snd_printk(KERN_ERR "CS46xx secondary codec doesn't respond!\n"); 2375 } 2376 #endif 2377 2378 static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec) 2379 { 2380 int idx, err; 2381 struct snd_ac97_template ac97; 2382 2383 memset(&ac97, 0, sizeof(ac97)); 2384 ac97.private_data = chip; 2385 ac97.private_free = snd_cs46xx_mixer_free_ac97; 2386 ac97.num = codec; 2387 if (chip->amplifier_ctrl == amp_voyetra) 2388 ac97.scaps = AC97_SCAP_INV_EAPD; 2389 2390 if (codec == CS46XX_SECONDARY_CODEC_INDEX) { 2391 snd_cs46xx_codec_write(chip, AC97_RESET, 0, codec); 2392 udelay(10); 2393 if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) { 2394 snd_printdd("snd_cs46xx: seconadry codec not present\n"); 2395 return -ENXIO; 2396 } 2397 } 2398 2399 snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000, codec); 2400 for (idx = 0; idx < 100; ++idx) { 2401 if (snd_cs46xx_codec_read(chip, AC97_MASTER, codec) == 0x8000) { 2402 err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]); 2403 return err; 2404 } 2405 msleep(10); 2406 } 2407 snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec); 2408 return -ENXIO; 2409 } 2410 2411 int __devinit snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) 2412 { 2413 struct snd_card *card = chip->card; 2414 struct snd_ctl_elem_id id; 2415 int err; 2416 unsigned int idx; 2417 static struct snd_ac97_bus_ops ops = { 2418 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2419 .reset = snd_cs46xx_codec_reset, 2420 #endif 2421 .write = snd_cs46xx_ac97_write, 2422 .read = snd_cs46xx_ac97_read, 2423 }; 2424 2425 /* detect primary codec */ 2426 chip->nr_ac97_codecs = 0; 2427 snd_printdd("snd_cs46xx: detecting primary codec\n"); 2428 if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0) 2429 return err; 2430 chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus; 2431 2432 if (cs46xx_detect_codec(chip, CS46XX_PRIMARY_CODEC_INDEX) < 0) 2433 return -ENXIO; 2434 chip->nr_ac97_codecs = 1; 2435 2436 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2437 snd_printdd("snd_cs46xx: detecting seconadry codec\n"); 2438 /* try detect a secondary codec */ 2439 if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX)) 2440 chip->nr_ac97_codecs = 2; 2497 2441 #endif /* CONFIG_SND_CS46XX_NEW_DSP */ 2498 2442 2499 /* add cs4630 mixer controls */ 2500 for (idx = 0; idx < ARRAY_SIZE(snd_cs46xx_controls); idx++) { 2501 snd_kcontrol_t *kctl; 2502 kctl = snd_ctl_new1(&snd_cs46xx_controls[idx], chip); 2503 if ((err = snd_ctl_add(card, kctl)) < 0) 2504 return err; 2505 } 2506 2507 /* get EAPD mixer switch (for voyetra hack) */ 2508 memset(&id, 0, sizeof(id)); 2509 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 2510 strcpy(id.name, "External Amplifier"); 2511 chip->eapd_switch = snd_ctl_find_id(chip->card, &id); 2512 2513 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2514 if (chip->nr_ac97_codecs == 1) { 2515 unsigned int id2 = chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]->id & 0xffff; 2516 if (id2 == 0x592b || id2 == 0x592d) { 2517 err = snd_ctl_add(card, snd_ctl_new1(&snd_cs46xx_front_dup_ctl, chip)); 2518 if (err < 0) 2519 return err; 2520 snd_ac97_write_cache(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], 2521 AC97_CSR_ACMODE, 0x200); 2522 } 2523 } 2524 /* do soundcard specific mixer setup */ 2525 if (chip->mixer_init) { 2526 snd_printdd ("calling chip->mixer_init(chip);\n"); 2527 chip->mixer_init(chip); 2528 } 2529 #endif 2530 2531 /* turn on amplifier */ 2532 chip->amplifier_ctrl(chip, 1); 2533 2534 return 0; 2443 /* add cs4630 mixer controls */ 2444 for (idx = 0; idx < ARRAY_SIZE(snd_cs46xx_controls); idx++) { 2445 struct snd_kcontrol *kctl; 2446 kctl = snd_ctl_new1(&snd_cs46xx_controls[idx], chip); 2447 if (kctl && kctl->id.iface == SNDRV_CTL_ELEM_IFACE_PCM) 2448 kctl->id.device = spdif_device; 2449 if ((err = snd_ctl_add(card, kctl)) < 0) 2450 return err; 2451 } 2452 2453 /* get EAPD mixer switch (for voyetra hack) */ 2454 memset(&id, 0, sizeof(id)); 2455 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 2456 strcpy(id.name, "External Amplifier"); 2457 chip->eapd_switch = snd_ctl_find_id(chip->card, &id); 2458 2459 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2460 if (chip->nr_ac97_codecs == 1) { 2461 unsigned int id2 = chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]->id & 0xffff; 2462 if (id2 == 0x592b || id2 == 0x592d) { 2463 err = snd_ctl_add(card, snd_ctl_new1(&snd_cs46xx_front_dup_ctl, chip)); 2464 if (err < 0) 2465 return err; 2466 snd_ac97_write_cache(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], 2467 AC97_CSR_ACMODE, 0x200); 2468 } 2469 } 2470 /* do soundcard specific mixer setup */ 2471 if (chip->mixer_init) { 2472 snd_printdd ("calling chip->mixer_init(chip);\n"); 2473 chip->mixer_init(chip); 2474 } 2475 #endif 2476 2477 /* turn on amplifier */ 2478 chip->amplifier_ctrl(chip, 1); 2479 2480 return 0; 2535 2481 } 2536 2482 … … 2539 2485 */ 2540 2486 2541 static void snd_cs46xx_midi_reset( cs46xx_t*chip)2542 { 2543 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, MIDCR_MRST);2544 udelay(100);2545 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);2546 } 2547 2548 static int snd_cs46xx_midi_input_open(s nd_rawmidi_substream_t *substream)2549 { 2550 cs46xx_t*chip = substream->rmidi->private_data;2551 2552 chip->active_ctrl(chip, 1);2553 spin_lock_irq(&chip->reg_lock);2554 chip->uartm |= CS46XX_MODE_INPUT;2555 chip->midcr |= MIDCR_RXE;2556 chip->midi_input = substream;2557 if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {2558 snd_cs46xx_midi_reset(chip);2559 } else {2560 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);2561 }2562 spin_unlock_irq(&chip->reg_lock);2563 return 0;2564 } 2565 2566 static int snd_cs46xx_midi_input_close(s nd_rawmidi_substream_t *substream)2567 { 2568 cs46xx_t*chip = substream->rmidi->private_data;2569 2570 spin_lock_irq(&chip->reg_lock);2571 chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE);2572 chip->midi_input = NULL;2573 if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {2574 snd_cs46xx_midi_reset(chip);2575 } else {2576 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);2577 }2578 chip->uartm &= ~CS46XX_MODE_INPUT;2579 spin_unlock_irq(&chip->reg_lock);2580 chip->active_ctrl(chip, -1);2581 return 0;2582 } 2583 2584 static int snd_cs46xx_midi_output_open(s nd_rawmidi_substream_t *substream)2585 { 2586 cs46xx_t*chip = substream->rmidi->private_data;2587 2588 chip->active_ctrl(chip, 1);2589 2590 spin_lock_irq(&chip->reg_lock);2591 chip->uartm |= CS46XX_MODE_OUTPUT;2592 chip->midcr |= MIDCR_TXE;2593 chip->midi_output = substream;2594 if (!(chip->uartm & CS46XX_MODE_INPUT)) {2595 snd_cs46xx_midi_reset(chip);2596 } else {2597 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);2598 }2599 spin_unlock_irq(&chip->reg_lock);2600 return 0;2601 } 2602 2603 static int snd_cs46xx_midi_output_close(s nd_rawmidi_substream_t *substream)2604 { 2605 cs46xx_t*chip = substream->rmidi->private_data;2606 2607 spin_lock_irq(&chip->reg_lock);2608 chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE);2609 chip->midi_output = NULL;2610 if (!(chip->uartm & CS46XX_MODE_INPUT)) {2611 snd_cs46xx_midi_reset(chip);2612 } else {2613 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);2614 }2615 chip->uartm &= ~CS46XX_MODE_OUTPUT;2616 spin_unlock_irq(&chip->reg_lock);2617 chip->active_ctrl(chip, -1);2618 return 0;2619 } 2620 2621 static void snd_cs46xx_midi_input_trigger(s nd_rawmidi_substream_t *substream, int up)2622 { 2623 unsigned long flags;2624 cs46xx_t*chip = substream->rmidi->private_data;2625 2626 spin_lock_irqsave(&chip->reg_lock, flags);2627 if (up) {2628 if ((chip->midcr & MIDCR_RIE) == 0) {2629 chip->midcr |= MIDCR_RIE;2630 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);2631 }2632 } else {2633 if (chip->midcr & MIDCR_RIE) {2634 chip->midcr &= ~MIDCR_RIE;2635 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);2636 }2637 }2638 spin_unlock_irqrestore(&chip->reg_lock, flags);2639 } 2640 2641 static void snd_cs46xx_midi_output_trigger(s nd_rawmidi_substream_t *substream, int up)2642 { 2643 unsigned long flags;2644 cs46xx_t*chip = substream->rmidi->private_data;2645 unsigned char byte;2646 2647 spin_lock_irqsave(&chip->reg_lock, flags);2648 if (up) {2649 if ((chip->midcr & MIDCR_TIE) == 0) {2650 chip->midcr |= MIDCR_TIE;2651 /* fill UART FIFO buffer at first, and turn Tx interrupts only if necessary */2652 while ((chip->midcr & MIDCR_TIE) &&2653 (snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {2654 if (snd_rawmidi_transmit(substream, &byte, 1) != 1) {2655 chip->midcr &= ~MIDCR_TIE;2656 } else {2657 snd_cs46xx_pokeBA0(chip, BA0_MIDWP, byte);2658 }2659 }2660 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);2661 }2662 } else {2663 if (chip->midcr & MIDCR_TIE) {2664 chip->midcr &= ~MIDCR_TIE;2665 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);2666 }2667 }2668 spin_unlock_irqrestore(&chip->reg_lock, flags);2669 } 2670 2671 static s nd_rawmidi_ops_tsnd_cs46xx_midi_output =2672 { 2673 snd_cs46xx_midi_output_open,2674 snd_cs46xx_midi_output_close,2675 snd_cs46xx_midi_output_trigger,0 2487 static void snd_cs46xx_midi_reset(struct snd_cs46xx *chip) 2488 { 2489 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, MIDCR_MRST); 2490 udelay(100); 2491 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); 2492 } 2493 2494 static int snd_cs46xx_midi_input_open(struct snd_rawmidi_substream *substream) 2495 { 2496 struct snd_cs46xx *chip = substream->rmidi->private_data; 2497 2498 chip->active_ctrl(chip, 1); 2499 spin_lock_irq(&chip->reg_lock); 2500 chip->uartm |= CS46XX_MODE_INPUT; 2501 chip->midcr |= MIDCR_RXE; 2502 chip->midi_input = substream; 2503 if (!(chip->uartm & CS46XX_MODE_OUTPUT)) { 2504 snd_cs46xx_midi_reset(chip); 2505 } else { 2506 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); 2507 } 2508 spin_unlock_irq(&chip->reg_lock); 2509 return 0; 2510 } 2511 2512 static int snd_cs46xx_midi_input_close(struct snd_rawmidi_substream *substream) 2513 { 2514 struct snd_cs46xx *chip = substream->rmidi->private_data; 2515 2516 spin_lock_irq(&chip->reg_lock); 2517 chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE); 2518 chip->midi_input = NULL; 2519 if (!(chip->uartm & CS46XX_MODE_OUTPUT)) { 2520 snd_cs46xx_midi_reset(chip); 2521 } else { 2522 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); 2523 } 2524 chip->uartm &= ~CS46XX_MODE_INPUT; 2525 spin_unlock_irq(&chip->reg_lock); 2526 chip->active_ctrl(chip, -1); 2527 return 0; 2528 } 2529 2530 static int snd_cs46xx_midi_output_open(struct snd_rawmidi_substream *substream) 2531 { 2532 struct snd_cs46xx *chip = substream->rmidi->private_data; 2533 2534 chip->active_ctrl(chip, 1); 2535 2536 spin_lock_irq(&chip->reg_lock); 2537 chip->uartm |= CS46XX_MODE_OUTPUT; 2538 chip->midcr |= MIDCR_TXE; 2539 chip->midi_output = substream; 2540 if (!(chip->uartm & CS46XX_MODE_INPUT)) { 2541 snd_cs46xx_midi_reset(chip); 2542 } else { 2543 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); 2544 } 2545 spin_unlock_irq(&chip->reg_lock); 2546 return 0; 2547 } 2548 2549 static int snd_cs46xx_midi_output_close(struct snd_rawmidi_substream *substream) 2550 { 2551 struct snd_cs46xx *chip = substream->rmidi->private_data; 2552 2553 spin_lock_irq(&chip->reg_lock); 2554 chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE); 2555 chip->midi_output = NULL; 2556 if (!(chip->uartm & CS46XX_MODE_INPUT)) { 2557 snd_cs46xx_midi_reset(chip); 2558 } else { 2559 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); 2560 } 2561 chip->uartm &= ~CS46XX_MODE_OUTPUT; 2562 spin_unlock_irq(&chip->reg_lock); 2563 chip->active_ctrl(chip, -1); 2564 return 0; 2565 } 2566 2567 static void snd_cs46xx_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) 2568 { 2569 unsigned long flags; 2570 struct snd_cs46xx *chip = substream->rmidi->private_data; 2571 2572 spin_lock_irqsave(&chip->reg_lock, flags); 2573 if (up) { 2574 if ((chip->midcr & MIDCR_RIE) == 0) { 2575 chip->midcr |= MIDCR_RIE; 2576 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); 2577 } 2578 } else { 2579 if (chip->midcr & MIDCR_RIE) { 2580 chip->midcr &= ~MIDCR_RIE; 2581 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); 2582 } 2583 } 2584 spin_unlock_irqrestore(&chip->reg_lock, flags); 2585 } 2586 2587 static void snd_cs46xx_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) 2588 { 2589 unsigned long flags; 2590 struct snd_cs46xx *chip = substream->rmidi->private_data; 2591 unsigned char byte; 2592 2593 spin_lock_irqsave(&chip->reg_lock, flags); 2594 if (up) { 2595 if ((chip->midcr & MIDCR_TIE) == 0) { 2596 chip->midcr |= MIDCR_TIE; 2597 /* fill UART FIFO buffer at first, and turn Tx interrupts only if necessary */ 2598 while ((chip->midcr & MIDCR_TIE) && 2599 (snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) { 2600 if (snd_rawmidi_transmit(substream, &byte, 1) != 1) { 2601 chip->midcr &= ~MIDCR_TIE; 2602 } else { 2603 snd_cs46xx_pokeBA0(chip, BA0_MIDWP, byte); 2604 } 2605 } 2606 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); 2607 } 2608 } else { 2609 if (chip->midcr & MIDCR_TIE) { 2610 chip->midcr &= ~MIDCR_TIE; 2611 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); 2612 } 2613 } 2614 spin_unlock_irqrestore(&chip->reg_lock, flags); 2615 } 2616 2617 static struct snd_rawmidi_ops snd_cs46xx_midi_output = 2618 { 2619 .open = snd_cs46xx_midi_output_open, 2620 .close = snd_cs46xx_midi_output_close, 2621 .trigger = snd_cs46xx_midi_output_trigger, 2676 2622 }; 2677 2623 2678 static s nd_rawmidi_ops_tsnd_cs46xx_midi_input =2679 { 2680 snd_cs46xx_midi_input_open,2681 snd_cs46xx_midi_input_close,2682 snd_cs46xx_midi_input_trigger,0 2624 static struct snd_rawmidi_ops snd_cs46xx_midi_input = 2625 { 2626 .open = snd_cs46xx_midi_input_open, 2627 .close = snd_cs46xx_midi_input_close, 2628 .trigger = snd_cs46xx_midi_input_trigger, 2683 2629 }; 2684 2630 2685 int __devinit snd_cs46xx_midi( cs46xx_t *chip, int device, snd_rawmidi_t**rrawmidi)2686 { 2687 snd_rawmidi_t*rmidi;2688 int err;2689 2690 if (rrawmidi)2691 *rrawmidi = NULL;2692 if ((err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi)) < 0)2693 return err;2694 strcpy(rmidi->name, "CS46XX");2695 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs46xx_midi_output);2696 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_cs46xx_midi_input);2697 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;2698 rmidi->private_data = chip;2699 chip->rmidi = rmidi;2700 if (rrawmidi)2701 *rrawmidi = NULL;2702 return 0;2631 int __devinit snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi) 2632 { 2633 struct snd_rawmidi *rmidi; 2634 int err; 2635 2636 if (rrawmidi) 2637 *rrawmidi = NULL; 2638 if ((err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi)) < 0) 2639 return err; 2640 strcpy(rmidi->name, "CS46XX"); 2641 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs46xx_midi_output); 2642 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_cs46xx_midi_input); 2643 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; 2644 rmidi->private_data = chip; 2645 chip->rmidi = rmidi; 2646 if (rrawmidi) 2647 *rrawmidi = NULL; 2648 return 0; 2703 2649 } 2704 2650 … … 2708 2654 */ 2709 2655 2710 #ifndef LINUX_2_2 2711 2712 typedef struct snd_cs46xx_gameport { 2713 struct gameport info; 2714 cs46xx_t *chip; 2715 } cs46xx_gameport_t; 2656 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) 2716 2657 2717 2658 static void snd_cs46xx_gameport_trigger(struct gameport *gameport) 2718 2659 { 2719 cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport; 2720 cs46xx_t *chip; 2721 snd_assert(gp, return); 2722 chip = gp->chip; 2723 snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF); 2660 struct snd_cs46xx *chip = gameport_get_port_data(gameport); 2661 2662 snd_assert(chip, return); 2663 snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF); 2724 2664 } 2725 2665 2726 2666 static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport) 2727 2667 { 2728 cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport; 2729 cs46xx_t *chip; 2730 snd_assert(gp, return 0); 2731 chip = gp->chip; 2732 return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io); 2668 struct snd_cs46xx *chip = gameport_get_port_data(gameport); 2669 2670 snd_assert(chip, return 0); 2671 return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io); 2733 2672 } 2734 2673 2735 2674 static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) 2736 2675 { 2737 cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport; 2738 cs46xx_t *chip; 2739 unsigned js1, js2, jst; 2740 2741 snd_assert(gp, return 0); 2742 chip = gp->chip; 2743 2744 js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1); 2745 js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2); 2746 jst = snd_cs46xx_peekBA0(chip, BA0_JSPT); 2747 2748 *buttons = (~jst >> 4) & 0x0F; 2749 2750 axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF; 2751 axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF; 2752 axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF; 2753 axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF; 2754 2755 for(jst=0;jst<4;++jst) 2756 if(axes[jst]==0xFFFF) axes[jst] = -1; 2757 return 0; 2676 struct snd_cs46xx *chip = gameport_get_port_data(gameport); 2677 unsigned js1, js2, jst; 2678 2679 snd_assert(chip, return 0); 2680 2681 js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1); 2682 js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2); 2683 jst = snd_cs46xx_peekBA0(chip, BA0_JSPT); 2684 2685 *buttons = (~jst >> 4) & 0x0F; 2686 2687 axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF; 2688 axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF; 2689 axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF; 2690 axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF; 2691 2692 for(jst=0;jst<4;++jst) 2693 if(axes[jst]==0xFFFF) axes[jst] = -1; 2694 return 0; 2758 2695 } 2759 2696 2760 2697 static int snd_cs46xx_gameport_open(struct gameport *gameport, int mode) 2761 2698 { 2762 switch (mode) { 2763 case GAMEPORT_MODE_COOKED: 2764 return 0; 2765 case GAMEPORT_MODE_RAW: 2766 return 0; 2767 default: 2768 return -1; 2769 } 2770 return 0; 2771 } 2772 2773 void __devinit snd_cs46xx_gameport(cs46xx_t *chip) 2774 { 2775 cs46xx_gameport_t *gp; 2776 gp = kmalloc(sizeof(*gp), GFP_KERNEL); 2777 if (! gp) { 2778 snd_printk("cannot allocate gameport area\n"); 2779 return; 2780 } 2781 memset(gp, 0, sizeof(*gp)); 2782 gp->info.open = snd_cs46xx_gameport_open; 2783 gp->info.read = snd_cs46xx_gameport_read; 2784 gp->info.trigger = snd_cs46xx_gameport_trigger; 2785 gp->info.cooked_read = snd_cs46xx_gameport_cooked_read; 2786 gp->chip = chip; 2787 chip->gameport = gp; 2788 2789 snd_cs46xx_pokeBA0(chip, BA0_JSIO, 0xFF); // ? 2790 snd_cs46xx_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW); 2791 gameport_register_port(&gp->info); 2792 } 2793 2794 #else /* LINUX_2_2 */ 2795 2796 void __devinit snd_cs46xx_gameport(cs46xx_t *chip) 2797 { 2798 } 2799 2800 #endif /* !LINUX_2_2 */ 2699 switch (mode) { 2700 case GAMEPORT_MODE_COOKED: 2701 return 0; 2702 case GAMEPORT_MODE_RAW: 2703 return 0; 2704 default: 2705 return -1; 2706 } 2707 return 0; 2708 } 2709 2710 int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip) 2711 { 2712 struct gameport *gp; 2713 2714 chip->gameport = gp = gameport_allocate_port(); 2715 if (!gp) { 2716 printk(KERN_ERR "cs46xx: cannot allocate memory for gameport\n"); 2717 return -ENOMEM; 2718 } 2719 2720 gameport_set_name(gp, "CS46xx Gameport"); 2721 gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); 2722 gameport_set_dev_parent(gp, &chip->pci->dev); 2723 gameport_set_port_data(gp, chip); 2724 2725 gp->open = snd_cs46xx_gameport_open; 2726 gp->read = snd_cs46xx_gameport_read; 2727 gp->trigger = snd_cs46xx_gameport_trigger; 2728 gp->cooked_read = snd_cs46xx_gameport_cooked_read; 2729 2730 snd_cs46xx_pokeBA0(chip, BA0_JSIO, 0xFF); // ? 2731 snd_cs46xx_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW); 2732 2733 gameport_register_port(gp); 2734 2735 return 0; 2736 } 2737 2738 static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) 2739 { 2740 if (chip->gameport) { 2741 gameport_unregister_port(chip->gameport); 2742 chip->gameport = NULL; 2743 } 2744 } 2745 #else 2746 int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; } 2747 static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { } 2748 #endif /* CONFIG_GAMEPORT */ 2801 2749 2802 2750 /* 2803 2751 * proc interface 2804 2752 */ 2805 static long snd_cs46xx_io_read(snd_info_entry_t *entry, void *file_private_data, 2753 2754 static long snd_cs46xx_io_read(struct snd_info_entry *entry, void *file_private_data, 2806 2755 struct file *file, char __user *buf, 2807 2756 unsigned long count, unsigned long pos) 2808 2757 { 2809 2758 long size; 2810 s nd_cs46xx_region_t *region = (snd_cs46xx_region_t *)entry->private_data;2811 2759 struct snd_cs46xx_region *region = entry->private_data; 2760 2812 2761 size = count; 2813 2762 if (pos + (size_t)size > region->size) … … 2821 2770 2822 2771 static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = { 2823 0,0,snd_cs46xx_io_read,0,0,0,0,0 2772 .read = snd_cs46xx_io_read, 2824 2773 }; 2825 2774 2826 static int __devinit snd_cs46xx_proc_init(s nd_card_t * card, cs46xx_t*chip)2827 { 2828 snd_info_entry_t*entry;2829 int idx;2830 2831 for (idx = 0; idx < 5; idx++) {2832 snd_cs46xx_region_t*region = &chip->region.idx[idx];2833 if (! snd_card_proc_new(card, region->name, &entry)) {2834 entry->content = SNDRV_INFO_CONTENT_DATA;2835 entry->private_data = chip;2836 entry->c.ops = &snd_cs46xx_proc_io_ops;2837 entry->size = region->size;2838 entry->mode = S_IFREG | S_IRUSR;2839 }2840 }2841 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2842 cs46xx_dsp_proc_init(card, chip);2843 #endif 2844 return 0;2845 } 2846 2847 static int snd_cs46xx_proc_done( cs46xx_t*chip)2848 { 2849 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2850 cs46xx_dsp_proc_done(chip);2851 #endif 2852 return 0;2775 static int __devinit snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip) 2776 { 2777 struct snd_info_entry *entry; 2778 int idx; 2779 2780 for (idx = 0; idx < 5; idx++) { 2781 struct snd_cs46xx_region *region = &chip->region.idx[idx]; 2782 if (! snd_card_proc_new(card, region->name, &entry)) { 2783 entry->content = SNDRV_INFO_CONTENT_DATA; 2784 entry->private_data = chip; 2785 entry->c.ops = &snd_cs46xx_proc_io_ops; 2786 entry->size = region->size; 2787 entry->mode = S_IFREG | S_IRUSR; 2788 } 2789 } 2790 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2791 cs46xx_dsp_proc_init(card, chip); 2792 #endif 2793 return 0; 2794 } 2795 2796 static int snd_cs46xx_proc_done(struct snd_cs46xx *chip) 2797 { 2798 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2799 cs46xx_dsp_proc_done(chip); 2800 #endif 2801 return 0; 2853 2802 } 2854 2803 … … 2856 2805 * stop the h/w 2857 2806 */ 2858 static void snd_cs46xx_hw_stop(cs46xx_t *chip) 2859 { 2860 unsigned int tmp; 2861 2862 tmp = snd_cs46xx_peek(chip, BA1_PFIE); 2863 tmp &= ~0x0000f03f; 2864 tmp |= 0x00000010; 2865 snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt disable */ 2866 2867 tmp = snd_cs46xx_peek(chip, BA1_CIE); 2868 tmp &= ~0x0000003f; 2869 tmp |= 0x00000011; 2870 snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt disable */ 2871 2872 /* 2873 * Stop playback DMA. 2874 */ 2875 tmp = snd_cs46xx_peek(chip, BA1_PCTL); 2876 snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff); 2877 2878 /* 2879 * Stop capture DMA. 2880 */ 2881 tmp = snd_cs46xx_peek(chip, BA1_CCTL); 2882 snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000); 2883 2884 /* 2885 * Reset the processor. 2886 */ 2887 snd_cs46xx_reset(chip); 2888 2889 snd_cs46xx_proc_stop(chip); 2890 2891 /* 2892 * Power down the PLL. 2893 */ 2894 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0); 2895 2896 /* 2897 * Turn off the Processor by turning off the software clock enable flag in 2898 * the clock control register. 2899 */ 2900 tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE; 2901 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); 2902 } 2903 2904 2905 static int snd_cs46xx_free(cs46xx_t *chip) 2906 { 2907 int idx; 2908 2909 snd_assert(chip != NULL, return -EINVAL); 2910 2911 if (chip->active_ctrl) 2912 chip->active_ctrl(chip, 1); 2913 2914 #ifndef LINUX_2_2 2915 if (chip->gameport) { 2916 gameport_unregister_port(&chip->gameport->info); 2917 kfree(chip->gameport); 2918 } 2919 #endif 2920 if (chip->amplifier_ctrl) 2921 chip->amplifier_ctrl(chip, -chip->amplifier); /* force to off */ 2922 2923 snd_cs46xx_proc_done(chip); 2924 2925 if (chip->region.idx[0].resource) 2926 snd_cs46xx_hw_stop(chip); 2927 2928 for (idx = 0; idx < 5; idx++) { 2929 snd_cs46xx_region_t *region = &chip->region.idx[idx]; 2930 if (region->remap_addr) 2931 iounmap((void *) region->remap_addr); 2932 if (region->resource) { 2933 release_resource(region->resource); 2934 kfree_nocheck(region->resource); 2935 } 2936 } 2937 if (chip->irq >= 0) 2938 free_irq(chip->irq, (void *)chip); 2939 2940 if (chip->active_ctrl) 2941 chip->active_ctrl(chip, -chip->amplifier); 2942 2943 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2944 if (chip->dsp_spos_instance) { 2945 cs46xx_dsp_spos_destroy(chip); 2946 chip->dsp_spos_instance = NULL; 2947 } 2948 #endif 2949 2950 pci_disable_device(chip->pci); 2951 kfree(chip); 2952 return 0; 2953 } 2954 2955 static int snd_cs46xx_dev_free(snd_device_t *device) 2956 { 2957 cs46xx_t *chip = device->device_data; 2958 return snd_cs46xx_free(chip); 2807 static void snd_cs46xx_hw_stop(struct snd_cs46xx *chip) 2808 { 2809 unsigned int tmp; 2810 2811 tmp = snd_cs46xx_peek(chip, BA1_PFIE); 2812 tmp &= ~0x0000f03f; 2813 tmp |= 0x00000010; 2814 snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt disable */ 2815 2816 tmp = snd_cs46xx_peek(chip, BA1_CIE); 2817 tmp &= ~0x0000003f; 2818 tmp |= 0x00000011; 2819 snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt disable */ 2820 2821 /* 2822 * Stop playback DMA. 2823 */ 2824 tmp = snd_cs46xx_peek(chip, BA1_PCTL); 2825 snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff); 2826 2827 /* 2828 * Stop capture DMA. 2829 */ 2830 tmp = snd_cs46xx_peek(chip, BA1_CCTL); 2831 snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000); 2832 2833 /* 2834 * Reset the processor. 2835 */ 2836 snd_cs46xx_reset(chip); 2837 2838 snd_cs46xx_proc_stop(chip); 2839 2840 /* 2841 * Power down the PLL. 2842 */ 2843 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0); 2844 2845 /* 2846 * Turn off the Processor by turning off the software clock enable flag in 2847 * the clock control register. 2848 */ 2849 tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE; 2850 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); 2851 } 2852 2853 2854 static int snd_cs46xx_free(struct snd_cs46xx *chip) 2855 { 2856 int idx; 2857 2858 snd_assert(chip != NULL, return -EINVAL); 2859 2860 if (chip->active_ctrl) 2861 chip->active_ctrl(chip, 1); 2862 2863 snd_cs46xx_remove_gameport(chip); 2864 2865 if (chip->amplifier_ctrl) 2866 chip->amplifier_ctrl(chip, -chip->amplifier); /* force to off */ 2867 2868 snd_cs46xx_proc_done(chip); 2869 2870 if (chip->region.idx[0].resource) 2871 snd_cs46xx_hw_stop(chip); 2872 2873 for (idx = 0; idx < 5; idx++) { 2874 struct snd_cs46xx_region *region = &chip->region.idx[idx]; 2875 if (region->remap_addr) 2876 iounmap(region->remap_addr); 2877 release_and_free_resource(region->resource); 2878 } 2879 if (chip->irq >= 0) 2880 free_irq(chip->irq, chip); 2881 2882 if (chip->active_ctrl) 2883 chip->active_ctrl(chip, -chip->amplifier); 2884 2885 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2886 if (chip->dsp_spos_instance) { 2887 cs46xx_dsp_spos_destroy(chip); 2888 chip->dsp_spos_instance = NULL; 2889 } 2890 #endif 2891 2892 pci_disable_device(chip->pci); 2893 kfree(chip); 2894 return 0; 2895 } 2896 2897 static int snd_cs46xx_dev_free(struct snd_device *device) 2898 { 2899 struct snd_cs46xx *chip = device->device_data; 2900 return snd_cs46xx_free(chip); 2959 2901 } 2960 2902 … … 2962 2904 * initialize chip 2963 2905 */ 2964 static int snd_cs46xx_chip_init( cs46xx_t*chip)2965 { 2966 int timeout;2967 2968 /* 2969 * First, blast the clock control register to zero so that the PLL starts2970 * out in a known state, and blast the master serial port control register2971 * to zero so that the serial ports also start out in a known state.2972 */2973 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0);2974 snd_cs46xx_pokeBA0(chip, BA0_SERMC1, 0);2975 2976 /*2977 * If we are in AC97 mode, then we must set the part to a host controlled2978 * AC-link. Otherwise, we won't be able to bring up the link.2979 */2980 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2981 snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0 | 2982 SERACC_TWO_CODECS); /* 2.00 dual codecs */2983 /* snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0); */ /* 2.00 codec */2906 static int snd_cs46xx_chip_init(struct snd_cs46xx *chip) 2907 { 2908 int timeout; 2909 2910 /* 2911 * First, blast the clock control register to zero so that the PLL starts 2912 * out in a known state, and blast the master serial port control register 2913 * to zero so that the serial ports also start out in a known state. 2914 */ 2915 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0); 2916 snd_cs46xx_pokeBA0(chip, BA0_SERMC1, 0); 2917 2918 /* 2919 * If we are in AC97 mode, then we must set the part to a host controlled 2920 * AC-link. Otherwise, we won't be able to bring up the link. 2921 */ 2922 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2923 snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0 | 2924 SERACC_TWO_CODECS); /* 2.00 dual codecs */ 2925 /* snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0); */ /* 2.00 codec */ 2984 2926 #else 2985 snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_1_03); /* 1.03 codec */ 2986 #endif 2987 2988 /* 2989 * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97 2990 * spec) and then drive it high. This is done for non AC97 modes since 2991 * there might be logic external to the CS461x that uses the ARST# line 2992 * for a reset. 2993 */ 2994 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, 0); 2995 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2996 snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, 0); 2997 #endif 2998 udelay(50); 2999 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_RSTN); 3000 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3001 snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_RSTN); 3002 #endif 3003 3004 /* 3005 * The first thing we do here is to enable sync generation. As soon 3006 * as we start receiving bit clock, we'll start producing the SYNC 3007 * signal. 3008 */ 3009 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN); 3010 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3011 snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_ESYN | ACCTL_RSTN); 3012 #endif 3013 3014 /* 3015 * Now wait for a short while to allow the AC97 part to start 3016 * generating bit clock (so we don't try to start the PLL without an 3017 * input clock). 3018 */ 3019 mdelay(10); 3020 3021 /* 3022 * Set the serial port timing configuration, so that 3023 * the clock control circuit gets its clock from the correct place. 3024 */ 3025 snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97); 3026 3027 /* 3028 * Write the selected clock control setup to the hardware. Do not turn on 3029 * SWCE yet (if requested), so that the devices clocked by the output of 3030 * PLL are not clocked until the PLL is stable. 3031 */ 3032 snd_cs46xx_pokeBA0(chip, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ); 3033 snd_cs46xx_pokeBA0(chip, BA0_PLLM, 0x3a); 3034 snd_cs46xx_pokeBA0(chip, BA0_CLKCR2, CLKCR2_PDIVS_8); 3035 3036 /* 3037 * Power up the PLL. 3038 */ 3039 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP); 3040 3041 /* 3042 * Wait until the PLL has stabilized. 3043 */ 3044 msleep(100); 3045 3046 /* 3047 * Turn on clocking of the core so that we can setup the serial ports. 3048 */ 3049 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP | CLKCR1_SWCE); 3050 3051 /* 3052 * Enable FIFO Host Bypass 3053 */ 3054 snd_cs46xx_pokeBA0(chip, BA0_SERBCF, SERBCF_HBP); 3055 3056 /* 3057 * Fill the serial port FIFOs with silence. 3058 */ 3059 snd_cs46xx_clear_serial_FIFOs(chip); 3060 3061 /* 3062 * Set the serial port FIFO pointer to the first sample in the FIFO. 3063 */ 3064 /* snd_cs46xx_pokeBA0(chip, BA0_SERBSP, 0); */ 3065 3066 /* 3067 * Write the serial port configuration to the part. The master 3068 * enable bit is not set until all other values have been written. 3069 */ 3070 snd_cs46xx_pokeBA0(chip, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN); 3071 snd_cs46xx_pokeBA0(chip, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN); 3072 snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE); 3073 3074 3075 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3076 snd_cs46xx_pokeBA0(chip, BA0_SERC7, SERC7_ASDI2EN); 3077 snd_cs46xx_pokeBA0(chip, BA0_SERC3, 0); 3078 snd_cs46xx_pokeBA0(chip, BA0_SERC4, 0); 3079 snd_cs46xx_pokeBA0(chip, BA0_SERC5, 0); 3080 snd_cs46xx_pokeBA0(chip, BA0_SERC6, 1); 3081 #endif 3082 3083 mdelay(5); 3084 3085 3086 /* 3087 * Wait for the codec ready signal from the AC97 codec. 3088 */ 3089 timeout = 150; 3090 while (timeout-- > 0) { 2927 snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_1_03); /* 1.03 codec */ 2928 #endif 2929 3091 2930 /* 3092 * Read the AC97 status register to see if we've seen a CODEC READY 3093 * signal from the AC97 codec. 2931 * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97 2932 * spec) and then drive it high. This is done for non AC97 modes since 2933 * there might be logic external to the CS461x that uses the ARST# line 2934 * for a reset. 3094 2935 */ 3095 if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY) 3096 goto ok1; 3097 msleep(10); 3098 } 3099 3100 3101 snd_printk("create - never read codec ready from AC'97\n"); 3102 snd_printk("it is not probably bug, try to use CS4236 driver\n"); 3103 return -EIO; 3104 ok1: 3105 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3106 { 3107 int count; 3108 for (count = 0; count < 150; count++) { 3109 /* First, we want to wait for a short time. */ 3110 udelay(25); 3111 3112 if (snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY) 3113 break; 3114 } 3115 3116 /* 3117 * Make sure CODEC is READY. 3118 */ 3119 if (!(snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY)) 3120 snd_printdd("cs46xx: never read card ready from secondary AC'97\n"); 3121 } 3122 #endif 3123 3124 /* 3125 * Assert the vaid frame signal so that we can start sending commands 3126 * to the AC97 codec. 3127 */ 3128 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); 3129 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3130 snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); 3131 #endif 3132 3133 3134 /* 3135 * Wait until we've sampled input slots 3 and 4 as valid, meaning that 3136 * the codec is pumping ADC data across the AC-link. 3137 */ 3138 timeout = 150; 3139 while (timeout-- > 0) { 3140 /* 3141 * Read the input slot valid register and see if input slots 3 and 3142 * 4 are valid yet. 3143 */ 3144 if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) 3145 goto ok2; 3146 msleep(10); 3147 } 2936 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, 0); 2937 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2938 snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, 0); 2939 #endif 2940 udelay(50); 2941 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_RSTN); 2942 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2943 snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_RSTN); 2944 #endif 2945 2946 /* 2947 * The first thing we do here is to enable sync generation. As soon 2948 * as we start receiving bit clock, we'll start producing the SYNC 2949 * signal. 2950 */ 2951 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN); 2952 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2953 snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_ESYN | ACCTL_RSTN); 2954 #endif 2955 2956 /* 2957 * Now wait for a short while to allow the AC97 part to start 2958 * generating bit clock (so we don't try to start the PLL without an 2959 * input clock). 2960 */ 2961 mdelay(10); 2962 2963 /* 2964 * Set the serial port timing configuration, so that 2965 * the clock control circuit gets its clock from the correct place. 2966 */ 2967 snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97); 2968 2969 /* 2970 * Write the selected clock control setup to the hardware. Do not turn on 2971 * SWCE yet (if requested), so that the devices clocked by the output of 2972 * PLL are not clocked until the PLL is stable. 2973 */ 2974 snd_cs46xx_pokeBA0(chip, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ); 2975 snd_cs46xx_pokeBA0(chip, BA0_PLLM, 0x3a); 2976 snd_cs46xx_pokeBA0(chip, BA0_CLKCR2, CLKCR2_PDIVS_8); 2977 2978 /* 2979 * Power up the PLL. 2980 */ 2981 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP); 2982 2983 /* 2984 * Wait until the PLL has stabilized. 2985 */ 2986 msleep(100); 2987 2988 /* 2989 * Turn on clocking of the core so that we can setup the serial ports. 2990 */ 2991 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP | CLKCR1_SWCE); 2992 2993 /* 2994 * Enable FIFO Host Bypass 2995 */ 2996 snd_cs46xx_pokeBA0(chip, BA0_SERBCF, SERBCF_HBP); 2997 2998 /* 2999 * Fill the serial port FIFOs with silence. 3000 */ 3001 snd_cs46xx_clear_serial_FIFOs(chip); 3002 3003 /* 3004 * Set the serial port FIFO pointer to the first sample in the FIFO. 3005 */ 3006 /* snd_cs46xx_pokeBA0(chip, BA0_SERBSP, 0); */ 3007 3008 /* 3009 * Write the serial port configuration to the part. The master 3010 * enable bit is not set until all other values have been written. 3011 */ 3012 snd_cs46xx_pokeBA0(chip, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN); 3013 snd_cs46xx_pokeBA0(chip, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN); 3014 snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE); 3015 3016 3017 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3018 snd_cs46xx_pokeBA0(chip, BA0_SERC7, SERC7_ASDI2EN); 3019 snd_cs46xx_pokeBA0(chip, BA0_SERC3, 0); 3020 snd_cs46xx_pokeBA0(chip, BA0_SERC4, 0); 3021 snd_cs46xx_pokeBA0(chip, BA0_SERC5, 0); 3022 snd_cs46xx_pokeBA0(chip, BA0_SERC6, 1); 3023 #endif 3024 3025 mdelay(5); 3026 3027 3028 /* 3029 * Wait for the codec ready signal from the AC97 codec. 3030 */ 3031 timeout = 150; 3032 while (timeout-- > 0) { 3033 /* 3034 * Read the AC97 status register to see if we've seen a CODEC READY 3035 * signal from the AC97 codec. 3036 */ 3037 if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY) 3038 goto ok1; 3039 msleep(10); 3040 } 3041 3042 3043 snd_printk(KERN_ERR "create - never read codec ready from AC'97\n"); 3044 snd_printk(KERN_ERR "it is not probably bug, try to use CS4236 driver\n"); 3045 return -EIO; 3046 ok1: 3047 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3048 { 3049 int count; 3050 for (count = 0; count < 150; count++) { 3051 /* First, we want to wait for a short time. */ 3052 udelay(25); 3053 3054 if (snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY) 3055 break; 3056 } 3057 3058 /* 3059 * Make sure CODEC is READY. 3060 */ 3061 if (!(snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY)) 3062 snd_printdd("cs46xx: never read card ready from secondary AC'97\n"); 3063 } 3064 #endif 3065 3066 /* 3067 * Assert the vaid frame signal so that we can start sending commands 3068 * to the AC97 codec. 3069 */ 3070 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); 3071 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3072 snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); 3073 #endif 3074 3075 3076 /* 3077 * Wait until we've sampled input slots 3 and 4 as valid, meaning that 3078 * the codec is pumping ADC data across the AC-link. 3079 */ 3080 timeout = 150; 3081 while (timeout-- > 0) { 3082 /* 3083 * Read the input slot valid register and see if input slots 3 and 3084 * 4 are valid yet. 3085 */ 3086 if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) 3087 goto ok2; 3088 msleep(10); 3089 } 3148 3090 3149 3091 #ifndef CONFIG_SND_CS46XX_NEW_DSP 3150 snd_printk("create - never read ISV3 & ISV4 from AC'97\n");3151 return -EIO;3092 snd_printk(KERN_ERR "create - never read ISV3 & ISV4 from AC'97\n"); 3093 return -EIO; 3152 3094 #else 3153 /* This may happen on a cold boot with a Terratec SiXPack 5.1.3154 Reloading the driver may help, if there's other soundcards 3155 with the same problem I would like to know. (Benny) */3156 3157 snd_printk("ERROR: snd-cs46xx: never read ISV3 & ISV4 from AC'97\n");3158 snd_printk(" Try reloading the ALSA driver, if you find something\n");3159 snd_printk( " broken or not working on your soundcard upon\n");3160 snd_printk(" this message please report to alsa-devel@lists.sourceforge.net\n");3161 3162 return -EIO;3163 #endif 3164 ok2:3165 3166 /*3167 * Now, assert valid frame and the slot 3 and 4 valid bits. This will3168 * commense the transfer of digital audio data to the AC97 codec.3169 */3170 3171 snd_cs46xx_pokeBA0(chip, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);3172 3173 3174 /*3175 * Power down the DAC and ADC. We will power them up (if) when we need3176 * them.3177 */3178 /* snd_cs46xx_pokeBA0(chip, BA0_AC97_POWERDOWN, 0x300); */3179 3180 /*3181 * Turn off the Processor by turning off the software clock enable flag in 3182 * the clock control register.3183 */3184 /* tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE; */3185 /* snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); */3186 3187 return 0;3095 /* This may happen on a cold boot with a Terratec SiXPack 5.1. 3096 Reloading the driver may help, if there's other soundcards 3097 with the same problem I would like to know. (Benny) */ 3098 3099 snd_printk(KERN_ERR "ERROR: snd-cs46xx: never read ISV3 & ISV4 from AC'97\n"); 3100 snd_printk(KERN_ERR " Try reloading the ALSA driver, if you find something\n"); 3101 snd_printk(KERN_ERR " broken or not working on your soundcard upon\n"); 3102 snd_printk(KERN_ERR " this message please report to alsa-devel@lists.sourceforge.net\n"); 3103 3104 return -EIO; 3105 #endif 3106 ok2: 3107 3108 /* 3109 * Now, assert valid frame and the slot 3 and 4 valid bits. This will 3110 * commense the transfer of digital audio data to the AC97 codec. 3111 */ 3112 3113 snd_cs46xx_pokeBA0(chip, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4); 3114 3115 3116 /* 3117 * Power down the DAC and ADC. We will power them up (if) when we need 3118 * them. 3119 */ 3120 /* snd_cs46xx_pokeBA0(chip, BA0_AC97_POWERDOWN, 0x300); */ 3121 3122 /* 3123 * Turn off the Processor by turning off the software clock enable flag in 3124 * the clock control register. 3125 */ 3126 /* tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE; */ 3127 /* snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); */ 3128 3129 return 0; 3188 3130 } 3189 3131 3190 3132 /* 3191 * start and load DSP 3133 * start and load DSP 3192 3134 */ 3193 int __devinit snd_cs46xx_start_dsp( cs46xx_t*chip)3194 { 3195 unsigned int tmp;3196 /*3197 * Reset the processor.3198 */3199 snd_cs46xx_reset(chip);3200 /*3201 * Download the image to the processor.3202 */3135 int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip) 3136 { 3137 unsigned int tmp; 3138 /* 3139 * Reset the processor. 3140 */ 3141 snd_cs46xx_reset(chip); 3142 /* 3143 * Download the image to the processor. 3144 */ 3203 3145 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3204 3146 #if 0 3205 if (cs46xx_dsp_load_module(chip, &cwcemb80_module) < 0) {3206 snd_printk(KERN_ERR "image download error\n");3207 return -EIO;3208 }3209 #endif 3210 3211 if (cs46xx_dsp_load_module(chip, &cwc4630_module) < 0) {3212 snd_printk(KERN_ERR "image download error [cwc4630]\n");3213 return -EIO;3214 }3215 3216 if (cs46xx_dsp_load_module(chip, &cwcasync_module) < 0) {3217 snd_printk(KERN_ERR "image download error [cwcasync]\n");3218 return -EIO;3219 }3220 3221 if (cs46xx_dsp_load_module(chip, &cwcsnoop_module) < 0) {3222 snd_printk(KERN_ERR "image download error [cwcsnoop]\n");3223 return -EIO;3224 }3225 3226 if (cs46xx_dsp_load_module(chip, &cwcbinhack_module) < 0) {3227 snd_printk(KERN_ERR "image download error [cwcbinhack]\n");3228 return -EIO;3229 }3230 3231 if (cs46xx_dsp_load_module(chip, &cwcdma_module) < 0) {3232 snd_printk(KERN_ERR "image download error [cwcdma]\n");3233 return -EIO;3234 }3235 3236 if (cs46xx_dsp_scb_and_task_init(chip) < 0)3237 return -EIO;3147 if (cs46xx_dsp_load_module(chip, &cwcemb80_module) < 0) { 3148 snd_printk(KERN_ERR "image download error\n"); 3149 return -EIO; 3150 } 3151 #endif 3152 3153 if (cs46xx_dsp_load_module(chip, &cwc4630_module) < 0) { 3154 snd_printk(KERN_ERR "image download error [cwc4630]\n"); 3155 return -EIO; 3156 } 3157 3158 if (cs46xx_dsp_load_module(chip, &cwcasync_module) < 0) { 3159 snd_printk(KERN_ERR "image download error [cwcasync]\n"); 3160 return -EIO; 3161 } 3162 3163 if (cs46xx_dsp_load_module(chip, &cwcsnoop_module) < 0) { 3164 snd_printk(KERN_ERR "image download error [cwcsnoop]\n"); 3165 return -EIO; 3166 } 3167 3168 if (cs46xx_dsp_load_module(chip, &cwcbinhack_module) < 0) { 3169 snd_printk(KERN_ERR "image download error [cwcbinhack]\n"); 3170 return -EIO; 3171 } 3172 3173 if (cs46xx_dsp_load_module(chip, &cwcdma_module) < 0) { 3174 snd_printk(KERN_ERR "image download error [cwcdma]\n"); 3175 return -EIO; 3176 } 3177 3178 if (cs46xx_dsp_scb_and_task_init(chip) < 0) 3179 return -EIO; 3238 3180 #else 3239 /* old image */3240 if (snd_cs46xx_download_image(chip) < 0) {3241 snd_printk("image download error\n");3242 return -EIO;3243 }3244 3245 /*3246 * Stop playback DMA.3247 */3248 tmp = snd_cs46xx_peek(chip, BA1_PCTL);3249 chip->play_ctl = tmp & 0xffff0000;3250 snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff);3251 #endif 3252 3253 /*3254 * Stop capture DMA.3255 */3256 tmp = snd_cs46xx_peek(chip, BA1_CCTL);3257 chip->capt.ctl = tmp & 0x0000ffff;3258 snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000);3259 3260 mdelay(5);3261 3262 snd_cs46xx_set_play_sample_rate(chip, 8000);3263 snd_cs46xx_set_capture_sample_rate(chip, 8000);3264 3265 snd_cs46xx_proc_start(chip);3266 3267 /*3268 * Enable interrupts on the part.3269 */3270 snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);3271 3272 tmp = snd_cs46xx_peek(chip, BA1_PFIE);3273 tmp &= ~0x0000f03f;3274 snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt enable */3275 3276 tmp = snd_cs46xx_peek(chip, BA1_CIE);3277 tmp &= ~0x0000003f;3278 tmp |= 0x00000001;3279 snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt enable */3280 3181 /* old image */ 3182 if (snd_cs46xx_download_image(chip) < 0) { 3183 snd_printk(KERN_ERR "image download error\n"); 3184 return -EIO; 3185 } 3186 3187 /* 3188 * Stop playback DMA. 3189 */ 3190 tmp = snd_cs46xx_peek(chip, BA1_PCTL); 3191 chip->play_ctl = tmp & 0xffff0000; 3192 snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff); 3193 #endif 3194 3195 /* 3196 * Stop capture DMA. 3197 */ 3198 tmp = snd_cs46xx_peek(chip, BA1_CCTL); 3199 chip->capt.ctl = tmp & 0x0000ffff; 3200 snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000); 3201 3202 mdelay(5); 3203 3204 snd_cs46xx_set_play_sample_rate(chip, 8000); 3205 snd_cs46xx_set_capture_sample_rate(chip, 8000); 3206 3207 snd_cs46xx_proc_start(chip); 3208 3209 /* 3210 * Enable interrupts on the part. 3211 */ 3212 snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM); 3213 3214 tmp = snd_cs46xx_peek(chip, BA1_PFIE); 3215 tmp &= ~0x0000f03f; 3216 snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt enable */ 3217 3218 tmp = snd_cs46xx_peek(chip, BA1_CIE); 3219 tmp &= ~0x0000003f; 3220 tmp |= 0x00000001; 3221 snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt enable */ 3222 3281 3223 #ifndef CONFIG_SND_CS46XX_NEW_DSP 3282 /* set the attenuation to 0dB */ 3283 snd_cs46xx_poke(chip, BA1_PVOL, 0x80008000);3284 snd_cs46xx_poke(chip, BA1_CVOL, 0x80008000);3285 #endif 3286 3287 return 0;3224 /* set the attenuation to 0dB */ 3225 snd_cs46xx_poke(chip, BA1_PVOL, 0x80008000); 3226 snd_cs46xx_poke(chip, BA1_CVOL, 0x80008000); 3227 #endif 3228 3229 return 0; 3288 3230 } 3289 3231 … … 3292 3234 * AMP control - null AMP 3293 3235 */ 3294 3295 static void amp_none( cs46xx_t*chip, int change)3296 { 3297 } 3298 3299 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3300 static int voyetra_setup_eapd_slot( cs46xx_t*chip)3301 { 3302 3303 u32 idx, valid_slots,tmp,powerdown = 0;3304 u16 modem_power,pin_config,logic_type;3305 3306 snd_printdd ("cs46xx: cs46xx_setup_eapd_slot()+\n");3307 3308 /*3309 * See if the devices are powered down. If so, we must power them up first3310 * or they will not respond.3311 */3312 tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1);3313 3314 if (!(tmp & CLKCR1_SWCE)) {3315 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE);3316 powerdown = 1;3317 }3318 3319 /*3320 * Clear PRA. The Bonzo chip will be used for GPIO not for modem3321 * stuff.3322 */3323 if(chip->nr_ac97_codecs != 2) {3324 snd_printk (KERN_ERR "cs46xx: cs46xx_setup_eapd_slot() - no secondary codec configured\n");3325 return -EINVAL;3326 }3327 3328 modem_power = snd_cs46xx_codec_read (chip, 3329 AC97_EXTENDED_MSTATUS,3330 CS46XX_SECONDARY_CODEC_INDEX);3331 modem_power &=0xFEFF;3332 3333 snd_cs46xx_codec_write(chip, 3334 AC97_EXTENDED_MSTATUS, modem_power,3335 CS46XX_SECONDARY_CODEC_INDEX);3336 3337 /*3338 * Set GPIO pin's 7 and 8 so that they are configured for output.3339 */3340 pin_config = snd_cs46xx_codec_read (chip, 3341 AC97_GPIO_CFG,3342 CS46XX_SECONDARY_CODEC_INDEX);3343 pin_config &=0x27F;3344 3345 snd_cs46xx_codec_write(chip, 3346 AC97_GPIO_CFG, pin_config,3347 CS46XX_SECONDARY_CODEC_INDEX);3348 3349 /*3350 * Set GPIO pin's 7 and 8 so that they are compatible with CMOS logic.3351 */3352 3353 logic_type = snd_cs46xx_codec_read(chip, AC97_GPIO_POLARITY,3354 CS46XX_SECONDARY_CODEC_INDEX);3355 logic_type &=0x27F; 3356 3357 snd_cs46xx_codec_write (chip, AC97_GPIO_POLARITY, logic_type,3358 CS46XX_SECONDARY_CODEC_INDEX);3359 3360 valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV);3361 valid_slots |= 0x200;3362 snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots);3363 3364 if ( cs46xx_wait_for_fifo(chip,1) ) {3365 snd_printdd("FIFO is busy\n");3366 3367 return -EINVAL;3368 }3369 3370 /*3371 * Fill slots 12 with the correct value for the GPIO pins. 3372 */3373 for(idx = 0x90; idx <= 0x9F; idx++) {3374 /*3375 * Initialize the fifo so that bits 7 and 8 are on.3376 *3377 * Remember that the GPIO pins in bonzo are shifted by 4 bits to3378 * the left. 0x1800 corresponds to bits 7 and 8.3379 */3380 snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0x1800);3381 3382 /*3383 * Wait for command to complete3384 */3385 if ( cs46xx_wait_for_fifo(chip,200) ) {3386 snd_printdd("failed waiting for FIFO at addr (%02X)\n",idx);3387 3388 return -EINVAL;3389 }3390 3391 /*3392 * Write the serial port FIFO index.3393 */3394 snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx);3395 3396 /*3397 * Tell the serial port to load the new value into the FIFO location.3398 */3399 snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);3400 }3401 3402 /* wait for last command to complete */3403 cs46xx_wait_for_fifo(chip,200);3404 3405 /*3406 * Now, if we powered up the devices, then power them back down again.3407 * This is kinda ugly, but should never happen.3408 */3409 if (powerdown)3410 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);3411 3412 return 0;3236 3237 static void amp_none(struct snd_cs46xx *chip, int change) 3238 { 3239 } 3240 3241 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3242 static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip) 3243 { 3244 3245 u32 idx, valid_slots,tmp,powerdown = 0; 3246 u16 modem_power,pin_config,logic_type; 3247 3248 snd_printdd ("cs46xx: cs46xx_setup_eapd_slot()+\n"); 3249 3250 /* 3251 * See if the devices are powered down. If so, we must power them up first 3252 * or they will not respond. 3253 */ 3254 tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1); 3255 3256 if (!(tmp & CLKCR1_SWCE)) { 3257 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE); 3258 powerdown = 1; 3259 } 3260 3261 /* 3262 * Clear PRA. The Bonzo chip will be used for GPIO not for modem 3263 * stuff. 3264 */ 3265 if(chip->nr_ac97_codecs != 2) { 3266 snd_printk (KERN_ERR "cs46xx: cs46xx_setup_eapd_slot() - no secondary codec configured\n"); 3267 return -EINVAL; 3268 } 3269 3270 modem_power = snd_cs46xx_codec_read (chip, 3271 AC97_EXTENDED_MSTATUS, 3272 CS46XX_SECONDARY_CODEC_INDEX); 3273 modem_power &=0xFEFF; 3274 3275 snd_cs46xx_codec_write(chip, 3276 AC97_EXTENDED_MSTATUS, modem_power, 3277 CS46XX_SECONDARY_CODEC_INDEX); 3278 3279 /* 3280 * Set GPIO pin's 7 and 8 so that they are configured for output. 3281 */ 3282 pin_config = snd_cs46xx_codec_read (chip, 3283 AC97_GPIO_CFG, 3284 CS46XX_SECONDARY_CODEC_INDEX); 3285 pin_config &=0x27F; 3286 3287 snd_cs46xx_codec_write(chip, 3288 AC97_GPIO_CFG, pin_config, 3289 CS46XX_SECONDARY_CODEC_INDEX); 3290 3291 /* 3292 * Set GPIO pin's 7 and 8 so that they are compatible with CMOS logic. 3293 */ 3294 3295 logic_type = snd_cs46xx_codec_read(chip, AC97_GPIO_POLARITY, 3296 CS46XX_SECONDARY_CODEC_INDEX); 3297 logic_type &=0x27F; 3298 3299 snd_cs46xx_codec_write (chip, AC97_GPIO_POLARITY, logic_type, 3300 CS46XX_SECONDARY_CODEC_INDEX); 3301 3302 valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV); 3303 valid_slots |= 0x200; 3304 snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots); 3305 3306 if ( cs46xx_wait_for_fifo(chip,1) ) { 3307 snd_printdd("FIFO is busy\n"); 3308 3309 return -EINVAL; 3310 } 3311 3312 /* 3313 * Fill slots 12 with the correct value for the GPIO pins. 3314 */ 3315 for(idx = 0x90; idx <= 0x9F; idx++) { 3316 /* 3317 * Initialize the fifo so that bits 7 and 8 are on. 3318 * 3319 * Remember that the GPIO pins in bonzo are shifted by 4 bits to 3320 * the left. 0x1800 corresponds to bits 7 and 8. 3321 */ 3322 snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0x1800); 3323 3324 /* 3325 * Wait for command to complete 3326 */ 3327 if ( cs46xx_wait_for_fifo(chip,200) ) { 3328 snd_printdd("failed waiting for FIFO at addr (%02X)\n",idx); 3329 3330 return -EINVAL; 3331 } 3332 3333 /* 3334 * Write the serial port FIFO index. 3335 */ 3336 snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx); 3337 3338 /* 3339 * Tell the serial port to load the new value into the FIFO location. 3340 */ 3341 snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC); 3342 } 3343 3344 /* wait for last command to complete */ 3345 cs46xx_wait_for_fifo(chip,200); 3346 3347 /* 3348 * Now, if we powered up the devices, then power them back down again. 3349 * This is kinda ugly, but should never happen. 3350 */ 3351 if (powerdown) 3352 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); 3353 3354 return 0; 3413 3355 } 3414 3356 #endif … … 3417 3359 * Crystal EAPD mode 3418 3360 */ 3419 3420 static void amp_voyetra( cs46xx_t*chip, int change)3421 { 3422 /* Manage the EAPD bit on the Crystal 4297 3423 and the Analog AD1885 */3424 3425 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3426 int old = chip->amplifier;3427 #endif 3428 int oval, val;3429 3430 chip->amplifier += change;3431 oval = snd_cs46xx_codec_read(chip, AC97_POWERDOWN,3432 CS46XX_PRIMARY_CODEC_INDEX);3433 val = oval;3434 if (chip->amplifier) {3435 /* Turn the EAPD amp on */3436 val |= 0x8000;3437 } else {3438 /* Turn the EAPD amp off */3439 val &= ~0x8000;3440 }3441 if (val != oval) {3442 snd_cs46xx_codec_write(chip, AC97_POWERDOWN, val,3443 CS46XX_PRIMARY_CODEC_INDEX);3444 if (chip->eapd_switch)3445 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,3446 &chip->eapd_switch->id);3447 }3448 3449 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3450 if (chip->amplifier && !old) {3451 voyetra_setup_eapd_slot(chip);3452 }3453 #endif 3454 } 3455 3456 static void hercules_init( cs46xx_t *chip)3457 { 3458 /* default: AMP off, and SPDIF input optical */3459 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);3460 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);3361 3362 static void amp_voyetra(struct snd_cs46xx *chip, int change) 3363 { 3364 /* Manage the EAPD bit on the Crystal 4297 3365 and the Analog AD1885 */ 3366 3367 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3368 int old = chip->amplifier; 3369 #endif 3370 int oval, val; 3371 3372 chip->amplifier += change; 3373 oval = snd_cs46xx_codec_read(chip, AC97_POWERDOWN, 3374 CS46XX_PRIMARY_CODEC_INDEX); 3375 val = oval; 3376 if (chip->amplifier) { 3377 /* Turn the EAPD amp on */ 3378 val |= 0x8000; 3379 } else { 3380 /* Turn the EAPD amp off */ 3381 val &= ~0x8000; 3382 } 3383 if (val != oval) { 3384 snd_cs46xx_codec_write(chip, AC97_POWERDOWN, val, 3385 CS46XX_PRIMARY_CODEC_INDEX); 3386 if (chip->eapd_switch) 3387 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, 3388 &chip->eapd_switch->id); 3389 } 3390 3391 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3392 if (chip->amplifier && !old) { 3393 voyetra_setup_eapd_slot(chip); 3394 } 3395 #endif 3396 } 3397 3398 static void hercules_init(struct snd_cs46xx *chip) 3399 { 3400 /* default: AMP off, and SPDIF input optical */ 3401 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0); 3402 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0); 3461 3403 } 3462 3404 … … 3464 3406 /* 3465 3407 * Game Theatre XP card - EGPIO[2] is used to enable the external amp. 3466 */ 3467 static void amp_hercules( cs46xx_t*chip, int change)3468 { 3469 int old = chip->amplifier;3470 int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);3471 int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);3472 3473 chip->amplifier += change;3474 if (chip->amplifier && !old) {3475 snd_printdd ("Hercules amplifier ON\n");3476 3477 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, 3478 EGPIODR_GPOE2 | val1); /* enable EGPIO2 output */3479 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, 3480 EGPIOPTR_GPPT2 | val2); /* open-drain on output */3481 } else if (old && !chip->amplifier) {3482 snd_printdd ("Hercules amplifier OFF\n");3483 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, val1 & ~EGPIODR_GPOE2); /* disable */3484 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT2); /* disable */3485 }3486 } 3487 3488 static void voyetra_mixer_init ( cs46xx_t*chip)3489 { 3490 snd_printdd ("initializing Voyetra mixer\n");3491 3492 /* Enable SPDIF out */3493 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);3494 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);3495 } 3496 3497 static void hercules_mixer_init ( cs46xx_t*chip)3498 { 3499 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3500 unsigned int idx;3501 int err;3502 snd_card_t*card = chip->card;3503 #endif 3504 3505 /* set EGPIO to default */3506 hercules_init(chip);3507 3508 snd_printdd ("initializing Hercules mixer\n");3509 3510 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3511 for (idx = 0 ; idx < ARRAY_SIZE(snd_hercules_controls); idx++) {3512 snd_kcontrol_t*kctl;3513 3514 kctl = snd_ctl_new1(&snd_hercules_controls[idx], chip);3515 if ((err = snd_ctl_add(card, kctl)) < 0) {3516 printk (KERN_ERR "cs46xx: failed to initialize Hercules mixer (%d)\n",err);3517 break;3518 }3519 }3408 */ 3409 static void amp_hercules(struct snd_cs46xx *chip, int change) 3410 { 3411 int old = chip->amplifier; 3412 int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR); 3413 int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR); 3414 3415 chip->amplifier += change; 3416 if (chip->amplifier && !old) { 3417 snd_printdd ("Hercules amplifier ON\n"); 3418 3419 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, 3420 EGPIODR_GPOE2 | val1); /* enable EGPIO2 output */ 3421 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, 3422 EGPIOPTR_GPPT2 | val2); /* open-drain on output */ 3423 } else if (old && !chip->amplifier) { 3424 snd_printdd ("Hercules amplifier OFF\n"); 3425 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, val1 & ~EGPIODR_GPOE2); /* disable */ 3426 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT2); /* disable */ 3427 } 3428 } 3429 3430 static void voyetra_mixer_init (struct snd_cs46xx *chip) 3431 { 3432 snd_printdd ("initializing Voyetra mixer\n"); 3433 3434 /* Enable SPDIF out */ 3435 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0); 3436 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0); 3437 } 3438 3439 static void hercules_mixer_init (struct snd_cs46xx *chip) 3440 { 3441 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3442 unsigned int idx; 3443 int err; 3444 struct snd_card *card = chip->card; 3445 #endif 3446 3447 /* set EGPIO to default */ 3448 hercules_init(chip); 3449 3450 snd_printdd ("initializing Hercules mixer\n"); 3451 3452 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3453 for (idx = 0 ; idx < ARRAY_SIZE(snd_hercules_controls); idx++) { 3454 struct snd_kcontrol *kctl; 3455 3456 kctl = snd_ctl_new1(&snd_hercules_controls[idx], chip); 3457 if ((err = snd_ctl_add(card, kctl)) < 0) { 3458 printk (KERN_ERR "cs46xx: failed to initialize Hercules mixer (%d)\n",err); 3459 break; 3460 } 3461 } 3520 3462 #endif 3521 3463 } … … 3526 3468 * Untested 3527 3469 */ 3528 3529 static void amp_voyetra_4294(cs46xx_t *chip, int change) 3530 { 3531 chip->amplifier += change; 3532 3533 if (chip->amplifier) { 3534 /* Switch the GPIO pins 7 and 8 to open drain */ 3535 snd_cs46xx_codec_write(chip, 0x4C, 3536 snd_cs46xx_codec_read(chip, 0x4C) & 0xFE7F); 3537 snd_cs46xx_codec_write(chip, 0x4E, 3538 snd_cs46xx_codec_read(chip, 0x4E) | 0x0180); 3539 /* Now wake the AMP (this might be backwards) */ 3540 snd_cs46xx_codec_write(chip, 0x54, 3541 snd_cs46xx_codec_read(chip, 0x54) & ~0x0180); 3542 } else { 3543 snd_cs46xx_codec_write(chip, 0x54, 3544 snd_cs46xx_codec_read(chip, 0x54) | 0x0180); 3545 } 3546 } 3547 #endif 3548 3549 3550 /* 3551 * piix4 pci ids 3552 */ 3553 #ifndef PCI_VENDOR_ID_INTEL 3554 #define PCI_VENDOR_ID_INTEL 0x8086 3555 #endif /* PCI_VENDOR_ID_INTEL */ 3556 3557 #ifndef PCI_DEVICE_ID_INTEL_82371AB_3 3558 #define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113 3559 #endif /* PCI_DEVICE_ID_INTEL_82371AB_3 */ 3470 3471 static void amp_voyetra_4294(struct snd_cs46xx *chip, int change) 3472 { 3473 chip->amplifier += change; 3474 3475 if (chip->amplifier) { 3476 /* Switch the GPIO pins 7 and 8 to open drain */ 3477 snd_cs46xx_codec_write(chip, 0x4C, 3478 snd_cs46xx_codec_read(chip, 0x4C) & 0xFE7F); 3479 snd_cs46xx_codec_write(chip, 0x4E, 3480 snd_cs46xx_codec_read(chip, 0x4E) | 0x0180); 3481 /* Now wake the AMP (this might be backwards) */ 3482 snd_cs46xx_codec_write(chip, 0x54, 3483 snd_cs46xx_codec_read(chip, 0x54) & ~0x0180); 3484 } else { 3485 snd_cs46xx_codec_write(chip, 0x54, 3486 snd_cs46xx_codec_read(chip, 0x54) | 0x0180); 3487 } 3488 } 3489 #endif 3490 3560 3491 3561 3492 /* … … 3567 3498 * enough to make them useful. 3568 3499 */ 3569 3570 static void clkrun_hack( cs46xx_t*chip, int change)3571 { 3572 u16 control, nval;3573 3574 if (chip->acpi_dev == NULL)3575 return;3576 3577 chip->amplifier += change;3578 3579 /* Read ACPI port */ 3580 nval = control = inw(chip->acpi_port + 0x10);3581 3582 /* Flip CLKRUN off while running */3583 if (! chip->amplifier)3584 nval |= 0x2000;3585 else3586 nval &= ~0x2000;3587 if (nval != control)3588 outw(nval, chip->acpi_port + 0x10);3589 } 3590 3591 3500 3501 static void clkrun_hack(struct snd_cs46xx *chip, int change) 3502 { 3503 u16 control, nval; 3504 3505 if (!chip->acpi_port) 3506 return; 3507 3508 chip->amplifier += change; 3509 3510 /* Read ACPI port */ 3511 nval = control = inw(chip->acpi_port + 0x10); 3512 3513 /* Flip CLKRUN off while running */ 3514 if (! chip->amplifier) 3515 nval |= 0x2000; 3516 else 3517 nval &= ~0x2000; 3518 if (nval != control) 3519 outw(nval, chip->acpi_port + 0x10); 3520 } 3521 3522 3592 3523 /* 3593 3524 * detect intel piix4 3594 3525 */ 3595 static void clkrun_init(cs46xx_t *chip) 3596 { 3597 u8 pp; 3598 3599 chip->acpi_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL); 3600 if (chip->acpi_dev == NULL) 3601 return; /* Not a thinkpad thats for sure */ 3602 3603 /* Find the control port */ 3604 pci_read_config_byte(chip->acpi_dev, 0x41, &pp); 3605 chip->acpi_port = pp << 8; 3526 static void clkrun_init(struct snd_cs46xx *chip) 3527 { 3528 struct pci_dev *pdev; 3529 u8 pp; 3530 3531 chip->acpi_port = 0; 3532 3533 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 3534 PCI_DEVICE_ID_INTEL_82371AB_3, NULL); 3535 if (pdev == NULL) 3536 return; /* Not a thinkpad thats for sure */ 3537 3538 /* Find the control port */ 3539 pci_read_config_byte(pdev, 0x41, &pp); 3540 chip->acpi_port = pp << 8; 3541 pci_dev_put(pdev); 3606 3542 } 3607 3543 … … 3610 3546 * Card subid table 3611 3547 */ 3612 3548 3613 3549 struct cs_card_type 3614 3550 { 3615 u16 vendor;3616 u16 id;3617 char *name;3618 void (*init)(cs46xx_t*);3619 void (*amp)(cs46xx_t*, int);3620 void (*active)(cs46xx_t*, int);3621 void (*mixer_init)(cs46xx_t*);3551 u16 vendor; 3552 u16 id; 3553 char *name; 3554 void (*init)(struct snd_cs46xx *); 3555 void (*amp)(struct snd_cs46xx *, int); 3556 void (*active)(struct snd_cs46xx *, int); 3557 void (*mixer_init)(struct snd_cs46xx *); 3622 3558 }; 3623 3559 3624 static struct cs_card_type __initdata cards[] = { 3625 {0x1489, 0x7001, "Genius Soundmaker 128 value", NULL, NULL, NULL, NULL}, 3626 {0x5053, 0x3357, "Voyetra", NULL, amp_voyetra, NULL, voyetra_mixer_init}, 3627 {0x1071, 0x6003, "Mitac MI6020/21", NULL, amp_voyetra, NULL, NULL}, 3628 {0x14AF, 0x0050, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init}, 3629 {0x1681, 0x0050, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init}, 3630 {0x1681, 0x0051, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init}, 3631 {0x1681, 0x0052, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init}, 3632 {0x1681, 0x0053, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init}, 3633 {0x1681, 0x0054, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init}, 3634 {0x153b, 0x1136, "Terratec SiXPack 5.1", NULL, NULL, NULL, NULL}, 3635 /* Not sure if the 570 needs the clkrun hack */ 3636 {PCI_VENDOR_ID_IBM, 0x0132, "Thinkpad 570", clkrun_init, NULL, clkrun_hack, NULL}, 3637 {PCI_VENDOR_ID_IBM, 0x0153, "Thinkpad 600X/A20/T20", clkrun_init, NULL, clkrun_hack, NULL}, 3638 {PCI_VENDOR_ID_IBM, 0x1010, "Thinkpad 600E (unsupported)", NULL, NULL, NULL, NULL}, 3639 {0, 0, NULL, NULL, NULL, NULL, NULL} 3560 static struct cs_card_type __devinitdata cards[] = { 3561 { 3562 .vendor = 0x1489, 3563 .id = 0x7001, 3564 .name = "Genius Soundmaker 128 value", 3565 /* nothing special */ 3566 }, 3567 { 3568 .vendor = 0x5053, 3569 .id = 0x3357, 3570 .name = "Voyetra", 3571 .amp = amp_voyetra, 3572 .mixer_init = voyetra_mixer_init, 3573 }, 3574 { 3575 .vendor = 0x1071, 3576 .id = 0x6003, 3577 .name = "Mitac MI6020/21", 3578 .amp = amp_voyetra, 3579 }, 3580 { 3581 .vendor = 0x14AF, 3582 .id = 0x0050, 3583 .name = "Hercules Game Theatre XP", 3584 .amp = amp_hercules, 3585 .mixer_init = hercules_mixer_init, 3586 }, 3587 { 3588 .vendor = 0x1681, 3589 .id = 0x0050, 3590 .name = "Hercules Game Theatre XP", 3591 .amp = amp_hercules, 3592 .mixer_init = hercules_mixer_init, 3593 }, 3594 { 3595 .vendor = 0x1681, 3596 .id = 0x0051, 3597 .name = "Hercules Game Theatre XP", 3598 .amp = amp_hercules, 3599 .mixer_init = hercules_mixer_init, 3600 3601 }, 3602 { 3603 .vendor = 0x1681, 3604 .id = 0x0052, 3605 .name = "Hercules Game Theatre XP", 3606 .amp = amp_hercules, 3607 .mixer_init = hercules_mixer_init, 3608 }, 3609 { 3610 .vendor = 0x1681, 3611 .id = 0x0053, 3612 .name = "Hercules Game Theatre XP", 3613 .amp = amp_hercules, 3614 .mixer_init = hercules_mixer_init, 3615 }, 3616 { 3617 .vendor = 0x1681, 3618 .id = 0x0054, 3619 .name = "Hercules Game Theatre XP", 3620 .amp = amp_hercules, 3621 .mixer_init = hercules_mixer_init, 3622 }, 3623 /* Teratec */ 3624 { 3625 .vendor = 0x153b, 3626 .id = 0x1136, 3627 .name = "Terratec SiXPack 5.1", 3628 }, 3629 /* Not sure if the 570 needs the clkrun hack */ 3630 { 3631 .vendor = PCI_VENDOR_ID_IBM, 3632 .id = 0x0132, 3633 .name = "Thinkpad 570", 3634 .init = clkrun_init, 3635 .active = clkrun_hack, 3636 }, 3637 { 3638 .vendor = PCI_VENDOR_ID_IBM, 3639 .id = 0x0153, 3640 .name = "Thinkpad 600X/A20/T20", 3641 .init = clkrun_init, 3642 .active = clkrun_hack, 3643 }, 3644 { 3645 .vendor = PCI_VENDOR_ID_IBM, 3646 .id = 0x1010, 3647 .name = "Thinkpad 600E (unsupported)", 3648 }, 3649 {0} /* terminator */ 3640 3650 }; 3641 3651 … … 3645 3655 */ 3646 3656 #ifdef CONFIG_PM 3647 static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state) 3648 { 3649 cs46xx_t *chip = card->pm_private_data; 3650 int amp_saved; 3651 3652 snd_pcm_suspend_all(chip->pcm); 3653 // chip->ac97_powerdown = snd_cs46xx_codec_read(chip, AC97_POWER_CONTROL); 3654 // chip->ac97_general_purpose = snd_cs46xx_codec_read(chip, BA0_AC97_GENERAL_PURPOSE); 3655 3656 snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); 3657 if (chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]) 3658 snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); 3659 3660 amp_saved = chip->amplifier; 3661 /* turn off amp */ 3662 chip->amplifier_ctrl(chip, -chip->amplifier); 3663 snd_cs46xx_hw_stop(chip); 3664 /* disable CLKRUN */ 3665 chip->active_ctrl(chip, -chip->amplifier); 3666 chip->amplifier = amp_saved; /* restore the status */ 3667 pci_disable_device(chip->pci); 3668 return 0; 3669 } 3670 3671 static int snd_cs46xx_resume(snd_card_t *card, unsigned int state) 3672 { 3673 cs46xx_t *chip = card->pm_private_data; 3674 int amp_saved; 3675 3676 pci_enable_device(chip->pci); 3677 pci_set_master(chip->pci); 3678 amp_saved = chip->amplifier; 3679 chip->amplifier = 0; 3680 chip->active_ctrl(chip, 1); /* force to on */ 3681 3682 snd_cs46xx_chip_init(chip); 3657 int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) 3658 { 3659 struct snd_card *card = pci_get_drvdata(pci); 3660 struct snd_cs46xx *chip = card->private_data; 3661 int amp_saved; 3662 3663 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 3664 snd_pcm_suspend_all(chip->pcm); 3665 // chip->ac97_powerdown = snd_cs46xx_codec_read(chip, AC97_POWER_CONTROL); 3666 // chip->ac97_general_purpose = snd_cs46xx_codec_read(chip, BA0_AC97_GENERAL_PURPOSE); 3667 3668 snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); 3669 snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); 3670 3671 amp_saved = chip->amplifier; 3672 /* turn off amp */ 3673 chip->amplifier_ctrl(chip, -chip->amplifier); 3674 snd_cs46xx_hw_stop(chip); 3675 /* disable CLKRUN */ 3676 chip->active_ctrl(chip, -chip->amplifier); 3677 chip->amplifier = amp_saved; /* restore the status */ 3678 pci_disable_device(pci); 3679 pci_save_state(pci); 3680 return 0; 3681 } 3682 3683 int snd_cs46xx_resume(struct pci_dev *pci) 3684 { 3685 struct snd_card *card = pci_get_drvdata(pci); 3686 struct snd_cs46xx *chip = card->private_data; 3687 int amp_saved; 3688 3689 pci_restore_state(pci); 3690 pci_enable_device(pci); 3691 pci_set_master(pci); 3692 amp_saved = chip->amplifier; 3693 chip->amplifier = 0; 3694 chip->active_ctrl(chip, 1); /* force to on */ 3695 3696 snd_cs46xx_chip_init(chip); 3683 3697 3684 3698 #if 0 3685 snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE, 3686 chip->ac97_general_purpose);3687 snd_cs46xx_codec_write(chip, AC97_POWER_CONTROL, 3688 chip->ac97_powerdown);3689 mdelay(10);3690 snd_cs46xx_codec_write(chip, BA0_AC97_POWERDOWN,3691 chip->ac97_powerdown);3692 mdelay(5);3693 #endif 3694 3695 snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);3696 if (chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]) 3697 snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); 3698 3699 if (amp_saved) 3700 chip->amplifier_ctrl(chip, 1); /* turn amp on */ 3701 else 3702 chip->active_ctrl(chip, -1); /* disable CLKRUN */ 3703 chip->amplifier = amp_saved;3704 return 0;3699 snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE, 3700 chip->ac97_general_purpose); 3701 snd_cs46xx_codec_write(chip, AC97_POWER_CONTROL, 3702 chip->ac97_powerdown); 3703 mdelay(10); 3704 snd_cs46xx_codec_write(chip, BA0_AC97_POWERDOWN, 3705 chip->ac97_powerdown); 3706 mdelay(5); 3707 #endif 3708 3709 snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); 3710 snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); 3711 3712 if (amp_saved) 3713 chip->amplifier_ctrl(chip, 1); /* turn amp on */ 3714 else 3715 chip->active_ctrl(chip, -1); /* disable CLKRUN */ 3716 chip->amplifier = amp_saved; 3717 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 3718 return 0; 3705 3719 } 3706 3720 #endif /* CONFIG_PM */ … … 3710 3724 */ 3711 3725 3712 int __devinit snd_cs46xx_create(snd_card_t * card, 3713 struct pci_dev * pci, 3714 int external_amp, int thinkpad, 3715 cs46xx_t ** rchip) 3716 { 3717 cs46xx_t *chip; 3718 int err, idx; 3719 snd_cs46xx_region_t *region; 3720 struct cs_card_type *cp; 3721 u16 ss_card, ss_vendor; 3722 #ifdef TARGET_OS2 3723 static snd_device_ops_t ops = { 3724 snd_cs46xx_dev_free,0,0,0 3725 }; 3726 #else 3727 static snd_device_ops_t ops = { 3728 .dev_free = snd_cs46xx_dev_free, 3729 }; 3730 #endif 3731 *rchip = NULL; 3732 3733 /* enable PCI device */ 3734 if ((err = pci_enable_device(pci)) < 0) 3735 return err; 3736 3737 chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); 3738 if (chip == NULL) 3739 return -ENOMEM; 3740 spin_lock_init(&chip->reg_lock); 3741 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3742 init_MUTEX(&chip->spos_mutex); 3743 #endif 3744 chip->card = card; 3745 chip->pci = pci; 3746 chip->irq = -1; 3747 chip->ba0_addr = pci_resource_start(pci, 0); 3748 chip->ba1_addr = pci_resource_start(pci, 1); 3749 if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 || 3750 chip->ba1_addr == 0 || chip->ba1_addr == (unsigned long)~0) { 3751 snd_printk("wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n", chip->ba0_addr, chip->ba1_addr); 3752 snd_cs46xx_free(chip); 3753 return -ENOMEM; 3754 } 3755 3756 region = &chip->region.name.ba0; 3757 strcpy(region->name, "CS46xx_BA0"); 3758 region->base = chip->ba0_addr; 3759 region->size = CS46XX_BA0_SIZE; 3760 3761 region = &chip->region.name.data0; 3762 strcpy(region->name, "CS46xx_BA1_data0"); 3763 region->base = chip->ba1_addr + BA1_SP_DMEM0; 3764 region->size = CS46XX_BA1_DATA0_SIZE; 3765 3766 region = &chip->region.name.data1; 3767 strcpy(region->name, "CS46xx_BA1_data1"); 3768 region->base = chip->ba1_addr + BA1_SP_DMEM1; 3769 region->size = CS46XX_BA1_DATA1_SIZE; 3770 3771 region = &chip->region.name.pmem; 3772 strcpy(region->name, "CS46xx_BA1_pmem"); 3773 region->base = chip->ba1_addr + BA1_SP_PMEM; 3774 region->size = CS46XX_BA1_PRG_SIZE; 3775 3776 region = &chip->region.name.reg; 3777 strcpy(region->name, "CS46xx_BA1_reg"); 3778 region->base = chip->ba1_addr + BA1_SP_REG; 3779 region->size = CS46XX_BA1_REG_SIZE; 3780 3781 /* set up amp and clkrun hack */ 3782 pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor); 3783 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &ss_card); 3784 3785 for (cp = &cards[0]; cp->name; cp++) { 3786 if (cp->vendor == ss_vendor && cp->id == ss_card) { 3787 snd_printdd ("hack for %s enabled\n", cp->name); 3788 3789 chip->amplifier_ctrl = cp->amp; 3790 chip->active_ctrl = cp->active; 3791 chip->mixer_init = cp->mixer_init; 3792 3793 if (cp->init) 3794 cp->init(chip); 3795 break; 3796 } 3797 } 3798 3799 if (external_amp) { 3800 snd_printk("Crystal EAPD support forced on.\n"); 3801 chip->amplifier_ctrl = amp_voyetra; 3802 } 3803 3804 if (thinkpad) { 3805 snd_printk("Activating CLKRUN hack for Thinkpad.\n"); 3806 chip->active_ctrl = clkrun_hack; 3807 clkrun_init(chip); 3808 } 3809 3810 if (chip->amplifier_ctrl == NULL) 3811 chip->amplifier_ctrl = amp_none; 3812 if (chip->active_ctrl == NULL) 3813 chip->active_ctrl = amp_none; 3814 3815 chip->active_ctrl(chip, 1); /* enable CLKRUN */ 3816 3817 pci_set_master(pci); 3818 3819 for (idx = 0; idx < 5; idx++) { 3820 region = &chip->region.idx[idx]; 3821 if ((region->resource = request_mem_region(region->base, region->size, region->name)) == NULL) { 3822 snd_printk("unable to request memory region 0x%lx-0x%lx\n", region->base, region->base + region->size - 1); 3823 snd_cs46xx_free(chip); 3824 return -EBUSY; 3825 } 3826 (unsigned long)region->remap_addr = (unsigned long) ioremap_nocache(region->base, region->size); 3827 if (region->remap_addr == 0) { 3828 snd_printk("%s ioremap problem\n", region->name); 3829 snd_cs46xx_free(chip); 3830 return -ENOMEM; 3831 } 3832 } 3833 3834 if (request_irq(pci->irq, snd_cs46xx_interrupt, SA_INTERRUPT|SA_SHIRQ, "CS46XX", (void *) chip)) { 3835 snd_printk("unable to grab IRQ %d\n", pci->irq); 3836 snd_cs46xx_free(chip); 3837 return -EBUSY; 3838 } 3839 chip->irq = pci->irq; 3840 3841 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3842 chip->dsp_spos_instance = cs46xx_dsp_spos_create(chip); 3843 if (chip->dsp_spos_instance == NULL) { 3844 snd_cs46xx_free(chip); 3845 return -ENOMEM; 3846 } 3847 #endif 3848 3849 err = snd_cs46xx_chip_init(chip); 3850 if (err < 0) { 3851 snd_cs46xx_free(chip); 3852 return err; 3853 } 3854 3855 snd_cs46xx_proc_init(card, chip); 3856 3857 snd_card_set_pm_callback(card, snd_cs46xx_suspend, snd_cs46xx_resume, chip); 3858 3859 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { 3860 snd_cs46xx_free(chip); 3861 return err; 3862 } 3863 3864 chip->active_ctrl(chip, -1); /* disable CLKRUN */ 3865 3866 *rchip = chip; 3867 return 0; 3868 } 3726 int __devinit snd_cs46xx_create(struct snd_card *card, 3727 struct pci_dev * pci, 3728 int external_amp, int thinkpad, 3729 struct snd_cs46xx ** rchip) 3730 { 3731 struct snd_cs46xx *chip; 3732 int err, idx; 3733 struct snd_cs46xx_region *region; 3734 struct cs_card_type *cp; 3735 u16 ss_card, ss_vendor; 3736 static struct snd_device_ops ops = { 3737 .dev_free = snd_cs46xx_dev_free, 3738 }; 3739 3740 *rchip = NULL; 3741 3742 /* enable PCI device */ 3743 if ((err = pci_enable_device(pci)) < 0) 3744 return err; 3745 3746 chip = (struct snd_cs46xx *)kzalloc(sizeof(*chip), GFP_KERNEL); 3747 if (chip == NULL) { 3748 pci_disable_device(pci); 3749 return -ENOMEM; 3750 } 3751 spin_lock_init(&chip->reg_lock); 3752 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3753 init_MUTEX(&chip->spos_mutex); 3754 #endif 3755 chip->card = card; 3756 chip->pci = pci; 3757 chip->irq = -1; 3758 chip->ba0_addr = pci_resource_start(pci, 0); 3759 chip->ba1_addr = pci_resource_start(pci, 1); 3760 if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 || 3761 chip->ba1_addr == 0 || chip->ba1_addr == (unsigned long)~0) { 3762 snd_printk(KERN_ERR "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n", 3763 chip->ba0_addr, chip->ba1_addr); 3764 snd_cs46xx_free(chip); 3765 return -ENOMEM; 3766 } 3767 3768 region = &chip->region.name.ba0; 3769 strcpy(region->name, "CS46xx_BA0"); 3770 region->base = chip->ba0_addr; 3771 region->size = CS46XX_BA0_SIZE; 3772 3773 region = &chip->region.name.data0; 3774 strcpy(region->name, "CS46xx_BA1_data0"); 3775 region->base = chip->ba1_addr + BA1_SP_DMEM0; 3776 region->size = CS46XX_BA1_DATA0_SIZE; 3777 3778 region = &chip->region.name.data1; 3779 strcpy(region->name, "CS46xx_BA1_data1"); 3780 region->base = chip->ba1_addr + BA1_SP_DMEM1; 3781 region->size = CS46XX_BA1_DATA1_SIZE; 3782 3783 region = &chip->region.name.pmem; 3784 strcpy(region->name, "CS46xx_BA1_pmem"); 3785 region->base = chip->ba1_addr + BA1_SP_PMEM; 3786 region->size = CS46XX_BA1_PRG_SIZE; 3787 3788 region = &chip->region.name.reg; 3789 strcpy(region->name, "CS46xx_BA1_reg"); 3790 region->base = chip->ba1_addr + BA1_SP_REG; 3791 region->size = CS46XX_BA1_REG_SIZE; 3792 3793 /* set up amp and clkrun hack */ 3794 pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor); 3795 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &ss_card); 3796 3797 for (cp = &cards[0]; cp->name; cp++) { 3798 if (cp->vendor == ss_vendor && cp->id == ss_card) { 3799 snd_printdd ("hack for %s enabled\n", cp->name); 3800 3801 chip->amplifier_ctrl = cp->amp; 3802 chip->active_ctrl = cp->active; 3803 chip->mixer_init = cp->mixer_init; 3804 3805 if (cp->init) 3806 cp->init(chip); 3807 break; 3808 } 3809 } 3810 3811 if (external_amp) { 3812 snd_printk(KERN_INFO "Crystal EAPD support forced on.\n"); 3813 chip->amplifier_ctrl = amp_voyetra; 3814 } 3815 3816 if (thinkpad) { 3817 snd_printk(KERN_INFO "Activating CLKRUN hack for Thinkpad.\n"); 3818 chip->active_ctrl = clkrun_hack; 3819 clkrun_init(chip); 3820 } 3821 3822 if (chip->amplifier_ctrl == NULL) 3823 chip->amplifier_ctrl = amp_none; 3824 if (chip->active_ctrl == NULL) 3825 chip->active_ctrl = amp_none; 3826 3827 chip->active_ctrl(chip, 1); /* enable CLKRUN */ 3828 3829 pci_set_master(pci); 3830 3831 for (idx = 0; idx < 5; idx++) { 3832 region = &chip->region.idx[idx]; 3833 if ((region->resource = request_mem_region(region->base, region->size, 3834 region->name)) == NULL) { 3835 snd_printk(KERN_ERR "unable to request memory region 0x%lx-0x%lx\n", 3836 region->base, region->base + region->size - 1); 3837 snd_cs46xx_free(chip); 3838 return -EBUSY; 3839 } 3840 region->remap_addr = ioremap_nocache(region->base, region->size); 3841 if (region->remap_addr == NULL) { 3842 snd_printk(KERN_ERR "%s ioremap problem\n", region->name); 3843 snd_cs46xx_free(chip); 3844 return -ENOMEM; 3845 } 3846 } 3847 3848 if (request_irq(pci->irq, snd_cs46xx_interrupt, SA_INTERRUPT|SA_SHIRQ, 3849 "CS46XX", chip)) { 3850 snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); 3851 snd_cs46xx_free(chip); 3852 return -EBUSY; 3853 } 3854 chip->irq = pci->irq; 3855 3856 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3857 chip->dsp_spos_instance = cs46xx_dsp_spos_create(chip); 3858 if (chip->dsp_spos_instance == NULL) { 3859 snd_cs46xx_free(chip); 3860 return -ENOMEM; 3861 } 3862 #endif 3863 3864 err = snd_cs46xx_chip_init(chip); 3865 if (err < 0) { 3866 snd_cs46xx_free(chip); 3867 return err; 3868 } 3869 3870 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { 3871 snd_cs46xx_free(chip); 3872 return err; 3873 } 3874 3875 snd_cs46xx_proc_init(card, chip); 3876 3877 chip->active_ctrl(chip, -1); /* disable CLKRUN */ 3878 3879 snd_card_set_dev(card, &pci->dev); 3880 3881 *rchip = chip; 3882 return 0; 3883 } -
GPL/trunk/alsa-kernel/pci/cs46xx/cs46xx_lib.h
r33 r34 54 54 #define BA1_MEMORY_COUNT 3 55 55 56 extern snd_pcm_ops_t snd_cs46xx_playback_ops;57 extern snd_pcm_ops_t snd_cs46xx_playback_indirect_ops;58 extern snd_pcm_ops_t snd_cs46xx_capture_ops;59 extern snd_pcm_ops_t snd_cs46xx_capture_indirect_ops;60 extern snd_pcm_ops_t snd_cs46xx_playback_rear_ops;61 extern snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops;62 extern snd_pcm_ops_t snd_cs46xx_playback_iec958_ops;63 extern snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops;64 extern snd_pcm_ops_t snd_cs46xx_playback_clfe_ops;65 extern snd_pcm_ops_t snd_cs46xx_playback_indirect_clfe_ops;66 67 68 56 /* 69 57 * common I/O routines 70 58 */ 71 59 72 static inline void snd_cs46xx_poke( cs46xx_t*chip, unsigned long reg, unsigned int val)60 static inline void snd_cs46xx_poke(struct snd_cs46xx *chip, unsigned long reg, unsigned int val) 73 61 { 74 62 unsigned int bank = reg >> 16; … … 79 67 } 80 68 81 static inline unsigned int snd_cs46xx_peek( cs46xx_t*chip, unsigned long reg)69 static inline unsigned int snd_cs46xx_peek(struct snd_cs46xx *chip, unsigned long reg) 82 70 { 83 71 unsigned int bank = reg >> 16; … … 86 74 } 87 75 88 static inline void snd_cs46xx_pokeBA0( cs46xx_t*chip, unsigned long offset, unsigned int val)76 static inline void snd_cs46xx_pokeBA0(struct snd_cs46xx *chip, unsigned long offset, unsigned int val) 89 77 { 90 78 writel(val, (char*)chip->region.name.ba0.remap_addr + offset); 91 79 } 92 80 93 static inline unsigned int snd_cs46xx_peekBA0( cs46xx_t*chip, unsigned long offset)81 static inline unsigned int snd_cs46xx_peekBA0(struct snd_cs46xx *chip, unsigned long offset) 94 82 { 95 83 return readl((char*)chip->region.name.ba0.remap_addr + offset); 96 84 } 97 85 98 dsp_spos_instance_t * cs46xx_dsp_spos_create (cs46xx_t * chip); 99 void cs46xx_dsp_spos_destroy (cs46xx_t * chip); 100 int cs46xx_dsp_load_module (cs46xx_t * chip,dsp_module_desc_t * module); 101 symbol_entry_t * cs46xx_dsp_lookup_symbol (cs46xx_t * chip,char * symbol_name,int symbol_type); 102 symbol_entry_t * cs46xx_dsp_lookup_symbol_addr (cs46xx_t * chip,u32 address,int symbol_type); 103 int cs46xx_dsp_proc_init (snd_card_t * card, cs46xx_t *chip); 104 int cs46xx_dsp_proc_done (cs46xx_t *chip); 105 int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip); 106 int cs46xx_dsp_async_init (cs46xx_t *chip,dsp_scb_descriptor_t * fg_entry); 107 int snd_cs46xx_download (cs46xx_t *chip,u32 *src,unsigned long offset, 108 unsigned long len); 109 int snd_cs46xx_clear_BA1(cs46xx_t *chip,unsigned long offset,unsigned long len); 110 int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip); 111 int cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip); 112 int cs46xx_dsp_disable_spdif_out (cs46xx_t *chip); 113 int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip); 114 int cs46xx_dsp_disable_spdif_in (cs46xx_t *chip); 115 int cs46xx_dsp_enable_pcm_capture (cs46xx_t *chip); 116 int cs46xx_dsp_disable_pcm_capture (cs46xx_t *chip); 117 int cs46xx_dsp_enable_adc_capture (cs46xx_t *chip); 118 int cs46xx_dsp_disable_adc_capture (cs46xx_t *chip); 119 int cs46xx_poke_via_dsp (cs46xx_t *chip,u32 address,u32 data); 120 dsp_scb_descriptor_t * cs46xx_dsp_create_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest); 121 void cs46xx_dsp_proc_free_scb_desc (dsp_scb_descriptor_t * scb); 122 void cs46xx_dsp_proc_register_scb_desc (cs46xx_t *chip,dsp_scb_descriptor_t * scb); 123 dsp_task_descriptor_t * cs46xx_dsp_create_task_tree (cs46xx_t *chip,char * name, 124 u32 * task_data,u32 dest,int size); 125 dsp_scb_descriptor_t * cs46xx_dsp_create_timing_master_scb (cs46xx_t *chip); 126 dsp_scb_descriptor_t * cs46xx_dsp_create_codec_out_scb(cs46xx_t * chip,char * codec_name, 127 u16 channel_disp,u16 fifo_addr, 128 u16 child_scb_addr, 129 u32 dest, 130 dsp_scb_descriptor_t * parent_scb, 131 int scb_child_type); 132 dsp_scb_descriptor_t * cs46xx_dsp_create_codec_in_scb(cs46xx_t * chip,char * codec_name, 133 u16 channel_disp,u16 fifo_addr, 134 u16 sample_buffer_addr, 135 u32 dest, 136 dsp_scb_descriptor_t * parent_scb, 137 int scb_child_type); 138 void cs46xx_dsp_remove_scb (cs46xx_t *chip,dsp_scb_descriptor_t * scb); 139 dsp_scb_descriptor_t * cs46xx_dsp_create_generic_scb (cs46xx_t *chip,char * name, 140 u32 * scb_data,u32 dest, 141 char * task_entry_name, 142 dsp_scb_descriptor_t * parent_scb, 143 int scb_child_type); 144 dsp_scb_descriptor_t * cs46xx_dsp_create_codec_in_scb(cs46xx_t * chip,char * codec_name, 145 u16 channel_disp,u16 fifo_addr, 146 u16 sample_buffer_addr, 147 u32 dest,dsp_scb_descriptor_t * parent_scb, 148 int scb_child_type); 149 dsp_scb_descriptor_t * cs46xx_dsp_create_pcm_reader_scb(cs46xx_t * chip,char * scb_name, 150 u16 sample_buffer_addr,u32 dest, 151 int virtual_channel,u32 playback_hw_addr, 152 dsp_scb_descriptor_t * parent_scb, 153 int scb_child_type); 154 dsp_scb_descriptor_t * cs46xx_dsp_create_src_task_scb(cs46xx_t * chip,char * scb_name, 155 int sample_rate, 156 u16 src_buffer_addr, 157 u16 src_delay_buffer_addr,u32 dest, 158 dsp_scb_descriptor_t * parent_scb, 159 int scb_child_type, 160 int pass_through); 161 dsp_scb_descriptor_t * cs46xx_dsp_create_mix_only_scb(cs46xx_t * chip,char * scb_name, 162 u16 mix_buffer_addr,u32 dest, 163 dsp_scb_descriptor_t * parent_scb, 164 int scb_child_type); 86 struct dsp_spos_instance *cs46xx_dsp_spos_create (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); 89 struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, 90 int symbol_type); 91 int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip); 92 int cs46xx_dsp_proc_done (struct snd_cs46xx *chip); 93 int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip); 94 int snd_cs46xx_download (struct snd_cs46xx *chip, u32 *src, unsigned long offset, 95 unsigned long len); 96 int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip, unsigned long offset, unsigned long len); 97 int cs46xx_dsp_enable_spdif_out (struct snd_cs46xx *chip); 98 int cs46xx_dsp_enable_spdif_hw (struct snd_cs46xx *chip); 99 int cs46xx_dsp_disable_spdif_out (struct snd_cs46xx *chip); 100 int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip); 101 int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip); 102 int cs46xx_dsp_enable_pcm_capture (struct snd_cs46xx *chip); 103 int cs46xx_dsp_disable_pcm_capture (struct snd_cs46xx *chip); 104 int cs46xx_dsp_enable_adc_capture (struct snd_cs46xx *chip); 105 int cs46xx_dsp_disable_adc_capture (struct snd_cs46xx *chip); 106 int cs46xx_poke_via_dsp (struct snd_cs46xx *chip, u32 address, u32 data); 107 struct dsp_scb_descriptor * cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, 108 u32 * scb_data, u32 dest); 109 void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb); 110 void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip, 111 struct dsp_scb_descriptor * scb); 112 struct dsp_scb_descriptor * cs46xx_dsp_create_timing_master_scb (struct snd_cs46xx *chip); 113 struct dsp_scb_descriptor * 114 cs46xx_dsp_create_codec_out_scb(struct snd_cs46xx * chip, 115 char * codec_name, u16 channel_disp, u16 fifo_addr, 116 u16 child_scb_addr, u32 dest, 117 struct dsp_scb_descriptor * parent_scb, 118 int scb_child_type); 119 struct dsp_scb_descriptor * 120 cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name, 121 u16 channel_disp, u16 fifo_addr, 122 u16 sample_buffer_addr, u32 dest, 123 struct dsp_scb_descriptor * parent_scb, 124 int scb_child_type); 125 void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, 126 struct dsp_scb_descriptor * scb); 127 struct dsp_scb_descriptor * 128 cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name, 129 u16 channel_disp, u16 fifo_addr, 130 u16 sample_buffer_addr, u32 dest, 131 struct dsp_scb_descriptor * parent_scb, 132 int scb_child_type); 133 struct dsp_scb_descriptor * 134 cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name, 135 int sample_rate, u16 src_buffer_addr, 136 u16 src_delay_buffer_addr, u32 dest, 137 struct dsp_scb_descriptor * parent_scb, 138 int scb_child_type, int pass_through); 139 struct dsp_scb_descriptor * 140 cs46xx_dsp_create_mix_only_scb(struct snd_cs46xx * chip, char * scb_name, 141 u16 mix_buffer_addr, u32 dest, 142 struct dsp_scb_descriptor * parent_scb, 143 int scb_child_type); 165 144 166 dsp_scb_descriptor_t * cs46xx_dsp_create_vari_decimate_scb(cs46xx_t * chip,char * scb_name, 167 u16 vari_buffer_addr0, 168 u16 vari_buffer_addr1, 169 u32 dest, 170 dsp_scb_descriptor_t * parent_scb, 171 int scb_child_type); 172 dsp_scb_descriptor_t * cs46xx_dsp_create_pcm_serial_input_scb(cs46xx_t * chip,char * scb_name,u32 dest, 173 dsp_scb_descriptor_t * input_scb, 174 dsp_scb_descriptor_t * parent_scb, 175 int scb_child_type); 176 dsp_scb_descriptor_t * cs46xx_dsp_create_asynch_fg_tx_scb(cs46xx_t * chip,char * scb_name,u32 dest, 177 u16 hfg_scb_address, 178 u16 asynch_buffer_address, 179 dsp_scb_descriptor_t * parent_scb, 180 int scb_child_type); 181 dsp_scb_descriptor_t * cs46xx_dsp_create_asynch_fg_rx_scb(cs46xx_t * chip,char * scb_name,u32 dest, 182 u16 hfg_scb_address, 183 u16 asynch_buffer_address, 184 dsp_scb_descriptor_t * parent_scb, 185 int scb_child_type); 186 dsp_scb_descriptor_t * cs46xx_dsp_create_spio_write_scb(cs46xx_t * chip,char * scb_name,u32 dest, 187 dsp_scb_descriptor_t * parent_scb, 188 int scb_child_type); 189 dsp_scb_descriptor_t * cs46xx_dsp_create_mix_to_ostream_scb(cs46xx_t * chip,char * scb_name, 190 u16 mix_buffer_addr,u16 writeback_spb,u32 dest, 191 dsp_scb_descriptor_t * parent_scb, 192 int scb_child_type); 193 dsp_scb_descriptor_t * cs46xx_dsp_create_output_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest, 194 u16 snoop_buffer_address, 195 dsp_scb_descriptor_t * snoop_scb, 196 dsp_scb_descriptor_t * parent_scb, 197 int scb_child_type); 198 dsp_scb_descriptor_t * cs46xx_dsp_create_magic_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest, 199 u16 snoop_buffer_address, 200 dsp_scb_descriptor_t * snoop_scb, 201 dsp_scb_descriptor_t * parent_scb, 202 int scb_child_type); 203 pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sample_rate, void * private_data, u32 hw_dma_addr, 204 int pcm_channel_id); 205 void cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip, 206 pcm_channel_descriptor_t * pcm_channel); 207 int cs46xx_dsp_pcm_unlink (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel); 208 int cs46xx_dsp_pcm_link (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel); 209 dsp_scb_descriptor_t * cs46xx_add_record_source (cs46xx_t *chip,dsp_scb_descriptor_t * source, 210 u16 addr,char * scb_name); 211 int cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * src); 212 int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src); 213 int cs46xx_iec958_pre_open (cs46xx_t *chip); 214 int cs46xx_iec958_post_close (cs46xx_t *chip); 215 int cs46xx_dsp_pcm_channel_set_period (cs46xx_t * chip, 216 pcm_channel_descriptor_t * pcm_channel, 217 int period_size); 218 int cs46xx_dsp_pcm_ostream_set_period (cs46xx_t * chip, 219 int period_size); 220 int cs46xx_dsp_set_dac_volume (cs46xx_t * chip,u16 left,u16 right); 221 int cs46xx_dsp_set_iec958_volume (cs46xx_t * chip,u16 left,u16 right); 145 struct dsp_scb_descriptor * 146 cs46xx_dsp_create_vari_decimate_scb(struct snd_cs46xx * chip, char * scb_name, 147 u16 vari_buffer_addr0, u16 vari_buffer_addr1, u32 dest, 148 struct dsp_scb_descriptor * parent_scb, 149 int scb_child_type); 150 struct dsp_scb_descriptor * 151 cs46xx_dsp_create_asynch_fg_rx_scb(struct snd_cs46xx * chip, char * scb_name, 152 u32 dest, u16 hfg_scb_address, u16 asynch_buffer_address, 153 struct dsp_scb_descriptor * parent_scb, 154 int scb_child_type); 155 struct dsp_scb_descriptor * 156 cs46xx_dsp_create_spio_write_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, 157 struct dsp_scb_descriptor * parent_scb, 158 int scb_child_type); 159 struct dsp_scb_descriptor * 160 cs46xx_dsp_create_mix_to_ostream_scb(struct snd_cs46xx * chip, char * scb_name, 161 u16 mix_buffer_addr, u16 writeback_spb, u32 dest, 162 struct dsp_scb_descriptor * parent_scb, 163 int scb_child_type); 164 struct dsp_scb_descriptor * 165 cs46xx_dsp_create_magic_snoop_scb(struct snd_cs46xx * chip, char * scb_name, 166 u32 dest, u16 snoop_buffer_address, 167 struct dsp_scb_descriptor * snoop_scb, 168 struct dsp_scb_descriptor * parent_scb, 169 int scb_child_type); 170 struct dsp_pcm_channel_descriptor * 171 cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, u32 sample_rate, 172 void * private_data, u32 hw_dma_addr, 173 int pcm_channel_id); 174 void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip, 175 struct dsp_pcm_channel_descriptor * pcm_channel); 176 int cs46xx_dsp_pcm_unlink (struct snd_cs46xx * chip, 177 struct dsp_pcm_channel_descriptor * pcm_channel); 178 int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip, 179 struct dsp_pcm_channel_descriptor * pcm_channel); 180 struct dsp_scb_descriptor * 181 cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * source, 182 u16 addr, char * scb_name); 183 int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src); 184 int cs46xx_src_link(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src); 185 int cs46xx_iec958_pre_open (struct snd_cs46xx *chip); 186 int cs46xx_iec958_post_close (struct snd_cs46xx *chip); 187 int cs46xx_dsp_pcm_channel_set_period (struct snd_cs46xx * chip, 188 struct dsp_pcm_channel_descriptor * pcm_channel, 189 int period_size); 190 int cs46xx_dsp_pcm_ostream_set_period (struct snd_cs46xx * chip, int period_size); 191 int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right); 192 int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right); 222 193 #endif /* __CS46XX_LIB_H__ */ -
GPL/trunk/alsa-kernel/pci/cs46xx/dsp_spos.c
r33 r34 38 38 #include "dsp_spos.h" 39 39 40 static wide_opcode_t wide_opcodes[] = { 41 WIDE_FOR_BEGIN_LOOP, 42 WIDE_FOR_BEGIN_LOOP2, 43 WIDE_COND_GOTO_ADDR, 44 WIDE_COND_GOTO_CALL, 45 WIDE_TBEQ_COND_GOTO_ADDR, 46 WIDE_TBEQ_COND_CALL_ADDR, 47 WIDE_TBEQ_NCOND_GOTO_ADDR, 48 WIDE_TBEQ_NCOND_CALL_ADDR, 49 WIDE_TBEQ_COND_GOTO1_ADDR, 50 WIDE_TBEQ_COND_CALL1_ADDR, 51 WIDE_TBEQ_NCOND_GOTOI_ADDR, 52 WIDE_TBEQ_NCOND_CALL1_ADDR 40 static int cs46xx_dsp_async_init (struct snd_cs46xx *chip, 41 struct dsp_scb_descriptor * fg_entry); 42 43 static enum wide_opcode wide_opcodes[] = { 44 WIDE_FOR_BEGIN_LOOP, 45 WIDE_FOR_BEGIN_LOOP2, 46 WIDE_COND_GOTO_ADDR, 47 WIDE_COND_GOTO_CALL, 48 WIDE_TBEQ_COND_GOTO_ADDR, 49 WIDE_TBEQ_COND_CALL_ADDR, 50 WIDE_TBEQ_NCOND_GOTO_ADDR, 51 WIDE_TBEQ_NCOND_CALL_ADDR, 52 WIDE_TBEQ_COND_GOTO1_ADDR, 53 WIDE_TBEQ_COND_CALL1_ADDR, 54 WIDE_TBEQ_NCOND_GOTOI_ADDR, 55 WIDE_TBEQ_NCOND_CALL1_ADDR 53 56 }; 54 57 55 static int shadow_and_reallocate_code (cs46xx_t * chip,u32 * data,u32 size, u32 overlay_begin_address) 56 { 57 unsigned int i = 0, j, nreallocated = 0; 58 u32 hival,loval,address; 59 u32 mop_operands,mop_type,wide_op; 60 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 61 62 snd_assert( ((size % 2) == 0), return -EINVAL); 63 64 while (i < size) { 65 loval = data[i++]; 66 hival = data[i++]; 67 68 if (ins->code.offset > 0) { 69 mop_operands = (hival >> 6) & 0x03fff; 70 mop_type = mop_operands >> 10; 71 72 /* check for wide type instruction */ 73 if (mop_type == 0 && 74 (mop_operands & WIDE_LADD_INSTR_MASK) == 0 && 75 (mop_operands & WIDE_INSTR_MASK) != 0) { 76 wide_op = loval & 0x7f; 77 for (j = 0;j < sizeof(wide_opcodes) / sizeof(wide_opcode_t); ++j) { 78 if (wide_opcodes[j] == wide_op) { 79 /* need to reallocate instruction */ 80 address = (hival & 0x00FFF) << 5; 81 address |= loval >> 15; 82 83 snd_printdd("handle_wideop[1]: %05x:%05x addr %04x\n",hival,loval,address); 84 85 if ( !(address & 0x8000) ) { 86 address += (ins->code.offset / 2) - overlay_begin_address; 87 } else { 88 snd_printdd("handle_wideop[1]: ROM symbol not reallocated\n"); 89 } 90 91 hival &= 0xFF000; 92 loval &= 0x07FFF; 93 94 hival |= ( (address >> 5) & 0x00FFF); 95 loval |= ( (address << 15) & 0xF8000); 96 97 address = (hival & 0x00FFF) << 5; 98 address |= loval >> 15; 99 100 snd_printdd("handle_wideop:[2] %05x:%05x addr %04x\n",hival,loval,address); 101 nreallocated ++; 102 } /* wide_opcodes[j] == wide_op */ 103 } /* for */ 104 } /* mod_type == 0 ... */ 105 } /* ins->code.offset > 0 */ 106 107 ins->code.data[ins->code.size++] = loval; 108 ins->code.data[ins->code.size++] = hival; 109 } 110 111 snd_printdd("dsp_spos: %d instructions reallocated\n",nreallocated); 112 return nreallocated; 113 } 114 115 static segment_desc_t * get_segment_desc (dsp_module_desc_t * module, int seg_type) 116 { 117 int i; 118 for (i = 0;i < module->nsegments; ++i) { 119 if (module->segments[i].segment_type == seg_type) { 120 return (module->segments + i); 121 } 122 } 123 124 return NULL; 58 static int shadow_and_reallocate_code (struct snd_cs46xx * chip, u32 * data, u32 size, 59 u32 overlay_begin_address) 60 { 61 unsigned int i = 0, j, nreallocated = 0; 62 u32 hival,loval,address; 63 u32 mop_operands,mop_type,wide_op; 64 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 65 66 snd_assert( ((size % 2) == 0), return -EINVAL); 67 68 while (i < size) { 69 loval = data[i++]; 70 hival = data[i++]; 71 72 if (ins->code.offset > 0) { 73 mop_operands = (hival >> 6) & 0x03fff; 74 mop_type = mop_operands >> 10; 75 76 /* check for wide type instruction */ 77 if (mop_type == 0 && 78 (mop_operands & WIDE_LADD_INSTR_MASK) == 0 && 79 (mop_operands & WIDE_INSTR_MASK) != 0) { 80 wide_op = loval & 0x7f; 81 for (j = 0;j < ARRAY_SIZE(wide_opcodes); ++j) { 82 if (wide_opcodes[j] == wide_op) { 83 /* need to reallocate instruction */ 84 address = (hival & 0x00FFF) << 5; 85 address |= loval >> 15; 86 87 snd_printdd("handle_wideop[1]: %05x:%05x addr %04x\n",hival,loval,address); 88 89 if ( !(address & 0x8000) ) { 90 address += (ins->code.offset / 2) - overlay_begin_address; 91 } else { 92 snd_printdd("handle_wideop[1]: ROM symbol not reallocated\n"); 93 } 94 95 hival &= 0xFF000; 96 loval &= 0x07FFF; 97 98 hival |= ( (address >> 5) & 0x00FFF); 99 loval |= ( (address << 15) & 0xF8000); 100 101 address = (hival & 0x00FFF) << 5; 102 address |= loval >> 15; 103 104 snd_printdd("handle_wideop:[2] %05x:%05x addr %04x\n",hival,loval,address); 105 nreallocated ++; 106 } /* wide_opcodes[j] == wide_op */ 107 } /* for */ 108 } /* mod_type == 0 ... */ 109 } /* ins->code.offset > 0 */ 110 111 ins->code.data[ins->code.size++] = loval; 112 ins->code.data[ins->code.size++] = hival; 113 } 114 115 snd_printdd("dsp_spos: %d instructions reallocated\n",nreallocated); 116 return nreallocated; 117 } 118 119 static struct dsp_segment_desc * get_segment_desc (struct dsp_module_desc * module, int seg_type) 120 { 121 int i; 122 for (i = 0;i < module->nsegments; ++i) { 123 if (module->segments[i].segment_type == seg_type) { 124 return (module->segments + i); 125 } 126 } 127 128 return NULL; 125 129 }; 126 130 127 static int find_free_symbol_index (dsp_spos_instance_t * ins) 128 { 129 int index = ins->symbol_table.nsymbols,i; 130 131 for (i = ins->symbol_table.highest_frag_index; i < ins->symbol_table.nsymbols; ++i) { 132 if (ins->symbol_table.symbols[i].deleted) { 133 index = i; 134 break; 135 } 136 } 137 138 return index; 139 } 140 141 static int add_symbols (cs46xx_t * chip, dsp_module_desc_t * module) 142 { 143 int i; 144 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 145 146 if (module->symbol_table.nsymbols > 0) { 147 if (!strcmp(module->symbol_table.symbols[0].symbol_name, "OVERLAYBEGINADDRESS") && 148 module->symbol_table.symbols[0].symbol_type == SYMBOL_CONSTANT ) { 149 module->overlay_begin_address = module->symbol_table.symbols[0].address; 150 } 151 } 152 153 for (i = 0;i < module->symbol_table.nsymbols; ++i) { 154 if (ins->symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) { 155 snd_printk(KERN_ERR "dsp_spos: symbol table is full\n"); 156 return -ENOMEM; 157 } 158 159 160 if (cs46xx_dsp_lookup_symbol(chip, 161 module->symbol_table.symbols[i].symbol_name, 162 module->symbol_table.symbols[i].symbol_type) == NULL) { 163 164 ins->symbol_table.symbols[ins->symbol_table.nsymbols] = module->symbol_table.symbols[i]; 165 ins->symbol_table.symbols[ins->symbol_table.nsymbols].address += ((ins->code.offset / 2) - module->overlay_begin_address); 166 ins->symbol_table.symbols[ins->symbol_table.nsymbols].module = module; 167 ins->symbol_table.symbols[ins->symbol_table.nsymbols].deleted = 0; 168 169 if (ins->symbol_table.nsymbols > ins->symbol_table.highest_frag_index) 170 ins->symbol_table.highest_frag_index = ins->symbol_table.nsymbols; 171 172 ins->symbol_table.nsymbols++; 173 } else { 174 /* if (0) printk ("dsp_spos: symbol <%s> duplicated, probably nothing wrong with that (Cirrus?)\n", 175 module->symbol_table.symbols[i].symbol_name); */ 176 } 177 } 178 179 return 0; 180 } 181 182 static symbol_entry_t * add_symbol (cs46xx_t * chip, char * symbol_name, u32 address, int type) 183 { 184 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 185 symbol_entry_t * symbol = NULL; 186 int index; 187 188 if (ins->symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) { 189 snd_printk(KERN_ERR "dsp_spos: symbol table is full\n"); 190 return NULL; 191 } 192 193 if (cs46xx_dsp_lookup_symbol(chip, 194 symbol_name, 195 type) != NULL) { 196 snd_printk(KERN_ERR "dsp_spos: symbol <%s> duplicated\n", symbol_name); 197 return NULL; 198 } 199 200 index = find_free_symbol_index (ins); 201 202 strcpy (ins->symbol_table.symbols[index].symbol_name, symbol_name); 203 ins->symbol_table.symbols[index].address = address; 204 ins->symbol_table.symbols[index].symbol_type = type; 205 ins->symbol_table.symbols[index].module = NULL; 206 ins->symbol_table.symbols[index].deleted = 0; 207 symbol = (ins->symbol_table.symbols + index); 208 209 if (index > ins->symbol_table.highest_frag_index) 210 ins->symbol_table.highest_frag_index = index; 211 212 if (index == ins->symbol_table.nsymbols) 213 ins->symbol_table.nsymbols++; /* no frag. in list */ 214 215 return symbol; 216 } 217 218 dsp_spos_instance_t * cs46xx_dsp_spos_create (cs46xx_t * chip) 219 { 220 dsp_spos_instance_t * ins = kmalloc(sizeof(dsp_spos_instance_t), GFP_KERNEL); 221 222 if (ins == NULL) 223 return NULL; 224 memset(ins, 0, sizeof(*ins)); 225 226 /* better to use vmalloc for this big table */ 227 ins->symbol_table.nsymbols = 0; 228 ins->symbol_table.symbols = vmalloc(sizeof(symbol_entry_t) * DSP_MAX_SYMBOLS); 229 ins->symbol_table.highest_frag_index = 0; 230 231 if (ins->symbol_table.symbols == NULL) { 232 cs46xx_dsp_spos_destroy(chip); 233 return NULL; 234 } 235 236 ins->code.offset = 0; 237 ins->code.size = 0; 238 ins->code.data = kmalloc(DSP_CODE_BYTE_SIZE, GFP_KERNEL); 239 240 if (ins->code.data == NULL) { 241 cs46xx_dsp_spos_destroy(chip); 242 return NULL; 243 } 244 245 ins->nscb = 0; 246 ins->ntask = 0; 247 248 ins->nmodules = 0; 249 ins->modules = kmalloc(sizeof(dsp_module_desc_t) * DSP_MAX_MODULES, GFP_KERNEL); 250 251 if (ins->modules == NULL) { 252 cs46xx_dsp_spos_destroy(chip); 253 return NULL; 254 } 255 256 /* default SPDIF input sample rate 257 to 48000 khz */ 258 ins->spdif_in_sample_rate = 48000; 259 260 /* maximize volume */ 261 ins->dac_volume_right = 0x8000; 262 ins->dac_volume_left = 0x8000; 263 ins->spdif_input_volume_right = 0x8000; 264 ins->spdif_input_volume_left = 0x8000; 265 266 /* set left and right validity bits and 267 default channel status */ 268 ins->spdif_csuv_default = 269 ins->spdif_csuv_stream = 270 /* byte 0 */ ((unsigned int)_wrap_all_bits( (SNDRV_PCM_DEFAULT_CON_SPDIF & 0xff)) << 24) | 271 /* byte 1 */ ((unsigned int)_wrap_all_bits( ((SNDRV_PCM_DEFAULT_CON_SPDIF >> 8) & 0xff)) << 16) | 272 /* byte 3 */ (unsigned int)_wrap_all_bits( (SNDRV_PCM_DEFAULT_CON_SPDIF >> 24) & 0xff) | 273 /* left and right validity bits */ (1 << 13) | (1 << 12); 274 275 return ins; 276 } 277 278 void cs46xx_dsp_spos_destroy (cs46xx_t * chip) 279 { 280 int i; 281 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 282 283 snd_assert(ins != NULL, return); 284 285 down(&chip->spos_mutex); 286 for (i = 0; i < ins->nscb; ++i) { 287 if (ins->scbs[i].deleted) continue; 288 289 cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); 290 } 291 292 if (ins->code.data) 293 kfree(ins->code.data); 294 295 if (ins->symbol_table.symbols) 296 vfree(ins->symbol_table.symbols); 297 298 if (ins->modules) 299 kfree(ins->modules); 300 301 kfree(ins); 302 up(&chip->spos_mutex); 303 } 304 305 int cs46xx_dsp_load_module (cs46xx_t * chip, dsp_module_desc_t * module) 306 { 307 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 308 segment_desc_t * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM); 309 segment_desc_t * parameter = get_segment_desc (module,SEGTYPE_SP_PARAMETER); 310 segment_desc_t * sample = get_segment_desc (module,SEGTYPE_SP_SAMPLE); 311 u32 doffset, dsize; 312 313 if (ins->nmodules == DSP_MAX_MODULES - 1) { 314 snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n"); 315 return -ENOMEM; 316 } 317 318 snd_printdd("dsp_spos: loading module %s into DSP\n", module->module_name); 319 320 if (ins->nmodules == 0) { 321 snd_printdd("dsp_spos: clearing parameter area\n"); 322 snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE); 323 } 324 325 if (parameter == NULL) { 326 snd_printdd("dsp_spos: module got no parameter segment\n"); 327 } else { 328 if (ins->nmodules > 0) { 329 snd_printk(KERN_WARNING "dsp_spos: WARNING current parameter data may be overwriten!\n"); 330 } 331 332 doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET); 333 dsize = parameter->size * 4; 334 335 snd_printdd("dsp_spos: downloading parameter data to chip (%08x-%08x)\n", 336 doffset,doffset + dsize); 337 338 if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) { 339 snd_printk(KERN_ERR "dsp_spos: failed to download parameter data to DSP\n"); 340 return -EINVAL; 341 } 342 } 343 344 if (ins->nmodules == 0) { 345 snd_printdd("dsp_spos: clearing sample area\n"); 346 snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE); 347 } 348 349 if (sample == NULL) { 350 snd_printdd("dsp_spos: module got no sample segment\n"); 351 } else { 352 if (ins->nmodules > 0) { 353 snd_printk(KERN_WARNING "dsp_spos: WARNING current sample data may be overwriten\n"); 354 } 355 356 doffset = (sample->offset * 4 + DSP_SAMPLE_BYTE_OFFSET); 357 dsize = sample->size * 4; 358 359 snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n", 360 doffset,doffset + dsize); 361 362 if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) { 363 snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n"); 364 return -EINVAL; 365 } 366 } 367 368 369 if (ins->nmodules == 0) { 370 snd_printdd("dsp_spos: clearing code area\n"); 371 snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE); 372 } 373 374 if (code == NULL) { 375 snd_printdd("dsp_spos: module got no code segment\n"); 376 } else { 377 if (ins->code.offset + code->size > DSP_CODE_BYTE_SIZE) { 378 snd_printk(KERN_ERR "dsp_spos: no space available in DSP\n"); 379 return -ENOMEM; 380 } 381 382 module->load_address = ins->code.offset; 383 module->overlay_begin_address = 0x000; 384 385 /* if module has a code segment it must have 386 symbol table */ 387 snd_assert(module->symbol_table.symbols != NULL ,return -ENOMEM); 388 if (add_symbols(chip,module)) { 389 snd_printk(KERN_ERR "dsp_spos: failed to load symbol table\n"); 390 return -ENOMEM; 391 } 392 393 doffset = (code->offset * 4 + ins->code.offset * 4 + DSP_CODE_BYTE_OFFSET); 394 dsize = code->size * 4; 395 snd_printdd("dsp_spos: downloading code to chip (%08x-%08x)\n", 396 doffset,doffset + dsize); 397 398 module->nfixups = shadow_and_reallocate_code(chip,code->data,code->size,module->overlay_begin_address); 399 400 if (snd_cs46xx_download (chip,(ins->code.data + ins->code.offset),doffset,dsize)) { 401 snd_printk(KERN_ERR "dsp_spos: failed to download code to DSP\n"); 402 return -EINVAL; 403 } 404 405 ins->code.offset += code->size; 406 } 407 408 /* NOTE: module segments and symbol table must be 409 statically allocated. Case that module data is 410 not generated by the ospparser */ 411 ins->modules[ins->nmodules] = *module; 412 ins->nmodules++; 413 414 return 0; 415 } 416 417 symbol_entry_t * cs46xx_dsp_lookup_symbol (cs46xx_t * chip, char * symbol_name, int symbol_type) 418 { 419 int i; 420 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 421 422 for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) { 423 424 if (ins->symbol_table.symbols[i].deleted) 425 continue; 426 427 if (!strcmp(ins->symbol_table.symbols[i].symbol_name,symbol_name) && 428 ins->symbol_table.symbols[i].symbol_type == symbol_type) { 429 return (ins->symbol_table.symbols + i); 430 } 431 } 131 static int find_free_symbol_index (struct dsp_spos_instance * ins) 132 { 133 int index = ins->symbol_table.nsymbols,i; 134 135 for (i = ins->symbol_table.highest_frag_index; i < ins->symbol_table.nsymbols; ++i) { 136 if (ins->symbol_table.symbols[i].deleted) { 137 index = i; 138 break; 139 } 140 } 141 142 return index; 143 } 144 145 static int add_symbols (struct snd_cs46xx * chip, struct dsp_module_desc * module) 146 { 147 int i; 148 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 149 150 if (module->symbol_table.nsymbols > 0) { 151 if (!strcmp(module->symbol_table.symbols[0].symbol_name, "OVERLAYBEGINADDRESS") && 152 module->symbol_table.symbols[0].symbol_type == SYMBOL_CONSTANT ) { 153 module->overlay_begin_address = module->symbol_table.symbols[0].address; 154 } 155 } 156 157 for (i = 0;i < module->symbol_table.nsymbols; ++i) { 158 if (ins->symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) { 159 snd_printk(KERN_ERR "dsp_spos: symbol table is full\n"); 160 return -ENOMEM; 161 } 162 163 164 if (cs46xx_dsp_lookup_symbol(chip, 165 module->symbol_table.symbols[i].symbol_name, 166 module->symbol_table.symbols[i].symbol_type) == NULL) { 167 168 ins->symbol_table.symbols[ins->symbol_table.nsymbols] = module->symbol_table.symbols[i]; 169 ins->symbol_table.symbols[ins->symbol_table.nsymbols].address += ((ins->code.offset / 2) - module->overlay_begin_address); 170 ins->symbol_table.symbols[ins->symbol_table.nsymbols].module = module; 171 ins->symbol_table.symbols[ins->symbol_table.nsymbols].deleted = 0; 172 173 if (ins->symbol_table.nsymbols > ins->symbol_table.highest_frag_index) 174 ins->symbol_table.highest_frag_index = ins->symbol_table.nsymbols; 175 176 ins->symbol_table.nsymbols++; 177 } else { 178 /* if (0) printk ("dsp_spos: symbol <%s> duplicated, probably nothing wrong with that (Cirrus?)\n", 179 module->symbol_table.symbols[i].symbol_name); */ 180 } 181 } 182 183 return 0; 184 } 185 186 static struct dsp_symbol_entry * 187 add_symbol (struct snd_cs46xx * chip, char * symbol_name, u32 address, int type) 188 { 189 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 190 struct dsp_symbol_entry * symbol = NULL; 191 int index; 192 193 if (ins->symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) { 194 snd_printk(KERN_ERR "dsp_spos: symbol table is full\n"); 195 return NULL; 196 } 197 198 if (cs46xx_dsp_lookup_symbol(chip, 199 symbol_name, 200 type) != NULL) { 201 snd_printk(KERN_ERR "dsp_spos: symbol <%s> duplicated\n", symbol_name); 202 return NULL; 203 } 204 205 index = find_free_symbol_index (ins); 206 207 strcpy (ins->symbol_table.symbols[index].symbol_name, symbol_name); 208 ins->symbol_table.symbols[index].address = address; 209 ins->symbol_table.symbols[index].symbol_type = type; 210 ins->symbol_table.symbols[index].module = NULL; 211 ins->symbol_table.symbols[index].deleted = 0; 212 symbol = (ins->symbol_table.symbols + index); 213 214 if (index > ins->symbol_table.highest_frag_index) 215 ins->symbol_table.highest_frag_index = index; 216 217 if (index == ins->symbol_table.nsymbols) 218 ins->symbol_table.nsymbols++; /* no frag. in list */ 219 220 return symbol; 221 } 222 223 struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip) 224 { 225 struct dsp_spos_instance * ins = kzalloc(sizeof(struct dsp_spos_instance), GFP_KERNEL); 226 227 if (ins == NULL) 228 return NULL; 229 230 /* better to use vmalloc for this big table */ 231 ins->symbol_table.nsymbols = 0; 232 ins->symbol_table.symbols = vmalloc(sizeof(struct dsp_symbol_entry) * 233 DSP_MAX_SYMBOLS); 234 ins->symbol_table.highest_frag_index = 0; 235 236 if (ins->symbol_table.symbols == NULL) { 237 cs46xx_dsp_spos_destroy(chip); 238 return NULL; 239 } 240 241 ins->code.offset = 0; 242 ins->code.size = 0; 243 ins->code.data = kmalloc(DSP_CODE_BYTE_SIZE, GFP_KERNEL); 244 245 if (ins->code.data == NULL) { 246 cs46xx_dsp_spos_destroy(chip); 247 return NULL; 248 } 249 250 ins->nscb = 0; 251 ins->ntask = 0; 252 253 ins->nmodules = 0; 254 ins->modules = kmalloc(sizeof(struct dsp_module_desc) * DSP_MAX_MODULES, GFP_KERNEL); 255 256 if (ins->modules == NULL) { 257 cs46xx_dsp_spos_destroy(chip); 258 return NULL; 259 } 260 261 /* default SPDIF input sample rate 262 to 48000 khz */ 263 ins->spdif_in_sample_rate = 48000; 264 265 /* maximize volume */ 266 ins->dac_volume_right = 0x8000; 267 ins->dac_volume_left = 0x8000; 268 ins->spdif_input_volume_right = 0x8000; 269 ins->spdif_input_volume_left = 0x8000; 270 271 /* set left and right validity bits and 272 default channel status */ 273 ins->spdif_csuv_default = 274 ins->spdif_csuv_stream = 275 /* byte 0 */ ((unsigned int)_wrap_all_bits( (SNDRV_PCM_DEFAULT_CON_SPDIF & 0xff)) << 24) | 276 /* byte 1 */ ((unsigned int)_wrap_all_bits( ((SNDRV_PCM_DEFAULT_CON_SPDIF >> 8) & 0xff)) << 16) | 277 /* byte 3 */ (unsigned int)_wrap_all_bits( (SNDRV_PCM_DEFAULT_CON_SPDIF >> 24) & 0xff) | 278 /* left and right validity bits */ (1 << 13) | (1 << 12); 279 280 return ins; 281 } 282 283 void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) 284 { 285 int i; 286 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 287 288 snd_assert(ins != NULL, return); 289 290 down(&chip->spos_mutex); 291 for (i = 0; i < ins->nscb; ++i) { 292 if (ins->scbs[i].deleted) continue; 293 294 cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); 295 } 296 297 kfree(ins->code.data); 298 vfree(ins->symbol_table.symbols); 299 kfree(ins->modules); 300 kfree(ins); 301 up(&chip->spos_mutex); 302 } 303 304 int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module) 305 { 306 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 307 struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM); 308 struct dsp_segment_desc * parameter = get_segment_desc (module,SEGTYPE_SP_PARAMETER); 309 struct dsp_segment_desc * sample = get_segment_desc (module,SEGTYPE_SP_SAMPLE); 310 u32 doffset, dsize; 311 312 if (ins->nmodules == DSP_MAX_MODULES - 1) { 313 snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n"); 314 return -ENOMEM; 315 } 316 317 snd_printdd("dsp_spos: loading module %s into DSP\n", module->module_name); 318 319 if (ins->nmodules == 0) { 320 snd_printdd("dsp_spos: clearing parameter area\n"); 321 snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE); 322 } 323 324 if (parameter == NULL) { 325 snd_printdd("dsp_spos: module got no parameter segment\n"); 326 } else { 327 if (ins->nmodules > 0) { 328 snd_printk(KERN_WARNING "dsp_spos: WARNING current parameter data may be overwriten!\n"); 329 } 330 331 doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET); 332 dsize = parameter->size * 4; 333 334 snd_printdd("dsp_spos: downloading parameter data to chip (%08x-%08x)\n", 335 doffset,doffset + dsize); 336 337 if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) { 338 snd_printk(KERN_ERR "dsp_spos: failed to download parameter data to DSP\n"); 339 return -EINVAL; 340 } 341 } 342 343 if (ins->nmodules == 0) { 344 snd_printdd("dsp_spos: clearing sample area\n"); 345 snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE); 346 } 347 348 if (sample == NULL) { 349 snd_printdd("dsp_spos: module got no sample segment\n"); 350 } else { 351 if (ins->nmodules > 0) { 352 snd_printk(KERN_WARNING "dsp_spos: WARNING current sample data may be overwriten\n"); 353 } 354 355 doffset = (sample->offset * 4 + DSP_SAMPLE_BYTE_OFFSET); 356 dsize = sample->size * 4; 357 358 snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n", 359 doffset,doffset + dsize); 360 361 if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) { 362 snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n"); 363 return -EINVAL; 364 } 365 } 366 367 368 if (ins->nmodules == 0) { 369 snd_printdd("dsp_spos: clearing code area\n"); 370 snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE); 371 } 372 373 if (code == NULL) { 374 snd_printdd("dsp_spos: module got no code segment\n"); 375 } else { 376 if (ins->code.offset + code->size > DSP_CODE_BYTE_SIZE) { 377 snd_printk(KERN_ERR "dsp_spos: no space available in DSP\n"); 378 return -ENOMEM; 379 } 380 381 module->load_address = ins->code.offset; 382 module->overlay_begin_address = 0x000; 383 384 /* if module has a code segment it must have 385 symbol table */ 386 snd_assert(module->symbol_table.symbols != NULL ,return -ENOMEM); 387 if (add_symbols(chip,module)) { 388 snd_printk(KERN_ERR "dsp_spos: failed to load symbol table\n"); 389 return -ENOMEM; 390 } 391 392 doffset = (code->offset * 4 + ins->code.offset * 4 + DSP_CODE_BYTE_OFFSET); 393 dsize = code->size * 4; 394 snd_printdd("dsp_spos: downloading code to chip (%08x-%08x)\n", 395 doffset,doffset + dsize); 396 397 module->nfixups = shadow_and_reallocate_code(chip,code->data,code->size,module->overlay_begin_address); 398 399 if (snd_cs46xx_download (chip,(ins->code.data + ins->code.offset),doffset,dsize)) { 400 snd_printk(KERN_ERR "dsp_spos: failed to download code to DSP\n"); 401 return -EINVAL; 402 } 403 404 ins->code.offset += code->size; 405 } 406 407 /* NOTE: module segments and symbol table must be 408 statically allocated. Case that module data is 409 not generated by the ospparser */ 410 ins->modules[ins->nmodules] = *module; 411 ins->nmodules++; 412 413 return 0; 414 } 415 416 struct dsp_symbol_entry * 417 cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, int symbol_type) 418 { 419 int i; 420 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 421 422 for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) { 423 424 if (ins->symbol_table.symbols[i].deleted) 425 continue; 426 427 if (!strcmp(ins->symbol_table.symbols[i].symbol_name,symbol_name) && 428 ins->symbol_table.symbols[i].symbol_type == symbol_type) { 429 return (ins->symbol_table.symbols + i); 430 } 431 } 432 432 433 433 #if 0 434 printk ("dsp_spos: symbol <%s> type %02x not found\n",435 symbol_name,symbol_type);434 printk ("dsp_spos: symbol <%s> type %02x not found\n", 435 symbol_name,symbol_type); 436 436 #endif 437 437 438 return NULL; 439 } 440 441 442 symbol_entry_t * cs46xx_dsp_lookup_symbol_addr (cs46xx_t * chip, u32 address, int symbol_type) 443 { 444 int i; 445 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 446 447 for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) { 448 449 if (ins->symbol_table.symbols[i].deleted) 450 continue; 451 452 if (ins->symbol_table.symbols[i].address == address && 453 ins->symbol_table.symbols[i].symbol_type == symbol_type) { 454 return (ins->symbol_table.symbols + i); 455 } 456 } 457 458 459 return NULL; 460 } 461 462 463 static void cs46xx_dsp_proc_symbol_table_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer) 464 { 465 cs46xx_t *chip = entry->private_data; 466 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 467 int i; 468 469 snd_iprintf(buffer, "SYMBOLS:\n"); 470 for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) { 471 char *module_str = "system"; 472 473 if (ins->symbol_table.symbols[i].deleted) 474 continue; 475 476 if (ins->symbol_table.symbols[i].module != NULL) { 477 module_str = ins->symbol_table.symbols[i].module->module_name; 478 } 479 480 481 snd_iprintf(buffer, "%04X <%02X> %s [%s]\n", 482 ins->symbol_table.symbols[i].address, 483 ins->symbol_table.symbols[i].symbol_type, 484 ins->symbol_table.symbols[i].symbol_name, 485 module_str); 486 } 487 } 488 489 490 static void cs46xx_dsp_proc_modules_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer) 491 { 492 cs46xx_t *chip = entry->private_data; 493 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 494 int i,j; 495 496 down(&chip->spos_mutex); 497 snd_iprintf(buffer, "MODULES:\n"); 498 for ( i = 0; i < ins->nmodules; ++i ) { 499 snd_iprintf(buffer, "\n%s:\n", ins->modules[i].module_name); 500 snd_iprintf(buffer, " %d symbols\n", ins->modules[i].symbol_table.nsymbols); 501 snd_iprintf(buffer, " %d fixups\n", ins->modules[i].nfixups); 502 503 for (j = 0; j < ins->modules[i].nsegments; ++ j) { 504 segment_desc_t * desc = (ins->modules[i].segments + j); 505 snd_iprintf(buffer, " segment %02x offset %08x size %08x\n", 506 desc->segment_type,desc->offset, desc->size); 507 } 508 } 509 up(&chip->spos_mutex); 510 } 511 512 static void cs46xx_dsp_proc_task_tree_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer) 513 { 514 cs46xx_t *chip = entry->private_data; 515 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 516 int i,j,col; 517 unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; 518 519 down(&chip->spos_mutex); 520 snd_iprintf(buffer, "TASK TREES:\n"); 521 for ( i = 0; i < ins->ntask; ++i) { 522 snd_iprintf(buffer,"\n%04x %s:\n",ins->tasks[i].address,ins->tasks[i].task_name); 523 524 for (col = 0,j = 0;j < ins->tasks[i].size; j++,col++) { 525 u32 val; 526 if (col == 4) { 527 snd_iprintf(buffer,"\n"); 528 col = 0; 529 } 530 val = readl(dst + (ins->tasks[i].address + j) * sizeof(u32)); 531 snd_iprintf(buffer,"%08x ",val); 532 } 533 } 534 535 snd_iprintf(buffer,"\n"); 536 up(&chip->spos_mutex); 537 } 538 539 static void cs46xx_dsp_proc_scb_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer) 540 { 541 cs46xx_t *chip = entry->private_data; 542 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 543 int i; 544 545 down(&chip->spos_mutex); 546 snd_iprintf(buffer, "SCB's:\n"); 547 for ( i = 0; i < ins->nscb; ++i) { 548 if (ins->scbs[i].deleted) 549 continue; 550 snd_iprintf(buffer,"\n%04x %s:\n\n",ins->scbs[i].address,ins->scbs[i].scb_name); 551 552 if (ins->scbs[i].parent_scb_ptr != NULL) { 553 snd_iprintf(buffer,"parent [%s:%04x] ", 554 ins->scbs[i].parent_scb_ptr->scb_name, 555 ins->scbs[i].parent_scb_ptr->address); 556 } else snd_iprintf(buffer,"parent [none] "); 557 558 snd_iprintf(buffer,"sub_list_ptr [%s:%04x]\nnext_scb_ptr [%s:%04x] task_entry [%s:%04x]\n", 559 ins->scbs[i].sub_list_ptr->scb_name, 560 ins->scbs[i].sub_list_ptr->address, 561 ins->scbs[i].next_scb_ptr->scb_name, 562 ins->scbs[i].next_scb_ptr->address, 563 ins->scbs[i].task_entry->symbol_name, 564 ins->scbs[i].task_entry->address); 565 } 566 567 snd_iprintf(buffer,"\n"); 568 up(&chip->spos_mutex); 569 } 570 571 static void cs46xx_dsp_proc_parameter_dump_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer) 572 { 573 cs46xx_t *chip = entry->private_data; 574 /*dsp_spos_instance_t * ins = chip->dsp_spos_instance; */ 575 unsigned int i,col = 0; 576 unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; 577 symbol_entry_t * symbol; 578 579 for (i = 0;i < DSP_PARAMETER_BYTE_SIZE; i += sizeof(u32),col ++) { 580 if (col == 4) { 581 snd_iprintf(buffer,"\n"); 582 col = 0; 583 } 584 585 if ( (symbol = cs46xx_dsp_lookup_symbol_addr (chip,i / sizeof(u32), SYMBOL_PARAMETER)) != NULL) { 586 col = 0; 587 snd_iprintf (buffer,"\n%s:\n",symbol->symbol_name); 588 } 589 590 if (col == 0) { 591 snd_iprintf(buffer, "%04X ", i / (unsigned int)sizeof(u32)); 592 } 593 594 snd_iprintf(buffer,"%08X ",readl(dst + i)); 595 } 596 } 597 598 static void cs46xx_dsp_proc_sample_dump_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer) 599 { 600 cs46xx_t *chip = entry->private_data; 601 int i,col = 0; 602 unsigned long dst = chip->region.idx[2].remap_addr; 603 604 snd_iprintf(buffer,"PCMREADER:\n"); 605 for (i = PCM_READER_BUF1;i < PCM_READER_BUF1 + 0x30; i += sizeof(u32),col ++) { 606 if (col == 4) { 607 snd_iprintf(buffer,"\n"); 608 col = 0; 609 } 610 611 if (col == 0) { 612 snd_iprintf(buffer, "%04X ",i); 613 } 614 615 snd_iprintf(buffer,"%08X ",readl(dst + i)); 616 } 617 618 snd_iprintf(buffer,"\nMIX_SAMPLE_BUF1:\n"); 619 620 col = 0; 621 for (i = MIX_SAMPLE_BUF1;i < MIX_SAMPLE_BUF1 + 0x40; i += sizeof(u32),col ++) { 622 if (col == 4) { 623 snd_iprintf(buffer,"\n"); 624 col = 0; 625 } 626 627 if (col == 0) { 628 snd_iprintf(buffer, "%04X ",i); 629 } 630 631 snd_iprintf(buffer,"%08X ",readl(dst + i)); 632 } 633 634 snd_iprintf(buffer,"\nSRC_TASK_SCB1:\n"); 635 col = 0; 636 for (i = 0x2480 ; i < 0x2480 + 0x40 ; i += sizeof(u32),col ++) { 637 if (col == 4) { 638 snd_iprintf(buffer,"\n"); 639 col = 0; 640 } 641 642 if (col == 0) { 643 snd_iprintf(buffer, "%04X ",i); 644 } 645 646 snd_iprintf(buffer,"%08X ",readl(dst + i)); 647 } 648 649 650 snd_iprintf(buffer,"\nSPDIFO_BUFFER:\n"); 651 col = 0; 652 for (i = SPDIFO_IP_OUTPUT_BUFFER1;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x30; i += sizeof(u32),col ++) { 653 if (col == 4) { 654 snd_iprintf(buffer,"\n"); 655 col = 0; 656 } 657 658 if (col == 0) { 659 snd_iprintf(buffer, "%04X ",i); 660 } 661 662 snd_iprintf(buffer,"%08X ",readl(dst + i)); 663 } 664 665 snd_iprintf(buffer,"\n...\n"); 666 col = 0; 667 668 for (i = SPDIFO_IP_OUTPUT_BUFFER1+0xD0;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x110; i += sizeof(u32),col ++) { 669 if (col == 4) { 670 snd_iprintf(buffer,"\n"); 671 col = 0; 672 } 673 674 if (col == 0) { 675 snd_iprintf(buffer, "%04X ",i); 676 } 677 678 snd_iprintf(buffer,"%08X ",readl(dst + i)); 679 } 680 681 682 snd_iprintf(buffer,"\nOUTPUT_SNOOP:\n"); 683 col = 0; 684 for (i = OUTPUT_SNOOP_BUFFER;i < OUTPUT_SNOOP_BUFFER + 0x40; i += sizeof(u32),col ++) { 685 if (col == 4) { 686 snd_iprintf(buffer,"\n"); 687 col = 0; 688 } 689 690 if (col == 0) { 691 snd_iprintf(buffer, "%04X ",i); 692 } 693 694 snd_iprintf(buffer,"%08X ",readl(dst + i)); 695 } 696 697 snd_iprintf(buffer,"\nCODEC_INPUT_BUF1: \n"); 698 col = 0; 699 for (i = CODEC_INPUT_BUF1;i < CODEC_INPUT_BUF1 + 0x40; i += sizeof(u32),col ++) { 700 if (col == 4) { 701 snd_iprintf(buffer,"\n"); 702 col = 0; 703 } 704 705 if (col == 0) { 706 snd_iprintf(buffer, "%04X ",i); 707 } 708 709 snd_iprintf(buffer,"%08X ",readl(dst + i)); 710 } 438 return NULL; 439 } 440 441 442 static struct dsp_symbol_entry * 443 cs46xx_dsp_lookup_symbol_addr (struct snd_cs46xx * chip, u32 address, int symbol_type) 444 { 445 int i; 446 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 447 448 for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) { 449 450 if (ins->symbol_table.symbols[i].deleted) 451 continue; 452 453 if (ins->symbol_table.symbols[i].address == address && 454 ins->symbol_table.symbols[i].symbol_type == symbol_type) { 455 return (ins->symbol_table.symbols + i); 456 } 457 } 458 459 460 return NULL; 461 } 462 463 464 static void cs46xx_dsp_proc_symbol_table_read (struct snd_info_entry *entry, 465 struct snd_info_buffer *buffer) 466 { 467 struct snd_cs46xx *chip = entry->private_data; 468 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 469 int i; 470 471 snd_iprintf(buffer, "SYMBOLS:\n"); 472 for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) { 473 char *module_str = "system"; 474 475 if (ins->symbol_table.symbols[i].deleted) 476 continue; 477 478 if (ins->symbol_table.symbols[i].module != NULL) { 479 module_str = ins->symbol_table.symbols[i].module->module_name; 480 } 481 482 483 snd_iprintf(buffer, "%04X <%02X> %s [%s]\n", 484 ins->symbol_table.symbols[i].address, 485 ins->symbol_table.symbols[i].symbol_type, 486 ins->symbol_table.symbols[i].symbol_name, 487 module_str); 488 } 489 } 490 491 492 static void cs46xx_dsp_proc_modules_read (struct snd_info_entry *entry, 493 struct snd_info_buffer *buffer) 494 { 495 struct snd_cs46xx *chip = entry->private_data; 496 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 497 int i,j; 498 499 down(&chip->spos_mutex); 500 snd_iprintf(buffer, "MODULES:\n"); 501 for ( i = 0; i < ins->nmodules; ++i ) { 502 snd_iprintf(buffer, "\n%s:\n", ins->modules[i].module_name); 503 snd_iprintf(buffer, " %d symbols\n", ins->modules[i].symbol_table.nsymbols); 504 snd_iprintf(buffer, " %d fixups\n", ins->modules[i].nfixups); 505 506 for (j = 0; j < ins->modules[i].nsegments; ++ j) { 507 struct dsp_segment_desc * desc = (ins->modules[i].segments + j); 508 snd_iprintf(buffer, " segment %02x offset %08x size %08x\n", 509 desc->segment_type,desc->offset, desc->size); 510 } 511 } 512 up(&chip->spos_mutex); 513 } 514 515 static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry, 516 struct snd_info_buffer *buffer) 517 { 518 struct snd_cs46xx *chip = entry->private_data; 519 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 520 int i, j, col; 521 void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; 522 523 down(&chip->spos_mutex); 524 snd_iprintf(buffer, "TASK TREES:\n"); 525 for ( i = 0; i < ins->ntask; ++i) { 526 snd_iprintf(buffer,"\n%04x %s:\n",ins->tasks[i].address,ins->tasks[i].task_name); 527 528 for (col = 0,j = 0;j < ins->tasks[i].size; j++,col++) { 529 u32 val; 530 if (col == 4) { 531 snd_iprintf(buffer,"\n"); 532 col = 0; 533 } 534 val = readl(dst + (ins->tasks[i].address + j) * sizeof(u32)); 535 snd_iprintf(buffer,"%08x ",val); 536 } 537 } 538 539 snd_iprintf(buffer,"\n"); 540 up(&chip->spos_mutex); 541 } 542 543 static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry, 544 struct snd_info_buffer *buffer) 545 { 546 struct snd_cs46xx *chip = entry->private_data; 547 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 548 int i; 549 550 down(&chip->spos_mutex); 551 snd_iprintf(buffer, "SCB's:\n"); 552 for ( i = 0; i < ins->nscb; ++i) { 553 if (ins->scbs[i].deleted) 554 continue; 555 snd_iprintf(buffer,"\n%04x %s:\n\n",ins->scbs[i].address,ins->scbs[i].scb_name); 556 557 if (ins->scbs[i].parent_scb_ptr != NULL) { 558 snd_iprintf(buffer,"parent [%s:%04x] ", 559 ins->scbs[i].parent_scb_ptr->scb_name, 560 ins->scbs[i].parent_scb_ptr->address); 561 } else snd_iprintf(buffer,"parent [none] "); 562 563 snd_iprintf(buffer,"sub_list_ptr [%s:%04x]\nnext_scb_ptr [%s:%04x] task_entry [%s:%04x]\n", 564 ins->scbs[i].sub_list_ptr->scb_name, 565 ins->scbs[i].sub_list_ptr->address, 566 ins->scbs[i].next_scb_ptr->scb_name, 567 ins->scbs[i].next_scb_ptr->address, 568 ins->scbs[i].task_entry->symbol_name, 569 ins->scbs[i].task_entry->address); 570 } 571 572 snd_iprintf(buffer,"\n"); 573 up(&chip->spos_mutex); 574 } 575 576 static void cs46xx_dsp_proc_parameter_dump_read (struct snd_info_entry *entry, 577 struct snd_info_buffer *buffer) 578 { 579 struct snd_cs46xx *chip = entry->private_data; 580 /*struct dsp_spos_instance * ins = chip->dsp_spos_instance; */ 581 unsigned int i, col = 0; 582 void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; 583 struct dsp_symbol_entry * symbol; 584 585 for (i = 0;i < DSP_PARAMETER_BYTE_SIZE; i += sizeof(u32),col ++) { 586 if (col == 4) { 587 snd_iprintf(buffer,"\n"); 588 col = 0; 589 } 590 591 if ( (symbol = cs46xx_dsp_lookup_symbol_addr (chip,i / sizeof(u32), SYMBOL_PARAMETER)) != NULL) { 592 col = 0; 593 snd_iprintf (buffer,"\n%s:\n",symbol->symbol_name); 594 } 595 596 if (col == 0) { 597 snd_iprintf(buffer, "%04X ", i / (unsigned int)sizeof(u32)); 598 } 599 600 snd_iprintf(buffer,"%08X ",readl(dst + i)); 601 } 602 } 603 604 static void cs46xx_dsp_proc_sample_dump_read (struct snd_info_entry *entry, 605 struct snd_info_buffer *buffer) 606 { 607 struct snd_cs46xx *chip = entry->private_data; 608 int i,col = 0; 609 void __iomem *dst = chip->region.idx[2].remap_addr; 610 611 snd_iprintf(buffer,"PCMREADER:\n"); 612 for (i = PCM_READER_BUF1;i < PCM_READER_BUF1 + 0x30; i += sizeof(u32),col ++) { 613 if (col == 4) { 614 snd_iprintf(buffer,"\n"); 615 col = 0; 616 } 617 618 if (col == 0) { 619 snd_iprintf(buffer, "%04X ",i); 620 } 621 622 snd_iprintf(buffer,"%08X ",readl(dst + i)); 623 } 624 625 snd_iprintf(buffer,"\nMIX_SAMPLE_BUF1:\n"); 626 627 col = 0; 628 for (i = MIX_SAMPLE_BUF1;i < MIX_SAMPLE_BUF1 + 0x40; i += sizeof(u32),col ++) { 629 if (col == 4) { 630 snd_iprintf(buffer,"\n"); 631 col = 0; 632 } 633 634 if (col == 0) { 635 snd_iprintf(buffer, "%04X ",i); 636 } 637 638 snd_iprintf(buffer,"%08X ",readl(dst + i)); 639 } 640 641 snd_iprintf(buffer,"\nSRC_TASK_SCB1:\n"); 642 col = 0; 643 for (i = 0x2480 ; i < 0x2480 + 0x40 ; i += sizeof(u32),col ++) { 644 if (col == 4) { 645 snd_iprintf(buffer,"\n"); 646 col = 0; 647 } 648 649 if (col == 0) { 650 snd_iprintf(buffer, "%04X ",i); 651 } 652 653 snd_iprintf(buffer,"%08X ",readl(dst + i)); 654 } 655 656 657 snd_iprintf(buffer,"\nSPDIFO_BUFFER:\n"); 658 col = 0; 659 for (i = SPDIFO_IP_OUTPUT_BUFFER1;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x30; i += sizeof(u32),col ++) { 660 if (col == 4) { 661 snd_iprintf(buffer,"\n"); 662 col = 0; 663 } 664 665 if (col == 0) { 666 snd_iprintf(buffer, "%04X ",i); 667 } 668 669 snd_iprintf(buffer,"%08X ",readl(dst + i)); 670 } 671 672 snd_iprintf(buffer,"\n...\n"); 673 col = 0; 674 675 for (i = SPDIFO_IP_OUTPUT_BUFFER1+0xD0;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x110; i += sizeof(u32),col ++) { 676 if (col == 4) { 677 snd_iprintf(buffer,"\n"); 678 col = 0; 679 } 680 681 if (col == 0) { 682 snd_iprintf(buffer, "%04X ",i); 683 } 684 685 snd_iprintf(buffer,"%08X ",readl(dst + i)); 686 } 687 688 689 snd_iprintf(buffer,"\nOUTPUT_SNOOP:\n"); 690 col = 0; 691 for (i = OUTPUT_SNOOP_BUFFER;i < OUTPUT_SNOOP_BUFFER + 0x40; i += sizeof(u32),col ++) { 692 if (col == 4) { 693 snd_iprintf(buffer,"\n"); 694 col = 0; 695 } 696 697 if (col == 0) { 698 snd_iprintf(buffer, "%04X ",i); 699 } 700 701 snd_iprintf(buffer,"%08X ",readl(dst + i)); 702 } 703 704 snd_iprintf(buffer,"\nCODEC_INPUT_BUF1: \n"); 705 col = 0; 706 for (i = CODEC_INPUT_BUF1;i < CODEC_INPUT_BUF1 + 0x40; i += sizeof(u32),col ++) { 707 if (col == 4) { 708 snd_iprintf(buffer,"\n"); 709 col = 0; 710 } 711 712 if (col == 0) { 713 snd_iprintf(buffer, "%04X ",i); 714 } 715 716 snd_iprintf(buffer,"%08X ",readl(dst + i)); 717 } 711 718 #if 0 712 snd_iprintf(buffer,"\nWRITE_BACK_BUF1: \n");713 col = 0;714 for (i = WRITE_BACK_BUF1;i < WRITE_BACK_BUF1 + 0x40; i += sizeof(u32),col ++) {715 if (col == 4) {716 snd_iprintf(buffer,"\n");717 col = 0;718 }719 720 if (col == 0) {721 snd_iprintf(buffer, "%04X ",i);722 }723 724 snd_iprintf(buffer,"%08X ",readl(dst + i));725 }719 snd_iprintf(buffer,"\nWRITE_BACK_BUF1: \n"); 720 col = 0; 721 for (i = WRITE_BACK_BUF1;i < WRITE_BACK_BUF1 + 0x40; i += sizeof(u32),col ++) { 722 if (col == 4) { 723 snd_iprintf(buffer,"\n"); 724 col = 0; 725 } 726 727 if (col == 0) { 728 snd_iprintf(buffer, "%04X ",i); 729 } 730 731 snd_iprintf(buffer,"%08X ",readl(dst + i)); 732 } 726 733 #endif 727 734 728 snd_iprintf(buffer,"\nSPDIFI_IP_OUTPUT_BUFFER1: \n"); 729 col = 0; 730 for (i = SPDIFI_IP_OUTPUT_BUFFER1;i < SPDIFI_IP_OUTPUT_BUFFER1 + 0x80; i += sizeof(u32),col ++) { 731 if (col == 4) { 732 snd_iprintf(buffer,"\n"); 733 col = 0; 734 } 735 736 if (col == 0) { 737 snd_iprintf(buffer, "%04X ",i); 738 } 739 740 snd_iprintf(buffer,"%08X ",readl(dst + i)); 741 } 742 snd_iprintf(buffer,"\n"); 743 } 744 745 int cs46xx_dsp_proc_init (snd_card_t * card, cs46xx_t *chip) 746 { 747 snd_info_entry_t *entry; 748 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 749 int i; 750 751 ins->snd_card = card; 752 753 if ((entry = snd_info_create_card_entry(card, "dsp", card->proc_root)) != NULL) { 754 entry->content = SNDRV_INFO_CONTENT_TEXT; 755 entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; 756 entry->c.text.read_size = 512; 757 758 if (snd_info_register(entry) < 0) { 759 snd_info_free_entry(entry); 760 entry = NULL; 761 } 762 } 763 764 ins->proc_dsp_dir = entry; 765 766 if (!ins->proc_dsp_dir) 767 return -ENOMEM; 768 769 if ((entry = snd_info_create_card_entry(card, "spos_symbols", ins->proc_dsp_dir)) != NULL) { 770 entry->content = SNDRV_INFO_CONTENT_TEXT; 771 entry->private_data = chip; 772 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 773 entry->c.text.read_size = 512; 774 entry->c.text.read = cs46xx_dsp_proc_symbol_table_read; 775 if (snd_info_register(entry) < 0) { 776 snd_info_free_entry(entry); 777 entry = NULL; 778 } 779 } 780 ins->proc_sym_info_entry = entry; 781 782 if ((entry = snd_info_create_card_entry(card, "spos_modules", ins->proc_dsp_dir)) != NULL) { 783 entry->content = SNDRV_INFO_CONTENT_TEXT; 784 entry->private_data = chip; 785 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 786 entry->c.text.read_size = 512; 787 entry->c.text.read = cs46xx_dsp_proc_modules_read; 788 if (snd_info_register(entry) < 0) { 789 snd_info_free_entry(entry); 790 entry = NULL; 791 } 792 } 793 ins->proc_modules_info_entry = entry; 794 795 if ((entry = snd_info_create_card_entry(card, "parameter", ins->proc_dsp_dir)) != NULL) { 796 entry->content = SNDRV_INFO_CONTENT_TEXT; 797 entry->private_data = chip; 798 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 799 entry->c.text.read_size = 512; 800 entry->c.text.read = cs46xx_dsp_proc_parameter_dump_read; 801 if (snd_info_register(entry) < 0) { 802 snd_info_free_entry(entry); 803 entry = NULL; 804 } 805 } 806 ins->proc_parameter_dump_info_entry = entry; 807 808 if ((entry = snd_info_create_card_entry(card, "sample", ins->proc_dsp_dir)) != NULL) { 809 entry->content = SNDRV_INFO_CONTENT_TEXT; 810 entry->private_data = chip; 811 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 812 entry->c.text.read_size = 512; 813 entry->c.text.read = cs46xx_dsp_proc_sample_dump_read; 814 if (snd_info_register(entry) < 0) { 815 snd_info_free_entry(entry); 816 entry = NULL; 817 } 818 } 819 ins->proc_sample_dump_info_entry = entry; 820 821 if ((entry = snd_info_create_card_entry(card, "task_tree", ins->proc_dsp_dir)) != NULL) { 822 entry->content = SNDRV_INFO_CONTENT_TEXT; 823 entry->private_data = chip; 824 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 825 entry->c.text.read_size = 512; 826 entry->c.text.read = cs46xx_dsp_proc_task_tree_read; 827 if (snd_info_register(entry) < 0) { 828 snd_info_free_entry(entry); 829 entry = NULL; 830 } 831 } 832 ins->proc_task_info_entry = entry; 833 834 if ((entry = snd_info_create_card_entry(card, "scb_info", ins->proc_dsp_dir)) != NULL) { 835 entry->content = SNDRV_INFO_CONTENT_TEXT; 836 entry->private_data = chip; 837 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 838 entry->c.text.read_size = 1024; 839 entry->c.text.read = cs46xx_dsp_proc_scb_read; 840 if (snd_info_register(entry) < 0) { 841 snd_info_free_entry(entry); 842 entry = NULL; 843 } 844 } 845 ins->proc_scb_info_entry = entry; 846 847 down(&chip->spos_mutex); 848 /* register/update SCB's entries on proc */ 849 for (i = 0; i < ins->nscb; ++i) { 850 if (ins->scbs[i].deleted) continue; 851 852 cs46xx_dsp_proc_register_scb_desc (chip, (ins->scbs + i)); 853 } 854 up(&chip->spos_mutex); 855 856 return 0; 857 } 858 859 int cs46xx_dsp_proc_done (cs46xx_t *chip) 860 { 861 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 862 int i; 863 864 if (ins->proc_sym_info_entry) { 865 snd_info_unregister(ins->proc_sym_info_entry); 866 ins->proc_sym_info_entry = NULL; 867 } 868 869 if (ins->proc_modules_info_entry) { 870 snd_info_unregister(ins->proc_modules_info_entry); 871 ins->proc_modules_info_entry = NULL; 872 } 873 874 if (ins->proc_parameter_dump_info_entry) { 875 snd_info_unregister(ins->proc_parameter_dump_info_entry); 876 ins->proc_parameter_dump_info_entry = NULL; 877 } 878 879 if (ins->proc_sample_dump_info_entry) { 880 snd_info_unregister(ins->proc_sample_dump_info_entry); 881 ins->proc_sample_dump_info_entry = NULL; 882 } 883 884 if (ins->proc_scb_info_entry) { 885 snd_info_unregister(ins->proc_scb_info_entry); 886 ins->proc_scb_info_entry = NULL; 887 } 888 889 if (ins->proc_task_info_entry) { 890 snd_info_unregister(ins->proc_task_info_entry); 891 ins->proc_task_info_entry = NULL; 892 } 893 894 down(&chip->spos_mutex); 895 for (i = 0; i < ins->nscb; ++i) { 896 if (ins->scbs[i].deleted) continue; 897 cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); 898 } 899 up(&chip->spos_mutex); 900 901 if (ins->proc_dsp_dir) { 902 snd_info_unregister (ins->proc_dsp_dir); 903 ins->proc_dsp_dir = NULL; 904 } 905 906 return 0; 907 } 908 909 static int debug_tree = 0; 910 static void _dsp_create_task_tree (cs46xx_t *chip,u32 * task_data, u32 dest, int size) 911 { 912 unsigned long spdst = chip->region.idx[1].remap_addr + 913 DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32); 914 int i; 915 916 for (i = 0; i < size; ++i) { 917 if (debug_tree) printk ("addr %08x, val %08x\n",(int)spdst,task_data[i]); 918 writel(task_data[i],spdst); 919 spdst += sizeof(u32); 920 } 921 } 922 923 static int debug_scb = 0; 924 static void _dsp_create_scb (cs46xx_t *chip,u32 * scb_data, u32 dest) 925 { 926 unsigned long spdst = chip->region.idx[1].remap_addr + 927 DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32); 928 int i; 929 930 for (i = 0; i < 0x10; ++i) { 931 if (debug_scb) printk ("addr %08x, val %08x\n",(int)spdst,scb_data[i]); 932 writel(scb_data[i],spdst); 933 spdst += sizeof(u32); 934 } 935 } 936 937 static int find_free_scb_index (dsp_spos_instance_t * ins) 938 { 939 int index = ins->nscb, i; 940 941 for (i = ins->scb_highest_frag_index; i < ins->nscb; ++i) { 942 if (ins->scbs[i].deleted) { 943 index = i; 944 break; 945 } 946 } 947 948 return index; 949 } 950 951 static dsp_scb_descriptor_t * _map_scb (cs46xx_t *chip,char * name,u32 dest) 952 { 953 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 954 dsp_scb_descriptor_t * desc = NULL; 955 int index; 956 957 if (ins->nscb == DSP_MAX_SCB_DESC - 1) { 958 snd_printk(KERN_ERR "dsp_spos: got no place for other SCB\n"); 959 return NULL; 960 } 961 962 index = find_free_scb_index (ins); 963 964 strcpy(ins->scbs[index].scb_name, name); 965 ins->scbs[index].address = dest; 966 ins->scbs[index].index = index; 967 ins->scbs[index].proc_info = NULL; 968 ins->scbs[index].ref_count = 1; 969 ins->scbs[index].deleted = 0; 970 spin_lock_init(&ins->scbs[index].lock); 971 972 desc = (ins->scbs + index); 973 ins->scbs[index].scb_symbol = add_symbol (chip, name, dest, SYMBOL_PARAMETER); 974 975 if (index > ins->scb_highest_frag_index) 976 ins->scb_highest_frag_index = index; 977 978 if (index == ins->nscb) 979 ins->nscb++; 980 981 return desc; 982 } 983 984 static dsp_task_descriptor_t * _map_task_tree (cs46xx_t *chip,char * name,u32 dest,u32 size) 985 { 986 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 987 dsp_task_descriptor_t * desc = NULL; 988 989 if (ins->ntask == DSP_MAX_TASK_DESC - 1) { 990 snd_printk(KERN_ERR "dsp_spos: got no place for other TASK\n"); 991 return NULL; 992 } 993 994 strcpy(ins->tasks[ins->ntask].task_name,name); 995 ins->tasks[ins->ntask].address = dest; 996 ins->tasks[ins->ntask].size = size; 997 998 /* quick find in list */ 999 ins->tasks[ins->ntask].index = ins->ntask; 1000 desc = (ins->tasks + ins->ntask); 1001 ins->ntask++; 1002 1003 add_symbol (chip,name,dest,SYMBOL_PARAMETER); 1004 return desc; 1005 } 1006 1007 dsp_scb_descriptor_t * cs46xx_dsp_create_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest) 1008 { 1009 dsp_scb_descriptor_t * desc; 1010 1011 desc = _map_scb (chip,name,dest); 1012 if (desc) { 1013 _dsp_create_scb(chip,scb_data,dest); 1014 } else { 1015 snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); 1016 } 1017 1018 return desc; 1019 } 1020 1021 1022 dsp_task_descriptor_t * cs46xx_dsp_create_task_tree (cs46xx_t *chip,char * name, u32 * task_data,u32 dest,int size) 1023 { 1024 dsp_task_descriptor_t * desc; 1025 1026 desc = _map_task_tree (chip,name,dest,size); 1027 if (desc) { 1028 _dsp_create_task_tree(chip,task_data,dest,size); 1029 } else { 1030 snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n"); 1031 } 1032 1033 return desc; 1034 } 1035 1036 int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip) 1037 { 1038 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1039 symbol_entry_t * fg_task_tree_header_code; 1040 symbol_entry_t * task_tree_header_code; 1041 symbol_entry_t * task_tree_thread; 1042 symbol_entry_t * null_algorithm; 1043 symbol_entry_t * magic_snoop_task; 1044 1045 dsp_scb_descriptor_t * timing_master_scb; 1046 dsp_scb_descriptor_t * codec_out_scb; 1047 dsp_scb_descriptor_t * codec_in_scb; 1048 dsp_scb_descriptor_t * src_task_scb; 1049 dsp_scb_descriptor_t * master_mix_scb; 1050 dsp_scb_descriptor_t * rear_mix_scb; 1051 dsp_scb_descriptor_t * record_mix_scb; 1052 dsp_scb_descriptor_t * write_back_scb; 1053 dsp_scb_descriptor_t * vari_decimate_scb; 1054 dsp_scb_descriptor_t * rear_codec_out_scb; 1055 dsp_scb_descriptor_t * clfe_codec_out_scb; 1056 dsp_scb_descriptor_t * magic_snoop_scb; 1057 1058 int fifo_addr,fifo_span,valid_slots; 1059 1060 static spos_control_block_t sposcb = { 1061 /* 0 */ HFG_TREE_SCB,HFG_STACK, 1062 /* 1 */ SPOSCB_ADDR,BG_TREE_SCB_ADDR, 1063 /* 2 */ DSP_SPOS_DC,0, 1064 /* 3 */ DSP_SPOS_DC,DSP_SPOS_DC, 1065 /* 4 */ 0,0, 1066 /* 5 */ DSP_SPOS_UU,0, 1067 /* 6 */ FG_TASK_HEADER_ADDR,0, 1068 /* 7 */ 0,0, 1069 /* 8 */ DSP_SPOS_UU,DSP_SPOS_DC, 1070 /* 9 */ 0, 1071 /* A */ 0,HFG_FIRST_EXECUTE_MODE, 1072 /* B */ DSP_SPOS_UU,DSP_SPOS_UU, 1073 /* C */ DSP_SPOS_DC_DC, 1074 /* D */ DSP_SPOS_DC_DC, 1075 /* E */ DSP_SPOS_DC_DC, 1076 /* F */ DSP_SPOS_DC_DC 1077 }; 1078 1079 cs46xx_dsp_create_task_tree(chip, "sposCB", (u32 *)&sposcb, SPOSCB_ADDR, 0x10); 1080 1081 null_algorithm = cs46xx_dsp_lookup_symbol(chip, "NULLALGORITHM", SYMBOL_CODE); 1082 if (null_algorithm == NULL) { 1083 snd_printk(KERN_ERR "dsp_spos: symbol NULLALGORITHM not found\n"); 1084 return -EIO; 1085 } 1086 1087 fg_task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "FGTASKTREEHEADERCODE", SYMBOL_CODE); 1088 if (fg_task_tree_header_code == NULL) { 1089 snd_printk(KERN_ERR "dsp_spos: symbol FGTASKTREEHEADERCODE not found\n"); 1090 return -EIO; 1091 } 1092 1093 task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "TASKTREEHEADERCODE", SYMBOL_CODE); 1094 if (task_tree_header_code == NULL) { 1095 snd_printk(KERN_ERR "dsp_spos: symbol TASKTREEHEADERCODE not found\n"); 1096 return -EIO; 1097 } 1098 1099 task_tree_thread = cs46xx_dsp_lookup_symbol(chip, "TASKTREETHREAD", SYMBOL_CODE); 1100 if (task_tree_thread == NULL) { 1101 snd_printk(KERN_ERR "dsp_spos: symbol TASKTREETHREAD not found\n"); 1102 return -EIO; 1103 } 1104 1105 magic_snoop_task = cs46xx_dsp_lookup_symbol(chip, "MAGICSNOOPTASK", SYMBOL_CODE); 1106 if (magic_snoop_task == NULL) { 1107 snd_printk(KERN_ERR "dsp_spos: symbol MAGICSNOOPTASK not found\n"); 1108 return -EIO; 1109 } 1110 1111 { 1112 /* create the null SCB */ 1113 static generic_scb_t null_scb = { 1114 { 0, 0, 0, 0 }, 1115 { 0, 0, 0, 0, 0 }, 1116 NULL_SCB_ADDR, NULL_SCB_ADDR, 1117 0,0, 1118 0,0,0, 1119 { 1120 0,0, 1121 0,0, 1122 } 1123 }; 1124 1125 null_scb.entry_point = null_algorithm->address; 1126 1127 ins->the_null_scb = cs46xx_dsp_create_scb(chip, "nullSCB", (u32 *)&null_scb, NULL_SCB_ADDR); 1128 ins->the_null_scb->task_entry = null_algorithm; 1129 ins->the_null_scb->sub_list_ptr = ins->the_null_scb; 1130 ins->the_null_scb->next_scb_ptr = ins->the_null_scb; 1131 ins->the_null_scb->parent_scb_ptr = NULL; 1132 cs46xx_dsp_proc_register_scb_desc (chip,ins->the_null_scb); 1133 } 1134 1135 { 1136 /* setup foreground task tree */ 1137 static task_tree_control_block_t fg_task_tree_hdr = { 1138 { FG_TASK_HEADER_ADDR | (DSP_SPOS_DC << 0x10), 1139 DSP_SPOS_DC_DC, 1140 DSP_SPOS_DC_DC, 1141 0x0000,DSP_SPOS_DC, 1142 DSP_SPOS_DC, DSP_SPOS_DC, 1143 DSP_SPOS_DC_DC, 1144 DSP_SPOS_DC_DC, 1145 DSP_SPOS_DC_DC, 1146 DSP_SPOS_DC,DSP_SPOS_DC }, 1147 1148 { 1149 BG_TREE_SCB_ADDR,TIMINGMASTER_SCB_ADDR, 1150 /*fg_task_tree_header_code->address*/0, 1151 FG_TASK_HEADER_ADDR + TCBData, 1152 }, 1153 1154 { 1155 4,0, 1156 1,0, 1157 2,SPOSCB_ADDR + HFGFlags, 1158 0,0, 1159 FG_TASK_HEADER_ADDR + TCBContextBlk,FG_STACK 1160 }, 1161 1162 { 1163 DSP_SPOS_DC,/*task_tree_thread->address*/0, 1164 DSP_SPOS_DC,DSP_SPOS_DC, 1165 DSP_SPOS_DC,DSP_SPOS_DC, 1166 DSP_SPOS_DC,DSP_SPOS_DC, 1167 DSP_SPOS_DC,DSP_SPOS_DC, 1168 DSP_SPOS_DCDC, 1169 DSP_SPOS_UU,1, 1170 DSP_SPOS_DCDC, 1171 DSP_SPOS_DCDC, 1172 DSP_SPOS_DCDC, 1173 DSP_SPOS_DCDC, 1174 DSP_SPOS_DCDC, 1175 DSP_SPOS_DCDC, 1176 DSP_SPOS_DCDC, 1177 DSP_SPOS_DCDC, 1178 DSP_SPOS_DCDC, 1179 DSP_SPOS_DCDC, 1180 DSP_SPOS_DCDC, 1181 DSP_SPOS_DCDC, 1182 DSP_SPOS_DCDC, 1183 DSP_SPOS_DCDC, 1184 DSP_SPOS_DCDC, 1185 DSP_SPOS_DCDC, 1186 DSP_SPOS_DCDC, 1187 DSP_SPOS_DCDC, 1188 DSP_SPOS_DCDC, 1189 DSP_SPOS_DCDC, 1190 DSP_SPOS_DCDC, 1191 DSP_SPOS_DCDC, 1192 DSP_SPOS_DCDC, 1193 DSP_SPOS_DCDC, 1194 DSP_SPOS_DCDC, 1195 DSP_SPOS_DCDC, 1196 DSP_SPOS_DCDC, 1197 DSP_SPOS_DCDC 1198 }, 1199 { 1200 FG_INTERVAL_TIMER_PERIOD,DSP_SPOS_UU, 1201 0,0 1202 } 1203 }; 1204 fg_task_tree_hdr.links.entry_point = fg_task_tree_header_code->address; 1205 fg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address; 1206 cs46xx_dsp_create_task_tree(chip,"FGtaskTreeHdr",(u32 *)&fg_task_tree_hdr,FG_TASK_HEADER_ADDR,0x35); 1207 } 1208 1209 1210 { 1211 /* setup foreground task tree */ 1212 task_tree_control_block_t bg_task_tree_hdr = { 1213 { DSP_SPOS_DC_DC, 1214 DSP_SPOS_DC_DC, 1215 DSP_SPOS_DC_DC, 1216 DSP_SPOS_DC, DSP_SPOS_DC, 1217 DSP_SPOS_DC, DSP_SPOS_DC, 1218 DSP_SPOS_DC_DC, 1219 DSP_SPOS_DC_DC, 1220 DSP_SPOS_DC_DC, 1221 DSP_SPOS_DC,DSP_SPOS_DC }, 1222 1223 { 1224 NULL_SCB_ADDR,NULL_SCB_ADDR, /* Set up the background to do nothing */ 1225 /*task_tree_header_code->address*/0, 1226 BG_TREE_SCB_ADDR + TCBData, 1227 }, 1228 1229 { 1230 9999,0, 1231 0,1, 1232 0,SPOSCB_ADDR + HFGFlags, 1233 0,0, 1234 BG_TREE_SCB_ADDR + TCBContextBlk,BG_STACK 1235 }, 1236 1237 { 1238 DSP_SPOS_DC,/*task_tree_thread->address*/0, 1239 DSP_SPOS_DC,DSP_SPOS_DC, 1240 DSP_SPOS_DC,DSP_SPOS_DC, 1241 DSP_SPOS_DC,DSP_SPOS_DC, 1242 DSP_SPOS_DC,DSP_SPOS_DC, 1243 DSP_SPOS_DCDC, 1244 DSP_SPOS_UU,1, 1245 DSP_SPOS_DCDC, 1246 DSP_SPOS_DCDC, 1247 DSP_SPOS_DCDC, 1248 DSP_SPOS_DCDC, 1249 DSP_SPOS_DCDC, 1250 DSP_SPOS_DCDC, 1251 DSP_SPOS_DCDC, 1252 DSP_SPOS_DCDC, 1253 DSP_SPOS_DCDC, 1254 DSP_SPOS_DCDC, 1255 DSP_SPOS_DCDC, 1256 DSP_SPOS_DCDC, 1257 DSP_SPOS_DCDC, 1258 DSP_SPOS_DCDC, 1259 DSP_SPOS_DCDC, 1260 DSP_SPOS_DCDC, 1261 DSP_SPOS_DCDC, 1262 DSP_SPOS_DCDC, 1263 DSP_SPOS_DCDC, 1264 DSP_SPOS_DCDC, 1265 DSP_SPOS_DCDC, 1266 DSP_SPOS_DCDC, 1267 DSP_SPOS_DCDC, 1268 DSP_SPOS_DCDC, 1269 DSP_SPOS_DCDC, 1270 DSP_SPOS_DCDC, 1271 DSP_SPOS_DCDC, 1272 DSP_SPOS_DCDC 1273 }, 1274 { 1275 BG_INTERVAL_TIMER_PERIOD,DSP_SPOS_UU, 1276 0,0 1277 } 1278 }; 1279 bg_task_tree_hdr.links.entry_point = task_tree_header_code->address; 1280 bg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address; 1281 cs46xx_dsp_create_task_tree(chip,"BGtaskTreeHdr",(u32 *)&bg_task_tree_hdr,BG_TREE_SCB_ADDR,0x35); 1282 } 1283 1284 /* create timing master SCB */ 1285 timing_master_scb = cs46xx_dsp_create_timing_master_scb(chip); 1286 1287 /* create the CODEC output task */ 1288 codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_I",0x0010,0x0000, 1289 MASTERMIX_SCB_ADDR, 1290 CODECOUT_SCB_ADDR,timing_master_scb, 1291 SCB_ON_PARENT_SUBLIST_SCB); 1292 1293 if (!codec_out_scb) goto _fail_end; 1294 /* create the master mix SCB */ 1295 master_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"MasterMixSCB", 1296 MIX_SAMPLE_BUF1,MASTERMIX_SCB_ADDR, 1297 codec_out_scb, 1298 SCB_ON_PARENT_SUBLIST_SCB); 1299 ins->master_mix_scb = master_mix_scb; 1300 1301 if (!master_mix_scb) goto _fail_end; 1302 1303 /* create codec in */ 1304 codec_in_scb = cs46xx_dsp_create_codec_in_scb(chip,"CodecInSCB",0x0010,0x00A0, 1305 CODEC_INPUT_BUF1, 1306 CODECIN_SCB_ADDR,codec_out_scb, 1307 SCB_ON_PARENT_NEXT_SCB); 1308 if (!codec_in_scb) goto _fail_end; 1309 ins->codec_in_scb = codec_in_scb; 1310 1311 /* create write back scb */ 1312 write_back_scb = cs46xx_dsp_create_mix_to_ostream_scb(chip,"WriteBackSCB", 1313 WRITE_BACK_BUF1,WRITE_BACK_SPB, 1314 WRITEBACK_SCB_ADDR, 1315 timing_master_scb, 1316 SCB_ON_PARENT_NEXT_SCB); 1317 if (!write_back_scb) goto _fail_end; 1318 1319 { 1320 mix2_ostream_spb_t mix2_ostream_spb = { 1321 0x00020000, 1322 0x0000ffff 1323 }; 1324 1325 /* dirty hack ... */ 1326 _dsp_create_task_tree (chip,(u32 *)&mix2_ostream_spb,WRITE_BACK_SPB,2); 1327 } 1328 1329 /* input sample converter */ 1330 vari_decimate_scb = cs46xx_dsp_create_vari_decimate_scb(chip,"VariDecimateSCB", 1331 VARI_DECIMATE_BUF0, 1332 VARI_DECIMATE_BUF1, 1333 VARIDECIMATE_SCB_ADDR, 1334 write_back_scb, 1335 SCB_ON_PARENT_SUBLIST_SCB); 1336 if (!vari_decimate_scb) goto _fail_end; 1337 1338 /* create the record mixer SCB */ 1339 record_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RecordMixerSCB", 1340 MIX_SAMPLE_BUF2, 1341 RECORD_MIXER_SCB_ADDR, 1342 vari_decimate_scb, 1343 SCB_ON_PARENT_SUBLIST_SCB); 1344 ins->record_mixer_scb = record_mix_scb; 1345 1346 if (!record_mix_scb) goto _fail_end; 1347 1348 valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV); 1349 1350 // snd_assert (chip->nr_ac97_codecs == 1 || chip->nr_ac97_codecs == 2); 1351 1352 if (chip->nr_ac97_codecs == 1) { 1353 /* output on slot 5 and 11 1354 on primary CODEC */ 1355 fifo_addr = 0x20; 1356 fifo_span = 0x60; 1357 1358 /* enable slot 5 and 11 */ 1359 valid_slots |= ACOSV_SLV5 | ACOSV_SLV11; 1360 } else { 1361 /* output on slot 7 and 8 1362 on secondary CODEC */ 1363 fifo_addr = 0x40; 1364 fifo_span = 0x10; 1365 1366 /* enable slot 7 and 8 */ 1367 valid_slots |= ACOSV_SLV7 | ACOSV_SLV8; 1368 } 1369 /* create CODEC tasklet for rear speakers output*/ 1370 rear_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_Rear",fifo_span,fifo_addr, 1371 REAR_MIXER_SCB_ADDR, 1372 REAR_CODECOUT_SCB_ADDR,codec_in_scb, 1373 SCB_ON_PARENT_NEXT_SCB); 1374 if (!rear_codec_out_scb) goto _fail_end; 1375 1376 1377 /* create the rear PCM channel mixer SCB */ 1378 rear_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RearMixerSCB", 1379 MIX_SAMPLE_BUF3, 1380 REAR_MIXER_SCB_ADDR, 1381 rear_codec_out_scb, 1382 SCB_ON_PARENT_SUBLIST_SCB); 1383 ins->rear_mix_scb = rear_mix_scb; 1384 if (!rear_mix_scb) goto _fail_end; 1385 1386 if (chip->nr_ac97_codecs == 2) { 1387 /* create CODEC tasklet for rear Center/LFE output 1388 slot 6 and 9 on seconadry CODEC */ 1389 clfe_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_CLFE",0x0030,0x0030, 1390 CLFE_MIXER_SCB_ADDR, 1391 CLFE_CODEC_SCB_ADDR, 1392 rear_codec_out_scb, 1393 SCB_ON_PARENT_NEXT_SCB); 1394 if (!clfe_codec_out_scb) goto _fail_end; 1395 1396 1397 /* create the rear PCM channel mixer SCB */ 1398 ins->center_lfe_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"CLFEMixerSCB", 1399 MIX_SAMPLE_BUF4, 1400 CLFE_MIXER_SCB_ADDR, 1401 clfe_codec_out_scb, 1402 SCB_ON_PARENT_SUBLIST_SCB); 1403 if (!ins->center_lfe_mix_scb) goto _fail_end; 1404 1405 /* enable slot 6 and 9 */ 1406 valid_slots |= ACOSV_SLV6 | ACOSV_SLV9; 1407 } else { 1408 clfe_codec_out_scb = rear_codec_out_scb; 1409 ins->center_lfe_mix_scb = rear_mix_scb; 1410 } 1411 1412 /* enable slots depending on CODEC configuration */ 1413 snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots); 1414 1415 /* the magic snooper */ 1416 magic_snoop_scb = cs46xx_dsp_create_magic_snoop_scb (chip,"MagicSnoopSCB_I",OUTPUTSNOOP_SCB_ADDR, 1417 OUTPUT_SNOOP_BUFFER, 1418 codec_out_scb, 1419 clfe_codec_out_scb, 1420 SCB_ON_PARENT_NEXT_SCB); 1421 1422 1423 if (!magic_snoop_scb) goto _fail_end; 1424 ins->ref_snoop_scb = magic_snoop_scb; 1425 1426 /* SP IO access */ 1427 if (!cs46xx_dsp_create_spio_write_scb(chip,"SPIOWriteSCB",SPIOWRITE_SCB_ADDR, 1428 magic_snoop_scb, 1429 SCB_ON_PARENT_NEXT_SCB)) 1430 goto _fail_end; 1431 1432 /* SPDIF input sampel rate converter */ 1433 src_task_scb = cs46xx_dsp_create_src_task_scb(chip,"SrcTaskSCB_SPDIFI", 1434 ins->spdif_in_sample_rate, 1435 SRC_OUTPUT_BUF1, 1436 SRC_DELAY_BUF1,SRCTASK_SCB_ADDR, 1437 master_mix_scb, 1438 SCB_ON_PARENT_SUBLIST_SCB,1); 1439 1440 if (!src_task_scb) goto _fail_end; 1441 cs46xx_src_unlink(chip,src_task_scb); 1442 1443 /* NOTE: when we now how to detect the SPDIF input 1444 sample rate we will use this SRC to adjust it */ 1445 ins->spdif_in_src = src_task_scb; 1446 1447 cs46xx_dsp_async_init(chip,timing_master_scb); 1448 return 0; 1449 1450 _fail_end: 1451 snd_printk(KERN_ERR "dsp_spos: failed to setup SCB's in DSP\n"); 1452 return -EINVAL; 1453 } 1454 1455 int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entry) 1456 { 1457 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1458 symbol_entry_t * s16_async_codec_input_task; 1459 symbol_entry_t * spdifo_task; 1460 symbol_entry_t * spdifi_task; 1461 dsp_scb_descriptor_t * spdifi_scb_desc,* spdifo_scb_desc,* async_codec_scb_desc; 1462 1463 s16_async_codec_input_task = cs46xx_dsp_lookup_symbol(chip, "S16_ASYNCCODECINPUTTASK", SYMBOL_CODE); 1464 if (s16_async_codec_input_task == NULL) { 1465 snd_printk(KERN_ERR "dsp_spos: symbol S16_ASYNCCODECINPUTTASK not found\n"); 1466 return -EIO; 1467 } 1468 spdifo_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFOTASK", SYMBOL_CODE); 1469 if (spdifo_task == NULL) { 1470 snd_printk(KERN_ERR "dsp_spos: symbol SPDIFOTASK not found\n"); 1471 return -EIO; 1472 } 1473 1474 spdifi_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFITASK", SYMBOL_CODE); 1475 if (spdifi_task == NULL) { 1476 snd_printk(KERN_ERR "dsp_spos: symbol SPDIFITASK not found\n"); 1477 return -EIO; 1478 } 1479 1480 { 1481 /* 0xBC0 */ 1482 spdifoscb_t spdifo_scb = { 1483 /* 0 */ DSP_SPOS_UUUU, 1484 { 1485 /* 1 */ 0xb0, 1486 /* 2 */ 0, 1487 /* 3 */ 0, 1488 /* 4 */ 0, 1489 }, 1490 /* NOTE: the SPDIF output task read samples in mono 1491 format, the AsynchFGTxSCB task writes to buffer 1492 in stereo format 1493 */ 1494 /* 5 */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_256, 1495 /* 6 */ ( SPDIFO_IP_OUTPUT_BUFFER1 << 0x10 ) | 0xFFFC, 1496 /* 7 */ 0,0, 1497 /* 8 */ 0, 1498 /* 9 */ FG_TASK_HEADER_ADDR, NULL_SCB_ADDR, 1499 /* A */ /*spdifo_task->address*/0, 1500 SPDIFO_SCB_INST + SPDIFOFIFOPointer, 1501 { 1502 /* B */ 0x0040, /*DSP_SPOS_UUUU,*/ 1503 /* C */ 0x20ff, /*DSP_SPOS_UUUU,*/ 1504 }, 1505 /* D */ 0x804c,0, /* SPDIFOFIFOPointer:SPDIFOStatRegAddr; */ 1506 /* E */ 0x0108,0x0001, /* SPDIFOStMoFormat:SPDIFOFIFOBaseAddr; */ 1507 /* F */ DSP_SPOS_UUUU /* SPDIFOFree; */ 1508 }; 1509 1510 /* 0xBB0 */ 1511 spdifiscb_t spdifi_scb = { 1512 /* 0 */ DSP_SPOS_UULO,DSP_SPOS_UUHI, 1513 /* 1 */ 0, 1514 /* 2 */ 0, 1515 /* 3 */ 1,4000, /* SPDIFICountLimit SPDIFICount */ 1516 /* 4 */ DSP_SPOS_UUUU, /* SPDIFIStatusData */ 1517 /* 5 */ 0,DSP_SPOS_UUHI, /* StatusData, Free4 */ 1518 /* 6 */ DSP_SPOS_UUUU, /* Free3 */ 1519 /* 7 */ DSP_SPOS_UU,DSP_SPOS_DC, /* Free2 BitCount*/ 1520 /* 8 */ DSP_SPOS_UUUU, /* TempStatus */ 1521 /* 9 */ SPDIFO_SCB_INST, NULL_SCB_ADDR, 1522 /* A */ /*spdifi_task->address*/0, 1523 SPDIFI_SCB_INST + SPDIFIFIFOPointer, 1524 /* NOTE: The SPDIF input task write the sample in mono 1525 format from the HW FIFO, the AsynchFGRxSCB task reads 1526 them in stereo 1527 */ 1528 /* B */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_128, 1529 /* C */ (SPDIFI_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC, 1530 /* D */ 0x8048,0, 1531 /* E */ 0x01f0,0x0001, 1532 /* F */ DSP_SPOS_UUUU /* SPDIN_STATUS monitor */ 1533 }; 1534 1535 /* 0xBA0 */ 1536 async_codec_input_scb_t async_codec_input_scb = { 1537 /* 0 */ DSP_SPOS_UUUU, 1538 /* 1 */ 0, 1539 /* 2 */ 0, 1540 /* 3 */ 1,4000, 1541 /* 4 */ 0x0118,0x0001, 1542 /* 5 */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_64, 1543 /* 6 */ (ASYNC_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC, 1544 /* 7 */ DSP_SPOS_UU,0x3, 1545 /* 8 */ DSP_SPOS_UUUU, 1546 /* 9 */ SPDIFI_SCB_INST,NULL_SCB_ADDR, 1547 /* A */ /*s16_async_codec_input_task->address*/0, 1548 HFG_TREE_SCB + AsyncCIOFIFOPointer, 1549 1550 /* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64, 1551 /* C */ (ASYNC_IP_OUTPUT_BUFFER1 << 0x10), /*(ASYNC_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,*/ 1552 735 snd_iprintf(buffer,"\nSPDIFI_IP_OUTPUT_BUFFER1: \n"); 736 col = 0; 737 for (i = SPDIFI_IP_OUTPUT_BUFFER1;i < SPDIFI_IP_OUTPUT_BUFFER1 + 0x80; i += sizeof(u32),col ++) { 738 if (col == 4) { 739 snd_iprintf(buffer,"\n"); 740 col = 0; 741 } 742 743 if (col == 0) { 744 snd_iprintf(buffer, "%04X ",i); 745 } 746 747 snd_iprintf(buffer,"%08X ",readl(dst + i)); 748 } 749 snd_iprintf(buffer,"\n"); 750 } 751 752 int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) 753 { 754 struct snd_info_entry *entry; 755 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 756 int i; 757 758 ins->snd_card = card; 759 760 if ((entry = snd_info_create_card_entry(card, "dsp", card->proc_root)) != NULL) { 761 entry->content = SNDRV_INFO_CONTENT_TEXT; 762 entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; 763 entry->c.text.read_size = 512; 764 765 if (snd_info_register(entry) < 0) { 766 snd_info_free_entry(entry); 767 entry = NULL; 768 } 769 } 770 771 ins->proc_dsp_dir = entry; 772 773 if (!ins->proc_dsp_dir) 774 return -ENOMEM; 775 776 if ((entry = snd_info_create_card_entry(card, "spos_symbols", ins->proc_dsp_dir)) != NULL) { 777 entry->content = SNDRV_INFO_CONTENT_TEXT; 778 entry->private_data = chip; 779 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 780 entry->c.text.read_size = 512; 781 entry->c.text.read = cs46xx_dsp_proc_symbol_table_read; 782 if (snd_info_register(entry) < 0) { 783 snd_info_free_entry(entry); 784 entry = NULL; 785 } 786 } 787 ins->proc_sym_info_entry = entry; 788 789 if ((entry = snd_info_create_card_entry(card, "spos_modules", ins->proc_dsp_dir)) != NULL) { 790 entry->content = SNDRV_INFO_CONTENT_TEXT; 791 entry->private_data = chip; 792 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 793 entry->c.text.read_size = 512; 794 entry->c.text.read = cs46xx_dsp_proc_modules_read; 795 if (snd_info_register(entry) < 0) { 796 snd_info_free_entry(entry); 797 entry = NULL; 798 } 799 } 800 ins->proc_modules_info_entry = entry; 801 802 if ((entry = snd_info_create_card_entry(card, "parameter", ins->proc_dsp_dir)) != NULL) { 803 entry->content = SNDRV_INFO_CONTENT_TEXT; 804 entry->private_data = chip; 805 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 806 entry->c.text.read_size = 512; 807 entry->c.text.read = cs46xx_dsp_proc_parameter_dump_read; 808 if (snd_info_register(entry) < 0) { 809 snd_info_free_entry(entry); 810 entry = NULL; 811 } 812 } 813 ins->proc_parameter_dump_info_entry = entry; 814 815 if ((entry = snd_info_create_card_entry(card, "sample", ins->proc_dsp_dir)) != NULL) { 816 entry->content = SNDRV_INFO_CONTENT_TEXT; 817 entry->private_data = chip; 818 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 819 entry->c.text.read_size = 512; 820 entry->c.text.read = cs46xx_dsp_proc_sample_dump_read; 821 if (snd_info_register(entry) < 0) { 822 snd_info_free_entry(entry); 823 entry = NULL; 824 } 825 } 826 ins->proc_sample_dump_info_entry = entry; 827 828 if ((entry = snd_info_create_card_entry(card, "task_tree", ins->proc_dsp_dir)) != NULL) { 829 entry->content = SNDRV_INFO_CONTENT_TEXT; 830 entry->private_data = chip; 831 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 832 entry->c.text.read_size = 512; 833 entry->c.text.read = cs46xx_dsp_proc_task_tree_read; 834 if (snd_info_register(entry) < 0) { 835 snd_info_free_entry(entry); 836 entry = NULL; 837 } 838 } 839 ins->proc_task_info_entry = entry; 840 841 if ((entry = snd_info_create_card_entry(card, "scb_info", ins->proc_dsp_dir)) != NULL) { 842 entry->content = SNDRV_INFO_CONTENT_TEXT; 843 entry->private_data = chip; 844 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 845 entry->c.text.read_size = 1024; 846 entry->c.text.read = cs46xx_dsp_proc_scb_read; 847 if (snd_info_register(entry) < 0) { 848 snd_info_free_entry(entry); 849 entry = NULL; 850 } 851 } 852 ins->proc_scb_info_entry = entry; 853 854 down(&chip->spos_mutex); 855 /* register/update SCB's entries on proc */ 856 for (i = 0; i < ins->nscb; ++i) { 857 if (ins->scbs[i].deleted) continue; 858 859 cs46xx_dsp_proc_register_scb_desc (chip, (ins->scbs + i)); 860 } 861 up(&chip->spos_mutex); 862 863 return 0; 864 } 865 866 int cs46xx_dsp_proc_done (struct snd_cs46xx *chip) 867 { 868 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 869 int i; 870 871 if (ins->proc_sym_info_entry) { 872 snd_info_unregister(ins->proc_sym_info_entry); 873 ins->proc_sym_info_entry = NULL; 874 } 875 876 if (ins->proc_modules_info_entry) { 877 snd_info_unregister(ins->proc_modules_info_entry); 878 ins->proc_modules_info_entry = NULL; 879 } 880 881 if (ins->proc_parameter_dump_info_entry) { 882 snd_info_unregister(ins->proc_parameter_dump_info_entry); 883 ins->proc_parameter_dump_info_entry = NULL; 884 } 885 886 if (ins->proc_sample_dump_info_entry) { 887 snd_info_unregister(ins->proc_sample_dump_info_entry); 888 ins->proc_sample_dump_info_entry = NULL; 889 } 890 891 if (ins->proc_scb_info_entry) { 892 snd_info_unregister(ins->proc_scb_info_entry); 893 ins->proc_scb_info_entry = NULL; 894 } 895 896 if (ins->proc_task_info_entry) { 897 snd_info_unregister(ins->proc_task_info_entry); 898 ins->proc_task_info_entry = NULL; 899 } 900 901 down(&chip->spos_mutex); 902 for (i = 0; i < ins->nscb; ++i) { 903 if (ins->scbs[i].deleted) continue; 904 cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); 905 } 906 up(&chip->spos_mutex); 907 908 if (ins->proc_dsp_dir) { 909 snd_info_unregister (ins->proc_dsp_dir); 910 ins->proc_dsp_dir = NULL; 911 } 912 913 return 0; 914 } 915 916 static int debug_tree; 917 static void _dsp_create_task_tree (struct snd_cs46xx *chip, u32 * task_data, 918 u32 dest, int size) 919 { 920 void __iomem *spdst = chip->region.idx[1].remap_addr + 921 DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32); 922 int i; 923 924 for (i = 0; i < size; ++i) { 925 if (debug_tree) printk ("addr %p, val %08x\n",spdst,task_data[i]); 926 writel(task_data[i],spdst); 927 spdst += sizeof(u32); 928 } 929 } 930 931 static int debug_scb; 932 static void _dsp_create_scb (struct snd_cs46xx *chip, u32 * scb_data, u32 dest) 933 { 934 void __iomem *spdst = chip->region.idx[1].remap_addr + 935 DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32); 936 int i; 937 938 for (i = 0; i < 0x10; ++i) { 939 if (debug_scb) printk ("addr %p, val %08x\n",spdst,scb_data[i]); 940 writel(scb_data[i],spdst); 941 spdst += sizeof(u32); 942 } 943 } 944 945 static int find_free_scb_index (struct dsp_spos_instance * ins) 946 { 947 int index = ins->nscb, i; 948 949 for (i = ins->scb_highest_frag_index; i < ins->nscb; ++i) { 950 if (ins->scbs[i].deleted) { 951 index = i; 952 break; 953 } 954 } 955 956 return index; 957 } 958 959 static struct dsp_scb_descriptor * _map_scb (struct snd_cs46xx *chip, char * name, u32 dest) 960 { 961 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 962 struct dsp_scb_descriptor * desc = NULL; 963 int index; 964 965 if (ins->nscb == DSP_MAX_SCB_DESC - 1) { 966 snd_printk(KERN_ERR "dsp_spos: got no place for other SCB\n"); 967 return NULL; 968 } 969 970 index = find_free_scb_index (ins); 971 972 strcpy(ins->scbs[index].scb_name, name); 973 ins->scbs[index].address = dest; 974 ins->scbs[index].index = index; 975 ins->scbs[index].proc_info = NULL; 976 ins->scbs[index].ref_count = 1; 977 ins->scbs[index].deleted = 0; 978 spin_lock_init(&ins->scbs[index].lock); 979 980 desc = (ins->scbs + index); 981 ins->scbs[index].scb_symbol = add_symbol (chip, name, dest, SYMBOL_PARAMETER); 982 983 if (index > ins->scb_highest_frag_index) 984 ins->scb_highest_frag_index = index; 985 986 if (index == ins->nscb) 987 ins->nscb++; 988 989 return desc; 990 } 991 992 static struct dsp_task_descriptor * 993 _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size) 994 { 995 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 996 struct dsp_task_descriptor * desc = NULL; 997 998 if (ins->ntask == DSP_MAX_TASK_DESC - 1) { 999 snd_printk(KERN_ERR "dsp_spos: got no place for other TASK\n"); 1000 return NULL; 1001 } 1002 1003 strcpy(ins->tasks[ins->ntask].task_name,name); 1004 ins->tasks[ins->ntask].address = dest; 1005 ins->tasks[ins->ntask].size = size; 1006 1007 /* quick find in list */ 1008 ins->tasks[ins->ntask].index = ins->ntask; 1009 desc = (ins->tasks + ins->ntask); 1010 ins->ntask++; 1011 1012 add_symbol (chip,name,dest,SYMBOL_PARAMETER); 1013 return desc; 1014 } 1015 1016 struct dsp_scb_descriptor * 1017 cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest) 1018 { 1019 struct dsp_scb_descriptor * desc; 1020 1021 desc = _map_scb (chip,name,dest); 1022 if (desc) { 1023 _dsp_create_scb(chip,scb_data,dest); 1024 } else { 1025 snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); 1026 } 1027 1028 return desc; 1029 } 1030 1031 1032 static struct dsp_task_descriptor * 1033 cs46xx_dsp_create_task_tree (struct snd_cs46xx *chip, char * name, u32 * task_data, 1034 u32 dest, int size) 1035 { 1036 struct dsp_task_descriptor * desc; 1037 1038 desc = _map_task_tree (chip,name,dest,size); 1039 if (desc) { 1040 _dsp_create_task_tree(chip,task_data,dest,size); 1041 } else { 1042 snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n"); 1043 } 1044 1045 return desc; 1046 } 1047 1048 int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip) 1049 { 1050 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1051 struct dsp_symbol_entry * fg_task_tree_header_code; 1052 struct dsp_symbol_entry * task_tree_header_code; 1053 struct dsp_symbol_entry * task_tree_thread; 1054 struct dsp_symbol_entry * null_algorithm; 1055 struct dsp_symbol_entry * magic_snoop_task; 1056 1057 struct dsp_scb_descriptor * timing_master_scb; 1058 struct dsp_scb_descriptor * codec_out_scb; 1059 struct dsp_scb_descriptor * codec_in_scb; 1060 struct dsp_scb_descriptor * src_task_scb; 1061 struct dsp_scb_descriptor * master_mix_scb; 1062 struct dsp_scb_descriptor * rear_mix_scb; 1063 struct dsp_scb_descriptor * record_mix_scb; 1064 struct dsp_scb_descriptor * write_back_scb; 1065 struct dsp_scb_descriptor * vari_decimate_scb; 1066 struct dsp_scb_descriptor * rear_codec_out_scb; 1067 struct dsp_scb_descriptor * clfe_codec_out_scb; 1068 struct dsp_scb_descriptor * magic_snoop_scb; 1069 1070 int fifo_addr, fifo_span, valid_slots; 1071 1072 static struct dsp_spos_control_block sposcb = { 1073 /* 0 */ HFG_TREE_SCB,HFG_STACK, 1074 /* 1 */ SPOSCB_ADDR,BG_TREE_SCB_ADDR, 1075 /* 2 */ DSP_SPOS_DC,0, 1076 /* 3 */ DSP_SPOS_DC,DSP_SPOS_DC, 1077 /* 4 */ 0,0, 1078 /* 5 */ DSP_SPOS_UU,0, 1079 /* 6 */ FG_TASK_HEADER_ADDR,0, 1080 /* 7 */ 0,0, 1081 /* 8 */ DSP_SPOS_UU,DSP_SPOS_DC, 1082 /* 9 */ 0, 1083 /* A */ 0,HFG_FIRST_EXECUTE_MODE, 1084 /* B */ DSP_SPOS_UU,DSP_SPOS_UU, 1085 /* C */ DSP_SPOS_DC_DC, 1086 /* D */ DSP_SPOS_DC_DC, 1087 /* E */ DSP_SPOS_DC_DC, 1088 /* F */ DSP_SPOS_DC_DC 1089 }; 1090 1091 cs46xx_dsp_create_task_tree(chip, "sposCB", (u32 *)&sposcb, SPOSCB_ADDR, 0x10); 1092 1093 null_algorithm = cs46xx_dsp_lookup_symbol(chip, "NULLALGORITHM", SYMBOL_CODE); 1094 if (null_algorithm == NULL) { 1095 snd_printk(KERN_ERR "dsp_spos: symbol NULLALGORITHM not found\n"); 1096 return -EIO; 1097 } 1098 1099 fg_task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "FGTASKTREEHEADERCODE", SYMBOL_CODE); 1100 if (fg_task_tree_header_code == NULL) { 1101 snd_printk(KERN_ERR "dsp_spos: symbol FGTASKTREEHEADERCODE not found\n"); 1102 return -EIO; 1103 } 1104 1105 task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "TASKTREEHEADERCODE", SYMBOL_CODE); 1106 if (task_tree_header_code == NULL) { 1107 snd_printk(KERN_ERR "dsp_spos: symbol TASKTREEHEADERCODE not found\n"); 1108 return -EIO; 1109 } 1110 1111 task_tree_thread = cs46xx_dsp_lookup_symbol(chip, "TASKTREETHREAD", SYMBOL_CODE); 1112 if (task_tree_thread == NULL) { 1113 snd_printk(KERN_ERR "dsp_spos: symbol TASKTREETHREAD not found\n"); 1114 return -EIO; 1115 } 1116 1117 magic_snoop_task = cs46xx_dsp_lookup_symbol(chip, "MAGICSNOOPTASK", SYMBOL_CODE); 1118 if (magic_snoop_task == NULL) { 1119 snd_printk(KERN_ERR "dsp_spos: symbol MAGICSNOOPTASK not found\n"); 1120 return -EIO; 1121 } 1122 1123 { 1124 /* create the null SCB */ 1125 static struct dsp_generic_scb null_scb = { 1126 { 0, 0, 0, 0 }, 1127 { 0, 0, 0, 0, 0 }, 1128 NULL_SCB_ADDR, NULL_SCB_ADDR, 1129 0, 0, 0, 0, 0, 1130 { 1131 0,0, 1132 0,0, 1133 } 1134 }; 1135 1136 null_scb.entry_point = null_algorithm->address; 1137 ins->the_null_scb = cs46xx_dsp_create_scb(chip, "nullSCB", (u32 *)&null_scb, NULL_SCB_ADDR); 1138 ins->the_null_scb->task_entry = null_algorithm; 1139 ins->the_null_scb->sub_list_ptr = ins->the_null_scb; 1140 ins->the_null_scb->next_scb_ptr = ins->the_null_scb; 1141 ins->the_null_scb->parent_scb_ptr = NULL; 1142 cs46xx_dsp_proc_register_scb_desc (chip,ins->the_null_scb); 1143 } 1144 1145 { 1146 /* setup foreground task tree */ 1147 static struct dsp_task_tree_control_block fg_task_tree_hdr = { 1148 { FG_TASK_HEADER_ADDR | (DSP_SPOS_DC << 0x10), 1149 DSP_SPOS_DC_DC, 1150 DSP_SPOS_DC_DC, 1151 0x0000,DSP_SPOS_DC, 1152 DSP_SPOS_DC, DSP_SPOS_DC, 1153 DSP_SPOS_DC_DC, 1154 DSP_SPOS_DC_DC, 1155 DSP_SPOS_DC_DC, 1156 DSP_SPOS_DC,DSP_SPOS_DC }, 1157 1158 { 1159 BG_TREE_SCB_ADDR,TIMINGMASTER_SCB_ADDR, 1160 0, 1161 FG_TASK_HEADER_ADDR + TCBData, 1162 }, 1163 1164 { 1165 4,0, 1166 1,0, 1167 2,SPOSCB_ADDR + HFGFlags, 1168 0,0, 1169 FG_TASK_HEADER_ADDR + TCBContextBlk,FG_STACK 1170 }, 1171 1172 { 1173 DSP_SPOS_DC,0, 1174 DSP_SPOS_DC,DSP_SPOS_DC, 1175 DSP_SPOS_DC,DSP_SPOS_DC, 1176 DSP_SPOS_DC,DSP_SPOS_DC, 1177 DSP_SPOS_DC,DSP_SPOS_DC, 1178 DSP_SPOS_DCDC, 1179 DSP_SPOS_UU,1, 1180 DSP_SPOS_DCDC, 1181 DSP_SPOS_DCDC, 1182 DSP_SPOS_DCDC, 1183 DSP_SPOS_DCDC, 1184 DSP_SPOS_DCDC, 1185 DSP_SPOS_DCDC, 1186 DSP_SPOS_DCDC, 1187 DSP_SPOS_DCDC, 1188 DSP_SPOS_DCDC, 1189 DSP_SPOS_DCDC, 1190 DSP_SPOS_DCDC, 1191 DSP_SPOS_DCDC, 1192 DSP_SPOS_DCDC, 1193 DSP_SPOS_DCDC, 1194 DSP_SPOS_DCDC, 1195 DSP_SPOS_DCDC, 1196 DSP_SPOS_DCDC, 1197 DSP_SPOS_DCDC, 1198 DSP_SPOS_DCDC, 1199 DSP_SPOS_DCDC, 1200 DSP_SPOS_DCDC, 1201 DSP_SPOS_DCDC, 1202 DSP_SPOS_DCDC, 1203 DSP_SPOS_DCDC, 1204 DSP_SPOS_DCDC, 1205 DSP_SPOS_DCDC, 1206 DSP_SPOS_DCDC, 1207 DSP_SPOS_DCDC 1208 }, 1209 { 1210 FG_INTERVAL_TIMER_PERIOD,DSP_SPOS_UU, 1211 0,0 1212 } 1213 }; 1214 1215 fg_task_tree_hdr.links.entry_point = fg_task_tree_header_code->address; 1216 fg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address; 1217 cs46xx_dsp_create_task_tree(chip,"FGtaskTreeHdr",(u32 *)&fg_task_tree_hdr,FG_TASK_HEADER_ADDR,0x35); 1218 } 1219 1220 1221 { 1222 /* setup foreground task tree */ 1223 static struct dsp_task_tree_control_block bg_task_tree_hdr = { 1224 { DSP_SPOS_DC_DC, 1225 DSP_SPOS_DC_DC, 1226 DSP_SPOS_DC_DC, 1227 DSP_SPOS_DC, DSP_SPOS_DC, 1228 DSP_SPOS_DC, DSP_SPOS_DC, 1229 DSP_SPOS_DC_DC, 1230 DSP_SPOS_DC_DC, 1231 DSP_SPOS_DC_DC, 1232 DSP_SPOS_DC,DSP_SPOS_DC }, 1233 1234 { 1235 NULL_SCB_ADDR,NULL_SCB_ADDR, /* Set up the background to do nothing */ 1236 0, 1237 BG_TREE_SCB_ADDR + TCBData, 1238 }, 1239 1240 { 1241 9999,0, 1242 0,1, 1243 0,SPOSCB_ADDR + HFGFlags, 1244 0,0, 1245 BG_TREE_SCB_ADDR + TCBContextBlk,BG_STACK 1246 }, 1247 1248 { 1249 DSP_SPOS_DC,0, 1250 DSP_SPOS_DC,DSP_SPOS_DC, 1251 DSP_SPOS_DC,DSP_SPOS_DC, 1252 DSP_SPOS_DC,DSP_SPOS_DC, 1253 DSP_SPOS_DC,DSP_SPOS_DC, 1254 DSP_SPOS_DCDC, 1255 DSP_SPOS_UU,1, 1256 DSP_SPOS_DCDC, 1257 DSP_SPOS_DCDC, 1258 DSP_SPOS_DCDC, 1259 DSP_SPOS_DCDC, 1260 DSP_SPOS_DCDC, 1261 DSP_SPOS_DCDC, 1262 DSP_SPOS_DCDC, 1263 DSP_SPOS_DCDC, 1264 DSP_SPOS_DCDC, 1265 DSP_SPOS_DCDC, 1266 DSP_SPOS_DCDC, 1267 DSP_SPOS_DCDC, 1268 DSP_SPOS_DCDC, 1269 DSP_SPOS_DCDC, 1270 DSP_SPOS_DCDC, 1271 DSP_SPOS_DCDC, 1272 DSP_SPOS_DCDC, 1273 DSP_SPOS_DCDC, 1274 DSP_SPOS_DCDC, 1275 DSP_SPOS_DCDC, 1276 DSP_SPOS_DCDC, 1277 DSP_SPOS_DCDC, 1278 DSP_SPOS_DCDC, 1279 DSP_SPOS_DCDC, 1280 DSP_SPOS_DCDC, 1281 DSP_SPOS_DCDC, 1282 DSP_SPOS_DCDC, 1283 DSP_SPOS_DCDC 1284 }, 1285 { 1286 BG_INTERVAL_TIMER_PERIOD,DSP_SPOS_UU, 1287 0,0 1288 } 1289 }; 1290 1291 bg_task_tree_hdr.links.entry_point = task_tree_header_code->address; 1292 bg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address; 1293 cs46xx_dsp_create_task_tree(chip,"BGtaskTreeHdr",(u32 *)&bg_task_tree_hdr,BG_TREE_SCB_ADDR,0x35); 1294 } 1295 1296 /* create timing master SCB */ 1297 timing_master_scb = cs46xx_dsp_create_timing_master_scb(chip); 1298 1299 /* create the CODEC output task */ 1300 codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_I",0x0010,0x0000, 1301 MASTERMIX_SCB_ADDR, 1302 CODECOUT_SCB_ADDR,timing_master_scb, 1303 SCB_ON_PARENT_SUBLIST_SCB); 1304 1305 if (!codec_out_scb) goto _fail_end; 1306 /* create the master mix SCB */ 1307 master_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"MasterMixSCB", 1308 MIX_SAMPLE_BUF1,MASTERMIX_SCB_ADDR, 1309 codec_out_scb, 1310 SCB_ON_PARENT_SUBLIST_SCB); 1311 ins->master_mix_scb = master_mix_scb; 1312 1313 if (!master_mix_scb) goto _fail_end; 1314 1315 /* create codec in */ 1316 codec_in_scb = cs46xx_dsp_create_codec_in_scb(chip,"CodecInSCB",0x0010,0x00A0, 1317 CODEC_INPUT_BUF1, 1318 CODECIN_SCB_ADDR,codec_out_scb, 1319 SCB_ON_PARENT_NEXT_SCB); 1320 if (!codec_in_scb) goto _fail_end; 1321 ins->codec_in_scb = codec_in_scb; 1322 1323 /* create write back scb */ 1324 write_back_scb = cs46xx_dsp_create_mix_to_ostream_scb(chip,"WriteBackSCB", 1325 WRITE_BACK_BUF1,WRITE_BACK_SPB, 1326 WRITEBACK_SCB_ADDR, 1327 timing_master_scb, 1328 SCB_ON_PARENT_NEXT_SCB); 1329 if (!write_back_scb) goto _fail_end; 1330 1331 { 1332 static struct dsp_mix2_ostream_spb mix2_ostream_spb = { 1333 0x00020000, 1334 0x0000ffff 1335 }; 1336 1337 /* dirty hack ... */ 1338 _dsp_create_task_tree (chip,(u32 *)&mix2_ostream_spb,WRITE_BACK_SPB,2); 1339 } 1340 1341 /* input sample converter */ 1342 vari_decimate_scb = cs46xx_dsp_create_vari_decimate_scb(chip,"VariDecimateSCB", 1343 VARI_DECIMATE_BUF0, 1344 VARI_DECIMATE_BUF1, 1345 VARIDECIMATE_SCB_ADDR, 1346 write_back_scb, 1347 SCB_ON_PARENT_SUBLIST_SCB); 1348 if (!vari_decimate_scb) goto _fail_end; 1349 1350 /* create the record mixer SCB */ 1351 record_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RecordMixerSCB", 1352 MIX_SAMPLE_BUF2, 1353 RECORD_MIXER_SCB_ADDR, 1354 vari_decimate_scb, 1355 SCB_ON_PARENT_SUBLIST_SCB); 1356 ins->record_mixer_scb = record_mix_scb; 1357 1358 if (!record_mix_scb) goto _fail_end; 1359 1360 valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV); 1361 1362 snd_assert (chip->nr_ac97_codecs == 1 || chip->nr_ac97_codecs == 2); 1363 1364 if (chip->nr_ac97_codecs == 1) { 1365 /* output on slot 5 and 11 1366 on primary CODEC */ 1367 fifo_addr = 0x20; 1368 fifo_span = 0x60; 1369 1370 /* enable slot 5 and 11 */ 1371 valid_slots |= ACOSV_SLV5 | ACOSV_SLV11; 1372 } else { 1373 /* output on slot 7 and 8 1374 on secondary CODEC */ 1375 fifo_addr = 0x40; 1376 fifo_span = 0x10; 1377 1378 /* enable slot 7 and 8 */ 1379 valid_slots |= ACOSV_SLV7 | ACOSV_SLV8; 1380 } 1381 /* create CODEC tasklet for rear speakers output*/ 1382 rear_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_Rear",fifo_span,fifo_addr, 1383 REAR_MIXER_SCB_ADDR, 1384 REAR_CODECOUT_SCB_ADDR,codec_in_scb, 1385 SCB_ON_PARENT_NEXT_SCB); 1386 if (!rear_codec_out_scb) goto _fail_end; 1387 1388 1389 /* create the rear PCM channel mixer SCB */ 1390 rear_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RearMixerSCB", 1391 MIX_SAMPLE_BUF3, 1392 REAR_MIXER_SCB_ADDR, 1393 rear_codec_out_scb, 1394 SCB_ON_PARENT_SUBLIST_SCB); 1395 ins->rear_mix_scb = rear_mix_scb; 1396 if (!rear_mix_scb) goto _fail_end; 1397 1398 if (chip->nr_ac97_codecs == 2) { 1399 /* create CODEC tasklet for rear Center/LFE output 1400 slot 6 and 9 on seconadry CODEC */ 1401 clfe_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_CLFE",0x0030,0x0030, 1402 CLFE_MIXER_SCB_ADDR, 1403 CLFE_CODEC_SCB_ADDR, 1404 rear_codec_out_scb, 1405 SCB_ON_PARENT_NEXT_SCB); 1406 if (!clfe_codec_out_scb) goto _fail_end; 1407 1408 1409 /* create the rear PCM channel mixer SCB */ 1410 ins->center_lfe_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"CLFEMixerSCB", 1411 MIX_SAMPLE_BUF4, 1412 CLFE_MIXER_SCB_ADDR, 1413 clfe_codec_out_scb, 1414 SCB_ON_PARENT_SUBLIST_SCB); 1415 if (!ins->center_lfe_mix_scb) goto _fail_end; 1416 1417 /* enable slot 6 and 9 */ 1418 valid_slots |= ACOSV_SLV6 | ACOSV_SLV9; 1419 } else { 1420 clfe_codec_out_scb = rear_codec_out_scb; 1421 ins->center_lfe_mix_scb = rear_mix_scb; 1422 } 1423 1424 /* enable slots depending on CODEC configuration */ 1425 snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots); 1426 1427 /* the magic snooper */ 1428 magic_snoop_scb = cs46xx_dsp_create_magic_snoop_scb (chip,"MagicSnoopSCB_I",OUTPUTSNOOP_SCB_ADDR, 1429 OUTPUT_SNOOP_BUFFER, 1430 codec_out_scb, 1431 clfe_codec_out_scb, 1432 SCB_ON_PARENT_NEXT_SCB); 1433 1434 1435 if (!magic_snoop_scb) goto _fail_end; 1436 ins->ref_snoop_scb = magic_snoop_scb; 1437 1438 /* SP IO access */ 1439 if (!cs46xx_dsp_create_spio_write_scb(chip,"SPIOWriteSCB",SPIOWRITE_SCB_ADDR, 1440 magic_snoop_scb, 1441 SCB_ON_PARENT_NEXT_SCB)) 1442 goto _fail_end; 1443 1444 /* SPDIF input sampel rate converter */ 1445 src_task_scb = cs46xx_dsp_create_src_task_scb(chip,"SrcTaskSCB_SPDIFI", 1446 ins->spdif_in_sample_rate, 1447 SRC_OUTPUT_BUF1, 1448 SRC_DELAY_BUF1,SRCTASK_SCB_ADDR, 1449 master_mix_scb, 1450 SCB_ON_PARENT_SUBLIST_SCB,1); 1451 1452 if (!src_task_scb) goto _fail_end; 1453 cs46xx_src_unlink(chip,src_task_scb); 1454 1455 /* NOTE: when we now how to detect the SPDIF input 1456 sample rate we will use this SRC to adjust it */ 1457 ins->spdif_in_src = src_task_scb; 1458 1459 cs46xx_dsp_async_init(chip,timing_master_scb); 1460 return 0; 1461 1462 _fail_end: 1463 snd_printk(KERN_ERR "dsp_spos: failed to setup SCB's in DSP\n"); 1464 return -EINVAL; 1465 } 1466 1467 static int cs46xx_dsp_async_init (struct snd_cs46xx *chip, 1468 struct dsp_scb_descriptor * fg_entry) 1469 { 1470 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1471 struct dsp_symbol_entry * s16_async_codec_input_task; 1472 struct dsp_symbol_entry * spdifo_task; 1473 struct dsp_symbol_entry * spdifi_task; 1474 struct dsp_scb_descriptor * spdifi_scb_desc, * spdifo_scb_desc, * async_codec_scb_desc; 1475 1476 s16_async_codec_input_task = cs46xx_dsp_lookup_symbol(chip, "S16_ASYNCCODECINPUTTASK", SYMBOL_CODE); 1477 if (s16_async_codec_input_task == NULL) { 1478 snd_printk(KERN_ERR "dsp_spos: symbol S16_ASYNCCODECINPUTTASK not found\n"); 1479 return -EIO; 1480 } 1481 spdifo_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFOTASK", SYMBOL_CODE); 1482 if (spdifo_task == NULL) { 1483 snd_printk(KERN_ERR "dsp_spos: symbol SPDIFOTASK not found\n"); 1484 return -EIO; 1485 } 1486 1487 spdifi_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFITASK", SYMBOL_CODE); 1488 if (spdifi_task == NULL) { 1489 snd_printk(KERN_ERR "dsp_spos: symbol SPDIFITASK not found\n"); 1490 return -EIO; 1491 } 1492 1493 { 1494 /* 0xBC0 */ 1495 struct dsp_spdifoscb spdifo_scb = { 1496 /* 0 */ DSP_SPOS_UUUU, 1497 { 1498 /* 1 */ 0xb0, 1499 /* 2 */ 0, 1500 /* 3 */ 0, 1501 /* 4 */ 0, 1502 }, 1503 /* NOTE: the SPDIF output task read samples in mono 1504 format, the AsynchFGTxSCB task writes to buffer 1505 in stereo format 1506 */ 1507 /* 5 */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_256, 1508 /* 6 */ ( SPDIFO_IP_OUTPUT_BUFFER1 << 0x10 ) | 0xFFFC, 1509 /* 7 */ 0,0, 1510 /* 8 */ 0, 1511 /* 9 */ FG_TASK_HEADER_ADDR, NULL_SCB_ADDR, 1512 /* A */ spdifo_task->address, 1513 SPDIFO_SCB_INST + SPDIFOFIFOPointer, 1514 { 1515 /* B */ 0x0040, /*DSP_SPOS_UUUU,*/ 1516 /* C */ 0x20ff, /*DSP_SPOS_UUUU,*/ 1517 }, 1518 /* D */ 0x804c,0, /* SPDIFOFIFOPointer:SPDIFOStatRegAddr; */ 1519 /* E */ 0x0108,0x0001, /* SPDIFOStMoFormat:SPDIFOFIFOBaseAddr; */ 1520 /* F */ DSP_SPOS_UUUU /* SPDIFOFree; */ 1521 }; 1522 1523 /* 0xBB0 */ 1524 struct dsp_spdifiscb spdifi_scb = { 1525 /* 0 */ DSP_SPOS_UULO,DSP_SPOS_UUHI, 1526 /* 1 */ 0, 1527 /* 2 */ 0, 1528 /* 3 */ 1,4000, /* SPDIFICountLimit SPDIFICount */ 1529 /* 4 */ DSP_SPOS_UUUU, /* SPDIFIStatusData */ 1530 /* 5 */ 0,DSP_SPOS_UUHI, /* StatusData, Free4 */ 1531 /* 6 */ DSP_SPOS_UUUU, /* Free3 */ 1532 /* 7 */ DSP_SPOS_UU,DSP_SPOS_DC, /* Free2 BitCount*/ 1533 /* 8 */ DSP_SPOS_UUUU, /* TempStatus */ 1534 /* 9 */ SPDIFO_SCB_INST, NULL_SCB_ADDR, 1535 /* A */ spdifi_task->address, 1536 SPDIFI_SCB_INST + SPDIFIFIFOPointer, 1537 /* NOTE: The SPDIF input task write the sample in mono 1538 format from the HW FIFO, the AsynchFGRxSCB task reads 1539 them in stereo 1540 */ 1541 /* B */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_128, 1542 /* C */ (SPDIFI_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC, 1543 /* D */ 0x8048,0, 1544 /* E */ 0x01f0,0x0001, 1545 /* F */ DSP_SPOS_UUUU /* SPDIN_STATUS monitor */ 1546 }; 1547 1548 /* 0xBA0 */ 1549 struct dsp_async_codec_input_scb async_codec_input_scb = { 1550 /* 0 */ DSP_SPOS_UUUU, 1551 /* 1 */ 0, 1552 /* 2 */ 0, 1553 /* 3 */ 1,4000, 1554 /* 4 */ 0x0118,0x0001, 1555 /* 5 */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_64, 1556 /* 6 */ (ASYNC_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC, 1557 /* 7 */ DSP_SPOS_UU,0x3, 1558 /* 8 */ DSP_SPOS_UUUU, 1559 /* 9 */ SPDIFI_SCB_INST,NULL_SCB_ADDR, 1560 /* A */ s16_async_codec_input_task->address, 1561 HFG_TREE_SCB + AsyncCIOFIFOPointer, 1562 1563 /* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64, 1564 /* C */ (ASYNC_IP_OUTPUT_BUFFER1 << 0x10), /*(ASYNC_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,*/ 1565 1553 1566 #ifdef UseASER1Input 1554 /* short AsyncCIFIFOPointer:AsyncCIStatRegAddr; 1555 Init. 0000:8042: for ASER11556 0000:8044: for ASER2 */1557 /* D */ 0x8042,0,1558 1559 /* short AsyncCIStMoFormat:AsyncCIFIFOBaseAddr;1560 Init 1 stero:8050 ASER11561 Init 0 mono:8070 ASER21562 Init 1 Stereo : 0100 ASER1 (Set by script) */1563 /* E */ 0x0100,0x0001,1564 1567 /* short AsyncCIFIFOPointer:AsyncCIStatRegAddr; 1568 Init. 0000:8042: for ASER1 1569 0000:8044: for ASER2 */ 1570 /* D */ 0x8042,0, 1571 1572 /* short AsyncCIStMoFormat:AsyncCIFIFOBaseAddr; 1573 Init 1 stero:8050 ASER1 1574 Init 0 mono:8070 ASER2 1575 Init 1 Stereo : 0100 ASER1 (Set by script) */ 1576 /* E */ 0x0100,0x0001, 1577 1565 1578 #endif 1566 1579 1567 1580 #ifdef UseASER2Input 1568 /* short AsyncCIFIFOPointer:AsyncCIStatRegAddr;1569 Init. 0000:8042: for ASER11570 0000:8044: for ASER2 */1571 /* D */ 0x8044,0,1572 1573 /* short AsyncCIStMoFormat:AsyncCIFIFOBaseAddr;1574 Init 1 stero:8050 ASER11575 Init 0 mono:8070 ASER21576 Init 1 Stereo : 0100 ASER1 (Set by script) */1577 /* E */ 0x0110,0x0001,1578 1581 /* short AsyncCIFIFOPointer:AsyncCIStatRegAddr; 1582 Init. 0000:8042: for ASER1 1583 0000:8044: for ASER2 */ 1584 /* D */ 0x8044,0, 1585 1586 /* short AsyncCIStMoFormat:AsyncCIFIFOBaseAddr; 1587 Init 1 stero:8050 ASER1 1588 Init 0 mono:8070 ASER2 1589 Init 1 Stereo : 0100 ASER1 (Set by script) */ 1590 /* E */ 0x0110,0x0001, 1591 1579 1592 #endif 1580 1581 /* short AsyncCIOutputBufModulo:AsyncCIFree; 1582 AsyncCIOutputBufModulo: The modulo size for 1583 the output buffer of this task */ 1584 /* F */ 0, /* DSP_SPOS_UUUU */ 1585 }; 1586 1587 spdifi_scb.entry_point = spdifi_task->address; 1588 spdifo_scb.entry_point = spdifo_task->address; 1589 async_codec_input_scb.io_entry_point = s16_async_codec_input_task->address; 1590 spdifo_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFOSCB",(u32 *)&spdifo_scb,SPDIFO_SCB_INST); 1591 1592 snd_assert(spdifo_scb_desc, return -EIO); 1593 spdifi_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFISCB",(u32 *)&spdifi_scb,SPDIFI_SCB_INST); 1594 snd_assert(spdifi_scb_desc, return -EIO); 1595 async_codec_scb_desc = cs46xx_dsp_create_scb(chip,"AsynCodecInputSCB",(u32 *)&async_codec_input_scb, HFG_TREE_SCB); 1596 snd_assert(async_codec_scb_desc, return -EIO); 1597 1598 async_codec_scb_desc->parent_scb_ptr = NULL; 1599 async_codec_scb_desc->next_scb_ptr = spdifi_scb_desc; 1600 async_codec_scb_desc->sub_list_ptr = ins->the_null_scb; 1601 async_codec_scb_desc->task_entry = s16_async_codec_input_task; 1602 1603 spdifi_scb_desc->parent_scb_ptr = async_codec_scb_desc; 1604 spdifi_scb_desc->next_scb_ptr = spdifo_scb_desc; 1605 spdifi_scb_desc->sub_list_ptr = ins->the_null_scb; 1606 spdifi_scb_desc->task_entry = spdifi_task; 1607 1608 spdifo_scb_desc->parent_scb_ptr = spdifi_scb_desc; 1609 spdifo_scb_desc->next_scb_ptr = fg_entry; 1610 spdifo_scb_desc->sub_list_ptr = ins->the_null_scb; 1611 spdifo_scb_desc->task_entry = spdifo_task; 1612 1613 /* this one is faked, as the parnet of SPDIFO task 1614 is the FG task tree */ 1615 fg_entry->parent_scb_ptr = spdifo_scb_desc; 1616 1617 /* for proc fs */ 1618 cs46xx_dsp_proc_register_scb_desc (chip,spdifo_scb_desc); 1619 cs46xx_dsp_proc_register_scb_desc (chip,spdifi_scb_desc); 1620 cs46xx_dsp_proc_register_scb_desc (chip,async_codec_scb_desc); 1621 1622 /* Async MASTER ENABLE, affects both SPDIF input and output */ 1623 snd_cs46xx_pokeBA0(chip, BA0_ASER_MASTER, 0x1 ); 1624 } 1625 1626 return 0; 1627 } 1628 1629 1630 static void cs46xx_dsp_disable_spdif_hw (cs46xx_t *chip) 1631 { 1632 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1633 1634 /* set SPDIF output FIFO slot */ 1635 snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, 0); 1636 1637 /* SPDIF output MASTER ENABLE */ 1638 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0); 1639 1640 /* right and left validate bit */ 1641 /*cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default);*/ 1642 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x0); 1643 1644 /* clear fifo pointer */ 1645 cs46xx_poke_via_dsp (chip,SP_SPDIN_FIFOPTR, 0x0); 1646 1647 /* monitor state */ 1648 ins->spdif_status_out &= ~DSP_SPDIF_STATUS_HW_ENABLED; 1649 } 1650 1651 int cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip) 1652 { 1653 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1654 1655 /* if hw-ctrl already enabled, turn off to reset logic ... */ 1656 cs46xx_dsp_disable_spdif_hw (chip); 1657 udelay(50); 1658 1659 /* set SPDIF output FIFO slot */ 1660 snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, ( 0x8000 | ((SP_SPDOUT_FIFO >> 4) << 4) )); 1661 1662 /* SPDIF output MASTER ENABLE */ 1663 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0x80000000); 1664 1665 /* right and left validate bit */ 1666 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default); 1667 1668 /* monitor state */ 1669 ins->spdif_status_out |= DSP_SPDIF_STATUS_HW_ENABLED; 1670 1671 return 0; 1672 } 1673 1674 int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip) 1675 { 1676 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1677 1678 /* turn on amplifier */ 1679 chip->active_ctrl(chip, 1); 1680 chip->amplifier_ctrl(chip, 1); 1681 1682 snd_assert (ins->asynch_rx_scb == NULL,return -EINVAL); 1683 snd_assert (ins->spdif_in_src != NULL,return -EINVAL); 1684 1685 down(&chip->spos_mutex); 1686 1687 if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED) ) { 1688 /* time countdown enable */ 1689 cs46xx_poke_via_dsp (chip,SP_ASER_COUNTDOWN, 0x80000005); 1690 /* NOTE: 80000005 value is just magic. With all values 1691 that I've tested this one seem to give the best result. 1692 Got no explication why. (Benny) */ 1693 1694 /* SPDIF input MASTER ENABLE */ 1695 cs46xx_poke_via_dsp (chip,SP_SPDIN_CONTROL, 0x800003ff); 1696 1697 ins->spdif_status_out |= DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED; 1698 } 1699 1700 /* create and start the asynchronous receiver SCB */ 1701 ins->asynch_rx_scb = cs46xx_dsp_create_asynch_fg_rx_scb(chip,"AsynchFGRxSCB", 1702 ASYNCRX_SCB_ADDR, 1703 SPDIFI_SCB_INST, 1704 SPDIFI_IP_OUTPUT_BUFFER1, 1705 ins->spdif_in_src, 1706 SCB_ON_PARENT_SUBLIST_SCB); 1707 1708 spin_lock_irq(&chip->reg_lock); 1709 1710 /* reset SPDIF input sample buffer pointer */ 1711 /*snd_cs46xx_poke (chip, (SPDIFI_SCB_INST + 0x0c) << 2, 1712 (SPDIFI_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC);*/ 1713 1714 /* reset FIFO ptr */ 1715 /*cs46xx_poke_via_dsp (chip,SP_SPDIN_FIFOPTR, 0x0);*/ 1716 cs46xx_src_link(chip,ins->spdif_in_src); 1717 1718 /* unmute SRC volume */ 1719 cs46xx_dsp_scb_set_volume (chip,ins->spdif_in_src,0x7fff,0x7fff); 1720 1721 spin_unlock_irq(&chip->reg_lock); 1722 1723 /* set SPDIF input sample rate and unmute 1724 NOTE: only 48khz support for SPDIF input this time */ 1725 /* cs46xx_dsp_set_src_sample_rate(chip,ins->spdif_in_src,48000); */ 1726 1727 /* monitor state */ 1728 ins->spdif_status_in = 1; 1729 up(&chip->spos_mutex); 1730 1731 return 0; 1732 } 1733 1734 int cs46xx_dsp_disable_spdif_in (cs46xx_t *chip) 1735 { 1736 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1737 1738 snd_assert (ins->asynch_rx_scb != NULL, return -EINVAL); 1739 snd_assert (ins->spdif_in_src != NULL,return -EINVAL); 1740 1741 down(&chip->spos_mutex); 1742 1743 /* Remove the asynchronous receiver SCB */ 1744 cs46xx_dsp_remove_scb (chip,ins->asynch_rx_scb); 1745 ins->asynch_rx_scb = NULL; 1746 1747 cs46xx_src_unlink(chip,ins->spdif_in_src); 1748 1749 /* monitor state */ 1750 ins->spdif_status_in = 0; 1751 up(&chip->spos_mutex); 1752 1753 /* restore amplifier */ 1754 chip->active_ctrl(chip, -1); 1755 chip->amplifier_ctrl(chip, -1); 1756 1757 return 0; 1758 } 1759 1760 int cs46xx_dsp_enable_pcm_capture (cs46xx_t *chip) 1761 { 1762 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1763 1764 snd_assert (ins->pcm_input == NULL,return -EINVAL); 1765 snd_assert (ins->ref_snoop_scb != NULL,return -EINVAL); 1766 1767 down(&chip->spos_mutex); 1768 ins->pcm_input = cs46xx_add_record_source(chip,ins->ref_snoop_scb,PCMSERIALIN_PCM_SCB_ADDR, 1769 "PCMSerialInput_Wave"); 1770 up(&chip->spos_mutex); 1771 1772 return 0; 1773 } 1774 1775 int cs46xx_dsp_disable_pcm_capture (cs46xx_t *chip) 1776 { 1777 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1778 1779 snd_assert (ins->pcm_input != NULL,return -EINVAL); 1780 1781 down(&chip->spos_mutex); 1782 cs46xx_dsp_remove_scb (chip,ins->pcm_input); 1783 ins->pcm_input = NULL; 1784 up(&chip->spos_mutex); 1785 1786 return 0; 1787 } 1788 1789 int cs46xx_dsp_enable_adc_capture (cs46xx_t *chip) 1790 { 1791 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1792 1793 snd_assert (ins->adc_input == NULL,return -EINVAL); 1794 snd_assert (ins->codec_in_scb != NULL,return -EINVAL); 1795 1796 down(&chip->spos_mutex); 1797 ins->adc_input = cs46xx_add_record_source(chip,ins->codec_in_scb,PCMSERIALIN_SCB_ADDR, 1798 "PCMSerialInput_ADC"); 1799 up(&chip->spos_mutex); 1800 1801 return 0; 1802 } 1803 1804 int cs46xx_dsp_disable_adc_capture (cs46xx_t *chip) 1805 { 1806 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1807 1808 snd_assert (ins->adc_input != NULL,return -EINVAL); 1809 1810 down(&chip->spos_mutex); 1811 cs46xx_dsp_remove_scb (chip,ins->adc_input); 1812 ins->adc_input = NULL; 1813 up(&chip->spos_mutex); 1814 1815 return 0; 1816 } 1817 1818 int cs46xx_poke_via_dsp (cs46xx_t *chip,u32 address,u32 data) 1819 { 1820 u32 temp; 1821 int i; 1822 1823 /* santiy check the parameters. (These numbers are not 100% correct. They are 1824 a rough guess from looking at the controller spec.) */ 1825 if (address < 0x8000 || address >= 0x9000) 1826 return -EINVAL; 1827 1828 /* initialize the SP_IO_WRITE SCB with the data. */ 1829 temp = ( address << 16 ) | ( address & 0x0000FFFF); /* offset 0 <-- address2 : address1 */ 1830 1831 snd_cs46xx_poke(chip,( SPIOWRITE_SCB_ADDR << 2), temp); 1832 snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 1) << 2), data); /* offset 1 <-- data1 */ 1833 snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 2) << 2), data); /* offset 1 <-- data2 */ 1834 1835 /* Poke this location to tell the task to start */ 1836 snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 6) << 2), SPIOWRITE_SCB_ADDR << 0x10); 1837 1838 /* Verify that the task ran */ 1839 for (i=0; i<25; i++) { 1840 udelay(125); 1841 1842 temp = snd_cs46xx_peek(chip,((SPIOWRITE_SCB_ADDR + 6) << 2)); 1843 if (temp == 0x00000000) 1844 break; 1845 } 1846 1847 if (i == 25) { 1848 snd_printk(KERN_ERR "dsp_spos: SPIOWriteTask not responding\n"); 1849 return -EBUSY; 1850 } 1851 1852 return 0; 1853 } 1854 1855 int cs46xx_dsp_set_dac_volume (cs46xx_t * chip,u16 left,u16 right) 1856 { 1857 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1858 dsp_scb_descriptor_t * scb; 1859 1860 down(&chip->spos_mutex); 1861 1862 /* main output */ 1863 scb = ins->master_mix_scb->sub_list_ptr; 1864 while (scb != ins->the_null_scb) { 1865 cs46xx_dsp_scb_set_volume (chip,scb,left,right); 1866 scb = scb->next_scb_ptr; 1867 } 1868 1869 /* rear output */ 1870 scb = ins->rear_mix_scb->sub_list_ptr; 1871 while (scb != ins->the_null_scb) { 1872 cs46xx_dsp_scb_set_volume (chip,scb,left,right); 1873 scb = scb->next_scb_ptr; 1874 } 1875 1876 ins->dac_volume_left = left; 1877 ins->dac_volume_right = right; 1878 1879 up(&chip->spos_mutex); 1880 1881 return 0; 1882 } 1883 1884 int cs46xx_dsp_set_iec958_volume (cs46xx_t * chip,u16 left,u16 right) { 1885 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1886 1887 down(&chip->spos_mutex); 1888 1889 if (ins->asynch_rx_scb != NULL) 1890 cs46xx_dsp_scb_set_volume (chip,ins->asynch_rx_scb, 1891 left,right); 1892 1893 ins->spdif_input_volume_left = left; 1894 ins->spdif_input_volume_right = right; 1895 1896 up(&chip->spos_mutex); 1897 1898 return 0; 1899 } 1593 1594 /* short AsyncCIOutputBufModulo:AsyncCIFree; 1595 AsyncCIOutputBufModulo: The modulo size for 1596 the output buffer of this task */ 1597 /* F */ 0, /* DSP_SPOS_UUUU */ 1598 }; 1599 1600 spdifo_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFOSCB",(u32 *)&spdifo_scb,SPDIFO_SCB_INST); 1601 1602 snd_assert(spdifo_scb_desc, return -EIO); 1603 spdifi_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFISCB",(u32 *)&spdifi_scb,SPDIFI_SCB_INST); 1604 snd_assert(spdifi_scb_desc, return -EIO); 1605 async_codec_scb_desc = cs46xx_dsp_create_scb(chip,"AsynCodecInputSCB",(u32 *)&async_codec_input_scb, HFG_TREE_SCB); 1606 snd_assert(async_codec_scb_desc, return -EIO); 1607 1608 async_codec_scb_desc->parent_scb_ptr = NULL; 1609 async_codec_scb_desc->next_scb_ptr = spdifi_scb_desc; 1610 async_codec_scb_desc->sub_list_ptr = ins->the_null_scb; 1611 async_codec_scb_desc->task_entry = s16_async_codec_input_task; 1612 1613 spdifi_scb_desc->parent_scb_ptr = async_codec_scb_desc; 1614 spdifi_scb_desc->next_scb_ptr = spdifo_scb_desc; 1615 spdifi_scb_desc->sub_list_ptr = ins->the_null_scb; 1616 spdifi_scb_desc->task_entry = spdifi_task; 1617 1618 spdifo_scb_desc->parent_scb_ptr = spdifi_scb_desc; 1619 spdifo_scb_desc->next_scb_ptr = fg_entry; 1620 spdifo_scb_desc->sub_list_ptr = ins->the_null_scb; 1621 spdifo_scb_desc->task_entry = spdifo_task; 1622 1623 /* this one is faked, as the parnet of SPDIFO task 1624 is the FG task tree */ 1625 fg_entry->parent_scb_ptr = spdifo_scb_desc; 1626 1627 /* for proc fs */ 1628 cs46xx_dsp_proc_register_scb_desc (chip,spdifo_scb_desc); 1629 cs46xx_dsp_proc_register_scb_desc (chip,spdifi_scb_desc); 1630 cs46xx_dsp_proc_register_scb_desc (chip,async_codec_scb_desc); 1631 1632 /* Async MASTER ENABLE, affects both SPDIF input and output */ 1633 snd_cs46xx_pokeBA0(chip, BA0_ASER_MASTER, 0x1 ); 1634 } 1635 1636 return 0; 1637 } 1638 1639 1640 static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip) 1641 { 1642 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1643 1644 /* set SPDIF output FIFO slot */ 1645 snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, 0); 1646 1647 /* SPDIF output MASTER ENABLE */ 1648 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0); 1649 1650 /* right and left validate bit */ 1651 /*cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default);*/ 1652 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x0); 1653 1654 /* clear fifo pointer */ 1655 cs46xx_poke_via_dsp (chip,SP_SPDIN_FIFOPTR, 0x0); 1656 1657 /* monitor state */ 1658 ins->spdif_status_out &= ~DSP_SPDIF_STATUS_HW_ENABLED; 1659 } 1660 1661 int cs46xx_dsp_enable_spdif_hw (struct snd_cs46xx *chip) 1662 { 1663 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1664 1665 /* if hw-ctrl already enabled, turn off to reset logic ... */ 1666 cs46xx_dsp_disable_spdif_hw (chip); 1667 udelay(50); 1668 1669 /* set SPDIF output FIFO slot */ 1670 snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, ( 0x8000 | ((SP_SPDOUT_FIFO >> 4) << 4) )); 1671 1672 /* SPDIF output MASTER ENABLE */ 1673 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0x80000000); 1674 1675 /* right and left validate bit */ 1676 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default); 1677 1678 /* monitor state */ 1679 ins->spdif_status_out |= DSP_SPDIF_STATUS_HW_ENABLED; 1680 1681 return 0; 1682 } 1683 1684 int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip) 1685 { 1686 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1687 1688 /* turn on amplifier */ 1689 chip->active_ctrl(chip, 1); 1690 chip->amplifier_ctrl(chip, 1); 1691 1692 snd_assert (ins->asynch_rx_scb == NULL,return -EINVAL); 1693 snd_assert (ins->spdif_in_src != NULL,return -EINVAL); 1694 1695 down(&chip->spos_mutex); 1696 1697 if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED) ) { 1698 /* time countdown enable */ 1699 cs46xx_poke_via_dsp (chip,SP_ASER_COUNTDOWN, 0x80000005); 1700 /* NOTE: 80000005 value is just magic. With all values 1701 that I've tested this one seem to give the best result. 1702 Got no explication why. (Benny) */ 1703 1704 /* SPDIF input MASTER ENABLE */ 1705 cs46xx_poke_via_dsp (chip,SP_SPDIN_CONTROL, 0x800003ff); 1706 1707 ins->spdif_status_out |= DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED; 1708 } 1709 1710 /* create and start the asynchronous receiver SCB */ 1711 ins->asynch_rx_scb = cs46xx_dsp_create_asynch_fg_rx_scb(chip,"AsynchFGRxSCB", 1712 ASYNCRX_SCB_ADDR, 1713 SPDIFI_SCB_INST, 1714 SPDIFI_IP_OUTPUT_BUFFER1, 1715 ins->spdif_in_src, 1716 SCB_ON_PARENT_SUBLIST_SCB); 1717 1718 spin_lock_irq(&chip->reg_lock); 1719 1720 /* reset SPDIF input sample buffer pointer */ 1721 /*snd_cs46xx_poke (chip, (SPDIFI_SCB_INST + 0x0c) << 2, 1722 (SPDIFI_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC);*/ 1723 1724 /* reset FIFO ptr */ 1725 /*cs46xx_poke_via_dsp (chip,SP_SPDIN_FIFOPTR, 0x0);*/ 1726 cs46xx_src_link(chip,ins->spdif_in_src); 1727 1728 /* unmute SRC volume */ 1729 cs46xx_dsp_scb_set_volume (chip,ins->spdif_in_src,0x7fff,0x7fff); 1730 1731 spin_unlock_irq(&chip->reg_lock); 1732 1733 /* set SPDIF input sample rate and unmute 1734 NOTE: only 48khz support for SPDIF input this time */ 1735 /* cs46xx_dsp_set_src_sample_rate(chip,ins->spdif_in_src,48000); */ 1736 1737 /* monitor state */ 1738 ins->spdif_status_in = 1; 1739 up(&chip->spos_mutex); 1740 1741 return 0; 1742 } 1743 1744 int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip) 1745 { 1746 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1747 1748 snd_assert (ins->asynch_rx_scb != NULL, return -EINVAL); 1749 snd_assert (ins->spdif_in_src != NULL,return -EINVAL); 1750 1751 down(&chip->spos_mutex); 1752 1753 /* Remove the asynchronous receiver SCB */ 1754 cs46xx_dsp_remove_scb (chip,ins->asynch_rx_scb); 1755 ins->asynch_rx_scb = NULL; 1756 1757 cs46xx_src_unlink(chip,ins->spdif_in_src); 1758 1759 /* monitor state */ 1760 ins->spdif_status_in = 0; 1761 up(&chip->spos_mutex); 1762 1763 /* restore amplifier */ 1764 chip->active_ctrl(chip, -1); 1765 chip->amplifier_ctrl(chip, -1); 1766 1767 return 0; 1768 } 1769 1770 int cs46xx_dsp_enable_pcm_capture (struct snd_cs46xx *chip) 1771 { 1772 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1773 1774 snd_assert (ins->pcm_input == NULL,return -EINVAL); 1775 snd_assert (ins->ref_snoop_scb != NULL,return -EINVAL); 1776 1777 down(&chip->spos_mutex); 1778 ins->pcm_input = cs46xx_add_record_source(chip,ins->ref_snoop_scb,PCMSERIALIN_PCM_SCB_ADDR, 1779 "PCMSerialInput_Wave"); 1780 up(&chip->spos_mutex); 1781 1782 return 0; 1783 } 1784 1785 int cs46xx_dsp_disable_pcm_capture (struct snd_cs46xx *chip) 1786 { 1787 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1788 1789 snd_assert (ins->pcm_input != NULL,return -EINVAL); 1790 1791 down(&chip->spos_mutex); 1792 cs46xx_dsp_remove_scb (chip,ins->pcm_input); 1793 ins->pcm_input = NULL; 1794 up(&chip->spos_mutex); 1795 1796 return 0; 1797 } 1798 1799 int cs46xx_dsp_enable_adc_capture (struct snd_cs46xx *chip) 1800 { 1801 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1802 1803 snd_assert (ins->adc_input == NULL,return -EINVAL); 1804 snd_assert (ins->codec_in_scb != NULL,return -EINVAL); 1805 1806 down(&chip->spos_mutex); 1807 ins->adc_input = cs46xx_add_record_source(chip,ins->codec_in_scb,PCMSERIALIN_SCB_ADDR, 1808 "PCMSerialInput_ADC"); 1809 up(&chip->spos_mutex); 1810 1811 return 0; 1812 } 1813 1814 int cs46xx_dsp_disable_adc_capture (struct snd_cs46xx *chip) 1815 { 1816 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1817 1818 snd_assert (ins->adc_input != NULL,return -EINVAL); 1819 1820 down(&chip->spos_mutex); 1821 cs46xx_dsp_remove_scb (chip,ins->adc_input); 1822 ins->adc_input = NULL; 1823 up(&chip->spos_mutex); 1824 1825 return 0; 1826 } 1827 1828 int cs46xx_poke_via_dsp (struct snd_cs46xx *chip, u32 address, u32 data) 1829 { 1830 u32 temp; 1831 int i; 1832 1833 /* santiy check the parameters. (These numbers are not 100% correct. They are 1834 a rough guess from looking at the controller spec.) */ 1835 if (address < 0x8000 || address >= 0x9000) 1836 return -EINVAL; 1837 1838 /* initialize the SP_IO_WRITE SCB with the data. */ 1839 temp = ( address << 16 ) | ( address & 0x0000FFFF); /* offset 0 <-- address2 : address1 */ 1840 1841 snd_cs46xx_poke(chip,( SPIOWRITE_SCB_ADDR << 2), temp); 1842 snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 1) << 2), data); /* offset 1 <-- data1 */ 1843 snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 2) << 2), data); /* offset 1 <-- data2 */ 1844 1845 /* Poke this location to tell the task to start */ 1846 snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 6) << 2), SPIOWRITE_SCB_ADDR << 0x10); 1847 1848 /* Verify that the task ran */ 1849 for (i=0; i<25; i++) { 1850 udelay(125); 1851 1852 temp = snd_cs46xx_peek(chip,((SPIOWRITE_SCB_ADDR + 6) << 2)); 1853 if (temp == 0x00000000) 1854 break; 1855 } 1856 1857 if (i == 25) { 1858 snd_printk(KERN_ERR "dsp_spos: SPIOWriteTask not responding\n"); 1859 return -EBUSY; 1860 } 1861 1862 return 0; 1863 } 1864 1865 int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right) 1866 { 1867 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1868 struct dsp_scb_descriptor * scb; 1869 1870 down(&chip->spos_mutex); 1871 1872 /* main output */ 1873 scb = ins->master_mix_scb->sub_list_ptr; 1874 while (scb != ins->the_null_scb) { 1875 cs46xx_dsp_scb_set_volume (chip,scb,left,right); 1876 scb = scb->next_scb_ptr; 1877 } 1878 1879 /* rear output */ 1880 scb = ins->rear_mix_scb->sub_list_ptr; 1881 while (scb != ins->the_null_scb) { 1882 cs46xx_dsp_scb_set_volume (chip,scb,left,right); 1883 scb = scb->next_scb_ptr; 1884 } 1885 1886 ins->dac_volume_left = left; 1887 ins->dac_volume_right = right; 1888 1889 up(&chip->spos_mutex); 1890 1891 return 0; 1892 } 1893 1894 int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right) 1895 { 1896 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1897 1898 down(&chip->spos_mutex); 1899 1900 if (ins->asynch_rx_scb != NULL) 1901 cs46xx_dsp_scb_set_volume (chip,ins->asynch_rx_scb, 1902 left,right); 1903 1904 ins->spdif_input_volume_left = left; 1905 ins->spdif_input_volume_right = right; 1906 1907 up(&chip->spos_mutex); 1908 1909 return 0; 1910 } -
GPL/trunk/alsa-kernel/pci/cs46xx/dsp_spos.h
r33 r34 44 44 needs to be reallocated when load 45 45 code into DSP */ 46 typedef enum{46 enum wide_opcode { 47 47 WIDE_FOR_BEGIN_LOOP = 0x20, 48 48 WIDE_FOR_BEGIN_LOOP2, … … 59 59 WIDE_TBEQ_NCOND_GOTOI_ADDR, 60 60 WIDE_TBEQ_NCOND_CALL1_ADDR, 61 } wide_opcode_t;61 }; 62 62 63 63 /* SAMPLE segment */ … … 187 187 #define SP_SPDOUT_CSUV 0x808E 188 188 189 static inline u8 _wrap_all_bits (u8 val) { 189 static inline u8 _wrap_all_bits (u8 val) 190 { 190 191 u8 wrapped; 191 192 … … 202 203 203 204 return wrapped; 204 205 205 } 206 206 207 208 static inline void cs46xx_dsp_spos_update_scb (cs46xx_t * chip,dsp_scb_descriptor_t* scb)207 static inline void cs46xx_dsp_spos_update_scb (struct snd_cs46xx * chip, 208 struct dsp_scb_descriptor * scb) 209 209 { 210 210 /* update nextSCB and subListPtr in SCB */ … … 215 215 } 216 216 217 static inline void cs46xx_dsp_scb_set_volume (cs46xx_t * chip,dsp_scb_descriptor_t * scb, 218 u16 left,u16 right) { 217 static inline void cs46xx_dsp_scb_set_volume (struct snd_cs46xx * chip, 218 struct dsp_scb_descriptor * scb, 219 u16 left, u16 right) 220 { 219 221 unsigned int val = ((0xffff - left) << 16 | (0xffff - right)); 220 222 -
GPL/trunk/alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c
r33 r34 37 37 #include "dsp_spos.h" 38 38 39 typedef struct _proc_scb_info_t{40 dsp_scb_descriptor_t* scb_desc;41 cs46xx_t*chip;42 } proc_scb_info_t;43 44 static void remove_symbol ( cs46xx_t * chip,symbol_entry_t* symbol)45 { 46 dsp_spos_instance_t* ins = chip->dsp_spos_instance;39 struct proc_scb_info { 40 struct dsp_scb_descriptor * scb_desc; 41 struct snd_cs46xx *chip; 42 }; 43 44 static void remove_symbol (struct snd_cs46xx * chip, struct dsp_symbol_entry * symbol) 45 { 46 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 47 47 int symbol_index = (int)(symbol - ins->symbol_table.symbols); 48 48 … … 65 65 } 66 66 67 static void cs46xx_dsp_proc_scb_info_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer) 68 { 69 proc_scb_info_t * scb_info = (proc_scb_info_t *)entry->private_data; 70 dsp_scb_descriptor_t * scb = scb_info->scb_desc; 71 dsp_spos_instance_t * ins; 72 cs46xx_t *chip = scb_info->chip; 67 static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry, 68 struct snd_info_buffer *buffer) 69 { 70 struct proc_scb_info * scb_info = entry->private_data; 71 struct dsp_scb_descriptor * scb = scb_info->scb_desc; 72 struct dsp_spos_instance * ins; 73 struct snd_cs46xx *chip = scb_info->chip; 73 74 int j,col; 74 unsigned longdst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;75 void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; 75 76 76 77 ins = chip->dsp_spos_instance; … … 107 108 } 108 109 109 static void _dsp_unlink_scb ( cs46xx_t *chip,dsp_scb_descriptor_t* scb)110 { 111 dsp_spos_instance_t* ins = chip->dsp_spos_instance;110 static void _dsp_unlink_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb) 111 { 112 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 112 113 unsigned long flags; 113 114 … … 161 162 } 162 163 163 static void _dsp_clear_sample_buffer (cs46xx_t *chip, u32 sample_buffer_addr, int dword_count) 164 { 165 unsigned long dst = chip->region.idx[2].remap_addr + sample_buffer_addr; 164 static void _dsp_clear_sample_buffer (struct snd_cs46xx *chip, u32 sample_buffer_addr, 165 int dword_count) 166 { 167 void __iomem *dst = chip->region.idx[2].remap_addr + sample_buffer_addr; 166 168 int i; 167 169 … … 172 174 } 173 175 174 void cs46xx_dsp_remove_scb ( cs46xx_t *chip, dsp_scb_descriptor_t* scb)175 { 176 dsp_spos_instance_t* ins = chip->dsp_spos_instance;176 void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb) 177 { 178 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 177 179 178 180 /* check integrety */ … … 219 221 220 222 221 void cs46xx_dsp_proc_free_scb_desc ( dsp_scb_descriptor_t* scb)223 void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb) 222 224 { 223 225 if (scb->proc_info) { 224 proc_scb_info_t * scb_info = (proc_scb_info_t *)scb->proc_info->private_data;226 struct proc_scb_info * scb_info = scb->proc_info->private_data; 225 227 226 228 snd_printdd("cs46xx_dsp_proc_free_scb_desc: freeing %s\n",scb->scb_name); … … 234 236 } 235 237 236 void cs46xx_dsp_proc_register_scb_desc (cs46xx_t *chip,dsp_scb_descriptor_t * scb) 237 { 238 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 239 snd_info_entry_t * entry; 240 proc_scb_info_t * scb_info; 238 void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip, 239 struct dsp_scb_descriptor * scb) 240 { 241 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 242 struct snd_info_entry * entry; 243 struct proc_scb_info * scb_info; 241 244 242 245 /* register to proc */ … … 246 249 if ((entry = snd_info_create_card_entry(ins->snd_card, scb->scb_name, 247 250 ins->proc_dsp_dir)) != NULL) { 248 scb_info = kmalloc(sizeof(proc_scb_info_t), GFP_KERNEL);249 if (!scb_info) {250 snd_info_free_entry(entry);251 entry = NULL;252 goto out;253 }254 251 scb_info = kmalloc(sizeof(struct proc_scb_info), GFP_KERNEL); 252 if (!scb_info) { 253 snd_info_free_entry(entry); 254 entry = NULL; 255 goto out; 256 } 257 255 258 scb_info->chip = chip; 256 259 scb_info->scb_desc = scb; … … 268 271 entry = NULL; 269 272 } 270 }271 out:273 } 274 out: 272 275 scb->proc_info = entry; 273 276 } 274 277 } 275 278 276 static dsp_scb_descriptor_t*277 _dsp_create_generic_scb ( cs46xx_t *chip,char * name, u32 * scb_data,u32 dest,278 s ymbol_entry_t* task_entry,279 dsp_scb_descriptor_t* parent_scb,279 static struct dsp_scb_descriptor * 280 _dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest, 281 struct dsp_symbol_entry * task_entry, 282 struct dsp_scb_descriptor * parent_scb, 280 283 int scb_child_type) 281 284 { 282 dsp_spos_instance_t* ins = chip->dsp_spos_instance;283 dsp_scb_descriptor_t* scb;285 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 286 struct dsp_scb_descriptor * scb; 284 287 285 288 unsigned long flags; … … 343 346 } 344 347 345 dsp_scb_descriptor_t*346 cs46xx_dsp_create_generic_scb ( cs46xx_t *chip,char * name, u32 * scb_data,u32 dest,347 char * task_entry_name,348 dsp_scb_descriptor_t* parent_scb,348 static struct dsp_scb_descriptor * 349 cs46xx_dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, 350 u32 dest, char * task_entry_name, 351 struct dsp_scb_descriptor * parent_scb, 349 352 int scb_child_type) 350 353 { 351 s ymbol_entry_t* task_entry;354 struct dsp_symbol_entry * task_entry; 352 355 353 356 task_entry = cs46xx_dsp_lookup_symbol (chip,task_entry_name, … … 363 366 } 364 367 365 dsp_scb_descriptor_t*366 cs46xx_dsp_create_timing_master_scb ( cs46xx_t*chip)367 { 368 dsp_scb_descriptor_t* scb;369 370 timing_master_scb_ttiming_master_scb = {368 struct dsp_scb_descriptor * 369 cs46xx_dsp_create_timing_master_scb (struct snd_cs46xx *chip) 370 { 371 struct dsp_scb_descriptor * scb; 372 373 struct dsp_timing_master_scb timing_master_scb = { 371 374 { 0, 372 375 0, … … 397 400 398 401 399 dsp_scb_descriptor_t * 400 cs46xx_dsp_create_codec_out_scb(cs46xx_t * chip,char * codec_name, 401 u16 channel_disp,u16 fifo_addr, 402 u16 child_scb_addr, 403 u32 dest,dsp_scb_descriptor_t * parent_scb, 402 struct dsp_scb_descriptor * 403 cs46xx_dsp_create_codec_out_scb(struct snd_cs46xx * chip, char * codec_name, 404 u16 channel_disp, u16 fifo_addr, u16 child_scb_addr, 405 u32 dest, struct dsp_scb_descriptor * parent_scb, 404 406 int scb_child_type) 405 407 { 406 dsp_scb_descriptor_t* scb;407 408 codec_output_scb_tcodec_out_scb = {408 struct dsp_scb_descriptor * scb; 409 410 struct dsp_codec_output_scb codec_out_scb = { 409 411 { 0, 410 412 0, … … 423 425 0, /* COstrmRsConfig */ 424 426 0, /* COstrmBufPtr */ 425 /*channel_disp*/0, 426 /*fifo_addr*/0, /* leftChanBaseIOaddr:rightChanIOdisp */ 427 channel_disp,fifo_addr, /* leftChanBaseIOaddr:rightChanIOdisp */ 427 428 0x0000,0x0080, /* (!AC97!) COexpVolChangeRate:COscaleShiftCount */ 428 0,/*child_scb_addr*/0 /* COreserved - need child scb to work with rom code */ 429 }; 430 431 codec_out_scb.left_chan_base_IO_addr = channel_disp; 432 codec_out_scb.right_chan_IO_disp = fifo_addr; 433 codec_out_scb.last_sub_ptr = child_scb_addr; 434 429 0,child_scb_addr /* COreserved - need child scb to work with rom code */ 430 }; 431 432 435 433 scb = cs46xx_dsp_create_generic_scb(chip,codec_name,(u32 *)&codec_out_scb, 436 434 dest,"S16_CODECOUTPUTTASK",parent_scb, … … 440 438 } 441 439 442 dsp_scb_descriptor_t * 443 cs46xx_dsp_create_codec_in_scb(cs46xx_t * chip,char * codec_name, 444 u16 channel_disp,u16 fifo_addr, 445 u16 sample_buffer_addr, 446 u32 dest,dsp_scb_descriptor_t * parent_scb, 447 int scb_child_type) 448 { 449 450 dsp_scb_descriptor_t * scb; 451 codec_input_scb_t codec_input_scb = { 440 struct dsp_scb_descriptor * 441 cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name, 442 u16 channel_disp, u16 fifo_addr, u16 sample_buffer_addr, 443 u32 dest, struct dsp_scb_descriptor * parent_scb, 444 int scb_child_type) 445 { 446 447 struct dsp_scb_descriptor * scb; 448 struct dsp_codec_input_scb codec_input_scb = { 452 449 { 0, 453 450 0, … … 471 468 472 469 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64, /* strmRsConfig */ 473 /*sample_buffer_addr << 0x10*/0, /* strmBufPtr; defined as a dword ptr, used as a byte ptr */474 /*channel_disp*/0,/*fifo_addr*/0, /* (!AC97!) leftChanBaseINaddr=AC97primary470 sample_buffer_addr << 0x10, /* strmBufPtr; defined as a dword ptr, used as a byte ptr */ 471 channel_disp,fifo_addr, /* (!AC97!) leftChanBaseINaddr=AC97primary 475 472 link input slot 3 :rightChanINdisp=""slot 4 */ 476 473 0x0000,0x0000, /* (!AC97!) ????:scaleShiftCount; no shift needed … … 478 475 0x80008000 /* ??clw cwcgame.scb has 0 */ 479 476 }; 480 481 codec_input_scb.strm_buf_ptr = sample_buffer_addr << 0x10; 482 codec_input_scb.rightChanINdisp = channel_disp; 483 codec_input_scb.left_chan_base_IN_addr = fifo_addr; 477 484 478 scb = cs46xx_dsp_create_generic_scb(chip,codec_name,(u32 *)&codec_input_scb, 485 479 dest,"S16_CODECINPUTTASK",parent_scb, … … 489 483 490 484 491 dsp_scb_descriptor_t*492 cs46xx_dsp_create_pcm_reader_scb( cs46xx_t * chip,char * scb_name,493 u16 sample_buffer_addr, u32 dest,485 static struct dsp_scb_descriptor * 486 cs46xx_dsp_create_pcm_reader_scb(struct snd_cs46xx * chip, char * scb_name, 487 u16 sample_buffer_addr, u32 dest, 494 488 int virtual_channel, u32 playback_hw_addr, 495 dsp_scb_descriptor_t * parent_scb, 496 489 struct dsp_scb_descriptor * parent_scb, 497 490 int scb_child_type) 498 491 { 499 dsp_spos_instance_t* ins = chip->dsp_spos_instance;500 dsp_scb_descriptor_t* scb;501 502 generic_scb_tpcm_reader_scb = {492 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 493 struct dsp_scb_descriptor * scb; 494 495 struct dsp_generic_scb pcm_reader_scb = { 503 496 504 497 /* … … 534 527 /* Barnette said that is what we should use since */ 535 528 /* we are not running in optimized mode? */ 536 /*DMA_RQ_C2_AC_NONE + */537 /*DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG +*//* set play interrupt (bit0) in HISR when source */529 DMA_RQ_C2_AC_NONE + 530 DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG + /* set play interrupt (bit0) in HISR when source */ 538 531 /* buffer (on host) crosses half-way point */ 539 /*virtual_channel*/0, /* Play DMA channel arbitrarily set to 0 */540 /*playback_hw_addr*/0, /* HostBuffAddr (source) */541 /*DMA_RQ_SD_SP_SAMPLE_ADDR + *//* destination buffer is in SP Sample Memory */542 /*sample_buffer_addr */0/* SP Buffer Address (destination) */532 virtual_channel, /* Play DMA channel arbitrarily set to 0 */ 533 playback_hw_addr, /* HostBuffAddr (source) */ 534 DMA_RQ_SD_SP_SAMPLE_ADDR + /* destination buffer is in SP Sample Memory */ 535 sample_buffer_addr /* SP Buffer Address (destination) */ 543 536 }, 544 537 /* Scatter/gather DMA requestor extension (5 ints) */ … … 556 549 /* rsConfig register for stream buffer (rsDMA reg. is loaded from basicReq.daw */ 557 550 /* for incoming streams, or basicReq.saw, for outgoing streams) */ 558 /*RSCONFIG_DMA_ENABLE + *//* enable DMA */559 /*(19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) + *//* MAX_DMA_SIZE picked to be 19 since SPUD */551 RSCONFIG_DMA_ENABLE + /* enable DMA */ 552 (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) + /* MAX_DMA_SIZE picked to be 19 since SPUD */ 560 553 /* uses it for some reason */ 561 /*((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) +*//* stream number = SCBaddr/16 */562 /*RSCONFIG_SAMPLE_16STEREO + */563 /*RSCONFIG_MODULO_32*/0, /* dest buffer(PCMreaderBuf) is 32 dwords (256 bytes) */554 ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) + /* stream number = SCBaddr/16 */ 555 RSCONFIG_SAMPLE_16STEREO + 556 RSCONFIG_MODULO_32, /* dest buffer(PCMreaderBuf) is 32 dwords (256 bytes) */ 564 557 /* Stream sample pointer & MAC-unit mode for this stream */ 565 /*(sample_buffer_addr << 0x10)*/0,558 (sample_buffer_addr << 0x10), 566 559 /* Fractional increment per output sample in the input sample buffer */ 567 560 0, … … 574 567 }; 575 568 576 pcm_reader_scb.basic_req.dmw = DMA_RQ_C2_AC_NONE +577 DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG +578 virtual_channel;579 pcm_reader_scb.basic_req.saw = playback_hw_addr;580 pcm_reader_scb.basic_req.daw = DMA_RQ_SD_SP_SAMPLE_ADDR + sample_buffer_addr;581 pcm_reader_scb.strm_rs_config = RSCONFIG_DMA_ENABLE +582 (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) +583 ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) +584 RSCONFIG_SAMPLE_16STEREO +585 RSCONFIG_MODULO_32;586 pcm_reader_scb.strm_buf_ptr = sample_buffer_addr << 0x10;587 569 if (ins->null_algorithm == NULL) { 588 570 ins->null_algorithm = cs46xx_dsp_lookup_symbol (chip,"NULLALGORITHM", … … 604 586 #define GOF_PER_SEC 200 605 587 606 dsp_scb_descriptor_t*607 cs46xx_dsp_create_src_task_scb( cs46xx_t * chip,char * scb_name,588 struct dsp_scb_descriptor * 589 cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name, 608 590 int rate, 609 591 u16 src_buffer_addr, 610 u16 src_delay_buffer_addr, u32 dest,611 dsp_scb_descriptor_t* parent_scb,592 u16 src_delay_buffer_addr, u32 dest, 593 struct dsp_scb_descriptor * parent_scb, 612 594 int scb_child_type, 613 595 int pass_through) 614 596 { 615 597 616 dsp_spos_instance_t* ins = chip->dsp_spos_instance;617 dsp_scb_descriptor_t* scb;598 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 599 struct dsp_scb_descriptor * scb; 618 600 unsigned int tmp1, tmp2; 619 601 unsigned int phiIncr; … … 652 634 653 635 { 654 s rc_task_scb_tsrc_task_scb = {636 struct dsp_src_task_scb src_task_scb = { 655 637 0x0028,0x00c8, 656 638 0x5555,0x0000, 657 639 0x0000,0x0000, 658 /*src_buffer_addr*/0,1,659 /*correctionPerGOF*/0,/*correctionPerSec*/0,640 src_buffer_addr,1, 641 correctionPerGOF,correctionPerSec, 660 642 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32, 661 0x0000, /*src_delay_buffer_addr*/0,643 0x0000,src_delay_buffer_addr, 662 644 0x0, 663 0x080, /*(src_delay_buffer_addr + (24 * 4))*/0,645 0x080,(src_delay_buffer_addr + (24 * 4)), 664 646 0,0, /* next_scb, sub_list_ptr */ 665 647 0,0, /* entry, this_spb */ 666 648 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8, 667 /*src_buffer_addr << 0x10*/0,668 /*phiIncr*/0,649 src_buffer_addr << 0x10, 650 phiIncr, 669 651 { 670 /*0xffff - ins->dac_volume_right*/0,/*0xffff - ins->dac_volume_left*/0,671 /*0xffff - ins->dac_volume_right*/0,/*0xffff - ins->dac_volume_left*/0652 0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left, 653 0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left 672 654 } 673 655 }; 674 675 src_task_scb.output_buf_producer_ptr = src_buffer_addr; 676 src_task_scb.gof_length = correctionPerGOF; 677 src_task_scb.gofs_per_sec = correctionPerSec; 678 src_task_scb.input_buf_consumer_ptr = src_delay_buffer_addr; 679 src_task_scb.input_buf_producer_ptr = (src_delay_buffer_addr + (24 * 4)); 680 src_task_scb.src_strm_buf_ptr = src_buffer_addr << 0x10; 681 src_task_scb.phiIncr6int_26frac = phiIncr; 682 src_task_scb.src_vol_ctrl.rightTarg = 0xffff - ins->dac_volume_right; 683 src_task_scb.src_vol_ctrl.leftTarg = 0xffff - ins->dac_volume_left; 684 src_task_scb.src_vol_ctrl.rightVol = 0xffff - ins->dac_volume_right; 685 src_task_scb.src_vol_ctrl.leftVol = 0xffff - ins->dac_volume_left; 686 656 687 657 if (ins->s16_up == NULL) { 688 658 ins->s16_up = cs46xx_dsp_lookup_symbol (chip,"S16_UPSRC", … … 702 672 /* wont work with any other rate than 703 673 the native DSP rate */ 704 //snd_assert (rate == 48000);674 snd_assert (rate = 48000); 705 675 706 676 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&src_task_scb, … … 719 689 } 720 690 721 dsp_scb_descriptor_t * 722 cs46xx_dsp_create_filter_scb(cs46xx_t * chip,char * scb_name, 723 u16 buffer_addr,u32 dest, 724 dsp_scb_descriptor_t * parent_scb, 691 #if 0 /* not used */ 692 struct dsp_scb_descriptor * 693 cs46xx_dsp_create_filter_scb(struct snd_cs46xx * chip, char * scb_name, 694 u16 buffer_addr, u32 dest, 695 struct dsp_scb_descriptor * parent_scb, 725 696 int scb_child_type) { 726 dsp_scb_descriptor_t* scb;697 struct dsp_scb_descriptor * scb; 727 698 728 filter_scb_tfilter_scb = {729 /* .a0_right = */0x41a9,730 /* .a0_left = */0x41a9,731 /* .a1_right = */0xb8e4,732 /* .a1_left = */0xb8e4,733 /* .a2_right = */0x3e55,734 /* .a2_left = */0x3e55,735 736 /* .filter_unused3 = */0x0000,737 /* .filter_unused2 = */0x0000,738 739 /* .output_buf_ptr = *//*buffer_addr*/0,740 /* .init = */0x000,741 742 /* .prev_sample_output1 = */0x00000000,743 /* .prev_sample_output2 = */0x00000000,744 745 /* .prev_sample_input1 = */0x00000000,746 /* .prev_sample_input2 = */0x00000000,747 748 /* .next_scb_ptr = */0x0000,749 /* .sub_list_ptr = */0x0000,750 751 /* .entry_point = */0x0000,752 /* .spb_ptr = */0x0000,753 754 /* .b0_right = */0x0e38,755 /* .b0_left = */0x0e38,756 /* .b1_right = */0x1c71,757 /* .b1_left = */0x1c71,758 /* .b2_right = */0x0e38,759 /* .b2_left = */0x0e38,699 struct dsp_filter_scb filter_scb = { 700 .a0_right = 0x41a9, 701 .a0_left = 0x41a9, 702 .a1_right = 0xb8e4, 703 .a1_left = 0xb8e4, 704 .a2_right = 0x3e55, 705 .a2_left = 0x3e55, 706 707 .filter_unused3 = 0x0000, 708 .filter_unused2 = 0x0000, 709 710 .output_buf_ptr = buffer_addr, 711 .init = 0x000, 712 713 .prev_sample_output1 = 0x00000000, 714 .prev_sample_output2 = 0x00000000, 715 716 .prev_sample_input1 = 0x00000000, 717 .prev_sample_input2 = 0x00000000, 718 719 .next_scb_ptr = 0x0000, 720 .sub_list_ptr = 0x0000, 721 722 .entry_point = 0x0000, 723 .spb_ptr = 0x0000, 724 725 .b0_right = 0x0e38, 726 .b0_left = 0x0e38, 727 .b1_right = 0x1c71, 728 .b1_left = 0x1c71, 729 .b2_right = 0x0e38, 730 .b2_left = 0x0e38, 760 731 }; 761 732 762 filter_scb.output_buf_ptr = buffer_addr;763 733 764 734 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&filter_scb, … … 768 738 return scb; 769 739 } 770 771 dsp_scb_descriptor_t * 772 cs46xx_dsp_create_mix_only_scb(cs46xx_t * chip,char * scb_name, 773 u16 mix_buffer_addr,u32 dest, 774 dsp_scb_descriptor_t * parent_scb, 740 #endif /* not used */ 741 742 struct dsp_scb_descriptor * 743 cs46xx_dsp_create_mix_only_scb(struct snd_cs46xx * chip, char * scb_name, 744 u16 mix_buffer_addr, u32 dest, 745 struct dsp_scb_descriptor * parent_scb, 775 746 int scb_child_type) 776 747 { 777 dsp_scb_descriptor_t* scb;778 779 mix_only_scb_tmaster_mix_scb = {748 struct dsp_scb_descriptor * scb; 749 750 struct dsp_mix_only_scb master_mix_scb = { 780 751 /* 0 */ { 0, 781 752 /* 1 */ 0, 782 /* 2 */ /*mix_buffer_addr*/0,753 /* 2 */ mix_buffer_addr, 783 754 /* 3 */ 0 784 755 /* */ }, … … 793 764 /* A */ 0,0, 794 765 /* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32, 795 /* C */ /*(mix_buffer_addr + (16 * 4)) << 0x10*/0,766 /* C */ (mix_buffer_addr + (16 * 4)) << 0x10, 796 767 /* D */ 0, 797 768 { … … 801 772 }; 802 773 803 master_mix_scb.basic_req.saw = mix_buffer_addr;804 master_mix_scb.strm_buf_ptr = (mix_buffer_addr + (16 * 4)) << 0x10;805 774 806 775 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&master_mix_scb, … … 811 780 812 781 813 dsp_scb_descriptor_t*814 cs46xx_dsp_create_mix_to_ostream_scb( cs46xx_t * chip,char * scb_name,815 u16 mix_buffer_addr, u16 writeback_spb,u32 dest,816 dsp_scb_descriptor_t* parent_scb,782 struct dsp_scb_descriptor * 783 cs46xx_dsp_create_mix_to_ostream_scb(struct snd_cs46xx * chip, char * scb_name, 784 u16 mix_buffer_addr, u16 writeback_spb, u32 dest, 785 struct dsp_scb_descriptor * parent_scb, 817 786 int scb_child_type) 818 787 { 819 dsp_scb_descriptor_t* scb;820 821 mix2_ostream_scb_tmix2_ostream_scb = {788 struct dsp_scb_descriptor * scb; 789 790 struct dsp_mix2_ostream_scb mix2_ostream_scb = { 822 791 /* Basic (non scatter/gather) DMA requestor (4 ints) */ 823 792 { … … 833 802 834 803 CS46XX_DSP_CAPTURE_CHANNEL, 835 /*DMA_RQ_SD_SP_SAMPLE_ADDR +836 mix_buffer_addr */0,804 DMA_RQ_SD_SP_SAMPLE_ADDR + 805 mix_buffer_addr, 837 806 0x0 838 807 }, … … 840 809 { 0, 0, 0, 0, 0, }, 841 810 0,0, 842 0, /*writeback_spb*/0,843 844 /*RSCONFIG_DMA_ENABLE +811 0,writeback_spb, 812 813 RSCONFIG_DMA_ENABLE + 845 814 (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) + 846 815 … … 848 817 RSCONFIG_DMA_TO_HOST + 849 818 RSCONFIG_SAMPLE_16STEREO + 850 RSCONFIG_MODULO_64 */0,851 /*(mix_buffer_addr + (32 * 4)) << 0x10*/0,819 RSCONFIG_MODULO_64, 820 (mix_buffer_addr + (32 * 4)) << 0x10, 852 821 1,0, 853 822 0x0001,0x0080, 854 823 0xFFFF,0 855 }; 856 857 mix2_ostream_scb.basic_req.saw = DMA_RQ_SD_SP_SAMPLE_ADDR + mix_buffer_addr; 858 mix2_ostream_scb.this_spb = writeback_spb; 859 mix2_ostream_scb.strm_rs_config = RSCONFIG_DMA_ENABLE + 860 (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) + 861 ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) + 862 RSCONFIG_DMA_TO_HOST + 863 RSCONFIG_SAMPLE_16STEREO + 864 RSCONFIG_MODULO_64; 865 mix2_ostream_scb.strm_buf_ptr = (mix_buffer_addr + (32 * 4)) << 0x10; 824 }; 866 825 867 826 … … 875 834 876 835 877 dsp_scb_descriptor_t*878 cs46xx_dsp_create_vari_decimate_scb( cs46xx_t* chip,char * scb_name,836 struct dsp_scb_descriptor * 837 cs46xx_dsp_create_vari_decimate_scb(struct snd_cs46xx * chip,char * scb_name, 879 838 u16 vari_buffer_addr0, 880 839 u16 vari_buffer_addr1, 881 840 u32 dest, 882 dsp_scb_descriptor_t* parent_scb,841 struct dsp_scb_descriptor * parent_scb, 883 842 int scb_child_type) 884 843 { 885 844 886 dsp_scb_descriptor_t* scb;887 888 vari_decimate_scb_tvari_decimate_scb = {845 struct dsp_scb_descriptor * scb; 846 847 struct dsp_vari_decimate_scb vari_decimate_scb = { 889 848 0x0028,0x00c8, 890 849 0x5555,0x0000, 891 850 0x0000,0x0000, 892 /*vari_buffer_addr0*/0,/*vari_buffer_addr1*/0,851 vari_buffer_addr0,vari_buffer_addr1, 893 852 894 853 0x0028,0x00c8, … … 897 856 0xFF800000, 898 857 0, 899 0x0080, /*vari_buffer_addr1 + (25 * 4)*/0,858 0x0080,vari_buffer_addr1 + (25 * 4), 900 859 901 860 0,0, … … 903 862 904 863 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8, 905 /*vari_buffer_addr0 << 0x10*/0,864 vari_buffer_addr0 << 0x10, 906 865 0x04000000, 907 866 { … … 911 870 }; 912 871 913 vari_decimate_scb.vdec_output_buf_producer_ptr = vari_buffer_addr0;914 vari_decimate_scb.vdec_input_buf_consumer_ptr = vari_buffer_addr1;915 vari_decimate_scb.vdec_input_buf_producer_ptr = vari_buffer_addr1 + (25 * 4);916 vari_decimate_scb.vdec_strm_buf_ptr = vari_buffer_addr0 << 0x10;917 918 872 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&vari_decimate_scb, 919 873 dest,"VARIDECIMATE",parent_scb, … … 924 878 925 879 926 dsp_scb_descriptor_t*927 cs46xx_dsp_create_pcm_serial_input_scb( cs46xx_t * chip,char * scb_name,u32 dest,928 dsp_scb_descriptor_t* input_scb,929 dsp_scb_descriptor_t* parent_scb,880 static struct dsp_scb_descriptor * 881 cs46xx_dsp_create_pcm_serial_input_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, 882 struct dsp_scb_descriptor * input_scb, 883 struct dsp_scb_descriptor * parent_scb, 930 884 int scb_child_type) 931 885 { 932 886 933 dsp_scb_descriptor_t* scb;934 935 936 pcm_serial_input_scb_tpcm_serial_input_scb = {887 struct dsp_scb_descriptor * scb; 888 889 890 struct dsp_pcm_serial_input_scb pcm_serial_input_scb = { 937 891 { 0, 938 892 0, … … 953 907 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_16, 954 908 0, 955 /* 0xD */ 0, /*input_scb->address*/0,909 /* 0xD */ 0,input_scb->address, 956 910 { 957 911 /* 0xE */ 0x8000,0x8000, … … 960 914 }; 961 915 962 pcm_serial_input_scb.codec_input_buf_scb = input_scb->address;963 964 916 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&pcm_serial_input_scb, 965 917 dest,"PCMSERIALINPUTTASK",parent_scb, … … 969 921 970 922 971 dsp_scb_descriptor_t*972 cs46xx_dsp_create_asynch_fg_tx_scb( cs46xx_t * chip,char * scb_name,u32 dest,923 static struct dsp_scb_descriptor * 924 cs46xx_dsp_create_asynch_fg_tx_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, 973 925 u16 hfg_scb_address, 974 926 u16 asynch_buffer_address, 975 dsp_scb_descriptor_t* parent_scb,927 struct dsp_scb_descriptor * parent_scb, 976 928 int scb_child_type) 977 929 { 978 930 979 dsp_scb_descriptor_t* scb;980 981 asynch_fg_tx_scb_tasynch_fg_tx_scb = {931 struct dsp_scb_descriptor * scb; 932 933 struct dsp_asynch_fg_tx_scb asynch_fg_tx_scb = { 982 934 0xfc00,0x03ff, /* Prototype sample buffer size of 256 dwords */ 983 935 0x0058,0x0028, /* Min Delta 7 dwords == 28 bytes */ 984 936 /* : Max delta 25 dwords == 100 bytes */ 985 0, /*hfg_scb_address*/0, /* Point to HFG task SCB */937 0,hfg_scb_address, /* Point to HFG task SCB */ 986 938 0,0, /* Initialize current Delta and Consumer ptr adjustment count */ 987 939 0, /* Initialize accumulated Phi to 0 */ … … 995 947 996 948 0,0, 997 0, /*dest + AFGTxAccumPhi*/0,949 0,dest + AFGTxAccumPhi, 998 950 999 951 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_256, /* Stereo, 256 dword */ 1000 /*(asynch_buffer_address) << 0x10*/0, /* This should be automagically synchronized952 (asynch_buffer_address) << 0x10, /* This should be automagically synchronized 1001 953 to the producer pointer */ 1002 954 … … 1006 958 0x8000,0x8000, /* Volume controls are unused at this time */ 1007 959 0x8000,0x8000 1008 }; 1009 asynch_fg_tx_scb.hfg_scb_ptr = hfg_scb_address; 1010 asynch_fg_tx_scb.this_ptr = dest + AFGTxAccumPhi; 1011 asynch_fg_tx_scb.strm_buf_ptr = (asynch_buffer_address) << 0x10; 960 }; 1012 961 1013 962 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&asynch_fg_tx_scb, … … 1019 968 1020 969 1021 dsp_scb_descriptor_t*1022 cs46xx_dsp_create_asynch_fg_rx_scb( cs46xx_t * chip,char * scb_name,u32 dest,970 struct dsp_scb_descriptor * 971 cs46xx_dsp_create_asynch_fg_rx_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, 1023 972 u16 hfg_scb_address, 1024 973 u16 asynch_buffer_address, 1025 dsp_scb_descriptor_t* parent_scb,974 struct dsp_scb_descriptor * parent_scb, 1026 975 int scb_child_type) 1027 976 { 1028 dsp_spos_instance_t* ins = chip->dsp_spos_instance;1029 dsp_scb_descriptor_t* scb;1030 1031 asynch_fg_rx_scb_tasynch_fg_rx_scb = {977 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 978 struct dsp_scb_descriptor * scb; 979 980 struct dsp_asynch_fg_rx_scb asynch_fg_rx_scb = { 1032 981 0xfe00,0x01ff, /* Prototype sample buffer size of 128 dwords */ 1033 982 0x0064,0x001c, /* Min Delta 7 dwords == 28 bytes */ 1034 983 /* : Max delta 25 dwords == 100 bytes */ 1035 0, /*hfg_scb_address*/0, /* Point to HFG task SCB */984 0,hfg_scb_address, /* Point to HFG task SCB */ 1036 985 0,0, /* Initialize current Delta and Consumer ptr adjustment count */ 1037 986 { … … 1044 993 1045 994 0,0, 1046 0, /*dest*/0,995 0,dest, 1047 996 1048 997 RSCONFIG_MODULO_128 | 1049 998 RSCONFIG_SAMPLE_16STEREO, /* Stereo, 128 dword */ 1050 /*( (asynch_buffer_address + (16 * 4)) << 0x10)*/0, /* This should be automagically999 ( (asynch_buffer_address + (16 * 4)) << 0x10), /* This should be automagically 1051 1000 synchrinized to the producer pointer */ 1052 1001 … … 1056 1005 1057 1006 /* Set IEC958 input volume */ 1058 /*0xffff - ins->spdif_input_volume_right*/0,/*0xffff - ins->spdif_input_volume_left*/0, 1059 /*0xffff - ins->spdif_input_volume_right*/0,/*0xffff - ins->spdif_input_volume_left*/0, 1060 }; 1061 1062 asynch_fg_rx_scb.hfg_scb_ptr = hfg_scb_address; 1063 asynch_fg_rx_scb.this_ptr = dest; 1064 asynch_fg_rx_scb.strm_buf_ptr = ( (asynch_buffer_address + (16 * 4)) << 0x10); 1065 asynch_fg_rx_scb.right_targ = 0xffff - ins->spdif_input_volume_right; 1066 asynch_fg_rx_scb.left_targ = 0xffff - ins->spdif_input_volume_left; 1067 asynch_fg_rx_scb.right_vol = 0xffff - ins->spdif_input_volume_right; 1068 asynch_fg_rx_scb.left_vol = 0xffff - ins->spdif_input_volume_left; 1007 0xffff - ins->spdif_input_volume_right,0xffff - ins->spdif_input_volume_left, 1008 0xffff - ins->spdif_input_volume_right,0xffff - ins->spdif_input_volume_left, 1009 }; 1069 1010 1070 1011 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&asynch_fg_rx_scb, … … 1076 1017 1077 1018 1078 dsp_scb_descriptor_t * 1079 cs46xx_dsp_create_output_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest, 1019 #if 0 /* not used */ 1020 struct dsp_scb_descriptor * 1021 cs46xx_dsp_create_output_snoop_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, 1080 1022 u16 snoop_buffer_address, 1081 dsp_scb_descriptor_t* snoop_scb,1082 dsp_scb_descriptor_t* parent_scb,1023 struct dsp_scb_descriptor * snoop_scb, 1024 struct dsp_scb_descriptor * parent_scb, 1083 1025 int scb_child_type) 1084 1026 { 1085 1027 1086 dsp_scb_descriptor_t* scb;1087 1088 output_snoop_scb_toutput_snoop_scb = {1028 struct dsp_scb_descriptor * scb; 1029 1030 struct dsp_output_snoop_scb output_snoop_scb = { 1089 1031 { 0, /* not used. Zero */ 1090 1032 0, … … 1104 1046 1105 1047 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64, 1106 /*snoop_buffer_address << 0x10*/0,1048 snoop_buffer_address << 0x10, 1107 1049 0,0, 1108 1050 0, 1109 0, /*snoop_scb->address*/01051 0,snoop_scb->address 1110 1052 }; 1111 1112 output_snoop_scb.strm_buf_ptr = snoop_buffer_address << 0x10; 1113 output_snoop_scb.input_scb = snoop_scb->address; 1053 1114 1054 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&output_snoop_scb, 1115 1055 dest,"OUTPUTSNOOP",parent_scb, … … 1117 1057 return scb; 1118 1058 } 1119 1120 1121 dsp_scb_descriptor_t * 1122 cs46xx_dsp_create_spio_write_scb(cs46xx_t * chip,char * scb_name,u32 dest, 1123 dsp_scb_descriptor_t * parent_scb, 1059 #endif /* not used */ 1060 1061 1062 struct dsp_scb_descriptor * 1063 cs46xx_dsp_create_spio_write_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, 1064 struct dsp_scb_descriptor * parent_scb, 1124 1065 int scb_child_type) 1125 1066 { 1126 dsp_scb_descriptor_t* scb;1127 1128 s pio_write_scb_tspio_write_scb = {1067 struct dsp_scb_descriptor * scb; 1068 1069 struct dsp_spio_write_scb spio_write_scb = { 1129 1070 0,0, /* SPIOWAddress2:SPIOWAddress1; */ 1130 1071 0, /* SPIOWData1; */ … … 1155 1096 } 1156 1097 1157 dsp_scb_descriptor_t * cs46xx_dsp_create_magic_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest, 1158 u16 snoop_buffer_address, 1159 dsp_scb_descriptor_t * snoop_scb, 1160 dsp_scb_descriptor_t * parent_scb, 1161 int scb_child_type) 1162 { 1163 dsp_scb_descriptor_t * scb; 1164 1165 magic_snoop_task_t magic_snoop_scb = { 1098 struct dsp_scb_descriptor * 1099 cs46xx_dsp_create_magic_snoop_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, 1100 u16 snoop_buffer_address, 1101 struct dsp_scb_descriptor * snoop_scb, 1102 struct dsp_scb_descriptor * parent_scb, 1103 int scb_child_type) 1104 { 1105 struct dsp_scb_descriptor * scb; 1106 1107 struct dsp_magic_snoop_task magic_snoop_scb = { 1166 1108 /* 0 */ 0, /* i0 */ 1167 1109 /* 1 */ 0, /* i1 */ 1168 /* 2 */ /*snoop_buffer_address << 0x10*/0,1169 /* 3 */ 0, /*snoop_scb->address*/0,1110 /* 2 */ snoop_buffer_address << 0x10, 1111 /* 3 */ 0,snoop_scb->address, 1170 1112 /* 4 */ 0, /* i3 */ 1171 1113 /* 5 */ 0, /* i4 */ … … 1176 1118 /* A */ 0,0, /* entry_point, this_ptr */ 1177 1119 /* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64, 1178 /* C */ /*snoop_buffer_address << 0x10*/0,1120 /* C */ snoop_buffer_address << 0x10, 1179 1121 /* D */ 0, 1180 1122 /* E */ { 0x8000,0x8000, … … 1183 1125 }; 1184 1126 1185 magic_snoop_scb.strm_buf_ptr1 = snoop_buffer_address << 0x10;1186 magic_snoop_scb.snoop_scb = snoop_scb->address;1187 magic_snoop_scb.strm_buf_ptr2 = snoop_buffer_address << 0x10;1188 1127 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&magic_snoop_scb, 1189 1128 dest,"MAGICSNOOPTASK",parent_scb, … … 1193 1132 } 1194 1133 1195 static dsp_scb_descriptor_t * find_next_free_scb (cs46xx_t * chip,dsp_scb_descriptor_t * from) 1196 { 1197 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1198 dsp_scb_descriptor_t * scb = from; 1134 static struct dsp_scb_descriptor * 1135 find_next_free_scb (struct snd_cs46xx * chip, struct dsp_scb_descriptor * from) 1136 { 1137 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1138 struct dsp_scb_descriptor * scb = from; 1199 1139 1200 1140 while (scb->next_scb_ptr != ins->the_null_scb) { … … 1276 1216 }; 1277 1217 1278 pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip, 1279 u32 sample_rate, void * private_data, 1280 u32 hw_dma_addr, 1281 int pcm_channel_id) 1282 { 1283 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1284 dsp_scb_descriptor_t * src_scb = NULL,* pcm_scb, * mixer_scb = NULL; 1285 dsp_scb_descriptor_t * src_parent_scb = NULL; 1286 1287 /* dsp_scb_descriptor_t * pcm_parent_scb; */ 1218 struct dsp_pcm_channel_descriptor * 1219 cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, 1220 u32 sample_rate, void * private_data, 1221 u32 hw_dma_addr, 1222 int pcm_channel_id) 1223 { 1224 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1225 struct dsp_scb_descriptor * src_scb = NULL, * pcm_scb, * mixer_scb = NULL; 1226 struct dsp_scb_descriptor * src_parent_scb = NULL; 1227 1228 /* struct dsp_scb_descriptor * pcm_parent_scb; */ 1288 1229 char scb_name[DSP_MAX_SCB_NAME]; 1289 int i, pcm_index = -1, insert_point, src_index = -1,pass_through = 0;1230 int i, pcm_index = -1, insert_point, src_index = -1, pass_through = 0; 1290 1231 unsigned long flags; 1291 1232 … … 1302 1243 case DSP_PCM_S71_CHANNEL: 1303 1244 /* TODO */ 1304 //snd_assert(0);1245 snd_assert(0); 1305 1246 break; 1306 1247 case DSP_IEC958_CHANNEL: … … 1318 1259 break; 1319 1260 default: 1320 //snd_assert (0);1261 snd_assert (0); 1321 1262 return NULL; 1322 1263 } … … 1375 1316 } 1376 1317 1377 sprintf (scb_name, /*DSP_MAX_SCB_NAME,*/"SrcTask_SCB%d",src_index);1318 sprintf (scb_name,"SrcTask_SCB%d",src_index); 1378 1319 1379 1320 snd_printdd( "dsp_spos: creating SRC \"%s\"\n",scb_name); … … 1399 1340 1400 1341 1401 sprintf (scb_name, /*DSP_MAX_SCB_NAME,*/"PCMReader_SCB%d",pcm_index);1342 sprintf (scb_name,"PCMReader_SCB%d",pcm_index); 1402 1343 1403 1344 snd_printdd( "dsp_spos: creating PCM \"%s\" (%d)\n",scb_name, … … 1435 1376 } 1436 1377 1437 int cs46xx_dsp_pcm_channel_set_period ( cs46xx_t* chip,1438 pcm_channel_descriptor_t* pcm_channel,1378 int cs46xx_dsp_pcm_channel_set_period (struct snd_cs46xx * chip, 1379 struct dsp_pcm_channel_descriptor * pcm_channel, 1439 1380 int period_size) 1440 1381 { … … 1474 1415 } 1475 1416 1476 int cs46xx_dsp_pcm_ostream_set_period ( cs46xx_t* chip,1417 int cs46xx_dsp_pcm_ostream_set_period (struct snd_cs46xx * chip, 1477 1418 int period_size) 1478 1419 { … … 1512 1453 } 1513 1454 1514 void cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel) 1515 { 1516 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1455 void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip, 1456 struct dsp_pcm_channel_descriptor * pcm_channel) 1457 { 1458 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1517 1459 unsigned long flags; 1518 1460 … … 1542 1484 } 1543 1485 1544 int cs46xx_dsp_pcm_unlink (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel) 1545 { 1546 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1486 int cs46xx_dsp_pcm_unlink (struct snd_cs46xx * chip, 1487 struct dsp_pcm_channel_descriptor * pcm_channel) 1488 { 1489 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1547 1490 unsigned long flags; 1548 1491 … … 1567 1510 } 1568 1511 1569 int cs46xx_dsp_pcm_link (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel) 1570 { 1571 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1572 dsp_scb_descriptor_t * parent_scb; 1573 dsp_scb_descriptor_t * src_scb = pcm_channel->src_scb; 1512 int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip, 1513 struct dsp_pcm_channel_descriptor * pcm_channel) 1514 { 1515 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1516 struct dsp_scb_descriptor * parent_scb; 1517 struct dsp_scb_descriptor * src_scb = pcm_channel->src_scb; 1574 1518 unsigned long flags; 1575 1519 … … 1608 1552 } 1609 1553 1610 dsp_scb_descriptor_t * cs46xx_add_record_source (cs46xx_t *chip,dsp_scb_descriptor_t * source, 1611 u16 addr,char * scb_name) 1612 { 1613 dsp_spos_instance_t * ins = chip->dsp_spos_instance; 1614 dsp_scb_descriptor_t * parent; 1615 dsp_scb_descriptor_t * pcm_input; 1554 struct dsp_scb_descriptor * 1555 cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * source, 1556 u16 addr, char * scb_name) 1557 { 1558 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1559 struct dsp_scb_descriptor * parent; 1560 struct dsp_scb_descriptor * pcm_input; 1616 1561 int insert_point; 1617 1562 … … 1633 1578 } 1634 1579 1635 int cs46xx_src_unlink( cs46xx_t *chip,dsp_scb_descriptor_t* src)1580 int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src) 1636 1581 { 1637 1582 snd_assert (src->parent_scb_ptr != NULL, return -EINVAL ); … … 1645 1590 } 1646 1591 1647 int cs46xx_src_link( cs46xx_t *chip,dsp_scb_descriptor_t* src)1648 { 1649 dsp_spos_instance_t* ins = chip->dsp_spos_instance;1650 dsp_scb_descriptor_t* parent_scb;1592 int cs46xx_src_link(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src) 1593 { 1594 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1595 struct dsp_scb_descriptor * parent_scb; 1651 1596 1652 1597 snd_assert (src->parent_scb_ptr == NULL, return -EINVAL ); … … 1669 1614 } 1670 1615 1671 int cs46xx_dsp_enable_spdif_out ( cs46xx_t*chip)1672 { 1673 dsp_spos_instance_t* ins = chip->dsp_spos_instance;1616 int cs46xx_dsp_enable_spdif_out (struct snd_cs46xx *chip) 1617 { 1618 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1674 1619 1675 1620 if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) ) { … … 1717 1662 } 1718 1663 1719 int cs46xx_dsp_disable_spdif_out ( cs46xx_t*chip)1720 { 1721 dsp_spos_instance_t* ins = chip->dsp_spos_instance;1664 int cs46xx_dsp_disable_spdif_out (struct snd_cs46xx *chip) 1665 { 1666 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1722 1667 1723 1668 /* dont touch anything if SPDIF is open */ … … 1749 1694 } 1750 1695 1751 int cs46xx_iec958_pre_open ( cs46xx_t*chip)1752 { 1753 dsp_spos_instance_t* ins = chip->dsp_spos_instance;1696 int cs46xx_iec958_pre_open (struct snd_cs46xx *chip) 1697 { 1698 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1754 1699 1755 1700 if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) { … … 1782 1727 } 1783 1728 1784 int cs46xx_iec958_post_close ( cs46xx_t*chip)1785 { 1786 dsp_spos_instance_t* ins = chip->dsp_spos_instance;1729 int cs46xx_iec958_post_close (struct snd_cs46xx *chip) 1730 { 1731 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 1787 1732 1788 1733 snd_assert (ins->asynch_tx_scb != NULL, return -EINVAL); -
GPL/trunk/alsa-kernel/pci/cs46xx/imgs/cwc4630.h
r33 r34 4 4 #define __HEADER_cwc4630_H__ 5 5 6 static s ymbol_entry_tcwc4630_symbols[] = {6 static struct dsp_symbol_entry cwc4630_symbols[] = { 7 7 { 0x0000, "BEGINADDRESS",0x00 }, 8 8 { 0x8000, "EXECCHILD",0x03 }, … … 303 303 304 304 305 static s egment_desc_tcwc4630_segments[] = {305 static struct dsp_segment_desc cwc4630_segments[] = { 306 306 { SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000328, cwc4630_code }, 307 307 { SEGTYPE_SP_PARAMETER, 0x00000000, 0x00000080, cwc4630_parameter }, 308 308 }; 309 309 310 static dsp_module_desc_tcwc4630_module = {310 static struct dsp_module_desc cwc4630_module = { 311 311 "cwc4630", 312 312 { -
GPL/trunk/alsa-kernel/pci/cs46xx/imgs/cwcasync.h
r33 r34 4 4 #define __HEADER_cwcasync_H__ 5 5 6 static s ymbol_entry_tcwcasync_symbols[] = {6 static struct dsp_symbol_entry cwcasync_symbols[] = { 7 7 { 0x8000, "EXECCHILD",0x03 }, 8 8 { 0x8001, "EXECCHILD_98",0x03 }, … … 160 160 /* #CODE_END */ 161 161 162 static s egment_desc_tcwcasync_segments[] = {162 static struct dsp_segment_desc cwcasync_segments[] = { 163 163 { SEGTYPE_SP_PROGRAM, 0x00000000, 0x000001b6, cwcasync_code }, 164 164 }; 165 165 166 static dsp_module_desc_tcwcasync_module = {166 static struct dsp_module_desc cwcasync_module = { 167 167 "cwcasync", 168 168 { -
GPL/trunk/alsa-kernel/pci/cs46xx/imgs/cwcbinhack.h
r33 r34 5 5 #define __HEADER_cwcbinhack_H__ 6 6 7 static s ymbol_entry_tcwcbinhack_symbols[] = {7 static struct dsp_symbol_entry cwcbinhack_symbols[] = { 8 8 { 0x02c8, "OVERLAYBEGINADDRESS",0x00 }, 9 9 { 0x02c8, "MAGICSNOOPTASK",0x03 }, … … 32 32 /* #CODE_END */ 33 33 34 static s egment_desc_tcwcbinhack_segments[] = {34 static struct dsp_segment_desc cwcbinhack_segments[] = { 35 35 { SEGTYPE_SP_PROGRAM, 0x00000000, 64, cwcbinhack_code }, 36 36 }; 37 37 38 static dsp_module_desc_tcwcbinhack_module = {38 static struct dsp_module_desc cwcbinhack_module = { 39 39 "cwcbinhack", 40 40 { -
GPL/trunk/alsa-kernel/pci/cs46xx/imgs/cwcdma.h
r33 r34 4 4 #define __HEADER_cwcdma_H__ 5 5 6 s ymbol_entry_tcwcdma_symbols[] = {6 static struct dsp_symbol_entry cwcdma_symbols[] = { 7 7 { 0x8000, "EXECCHILD",0x03 }, 8 8 { 0x8001, "EXECCHILD_98",0x03 }, … … 34 34 }; /* cwcdma symbols */ 35 35 36 u32 cwcdma_code[] = {36 static u32 cwcdma_code[] = { 37 37 /* OVERLAYBEGINADDRESS */ 38 38 /* 0000 */ 0x00002731,0x00001400,0x0004c108,0x000e5044, … … 52 52 /* #CODE_END */ 53 53 54 s egment_desc_tcwcdma_segments[] = {54 static struct dsp_segment_desc cwcdma_segments[] = { 55 55 { SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000030, cwcdma_code }, 56 56 }; 57 57 58 dsp_module_desc_tcwcdma_module = {58 static struct dsp_module_desc cwcdma_module = { 59 59 "cwcdma", 60 60 { -
GPL/trunk/alsa-kernel/pci/cs46xx/imgs/cwcemb80.h
r33 r34 4 4 #define __HEADER_cwcemb80_H__ 5 5 6 static s ymbol_entry_tcwcemb80_symbols[] = {6 static struct dsp_symbol_entry cwcemb80_symbols[] = { 7 7 { 0x0000, "BEGINADDRESS",0x00 }, 8 8 { 0x8000, "EXECCHILD",0x03 }, … … 1589 1589 1590 1590 1591 static s egment_desc_tcwcemb80_segments[] = {1591 static struct dsp_segment_desc cwcemb80_segments[] = { 1592 1592 { SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000031c, cwcemb80_code }, 1593 1593 { SEGTYPE_SP_PARAMETER, 0x00000000, 0x00000697, cwcemb80_parameter }, … … 1595 1595 }; 1596 1596 1597 static dsp_module_desc_tcwcemb80_module = {1597 static struct dsp_module_desc cwcemb80_module = { 1598 1598 "cwcemb80", 1599 1599 { -
GPL/trunk/alsa-kernel/pci/cs46xx/imgs/cwcsnoop.h
r33 r34 4 4 #define __HEADER_cwcsnoop_H__ 5 5 6 static s ymbol_entry_tcwcsnoop_symbols[] = {6 static struct dsp_symbol_entry cwcsnoop_symbols[] = { 7 7 { 0x0500, "OVERLAYBEGINADDRESS",0x00 }, 8 8 { 0x0500, "OUTPUTSNOOP",0x03 }, … … 30 30 /* #CODE_END */ 31 31 32 static s egment_desc_tcwcsnoop_segments[] = {32 static struct dsp_segment_desc cwcsnoop_segments[] = { 33 33 { SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000003e, cwcsnoop_code }, 34 34 }; 35 35 36 static dsp_module_desc_tcwcsnoop_module = {36 static struct dsp_module_desc cwcsnoop_module = { 37 37 "cwcsnoop", 38 38 {
Note:
See TracChangeset
for help on using the changeset viewer.
