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
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 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 175 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 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 308 309 310 311 dst = (unsigned long)chip->region.idx[bank+1].remap_addr + offset;312 313 314 315 316 317 318 319 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 336 337 338 339 340 341 342 343 344 345 346 347 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 357 358 359 360 361 362 363 364 365 366 } 367 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 526 527 528 529 530 531 532 533 534 535 536 537 * GOF_PER_SEC)538 * ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M539 * GOF_PER_SEC * correctionPerGOF540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 } 568 569 static void snd_cs46xx_set_capture_sample_rate( cs46xx_t*chip, unsigned int rate)570 { 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 if (((rate / cnt) * cnt) != rate) 660 661 }662 663 664 665 666 667 668 669 670 671 672 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 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 692 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 701 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 708 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 715 cs46xx_pcm_t*cpcm = substream->runtime->private_data;716 717 718 #ifdef CONFIG_SND_CS46XX_NEW_DSP 719 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 722 #endif 723 724 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 731 cs46xx_pcm_t*cpcm = substream->runtime->private_data;732 733 #ifdef CONFIG_SND_CS46XX_NEW_DSP 734 735 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 738 #endif 739 740 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 747 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 754 755 } 756 757 static int snd_cs46xx_playback_trigger(s nd_pcm_substream_t *substream,758 759 { 760 cs46xx_t*chip = snd_pcm_substream_chip(substream);761 /*snd_pcm_runtime_t*runtime = substream->runtime;*/762 763 764 #ifdef CONFIG_SND_CS46XX_NEW_DSP 765 cs46xx_pcm_t*cpcm = substream->runtime->private_data;766 767 768 769 #endif 770 771 772 773 #ifdef CONFIG_SND_CS46XX_NEW_DSP 774 775 snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 776 777 778 779 780 781 782 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 785 786 787 788 789 790 791 792 793 #endif 794 795 796 797 #ifdef CONFIG_SND_CS46XX_NEW_DSP 798 799 snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 800 801 802 803 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 806 807 808 809 810 811 812 #endif 813 814 815 816 817 818 819 820 } 821 822 static int snd_cs46xx_capture_trigger(s nd_pcm_substream_t *substream,823 824 { 825 cs46xx_t*chip = snd_pcm_substream_chip(substream);826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 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 858 859 cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, 860 cpcm, cpcm->hw_addr,cpcm->pcm_channel_id);861 862 863 864 865 866 867 868 869 870 871 872 if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm, 873 cpcm->hw_addr,874 875 876 877 878 879 880 881 882 883 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 894 #ifdef CONFIG_SND_CS46XX_NEW_DSP 895 cs46xx_t*chip = snd_pcm_substream_chip(substream);896 897 898 #endif 899 900 901 #ifdef CONFIG_SND_CS46XX_NEW_DSP 902 903 904 905 906 907 908 909 910 911 //snd_assert (cpcm->pcm_channel != NULL);912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 #endif 927 928 929 930 931 932 933 934 935 936 #ifdef CONFIG_SND_CS46XX_NEW_DSP 937 938 939 940 941 942 943 944 945 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 950 #endif 951 952 953 954 955 956 957 958 959 #ifdef CONFIG_SND_CS46XX_NEW_DSP 960 961 #endif 962 963 964 965 #ifdef CONFIG_SND_CS46XX_NEW_DSP 966 967 968 969 970 971 972 973 974 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 979 #endif 980 981 982 983 #ifdef CONFIG_SND_CS46XX_NEW_DSP 984 985 #endif 986 987 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 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 } 1011 1012 static int snd_cs46xx_playback_prepare(s nd_pcm_substream_t *substream)1013 { 1014 1015 1016 cs46xx_t*chip = snd_pcm_substream_chip(substream);1017 snd_pcm_runtime_t*runtime = substream->runtime;1018 cs46xx_pcm_t*cpcm;1019 1020 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 1026 1033 pfie = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2 ); 1034 pfie &= ~0x0000f03f; 1027 1035 #else 1028 1029 1030 1031 #endif 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1060 1061 1062 1063 1064 1065 1066 1067 1068 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 1071 1072 1073 1074 1075 1076 1077 #endif 1078 1079 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 1088 1089 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1090 1091 #endif 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 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 1119 1120 1121 1122 1123 1124 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 1133 1134 1135 1136 1137 1138 1139 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 1280 1281 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 1349 #endif 1350 1351 1352 1353 1354 1355 1356 } 1357 1358 static int snd_cs46xx_playback_open(s nd_pcm_substream_t *substream)1359 { 1360 1361 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 1368 1369 1370 } 1371 1372 static int snd_cs46xx_playback_open_clfe(s nd_pcm_substream_t *substream)1373 { 1374 1375 1376 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 1384 1385 1386 1387 1388 1389 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 1397 cs46xx_t*chip = snd_pcm_substream_chip(substream);1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 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 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1427 1428 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 1429 1430 #endif 1431 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 1441 1442 1443 1444 1445 #ifdef CONFIG_SND_CS46XX_NEW_DSP 1446 1447 1448 1449 1450 1451 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 1565 1566 1567 1568 1569 1570 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 1589 1590 1591 1592 1593 1594 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 1766 } 1767 1768 static void snd_cs46xx_mixer_free_ac97( ac97_t*ac97)1769 { 1770 cs46xx_t*chip = ac97->private_data;1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 } 1783 1784 static int snd_cs46xx_vol_info(s nd_kcontrol_t *kcontrol,1785 snd_ctl_elem_info_t*uinfo)1786 { 1787 1788 1789 1790 1791 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 1798 1799 1800 1801 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 1808 unsigned int val = ((0xffff - ucontrol->value.integer.value[0]) << 16 | 1809 1810 1811 1812 1813 1814 1815 1816 1817 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 1827 1828 1829 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 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 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 1854 1855 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 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 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 1879 1880 1881 1882 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 1890 1891 1892 1893 1894 1895 1896 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 1904 1905 1906 1907 1908 1909 if (ucontrol->value.integer.value[0] && !change) 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 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 1944 else 1945 1946 1947 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 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 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 2006 2007 2008 2009 2010 2011 2012 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 2023 2024 2025 2026 2027 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, 2028 2029 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, 2030 2031 2032 2033 2034 2035 2036 2037 /* checking diff from the EGPIO direction register 2038 2039 2040 } 2041 2042 2043 static int snd_cs46xx_spdif_info(s nd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)2044 { 2045 2046 2047 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 2057 2058 2059 2060 2061 2062 2063 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 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 } 2092 2093 static int snd_cs46xx_spdif_mask_get(s nd_kcontrol_t *kcontrol,2094 snd_ctl_elem_value_t *ucontrol)2095 { 2096 2097 2098 2099 2100 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 2110 2111 2112 2113 2114 2115 2116 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 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 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 2154 2155 2156 2157 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 2165 2166 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 2174 2175 2176 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 2185 2186 2187 ucontrol->value.integer.value[0] = 2188 2189 2190 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 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 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 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 2221 2222 2164 .get = snd_cs46xx_vol_get, 2165 .put = snd_cs46xx_vol_put, 2166 .private_value = BA1_PVOL, 2223 2167 #else 2224 2225 2226 0 2227 #endif 2228 }, 2229 2230 SNDRV_CTL_ELEM_IFACE_MIXER,0,0,2231 "ADC Volume",0,0,0,2232 2233 2234 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 2180 .private_value = BA1_CVOL, 2237 2181 #else 2238 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 2348 2349 2350 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 2358 2359 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 2544 2545 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 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 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 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 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 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 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 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 } 2620 2621 static void snd_cs46xx_midi_input_trigger(s nd_rawmidi_substream_t *substream, int up)2622 { 2623 2624 cs46xx_t*chip = substream->rmidi->private_data;2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 } 2640 2641 static void snd_cs46xx_midi_output_trigger(s nd_rawmidi_substream_t *substream, int up)2642 { 2643 2644 cs46xx_t*chip = substream->rmidi->private_data;2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 } 2670 2671 static s nd_rawmidi_ops_tsnd_cs46xx_midi_output =2672 { 2673 2674 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 2681 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 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 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 2830 2831 2832 snd_cs46xx_region_t*region = &chip->region.idx[idx];2833 2834 2835 2836 2837 2838 2839 2840 2841 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2842 2843 #endif 2844 2845 } 2846 2847 static int snd_cs46xx_proc_done( cs46xx_t*chip)2848 { 2849 #ifdef CONFIG_SND_CS46XX_NEW_DSP 2850 2851 #endif 2852 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 2967 2968 /* 2969 2970 * 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 2978 * 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 2983 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 3092 snd_printk(KERN_ERR "create - never read ISV3 & ISV4 from AC'97\n"); 3093 return -EIO; 3152 3094 #else 3153 3154 Reloading the driver may help, if there's other soundcards 3155 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 3163 #endif 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 * Turn off the Processor by turning off the software clock enable flag in 3182 3183 3184 3185 3186 3187 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 3196 3197 3198 3199 3200 3201 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 3206 3207 3208 3209 #endif 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 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 3240 3241 snd_printk("image download error\n");3242 3243 3244 3245 3246 * Stop playback DMA.3247 3248 3249 3250 3251 #endif 3252 3253 3254 * Stop capture DMA.3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 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 3284 3285 #endif 3286 3287 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 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 modem_power = snd_cs46xx_codec_read (chip, 3329 3330 3331 3332 3333 snd_cs46xx_codec_write(chip, 3334 3335 3336 3337 3338 3339 3340 pin_config = snd_cs46xx_codec_read (chip, 3341 3342 3343 3344 3345 snd_cs46xx_codec_write(chip, 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 logic_type &=0x27F; 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 * Fill slots 12 with the correct value for the GPIO pins. 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 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 3424 3425 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3426 3427 #endif 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3450 3451 3452 3453 #endif 3454 } 3455 3456 static void hercules_init( cs46xx_t *chip)3457 { 3458 3459 3460 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 3470 3471 3472 3473 3474 3475 3476 3477 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, 3478 3479 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, 3480 3481 3482 3483 3484 3485 3486 } 3487 3488 static void voyetra_mixer_init ( cs46xx_t*chip)3489 { 3490 3491 3492 3493 3494 3495 } 3496 3497 static void hercules_mixer_init ( cs46xx_t*chip)3498 { 3499 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3500 3501 3502 snd_card_t*card = chip->card;3503 #endif 3504 3505 3506 3507 3508 3509 3510 #ifdef CONFIG_SND_CS46XX_NEW_DSP 3511 3512 snd_kcontrol_t*kctl;3513 3514 3515 3516 3517 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 3573 3574 if (chip->acpi_dev == NULL)3575 3576 3577 3578 3579 /* Read ACPI port */ 3580 3581 3582 3583 3584 3585 3586 3587 3588 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 3616 3617 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 3687 snd_cs46xx_codec_write(chip, AC97_POWER_CONTROL, 3688 3689 3690 3691 3692 3693 #endif 3694 3695 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 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 435 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 713 714 715 716 717 718 719 720 721 722 723 724 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 1556 1557 1558 1559 1560 1561 1562 1563 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 1569 1570 1571 1572 1573 1574 1575 1576 1577 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 250 251 252 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 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 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.