Import 1.3.39
[davej-history.git] / drivers / sound / trix.c
blob3c12d0e1df0de09c4d81f7b8a6a1df85243a120e
1 /*
2 * sound/trix.c
4 * Low level driver for the MediaTriX AudioTriX Pro
5 * (MT-0002-PC Control Chip)
7 * Copyright by Hannu Savolainen 1995
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met: 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 2.
13 * Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
31 #include "sound_config.h"
33 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_TRIX)
35 #ifdef INCLUDE_TRIX_BOOT
36 #include "trix_boot.h"
37 #endif
39 static int kilroy_was_here = 0; /* Don't detect twice */
40 static int sb_initialized = 0;
41 static int mpu_initialized = 0;
43 static sound_os_info *trix_osp = NULL;
45 static unsigned char
46 trix_read (int addr)
48 outb ((unsigned char) addr, 0x390); /* MT-0002-PC ASIC address */
49 return inb (0x391); /* MT-0002-PC ASIC data */
52 static void
53 trix_write (int addr, int data)
55 outb ((unsigned char) addr, 0x390); /* MT-0002-PC ASIC address */
56 outb ((unsigned char) data, 0x391); /* MT-0002-PC ASIC data */
59 static void
60 download_boot (int base)
62 #ifdef INCLUDE_TRIX_BOOT
63 int i = 0, n = sizeof (trix_boot);
65 trix_write (0xf8, 0x00); /* ??????? */
66 outb (0x01, base + 6); /* Clear the internal data pointer */
67 outb (0x00, base + 6); /* Restart */
70 * Write the boot code to the RAM upload/download register.
71 * Each write increments the internal data pointer.
73 outb (0x01, base + 6); /* Clear the internal data pointer */
74 outb (0x1A, 0x390); /* Select RAM download/upload port */
76 for (i = 0; i < n; i++)
77 outb (trix_boot[i], 0x391);
78 for (i = n; i < 10016; i++) /* Clear up to first 16 bytes of data RAM */
79 outb (0x00, 0x391);
80 outb (0x00, base + 6); /* Reset */
81 outb (0x50, 0x390); /* ?????? */
82 #endif
85 static int
86 trix_set_wss_port (struct address_info *hw_config)
88 unsigned char addr_bits;
90 if (check_region (0x390, 2))
92 printk ("AudioTriX: Config port I/O conflict\n");
93 return 0;
96 if (kilroy_was_here) /* Already initialized */
97 return 0;
99 if (trix_read (0x15) != 0x71) /* No asic signature */
101 DDB (printk ("No AudioTriX ASIC signature found\n"));
102 return 0;
105 request_region (0x390, 2, "AudioTriX");
107 kilroy_was_here = 1;
110 * Reset some registers.
113 trix_write (0x13, 0);
114 trix_write (0x14, 0);
117 * Configure the ASIC to place the codec to the proper I/O location
120 switch (hw_config->io_base)
122 case 0x530:
123 addr_bits = 0;
124 break;
125 case 0x604:
126 addr_bits = 1;
127 break;
128 case 0xE80:
129 addr_bits = 2;
130 break;
131 case 0xF40:
132 addr_bits = 3;
133 break;
134 default:
135 return 0;
138 trix_write (0x19, (trix_read (0x19) & 0x03) | addr_bits);
139 return 1;
143 * Probe and attach routines for the Windows Sound System mode of
144 * AudioTriX Pro
148 probe_trix_wss (struct address_info *hw_config)
151 * Check if the IO port returns valid signature. The original MS Sound
152 * system returns 0x04 while some cards (AudioTriX Pro for example)
153 * return 0x00.
155 if (check_region (hw_config->io_base, 8))
157 printk ("AudioTriX: MSS I/O port conflict\n");
158 return 0;
161 trix_osp = hw_config->osp;
163 if (!trix_set_wss_port (hw_config))
164 return 0;
166 if ((inb (hw_config->io_base + 3) & 0x3f) != 0x00)
168 DDB (printk ("No MSS signature detected on port 0x%x\n", hw_config->io_base));
169 return 0;
172 if (hw_config->irq > 11)
174 printk ("AudioTriX: Bad WSS IRQ %d\n", hw_config->irq);
175 return 0;
178 if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
180 printk ("AudioTriX: Bad WSS DMA %d\n", hw_config->dma);
181 return 0;
184 if (hw_config->dma2 != -1)
185 if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3)
187 printk ("AudioTriX: Bad capture DMA %d\n", hw_config->dma2);
188 return 0;
192 * Check that DMA0 is not in use with a 8 bit board.
195 if (hw_config->dma == 0 && inb (hw_config->io_base + 3) & 0x80)
197 printk ("AudioTriX: Can't use DMA0 with a 8 bit card\n");
198 return 0;
201 if (hw_config->irq > 7 && hw_config->irq != 9 && inb (hw_config->io_base + 3) & 0x80)
203 printk ("AudioTriX: Can't use IRQ%d with a 8 bit card\n", hw_config->irq);
204 return 0;
207 return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp);
210 long
211 attach_trix_wss (long mem_start, struct address_info *hw_config)
213 static unsigned char interrupt_bits[12] =
214 {-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20};
215 char bits;
217 static unsigned char dma_bits[4] =
218 {1, 2, 0, 3};
220 int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
221 int dma1 = hw_config->dma, dma2 = hw_config->dma2;
223 trix_osp = hw_config->osp;
225 if (!kilroy_was_here)
227 DDB (printk ("AudioTriX: Attach called but not probed yet???\n"));
228 return mem_start;
232 * Set the IRQ and DMA addresses.
235 bits = interrupt_bits[hw_config->irq];
236 if (bits == -1)
238 printk ("AudioTriX: Bad IRQ (%d)\n", hw_config->irq);
239 return mem_start;
242 outb (bits | 0x40, config_port);
243 if ((inb (version_port) & 0x40) == 0)
244 printk ("[IRQ Conflict?]");
246 if (hw_config->dma2 == -1) /* Single DMA mode */
248 bits |= dma_bits[dma1];
249 dma2 = dma1;
251 else
253 unsigned char tmp;
255 tmp = trix_read (0x13) & ~30;
256 trix_write (0x13, tmp | 0x80 | (dma1 << 4));
258 tmp = trix_read (0x14) & ~30;
259 trix_write (0x14, tmp | 0x80 | (dma2 << 4));
262 outb (bits, config_port); /* Write IRQ+DMA setup */
264 ad1848_init ("AudioTriX Pro", hw_config->io_base + 4,
265 hw_config->irq,
266 dma1,
267 dma2,
269 hw_config->osp);
270 request_region (hw_config->io_base, 4, "MSS config");
271 return mem_start;
275 probe_trix_sb (struct address_info *hw_config)
278 int tmp;
279 unsigned char conf;
280 static char irq_translate[] =
281 {-1, -1, -1, 0, 1, 2, -1, 3};
283 #ifndef INCLUDE_TRIX_BOOT
284 return 0; /* No boot code -> no fun */
285 #endif
286 if (!kilroy_was_here)
287 return 0; /* AudioTriX Pro has not been detected earlier */
289 if (sb_initialized)
290 return 0;
292 if (check_region (hw_config->io_base, 16))
294 printk ("AudioTriX: SB I/O port conflict\n");
295 return 0;
298 if (hw_config->io_base & 0xffffff8f != 0x200)
299 return 0;
301 tmp = hw_config->irq;
302 if (tmp > 7)
303 return 0;
304 if (irq_translate[tmp] == -1)
305 return 0;
307 tmp = hw_config->dma;
308 if (tmp != 1 && tmp != 3)
309 return 0;
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 return 1;
324 long
325 attach_trix_sb (long mem_start, struct address_info *hw_config)
327 #ifndef EXCLUDE_SB
328 extern int sb_no_recording;
330 sb_dsp_disable_midi ();
331 sb_no_recording = 1;
332 #endif
333 printk (" <AudioTriX (SB)>");
334 return mem_start;
337 long
338 attach_trix_mpu (long mem_start, struct address_info *hw_config)
340 #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
341 return attach_mpu401 (mem_start, hw_config);
342 #else
343 return mem_start;
344 #endif
348 probe_trix_mpu (struct address_info *hw_config)
350 #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
351 unsigned char conf;
352 static char irq_bits[] =
353 {-1, -1, -1, 1, 2, 3, -1, 4, -1, 5};
355 if (!kilroy_was_here)
357 DDB (printk ("Trix: WSS and SB modes must be initialized before MPU\n"));
358 return 0; /* AudioTriX Pro has not been detected earlier */
361 if (!sb_initialized)
363 DDB (printk ("Trix: SB mode must be initialized before MPU\n"));
364 return 0;
367 if (mpu_initialized)
369 DDB (printk ("Trix: MPU mode already initialized\n"));
370 return 0;
373 if (check_region (hw_config->io_base, 4))
375 printk ("AudioTriX: MPU I/O port conflict\n");
376 return 0;
379 if (hw_config->irq > 9)
381 printk ("AudioTriX: Bad MPU IRQ %d\n", hw_config->irq);
382 return 0;
385 if (irq_bits[hw_config->irq] == -1)
387 printk ("AudioTriX: Bad MPU IRQ %d\n", hw_config->irq);
388 return 0;
391 switch (hw_config->io_base)
393 case 0x330:
394 conf = 0x00;
395 break;
396 case 0x370:
397 conf = 0x04;
398 break;
399 case 0x3b0:
400 conf = 0x08;
401 break;
402 case 0x3f0:
403 conf = 0x0c;
404 break;
405 default:
406 return 0; /* Invalid port */
409 conf |= irq_bits[hw_config->irq] << 4;
411 trix_write (0x19, (trix_read (0x19) & 0x83) | conf);
413 mpu_initialized = 1;
415 return probe_mpu401 (hw_config);
416 #else
417 return 0;
418 #endif
421 void
422 unload_trix_wss (struct address_info *hw_config)
424 int dma2 = hw_config->dma2;
426 if (dma2 == -1)
427 dma2 = hw_config->dma;
429 release_region (0x390, 2);
430 release_region (hw_config->io_base, 4);
432 ad1848_unload (hw_config->io_base + 4,
433 hw_config->irq,
434 hw_config->dma,
435 dma2,
439 void
440 unload_trix_mpu (struct address_info *hw_config)
442 #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
443 unload_mpu401 (hw_config);
444 #endif
446 void
447 unload_trix_sb (struct address_info *hw_config)
452 #endif