hvc_console: Add support for tty window resizing
[linux-2.6] / sound / oss / trix.c
1 /*
2  * sound/oss/trix.c
3  *
4  * Low level driver for the MediaTrix AudioTrix Pro
5  * (MT-0002-PC Control Chip)
6  *
7  *
8  * Copyright (C) by Hannu Savolainen 1993-1997
9  *
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.
13  *
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
18  */
19  
20 #include <linux/init.h>
21 #include <linux/module.h>
22
23 #include "sound_config.h"
24 #include "sb.h"
25 #include "sound_firmware.h"
26
27 #include "ad1848.h"
28 #include "mpu401.h"
29
30 #include "trix_boot.h"
31
32 static int mpu;
33
34 static int joystick;
35
36 static unsigned char trix_read(int addr)
37 {
38         outb(((unsigned char) addr), 0x390);    /* MT-0002-PC ASIC address */
39         return inb(0x391);      /* MT-0002-PC ASIC data */
40 }
41
42 static void trix_write(int addr, int data)
43 {
44         outb(((unsigned char) addr), 0x390);    /* MT-0002-PC ASIC address */
45         outb(((unsigned char) data), 0x391);    /* MT-0002-PC ASIC data */
46 }
47
48 static void download_boot(int base)
49 {
50         int i = 0, n = trix_boot_len;
51
52         if (trix_boot_len == 0)
53                 return;
54
55         trix_write(0xf8, 0x00); /* ??????? */
56         outb((0x01), base + 6); /* Clear the internal data pointer */
57         outb((0x00), base + 6); /* Restart */
58
59         /*
60            *  Write the boot code to the RAM upload/download register.
61            *  Each write increments the internal data pointer.
62          */
63         outb((0x01), base + 6); /* Clear the internal data pointer */
64         outb((0x1A), 0x390);    /* Select RAM download/upload port */
65
66         for (i = 0; i < n; i++)
67                 outb((trix_boot[i]), 0x391);
68         for (i = n; i < 10016; i++)     /* Clear up to first 16 bytes of data RAM */
69                 outb((0x00), 0x391);
70         outb((0x00), base + 6); /* Reset */
71         outb((0x50), 0x390);    /* ?????? */
72
73 }
74
75 static int trix_set_wss_port(struct address_info *hw_config)
76 {
77         unsigned char   addr_bits;
78
79         if (trix_read(0x15) != 0x71)    /* No ASIC signature */
80         {
81                 MDB(printk(KERN_ERR "No AudioTrix ASIC signature found\n"));
82                 return 0;
83         }
84
85         /*
86          * Reset some registers.
87          */
88
89         trix_write(0x13, 0);
90         trix_write(0x14, 0);
91
92         /*
93          * Configure the ASIC to place the codec to the proper I/O location
94          */
95
96         switch (hw_config->io_base)
97         {
98                 case 0x530:
99                         addr_bits = 0;
100                         break;
101                 case 0x604:
102                         addr_bits = 1;
103                         break;
104                 case 0xE80:
105                         addr_bits = 2;
106                         break;
107                 case 0xF40:
108                         addr_bits = 3;
109                         break;
110                 default:
111                         return 0;
112         }
113
114         trix_write(0x19, (trix_read(0x19) & 0x03) | addr_bits);
115         return 1;
116 }
117
118 /*
119  *    Probe and attach routines for the Windows Sound System mode of
120  *      AudioTrix Pro
121  */
122
123 static int __init init_trix_wss(struct address_info *hw_config)
124 {
125         static unsigned char dma_bits[4] = {
126                 1, 2, 0, 3
127         };
128         struct resource *ports;
129         int config_port = hw_config->io_base + 0;
130         int dma1 = hw_config->dma, dma2 = hw_config->dma2;
131         int old_num_mixers = num_mixers;
132         u8 config, bits;
133         int ret;
134  
135         switch(hw_config->irq) {
136         case 7:
137                 bits = 8;
138                 break;
139         case 9:
140                 bits = 0x10;
141                 break;
142         case 10:
143                 bits = 0x18;
144                 break;
145         case 11:
146                 bits = 0x20;
147                 break;
148         default:
149                 printk(KERN_ERR "AudioTrix: Bad WSS IRQ %d\n", hw_config->irq);
150                 return 0;
151         }
152
153         switch (dma1) {
154         case 0:
155         case 1:
156         case 3:
157                 break;
158         default:
159                 printk(KERN_ERR "AudioTrix: Bad WSS DMA %d\n", dma1);
160                 return 0;
161         }
162
163         switch (dma2) {
164         case -1:
165         case 0:
166         case 1:
167         case 3:
168                 break;
169         default:
170                 printk(KERN_ERR "AudioTrix: Bad capture DMA %d\n", dma2);
171                 return 0;
172         }
173
174         /*
175          * Check if the IO port returns valid signature. The original MS Sound
176          * system returns 0x04 while some cards (AudioTrix Pro for example)
177          * return 0x00.
178          */
179         ports = request_region(hw_config->io_base + 4, 4, "ad1848");
180         if (!ports) {
181                 printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base);
182                 return 0;
183         }
184
185         if (!request_region(hw_config->io_base, 4, "MSS config")) {
186                 printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base);
187                 release_region(hw_config->io_base + 4, 4);
188                 return 0;
189         }
190
191         if (!trix_set_wss_port(hw_config))
192                 goto fail;
193
194         config = inb(hw_config->io_base + 3);
195
196         if ((config & 0x3f) != 0x00)
197         {
198                 MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x\n", hw_config->io_base));
199                 goto fail;
200         }
201
202         /*
203          * Check that DMA0 is not in use with a 8 bit board.
204          */
205
206         if (dma1 == 0 && config & 0x80)
207         {
208                 printk(KERN_ERR "AudioTrix: Can't use DMA0 with a 8 bit card slot\n");
209                 goto fail;
210         }
211         if (hw_config->irq > 9 && config & 0x80)
212         {
213                 printk(KERN_ERR "AudioTrix: Can't use IRQ%d with a 8 bit card slot\n", hw_config->irq);
214                 goto fail;
215         }
216
217         ret = ad1848_detect(ports, NULL, hw_config->osp);
218         if (!ret)
219                 goto fail;
220
221         if (joystick==1)
222                 trix_write(0x15, 0x80);
223
224         /*
225          * Set the IRQ and DMA addresses.
226          */
227
228         outb((bits | 0x40), config_port);
229
230         if (dma2 == -1 || dma2 == dma1)
231         {
232                   bits |= dma_bits[dma1];
233                   dma2 = dma1;
234         }
235         else
236         {
237                 unsigned char tmp;
238
239                 tmp = trix_read(0x13) & ~30;
240                 trix_write(0x13, tmp | 0x80 | (dma1 << 4));
241
242                 tmp = trix_read(0x14) & ~30;
243                 trix_write(0x14, tmp | 0x80 | (dma2 << 4));
244         }
245
246         outb((bits), config_port);      /* Write IRQ+DMA setup */
247
248         hw_config->slots[0] = ad1848_init("AudioTrix Pro", ports,
249                                           hw_config->irq,
250                                           dma1,
251                                           dma2,
252                                           0,
253                                           hw_config->osp,
254                                           THIS_MODULE);
255
256         if (num_mixers > old_num_mixers)        /* Mixer got installed */
257         {
258                 AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);    /* Line in */
259                 AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD);
260                 AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH);           /* OPL4 */
261                 AD1848_REROUTE(SOUND_MIXER_SPEAKER, SOUND_MIXER_ALTPCM);        /* SB */
262         }
263         return 1;
264
265 fail:
266         release_region(hw_config->io_base, 4);
267         release_region(hw_config->io_base + 4, 4);
268         return 0;
269 }
270
271 static int __init probe_trix_sb(struct address_info *hw_config)
272 {
273
274         int tmp;
275         unsigned char conf;
276         extern int sb_be_quiet;
277         int old_quiet;
278         static signed char irq_translate[] = {
279                 -1, -1, -1, 0, 1, 2, -1, 3
280         };
281
282         if (trix_boot_len == 0)
283                 return 0;       /* No boot code -> no fun */
284
285         if ((hw_config->io_base & 0xffffff8f) != 0x200)
286                 return 0;
287
288         tmp = hw_config->irq;
289         if (tmp > 7)
290                 return 0;
291         if (irq_translate[tmp] == -1)
292                 return 0;
293
294         tmp = hw_config->dma;
295         if (tmp != 1 && tmp != 3)
296                 return 0;
297
298         if (!request_region(hw_config->io_base, 16, "soundblaster")) {
299                 printk(KERN_ERR "AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base);
300                 return 0;
301         }
302
303         conf = 0x84;            /* DMA and IRQ enable */
304         conf |= hw_config->io_base & 0x70;      /* I/O address bits */
305         conf |= irq_translate[hw_config->irq];
306         if (hw_config->dma == 3)
307                 conf |= 0x08;
308         trix_write(0x1b, conf);
309
310         download_boot(hw_config->io_base);
311
312         hw_config->name = "AudioTrix SB";
313         if (!sb_dsp_detect(hw_config, 0, 0, NULL)) {
314                 release_region(hw_config->io_base, 16);
315                 return 0;
316         }
317
318         hw_config->driver_use_1 = SB_NO_MIDI | SB_NO_MIXER | SB_NO_RECORDING;
319
320         /* Prevent false alarms */
321         old_quiet = sb_be_quiet;
322         sb_be_quiet = 1;
323
324         sb_dsp_init(hw_config, THIS_MODULE);
325
326         sb_be_quiet = old_quiet;
327         return 1;
328 }
329
330 static int __init probe_trix_mpu(struct address_info *hw_config)
331 {
332         unsigned char conf;
333         static int irq_bits[] = {
334                 -1, -1, -1, 1, 2, 3, -1, 4, -1, 5
335         };
336
337         if (hw_config->irq > 9)
338         {
339                 printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
340                 return 0;
341         }
342         if (irq_bits[hw_config->irq] == -1)
343         {
344                 printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
345                 return 0;
346         }
347         switch (hw_config->io_base)
348         {
349                 case 0x330:
350                         conf = 0x00;
351                         break;
352                 case 0x370:
353                         conf = 0x04;
354                         break;
355                 case 0x3b0:
356                         conf = 0x08;
357                         break;
358                 case 0x3f0:
359                         conf = 0x0c;
360                         break;
361                 default:
362                         return 0;       /* Invalid port */
363         }
364
365         conf |= irq_bits[hw_config->irq] << 4;
366         trix_write(0x19, (trix_read(0x19) & 0x83) | conf);
367         hw_config->name = "AudioTrix Pro";
368         return probe_uart401(hw_config, THIS_MODULE);
369 }
370
371 static void __exit unload_trix_wss(struct address_info *hw_config)
372 {
373         int dma2 = hw_config->dma2;
374
375         if (dma2 == -1)
376                 dma2 = hw_config->dma;
377
378         release_region(0x390, 2);
379         release_region(hw_config->io_base, 4);
380
381         ad1848_unload(hw_config->io_base + 4,
382                       hw_config->irq,
383                       hw_config->dma,
384                       dma2,
385                       0);
386         sound_unload_audiodev(hw_config->slots[0]);
387 }
388
389 static inline void __exit unload_trix_mpu(struct address_info *hw_config)
390 {
391         unload_uart401(hw_config);
392 }
393
394 static inline void __exit unload_trix_sb(struct address_info *hw_config)
395 {
396         sb_dsp_unload(hw_config, mpu);
397 }
398
399 static struct address_info cfg;
400 static struct address_info cfg2;
401 static struct address_info cfg_mpu;
402
403 static int sb;
404 static int fw_load;
405
406 static int __initdata io        = -1;
407 static int __initdata irq       = -1;
408 static int __initdata dma       = -1;
409 static int __initdata dma2      = -1;   /* Set this for modules that need it */
410 static int __initdata sb_io     = -1;
411 static int __initdata sb_dma    = -1;
412 static int __initdata sb_irq    = -1;
413 static int __initdata mpu_io    = -1;
414 static int __initdata mpu_irq   = -1;
415
416 module_param(io, int, 0);
417 module_param(irq, int, 0);
418 module_param(dma, int, 0);
419 module_param(dma2, int, 0);
420 module_param(sb_io, int, 0);
421 module_param(sb_dma, int, 0);
422 module_param(sb_irq, int, 0);
423 module_param(mpu_io, int, 0);
424 module_param(mpu_irq, int, 0);
425 module_param(joystick, bool, 0);
426
427 static int __init init_trix(void)
428 {
429         printk(KERN_INFO "MediaTrix audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
430
431         cfg.io_base = io;
432         cfg.irq = irq;
433         cfg.dma = dma;
434         cfg.dma2 = dma2;
435
436         cfg2.io_base = sb_io;
437         cfg2.irq = sb_irq;
438         cfg2.dma = sb_dma;
439
440         cfg_mpu.io_base = mpu_io;
441         cfg_mpu.irq = mpu_irq;
442
443         if (cfg.io_base == -1 || cfg.dma == -1 || cfg.irq == -1) {
444                 printk(KERN_INFO "I/O, IRQ, DMA and type are mandatory\n");
445                 return -EINVAL;
446         }
447
448         if (cfg2.io_base != -1 && (cfg2.irq == -1 || cfg2.dma == -1)) {
449                 printk(KERN_INFO "CONFIG_SB_IRQ and CONFIG_SB_DMA must be specified if SB_IO is set.\n");
450                 return -EINVAL;
451         }
452         if (cfg_mpu.io_base != -1 && cfg_mpu.irq == -1) {
453                 printk(KERN_INFO "CONFIG_MPU_IRQ must be specified if MPU_IO is set.\n");
454                 return -EINVAL;
455         }
456         if (!trix_boot)
457         {
458                 fw_load = 1;
459                 trix_boot_len = mod_firmware_load("/etc/sound/trxpro.bin",
460                                                     (char **) &trix_boot);
461         }
462
463         if (!request_region(0x390, 2, "AudioTrix")) {
464                 printk(KERN_ERR "AudioTrix: Config port I/O conflict\n");
465                 return -ENODEV;
466         }
467
468         if (!init_trix_wss(&cfg)) {
469                 release_region(0x390, 2);
470                 return -ENODEV;
471         }
472
473         /*
474          *    We must attach in the right order to get the firmware
475          *      loaded up in time.
476          */
477
478         if (cfg2.io_base != -1) {
479                 sb = probe_trix_sb(&cfg2);
480         }
481         
482         if (cfg_mpu.io_base != -1)
483                 mpu = probe_trix_mpu(&cfg_mpu);
484
485         return 0;
486 }
487
488 static void __exit cleanup_trix(void)
489 {
490         if (fw_load && trix_boot)
491                 vfree(trix_boot);
492         if (sb)
493                 unload_trix_sb(&cfg2);
494         if (mpu)
495                 unload_trix_mpu(&cfg_mpu);
496         unload_trix_wss(&cfg);
497 }
498
499 module_init(init_trix);
500 module_exit(cleanup_trix);
501
502 #ifndef MODULE
503 static int __init setup_trix (char *str)
504 {
505         /* io, irq, dma, dma2, sb_io, sb_irq, sb_dma, mpu_io, mpu_irq */
506         int ints[9];
507         
508         str = get_options(str, ARRAY_SIZE(ints), ints);
509
510         io      = ints[1];
511         irq     = ints[2];
512         dma     = ints[3];
513         dma2    = ints[4];
514         sb_io   = ints[5];
515         sb_irq  = ints[6];
516         sb_dma  = ints[6];
517         mpu_io  = ints[7];
518         mpu_irq = ints[8];
519
520         return 1;
521 }
522
523 __setup("trix=", setup_trix);
524 #endif
525 MODULE_LICENSE("GPL");