Changeset 305 for GPL/branches/uniaud-2.0/alsa-kernel/isa/sgalaxy.c
- Timestamp:
- Mar 24, 2008, 2:43:42 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GPL/branches/uniaud-2.0/alsa-kernel/isa/sgalaxy.c
r32 r305 18 18 * You should have received a copy of the GNU General Public License 19 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 21 * 22 22 */ 23 23 24 #define SNDRV_MAIN_OBJECT_FILE 25 #include <sound/driver.h> 24 #include <linux/init.h> 25 #include <linux/err.h> 26 #include <linux/isa.h> 27 #include <linux/delay.h> 28 #include <linux/time.h> 29 #include <linux/interrupt.h> 30 #include <linux/moduleparam.h> 31 #include <asm/dma.h> 32 #include <sound/core.h> 26 33 #include <sound/sb.h> 27 34 #include <sound/ad1848.h> 35 #include <sound/control.h> 28 36 #define SNDRV_LEGACY_FIND_FREE_IRQ 29 37 #define SNDRV_LEGACY_FIND_FREE_DMA 30 #define SNDRV_GET_ID31 38 #include <sound/initval.h> 32 39 33 EXPORT_NO_SYMBOLS;40 MODULE_AUTHOR("Christopher Butler <chrisb@sandy.force9.co.uk>"); 34 41 MODULE_DESCRIPTION("Aztech Sound Galaxy"); 35 MODULE_CLASSES("{sound}"); 36 MODULE_DEVICES("{{Aztech Systems,Sound Galaxy}}"); 37 38 static int snd_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 39 static char *snd_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 40 static int snd_enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ 41 static long snd_sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240 */ 42 static long snd_wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530,0xe80,0xf40,0x604 */ 43 static int snd_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 7,9,10,11 */ 44 static int snd_dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ 45 46 MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); 47 MODULE_PARM_DESC(snd_index, "Index value for Sound Galaxy soundcard."); 48 MODULE_PARM_SYNTAX(snd_index, SNDRV_INDEX_DESC); 49 MODULE_PARM(snd_id, "1-" __MODULE_STRING(SNDRV_CARDS) "s"); 50 MODULE_PARM_DESC(snd_id, "ID string for Sound Galaxy soundcard."); 51 MODULE_PARM_SYNTAX(snd_id, SNDRV_ID_DESC); 52 MODULE_PARM(snd_sbport, "1-" __MODULE_STRING(SNDRV_CARDS) "l"); 53 MODULE_PARM_DESC(snd_sbport, "Port # for Sound Galaxy SB driver."); 54 MODULE_PARM_SYNTAX(snd_sbport, SNDRV_ENABLED ",allows:{{0x220},{0x240}},dialog:list"); 55 MODULE_PARM(snd_wssport, "1-" __MODULE_STRING(SNDRV_CARDS) "l"); 56 MODULE_PARM_DESC(snd_wssport, "Port # for Sound Galaxy WSS driver."); 57 MODULE_PARM_SYNTAX(snd_wssport, SNDRV_ENABLED ",allows:{{0x530},{0xe80},{0xf40},{0x604}},dialog:list"); 58 MODULE_PARM(snd_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); 59 MODULE_PARM_DESC(snd_irq, "IRQ # for Sound Galaxy driver."); 60 MODULE_PARM_SYNTAX(snd_irq, SNDRV_ENABLED ",allows:{{7},{9},{10},{11}},dialog:list"); 61 MODULE_PARM(snd_dma1, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); 62 MODULE_PARM_DESC(snd_dma1, "DMA1 # for Sound Galaxy driver."); 63 MODULE_PARM_SYNTAX(snd_dma1, SNDRV_DMA8_DESC); 42 MODULE_LICENSE("GPL"); 43 MODULE_SUPPORTED_DEVICE("{{Aztech Systems,Sound Galaxy}}"); 44 45 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 46 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 47 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ 48 static long sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240 */ 49 static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530,0xe80,0xf40,0x604 */ 50 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 7,9,10,11 */ 51 static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ 52 53 module_param_array(index, int, NULL, 0444); 54 MODULE_PARM_DESC(index, "Index value for Sound Galaxy soundcard."); 55 module_param_array(id, charp, NULL, 0444); 56 MODULE_PARM_DESC(id, "ID string for Sound Galaxy soundcard."); 57 module_param_array(sbport, long, NULL, 0444); 58 MODULE_PARM_DESC(sbport, "Port # for Sound Galaxy SB driver."); 59 module_param_array(wssport, long, NULL, 0444); 60 MODULE_PARM_DESC(wssport, "Port # for Sound Galaxy WSS driver."); 61 module_param_array(irq, int, NULL, 0444); 62 MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver."); 63 module_param_array(dma1, int, NULL, 0444); 64 MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver."); 64 65 65 66 #define SGALAXY_AUXC_LEFT 18 66 67 #define SGALAXY_AUXC_RIGHT 19 67 68 68 static snd_card_t *snd_sgalaxy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; 69 #define PFX "sgalaxy: " 69 70 70 71 /* … … 74 75 #define AD1848P1( port, x ) ( port + c_d_c_AD1848##x ) 75 76 76 /* from lowlevel/sb/sb.c - to avoid having to allocate a s b_tfor the */77 /* from lowlevel/sb/sb.c - to avoid having to allocate a struct snd_sb for the */ 77 78 /* short time we actually need it.. */ 78 79 … … 93 94 } 94 95 95 static int __init snd_sgalaxy_sbdsp_command(unsigned long port, unsigned char val) 96 static int __devinit snd_sgalaxy_sbdsp_command(unsigned long port, 97 unsigned char val) 96 98 { 97 99 int i; … … 106 108 } 107 109 108 static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma) 110 static irqreturn_t snd_sgalaxy_dummy_interrupt(int irq, void *dev_id) 111 { 112 return IRQ_NONE; 113 } 114 115 static int __devinit snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma) 109 116 { 110 117 static int interrupt_bits[] = {-1, -1, -1, -1, -1, -1, -1, 0x08, -1, … … 113 120 int tmp, tmp1; 114 121 115 unsigned int flags;116 117 122 if ((tmp = inb(port + 3)) == 0xff) 118 123 { 119 snd_printdd("I/O address dead (0x%lx)\n", tmp);124 snd_printdd("I/O address dead (0x%lx)\n", port); 120 125 return 0; 121 126 } … … 133 138 134 139 #if 0 135 snd_printdd("sgalaxy - setting up IRQ/DMA for WSS\n"); 136 #endif 137 138 save_flags(flags); 139 cli(); 140 snd_printdd(PFX "setting up IRQ/DMA for WSS\n"); 141 #endif 140 142 141 143 /* initialize IRQ for WSS codec */ 142 144 tmp = interrupt_bits[irq % 16]; 143 if (tmp < 0) { 144 restore_flags(flags); 145 if (tmp < 0) 145 146 return -EINVAL; 146 } 147 148 if (request_irq(irq, snd_sgalaxy_dummy_interrupt, IRQF_DISABLED, "sgalaxy", NULL)) { 149 snd_printk(KERN_ERR "sgalaxy: can't grab irq %d\n", irq); 150 return -EIO; 151 } 152 147 153 outb(tmp | 0x40, port); 148 154 tmp1 = dma_bits[dma % 4]; 149 155 outb(tmp | tmp1, port); 150 156 151 restore_flags(flags); 152 return 0; 153 } 154 155 static int __init snd_sgalaxy_detect(int dev, int irq, int dma) 157 free_irq(irq, NULL); 158 159 return 0; 160 } 161 162 static int __devinit snd_sgalaxy_detect(int dev, int irq, int dma) 156 163 { 157 164 #if 0 158 snd_printdd( "sgalaxy -switching to WSS mode\n");165 snd_printdd(PFX "switching to WSS mode\n"); 159 166 #endif 160 167 161 168 /* switch to WSS mode */ 162 snd_sgalaxy_sbdsp_reset(s nd_sbport[dev]);163 164 snd_sgalaxy_sbdsp_command(s nd_sbport[dev], 9);165 snd_sgalaxy_sbdsp_command(s nd_sbport[dev], 0);169 snd_sgalaxy_sbdsp_reset(sbport[dev]); 170 171 snd_sgalaxy_sbdsp_command(sbport[dev], 9); 172 snd_sgalaxy_sbdsp_command(sbport[dev], 0); 166 173 167 174 udelay(400); 168 return snd_sgalaxy_setup_wss(snd_wssport[dev], irq, dma); 169 } 170 171 #define SGALAXY_CONTROLS 2 172 173 static snd_kcontrol_new_t snd_sgalaxy_controls[2] = { 175 return snd_sgalaxy_setup_wss(wssport[dev], irq, dma); 176 } 177 178 static struct ad1848_mix_elem snd_sgalaxy_controls[] = { 174 179 AD1848_DOUBLE("Aux Playback Switch", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1), 175 180 AD1848_DOUBLE("Aux Playback Volume", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0) 176 181 }; 177 182 178 static int __init snd_sgalaxy_mixer(ad1848_t *chip) 179 { 180 snd_card_t *card = chip->card; 181 snd_ctl_elem_id_t id1, id2; 182 int idx, err; 183 static int __devinit snd_sgalaxy_mixer(struct snd_ad1848 *chip) 184 { 185 struct snd_card *card = chip->card; 186 struct snd_ctl_elem_id id1, id2; 187 unsigned int idx; 188 int err; 183 189 184 190 memset(&id1, 0, sizeof(id1)); … … 204 210 return err; 205 211 /* build AUX2 input */ 206 for (idx = 0; idx < SGALAXY_CONTROLS; idx++) {207 if ((err = snd_ ctl_add(card, snd_ctl_new1(&snd_sgalaxy_controls[idx], chip))) < 0)212 for (idx = 0; idx < ARRAY_SIZE(snd_sgalaxy_controls); idx++) { 213 if ((err = snd_ad1848_add_ctl_elem(chip, &snd_sgalaxy_controls[idx])) < 0) 208 214 return err; 209 215 } … … 211 217 } 212 218 213 static int __init snd_sgalaxy_probe(int dev) 219 static int __devinit snd_sgalaxy_match(struct device *devptr, unsigned int dev) 220 { 221 if (!enable[dev]) 222 return 0; 223 if (sbport[dev] == SNDRV_AUTO_PORT) { 224 snd_printk(KERN_ERR PFX "specify SB port\n"); 225 return 0; 226 } 227 if (wssport[dev] == SNDRV_AUTO_PORT) { 228 snd_printk(KERN_ERR PFX "specify WSS port\n"); 229 return 0; 230 } 231 return 1; 232 } 233 234 static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev) 214 235 { 215 236 static int possible_irqs[] = {7, 9, 10, 11, -1}; 216 237 static int possible_dmas[] = {1, 3, 0, -1}; 217 int err, irq, dma1; 218 snd_card_t *card; 219 ad1848_t *chip; 220 221 if (snd_sbport[dev] == SNDRV_AUTO_PORT) { 222 snd_printk("specify SB port\n"); 223 return -EINVAL; 224 } 225 if (snd_wssport[dev] == SNDRV_AUTO_PORT) { 226 snd_printk("specify WSS port\n"); 227 return -EINVAL; 228 } 229 card = snd_card_new(snd_index[dev], snd_id[dev], THIS_MODULE, 0); 238 int err, xirq, xdma1; 239 struct snd_card *card; 240 struct snd_ad1848 *chip; 241 242 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); 230 243 if (card == NULL) 231 244 return -ENOMEM; 232 245 233 irq = snd_irq[dev];234 if ( irq == SNDRV_AUTO_IRQ) {235 if (( irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {236 snd_ card_free(card);237 snd_printk("unable to find a free IRQ\n");238 return -EBUSY;246 xirq = irq[dev]; 247 if (xirq == SNDRV_AUTO_IRQ) { 248 if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) { 249 snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); 250 err = -EBUSY; 251 goto _err; 239 252 } 240 253 } 241 dma1 = snd_dma1[dev];242 if ( dma1 == SNDRV_AUTO_DMA) {243 if (( dma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {244 snd_ card_free(card);245 snd_printk("unable to find a free DMA\n");246 return -EBUSY;254 xdma1 = dma1[dev]; 255 if (xdma1 == SNDRV_AUTO_DMA) { 256 if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) { 257 snd_printk(KERN_ERR PFX "unable to find a free DMA\n"); 258 err = -EBUSY; 259 goto _err; 247 260 } 248 261 } 249 262 250 if ((err = snd_sgalaxy_detect(dev, irq, dma1)) < 0) { 251 snd_card_free(card); 252 return err; 253 } 254 255 if ((err = snd_ad1848_create(card, snd_wssport[dev] + 4, 256 irq, dma1, 257 AD1848_HW_DETECT, &chip)) < 0) { 258 snd_card_free(card); 259 return err; 260 } 263 if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0) 264 goto _err; 265 266 if ((err = snd_ad1848_create(card, wssport[dev] + 4, 267 xirq, xdma1, 268 AD1848_HW_DETECT, &chip)) < 0) 269 goto _err; 270 card->private_data = chip; 261 271 262 272 if ((err = snd_ad1848_pcm(chip, 0, NULL)) < 0) { 263 snd_printdd("sgalaxy - error creating new ad1848 PCM device\n"); 264 snd_card_free(card); 265 return err; 273 snd_printdd(PFX "error creating new ad1848 PCM device\n"); 274 goto _err; 266 275 } 267 276 if ((err = snd_ad1848_mixer(chip)) < 0) { 268 snd_printdd("sgalaxy - error creating new ad1848 mixer\n"); 269 snd_card_free(card); 270 return err; 271 } 272 if (snd_sgalaxy_mixer(chip) < 0) { 273 snd_printdd("sgalaxy - the mixer rewrite failed\n"); 274 snd_card_free(card); 275 return err; 277 snd_printdd(PFX "error creating new ad1848 mixer\n"); 278 goto _err; 279 } 280 if ((err = snd_sgalaxy_mixer(chip)) < 0) { 281 snd_printdd(PFX "the mixer rewrite failed\n"); 282 goto _err; 276 283 } 277 284 … … 279 286 strcpy(card->shortname, "Sound Galaxy"); 280 287 sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d", 281 snd_wssport[dev], irq, dma1); 282 283 if ((err = snd_card_register(card)) < 0) { 284 snd_card_free(card); 285 return err; 286 } 287 snd_sgalaxy_cards[dev] = card; 288 return 0; 289 } 288 wssport[dev], xirq, xdma1); 289 290 snd_card_set_dev(card, devptr); 291 292 if ((err = snd_card_register(card)) < 0) 293 goto _err; 294 295 dev_set_drvdata(devptr, card); 296 return 0; 297 298 _err: 299 snd_card_free(card); 300 return err; 301 } 302 303 static int __devexit snd_sgalaxy_remove(struct device *devptr, unsigned int dev) 304 { 305 snd_card_free(dev_get_drvdata(devptr)); 306 dev_set_drvdata(devptr, NULL); 307 return 0; 308 } 309 310 #ifdef CONFIG_PM 311 static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n, 312 pm_message_t state) 313 { 314 struct snd_card *card = dev_get_drvdata(pdev); 315 struct snd_ad1848 *chip = card->private_data; 316 317 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 318 chip->suspend(chip); 319 return 0; 320 } 321 322 static int snd_sgalaxy_resume(struct device *pdev, unsigned int n) 323 { 324 struct snd_card *card = dev_get_drvdata(pdev); 325 struct snd_ad1848 *chip = card->private_data; 326 327 chip->resume(chip); 328 snd_ad1848_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]); 329 snd_ad1848_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]); 330 331 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 332 return 0; 333 } 334 #endif 335 336 #define DEV_NAME "sgalaxy" 337 338 static struct isa_driver snd_sgalaxy_driver = { 339 .match = snd_sgalaxy_match, 340 .probe = snd_sgalaxy_probe, 341 .remove = __devexit_p(snd_sgalaxy_remove), 342 #ifdef CONFIG_PM 343 .suspend = snd_sgalaxy_suspend, 344 .resume = snd_sgalaxy_resume, 345 #endif 346 .driver = { 347 .name = DEV_NAME 348 }, 349 }; 290 350 291 351 static int __init alsa_card_sgalaxy_init(void) 292 352 { 293 int dev, cards; 294 295 for (dev = cards = 0; dev < SNDRV_CARDS && snd_enable[dev]; dev++) { 296 if (snd_sgalaxy_probe(dev) >= 0) 297 cards++; 298 } 299 if (!cards) { 300 #ifdef MODULE 301 snd_printk("Sound Galaxy soundcard not found or device busy\n"); 302 #endif 303 return -ENODEV; 304 } 305 306 return 0; 353 return isa_register_driver(&snd_sgalaxy_driver, SNDRV_CARDS); 307 354 } 308 355 309 356 static void __exit alsa_card_sgalaxy_exit(void) 310 357 { 311 int idx; 312 313 for (idx = 0; idx < SNDRV_CARDS; idx++) 314 snd_card_free(snd_sgalaxy_cards[idx]); 358 isa_unregister_driver(&snd_sgalaxy_driver); 315 359 } 316 360 317 361 module_init(alsa_card_sgalaxy_init) 318 362 module_exit(alsa_card_sgalaxy_exit) 319 320 #ifndef MODULE321 322 /* format is: snd-card-sgalaxy=snd_enable,snd_index,snd_id,323 snd_sbport,snd_wssport,324 snd_irq,snd_dma1 */325 326 static int __init alsa_card_sgalaxy_setup(char *str)327 {328 static unsigned __initdata nr_dev = 0;329 330 if (nr_dev >= SNDRV_CARDS)331 return 0;332 (void)(get_option(&str,&snd_enable[nr_dev]) == 2 &&333 get_option(&str,&snd_index[nr_dev]) == 2 &&334 get_id(&str,&snd_id[nr_dev]) == 2 &&335 get_option(&str,(int *)&snd_sbport[nr_dev]) == 2 &&336 get_option(&str,(int *)&snd_wssport[nr_dev]) == 2 &&337 get_option(&str,(int *)&snd_irq[nr_dev]) == 2 &&338 get_option(&str,(int *)&snd_dma1[nr_dev]) == 2);339 nr_dev++;340 return 1;341 }342 343 __setup("snd-card-sgalaxy=", alsa_card_sgalaxy_setup);344 345 #endif /* ifndef MODULE */
Note:
See TracChangeset
for help on using the changeset viewer.