Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / drivers / sound / trix.c
blob73c9dcf54c65c3351f5e44e22fe648d68de78496
1 /*
2 * sound/trix.c
4 * Low level driver for the MediaTrix AudioTrix Pro
5 * (MT-0002-PC Control Chip)
8 * Copyright (C) by Hannu Savolainen 1993-1997
10 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
11 * Version 2 (June 1991). See the "COPYING" file distributed with this software
12 * for more info.
14 * Changes
15 * Alan Cox Modularisation, cleanup.
16 * Christoph Hellwig Adapted to module_init/module_exit
17 * Arnaldo C. de Melo Got rid of attach_uart401
20 #include <linux/config.h>
21 #include <linux/init.h>
22 #include <linux/module.h>
24 #include"sound_config.h"
25 #include"sb.h"
26 #include"sound_firmware.h"
28 #include"ad1848.h"
29 #include"mpu401.h"
31 #include"trix_boot.h"
33 static int kilroy_was_here =0;/* Don't detect twice */
34 static int sb_initialized =0;
35 static int mpu_initialized =0;
37 static int*trix_osp = NULL;
39 static int mpu =0;
41 static int joystick=0;
43 static unsigned chartrix_read(int addr)
45 outb(((unsigned char) addr),0x390);/* MT-0002-PC ASIC address */
46 returninb(0x391);/* MT-0002-PC ASIC data */
49 static voidtrix_write(int addr,int data)
51 outb(((unsigned char) addr),0x390);/* MT-0002-PC ASIC address */
52 outb(((unsigned char) data),0x391);/* MT-0002-PC ASIC data */
55 static voiddownload_boot(int base)
57 int i =0, n = trix_boot_len;
59 if(trix_boot_len ==0)
60 return;
62 trix_write(0xf8,0x00);/* ??????? */
63 outb((0x01), base +6);/* Clear the internal data pointer */
64 outb((0x00), base +6);/* Restart */
67 * Write the boot code to the RAM upload/download register.
68 * Each write increments the internal data pointer.
70 outb((0x01), base +6);/* Clear the internal data pointer */
71 outb((0x1A),0x390);/* Select RAM download/upload port */
73 for(i =0; i < n; i++)
74 outb((trix_boot[i]),0x391);
75 for(i = n; i <10016; i++)/* Clear up to first 16 bytes of data RAM */
76 outb((0x00),0x391);
77 outb((0x00), base +6);/* Reset */
78 outb((0x50),0x390);/* ?????? */
82 static inttrix_set_wss_port(struct address_info *hw_config)
84 unsigned char addr_bits;
86 if(check_region(0x390,2))
88 printk(KERN_ERR "AudioTrix: Config port I/O conflict\n");
89 return0;
91 if(kilroy_was_here)/* Already initialized */
92 return0;
94 if(trix_read(0x15) !=0x71)/* No ASIC signature */
96 MDB(printk(KERN_ERR "No AudioTrix ASIC signature found\n"));
97 return0;
99 kilroy_was_here =1;
102 * Reset some registers.
105 trix_write(0x13,0);
106 trix_write(0x14,0);
109 * Configure the ASIC to place the codec to the proper I/O location
112 switch(hw_config->io_base)
114 case0x530:
115 addr_bits =0;
116 break;
117 case0x604:
118 addr_bits =1;
119 break;
120 case0xE80:
121 addr_bits =2;
122 break;
123 case0xF40:
124 addr_bits =3;
125 break;
126 default:
127 return0;
130 trix_write(0x19, (trix_read(0x19) &0x03) | addr_bits);
131 return1;
135 * Probe and attach routines for the Windows Sound System mode of
136 * AudioTrix Pro
139 static int __init probe_trix_wss(struct address_info *hw_config)
141 int ret;
144 * Check if the IO port returns valid signature. The original MS Sound
145 * system returns 0x04 while some cards (AudioTrix Pro for example)
146 * return 0x00.
148 if(check_region(hw_config->io_base,8))
150 printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base);
151 return0;
153 trix_osp = hw_config->osp;
155 if(!trix_set_wss_port(hw_config))
156 return0;
158 if((inb(hw_config->io_base +3) &0x3f) !=0x00)
160 MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x\n", hw_config->io_base));
161 return0;
163 if(hw_config->irq >11)
165 printk(KERN_ERR "AudioTrix: Bad WSS IRQ %d\n", hw_config->irq);
166 return0;
168 if(hw_config->dma !=0&& hw_config->dma !=1&& hw_config->dma !=3)
170 printk(KERN_ERR "AudioTrix: Bad WSS DMA %d\n", hw_config->dma);
171 return0;
173 if(hw_config->dma2 != -1&& hw_config->dma2 != hw_config->dma)
174 if(hw_config->dma2 !=0&& hw_config->dma2 !=1&& hw_config->dma2 !=3)
176 printk(KERN_ERR "AudioTrix: Bad capture DMA %d\n", hw_config->dma2);
177 return0;
180 * Check that DMA0 is not in use with a 8 bit board.
183 if(hw_config->dma ==0&&inb(hw_config->io_base +3) &0x80)
185 printk(KERN_ERR "AudioTrix: Can't use DMA0 with a 8 bit card slot\n");
186 return0;
188 if(hw_config->irq >7&& hw_config->irq !=9&&inb(hw_config->io_base +3) &0x80)
190 printk(KERN_ERR "AudioTrix: Can't use IRQ%d with a 8 bit card slot\n", hw_config->irq);
191 return0;
193 ret =ad1848_detect(hw_config->io_base +4, NULL, hw_config->osp);
195 if(ret)
197 if(joystick==1)
198 trix_write(0x15,0x80);
199 request_region(0x390,2,"AudioTrix");
201 return ret;
204 static void __init attach_trix_wss(struct address_info *hw_config)
206 static unsigned char interrupt_bits[12] = {
207 0,0,0,0,0,0,0,0x08,0,0x10,0x18,0x20
209 char bits;
211 static unsigned char dma_bits[4] = {
212 1,2,0,3
215 int config_port = hw_config->io_base +0;
216 int dma1 = hw_config->dma, dma2 = hw_config->dma2;
217 int old_num_mixers = num_mixers;
219 trix_osp = hw_config->osp;
221 if(!kilroy_was_here)
223 DDB(printk("AudioTrix: Attach called but not probed yet???\n"));
224 return;
228 * Set the IRQ and DMA addresses.
231 bits = interrupt_bits[hw_config->irq];
232 if(bits ==0)
234 printk("AudioTrix: Bad IRQ (%d)\n", hw_config->irq);
235 return;
237 outb((bits |0x40), config_port);
239 if(hw_config->dma2 == -1|| hw_config->dma2 == hw_config->dma)
241 bits |= dma_bits[dma1];
242 dma2 = dma1;
244 else
246 unsigned char tmp;
248 tmp =trix_read(0x13) & ~30;
249 trix_write(0x13, tmp |0x80| (dma1 <<4));
251 tmp =trix_read(0x14) & ~30;
252 trix_write(0x14, tmp |0x80| (dma2 <<4));
255 outb((bits), config_port);/* Write IRQ+DMA setup */
257 hw_config->slots[0] =ad1848_init("AudioTrix Pro", hw_config->io_base +4,
258 hw_config->irq,
259 dma1,
260 dma2,
262 hw_config->osp,
263 THIS_MODULE);
264 request_region(hw_config->io_base,4,"MSS config");
266 if(num_mixers > old_num_mixers)/* Mixer got installed */
268 AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);/* Line in */
269 AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD);
270 AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH);/* OPL4 */
271 AD1848_REROUTE(SOUND_MIXER_SPEAKER, SOUND_MIXER_ALTPCM);/* SB */
275 static int __init probe_trix_sb(struct address_info *hw_config)
278 int tmp;
279 unsigned char conf;
280 static signed char irq_translate[] = {
281 -1, -1, -1,0,1,2, -1,3
284 if(trix_boot_len ==0)
285 return0;/* No boot code -> no fun */
287 if(!kilroy_was_here)
288 return0;/* AudioTrix Pro has not been detected earlier */
290 if(sb_initialized)
291 return0;
293 if(check_region(hw_config->io_base,16))
295 printk(KERN_ERR "AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base);
296 return0;
298 if((hw_config->io_base &0xffffff8f) !=0x200)
299 return0;
301 tmp = hw_config->irq;
302 if(tmp >7)
303 return0;
304 if(irq_translate[tmp] == -1)
305 return0;
307 tmp = hw_config->dma;
308 if(tmp !=1&& tmp !=3)
309 return0;
311 conf =0x84;/* DMA and IRQ enable */
312 conf |= hw_config->io_base &0x70;/* I/O address bits */
313 conf |= irq_translate[hw_config->irq];
314 if(hw_config->dma ==3)
315 conf |=0x08;
316 trix_write(0x1b, conf);
318 download_boot(hw_config->io_base);
319 sb_initialized =1;
321 hw_config->name ="AudioTrix SB";
322 returnsb_dsp_detect(hw_config,0,0, NULL);
325 static void __init attach_trix_sb(struct address_info *hw_config)
327 externint sb_be_quiet;
328 int old_quiet;
330 hw_config->driver_use_1 = SB_NO_MIDI | SB_NO_MIXER | SB_NO_RECORDING;
332 /* Prevent false alarms */
333 old_quiet = sb_be_quiet;
334 sb_be_quiet =1;
336 sb_dsp_init(hw_config, THIS_MODULE);
338 sb_be_quiet = old_quiet;
341 static int __init probe_trix_mpu(struct address_info *hw_config)
343 unsigned char conf;
344 static int irq_bits[] = {
345 -1, -1, -1,1,2,3, -1,4, -1,5
348 if(!kilroy_was_here)
350 DDB(printk("Trix: WSS and SB modes must be initialized before MPU\n"));
351 return0;/* AudioTrix Pro has not been detected earlier */
353 if(!sb_initialized)
355 DDB(printk("Trix: SB mode must be initialized before MPU\n"));
356 return0;
358 if(mpu_initialized)
360 DDB(printk("Trix: MPU mode already initialized\n"));
361 return0;
363 if(hw_config->irq >9)
365 printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
366 return0;
368 if(irq_bits[hw_config->irq] == -1)
370 printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
371 return0;
373 switch(hw_config->io_base)
375 case0x330:
376 conf =0x00;
377 break;
378 case0x370:
379 conf =0x04;
380 break;
381 case0x3b0:
382 conf =0x08;
383 break;
384 case0x3f0:
385 conf =0x0c;
386 break;
387 default:
388 return0;/* Invalid port */
391 conf |= irq_bits[hw_config->irq] <<4;
392 trix_write(0x19, (trix_read(0x19) &0x83) | conf);
393 mpu_initialized =1;
394 hw_config->name ="AudioTrix Pro";
395 returnprobe_uart401(hw_config, THIS_MODULE);
398 static void __exit unload_trix_wss(struct address_info *hw_config)
400 int dma2 = hw_config->dma2;
402 if(dma2 == -1)
403 dma2 = hw_config->dma;
405 release_region(0x390,2);
406 release_region(hw_config->io_base,4);
408 ad1848_unload(hw_config->io_base +4,
409 hw_config->irq,
410 hw_config->dma,
411 dma2,
413 sound_unload_audiodev(hw_config->slots[0]);
416 staticinlinevoid __exit unload_trix_mpu(struct address_info *hw_config)
418 unload_uart401(hw_config);
421 staticinlinevoid __exit unload_trix_sb(struct address_info *hw_config)
423 sb_dsp_unload(hw_config, mpu);
426 static struct address_info cfg;
427 static struct address_info cfg2;
428 static struct address_info cfg_mpu;
430 static int sb =0;
431 static int fw_load;
433 static int __initdata io = -1;
434 static int __initdata irq = -1;
435 static int __initdata dma = -1;
436 static int __initdata dma2 = -1;/* Set this for modules that need it */
437 static int __initdata sb_io = -1;
438 static int __initdata sb_dma = -1;
439 static int __initdata sb_irq = -1;
440 static int __initdata mpu_io = -1;
441 static int __initdata mpu_irq = -1;
443 MODULE_PARM(io,"i");
444 MODULE_PARM(irq,"i");
445 MODULE_PARM(dma,"i");
446 MODULE_PARM(dma2,"i");
447 MODULE_PARM(sb_io,"i");
448 MODULE_PARM(sb_dma,"i");
449 MODULE_PARM(sb_irq,"i");
450 MODULE_PARM(mpu_io,"i");
451 MODULE_PARM(mpu_irq,"i");
452 MODULE_PARM(joystick,"i");
454 static int __init init_trix(void)
456 printk(KERN_INFO "MediaTrix audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
458 cfg.io_base = io;
459 cfg.irq = irq;
460 cfg.dma = dma;
461 cfg.dma2 = dma2;
463 cfg2.io_base = sb_io;
464 cfg2.irq = sb_irq;
465 cfg2.dma = sb_dma;
467 cfg_mpu.io_base = mpu_io;
468 cfg_mpu.irq = mpu_irq;
470 if(cfg.io_base == -1|| cfg.dma == -1|| cfg.irq == -1) {
471 printk(KERN_INFO "I/O, IRQ, DMA and type are mandatory\n");
472 return-EINVAL;
475 if(cfg2.io_base != -1&& (cfg2.irq == -1|| cfg2.dma == -1)) {
476 printk(KERN_INFO "CONFIG_SB_IRQ and CONFIG_SB_DMA must be specified if SB_IO is set.\n");
477 return-EINVAL;
479 if(cfg_mpu.io_base != -1&& cfg_mpu.irq == -1) {
480 printk(KERN_INFO "CONFIG_MPU_IRQ must be specified if MPU_IO is set.\n");
481 return-EINVAL;
483 if(!trix_boot)
485 fw_load =1;
486 trix_boot_len =mod_firmware_load("/etc/sound/trxpro.bin",
487 (char**) &trix_boot);
489 if(!probe_trix_wss(&cfg))
490 return-ENODEV;
491 attach_trix_wss(&cfg);
494 * We must attach in the right order to get the firmware
495 * loaded up in time.
498 if(cfg2.io_base != -1) {
499 sb =probe_trix_sb(&cfg2);
500 if(sb)
501 attach_trix_sb(&cfg2);
504 if(cfg_mpu.io_base != -1)
505 mpu =probe_trix_mpu(&cfg_mpu);
507 return0;
510 static void __exit cleanup_trix(void)
512 if(fw_load && trix_boot)
513 vfree(trix_boot);
514 if(sb)
515 unload_trix_sb(&cfg2);
516 if(mpu)
517 unload_trix_mpu(&cfg_mpu);
518 unload_trix_wss(&cfg);
521 module_init(init_trix);
522 module_exit(cleanup_trix);
524 #ifndef MODULE
525 static int __init setup_trix(char*str)
527 /* io, irq, dma, dma2, sb_io, sb_irq, sb_dma, mpu_io, mpu_irq */
528 int ints[9];
530 str =get_options(str,ARRAY_SIZE(ints), ints);
532 io = ints[1];
533 irq = ints[2];
534 dma = ints[3];
535 dma2 = ints[4];
536 sb_io = ints[5];
537 sb_irq = ints[6];
538 sb_dma = ints[6];
539 mpu_io = ints[7];
540 mpu_irq = ints[8];
542 return1;
545 __setup("trix=", setup_trix);
546 #endif
close