Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Copyright (C) by Hannu Savolainen 1993-1997 | |
3 | * | |
4 | * mad16.c | |
5 | * | |
6 | * Initialization code for OPTi MAD16 compatible audio chips. Including | |
7 | * | |
8 | * OPTi 82C928 MAD16 (replaced by C929) | |
9 | * OAK OTI-601D Mozart | |
10 | * OAK OTI-605 Mozart (later version with MPU401 Midi) | |
11 | * OPTi 82C929 MAD16 Pro | |
12 | * OPTi 82C930 | |
13 | * OPTi 82C924 | |
14 | * | |
15 | * These audio interface chips don't produce sound themselves. They just | |
16 | * connect some other components (OPL-[234] and a WSS compatible codec) | |
17 | * to the PC bus and perform I/O, DMA and IRQ address decoding. There is | |
18 | * also a UART for the MPU-401 mode (not 82C928/Mozart). | |
19 | * The Mozart chip appears to be compatible with the 82C928, although later | |
20 | * issues of the card, using the OTI-605 chip, have an MPU-401 compatible Midi | |
21 | * port. This port is configured differently to that of the OPTi audio chips. | |
22 | * | |
23 | * Changes | |
24 | * | |
25 | * Alan Cox Clean up, added module selections. | |
26 | * | |
27 | * A. Wik Added support for Opti924 PnP. | |
28 | * Improved debugging support. 16-May-1998 | |
29 | * Fixed bug. 16-Jun-1998 | |
30 | * | |
31 | * Torsten Duwe Made Opti924 PnP support non-destructive | |
32 | * 23-Dec-1998 | |
33 | * | |
34 | * Paul Grayson Added support for Midi on later Mozart cards. | |
35 | * 25-Nov-1999 | |
36 | * Christoph Hellwig Adapted to module_init/module_exit. | |
37 | * Arnaldo C. de Melo got rid of attach_uart401 21-Sep-2000 | |
38 | * | |
39 | * Pavel Rabel Clean up Nov-2000 | |
40 | */ | |
41 | ||
42 | #include <linux/config.h> | |
43 | #include <linux/init.h> | |
44 | #include <linux/module.h> | |
45 | #include <linux/gameport.h> | |
46 | #include <linux/spinlock.h> | |
47 | #include "sound_config.h" | |
48 | ||
49 | #include "ad1848.h" | |
50 | #include "sb.h" | |
51 | #include "mpu401.h" | |
52 | ||
e608460d DT |
53 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) |
54 | #define SUPPORT_JOYSTICK 1 | |
55 | #endif | |
56 | ||
1da177e4 LT |
57 | static int mad16_conf; |
58 | static int mad16_cdsel; | |
1da177e4 LT |
59 | static DEFINE_SPINLOCK(lock); |
60 | ||
61 | #define C928 1 | |
62 | #define MOZART 2 | |
63 | #define C929 3 | |
64 | #define C930 4 | |
65 | #define C924 5 | |
66 | ||
67 | /* | |
68 | * Registers | |
69 | * | |
70 | * The MAD16 occupies I/O ports 0xf8d to 0xf93 (fixed locations). | |
71 | * All ports are inactive by default. They can be activated by | |
72 | * writing 0xE2 or 0xE3 to the password register. The password is valid | |
73 | * only until the next I/O read or write. | |
74 | * | |
75 | * 82C930 uses 0xE4 as the password and indirect addressing to access | |
76 | * the config registers. | |
77 | */ | |
78 | ||
79 | #define MC0_PORT 0xf8c /* Dummy port */ | |
80 | #define MC1_PORT 0xf8d /* SB address, CD-ROM interface type, joystick */ | |
81 | #define MC2_PORT 0xf8e /* CD-ROM address, IRQ, DMA, plus OPL4 bit */ | |
82 | #define MC3_PORT 0xf8f | |
83 | #define PASSWD_REG 0xf8f | |
84 | #define MC4_PORT 0xf90 | |
85 | #define MC5_PORT 0xf91 | |
86 | #define MC6_PORT 0xf92 | |
87 | #define MC7_PORT 0xf93 | |
88 | #define MC8_PORT 0xf94 | |
89 | #define MC9_PORT 0xf95 | |
90 | #define MC10_PORT 0xf96 | |
91 | #define MC11_PORT 0xf97 | |
92 | #define MC12_PORT 0xf98 | |
93 | ||
94 | static int board_type = C928; | |
95 | ||
96 | static int *mad16_osp; | |
97 | static int c931_detected; /* minor differences from C930 */ | |
98 | static char c924pnp; /* " " " C924 */ | |
99 | static int debug; /* debugging output */ | |
100 | ||
101 | #ifdef DDB | |
102 | #undef DDB | |
103 | #endif | |
104 | #define DDB(x) do {if (debug) x;} while (0) | |
105 | ||
106 | static unsigned char mad_read(int port) | |
107 | { | |
108 | unsigned long flags; | |
109 | unsigned char tmp; | |
110 | ||
111 | spin_lock_irqsave(&lock,flags); | |
112 | ||
113 | switch (board_type) /* Output password */ | |
114 | { | |
115 | case C928: | |
116 | case MOZART: | |
117 | outb((0xE2), PASSWD_REG); | |
118 | break; | |
119 | ||
120 | case C929: | |
121 | outb((0xE3), PASSWD_REG); | |
122 | break; | |
123 | ||
124 | case C930: | |
125 | /* outb(( 0xE4), PASSWD_REG); */ | |
126 | break; | |
127 | ||
128 | case C924: | |
129 | /* the c924 has its ports relocated by -128 if | |
130 | PnP is enabled -aw */ | |
131 | if (!c924pnp) | |
132 | outb((0xE5), PASSWD_REG); else | |
133 | outb((0xE5), PASSWD_REG - 0x80); | |
134 | break; | |
135 | } | |
136 | ||
137 | if (board_type == C930) | |
138 | { | |
139 | outb((port - MC0_PORT), 0xe0e); /* Write to index reg */ | |
140 | tmp = inb(0xe0f); /* Read from data reg */ | |
141 | } | |
142 | else | |
143 | if (!c924pnp) | |
144 | tmp = inb(port); else | |
145 | tmp = inb(port-0x80); | |
146 | spin_unlock_irqrestore(&lock,flags); | |
147 | ||
148 | return tmp; | |
149 | } | |
150 | ||
151 | static void mad_write(int port, int value) | |
152 | { | |
153 | unsigned long flags; | |
154 | ||
155 | spin_lock_irqsave(&lock,flags); | |
156 | ||
157 | switch (board_type) /* Output password */ | |
158 | { | |
159 | case C928: | |
160 | case MOZART: | |
161 | outb((0xE2), PASSWD_REG); | |
162 | break; | |
163 | ||
164 | case C929: | |
165 | outb((0xE3), PASSWD_REG); | |
166 | break; | |
167 | ||
168 | case C930: | |
169 | /* outb(( 0xE4), PASSWD_REG); */ | |
170 | break; | |
171 | ||
172 | case C924: | |
173 | if (!c924pnp) | |
174 | outb((0xE5), PASSWD_REG); else | |
175 | outb((0xE5), PASSWD_REG - 0x80); | |
176 | break; | |
177 | } | |
178 | ||
179 | if (board_type == C930) | |
180 | { | |
181 | outb((port - MC0_PORT), 0xe0e); /* Write to index reg */ | |
182 | outb(((unsigned char) (value & 0xff)), 0xe0f); | |
183 | } | |
184 | else | |
185 | if (!c924pnp) | |
186 | outb(((unsigned char) (value & 0xff)), port); else | |
187 | outb(((unsigned char) (value & 0xff)), port-0x80); | |
188 | spin_unlock_irqrestore(&lock,flags); | |
189 | } | |
190 | ||
191 | static int __init detect_c930(void) | |
192 | { | |
193 | unsigned char tmp = mad_read(MC1_PORT); | |
194 | ||
195 | if ((tmp & 0x06) != 0x06) | |
196 | { | |
197 | DDB(printk("Wrong C930 signature (%x)\n", tmp)); | |
198 | /* return 0; */ | |
199 | } | |
200 | mad_write(MC1_PORT, 0); | |
201 | ||
202 | if (mad_read(MC1_PORT) != 0x06) | |
203 | { | |
204 | DDB(printk("Wrong C930 signature2 (%x)\n", tmp)); | |
205 | /* return 0; */ | |
206 | } | |
207 | mad_write(MC1_PORT, tmp); /* Restore bits */ | |
208 | ||
209 | mad_write(MC7_PORT, 0); | |
210 | if ((tmp = mad_read(MC7_PORT)) != 0) | |
211 | { | |
212 | DDB(printk("MC7 not writable (%x)\n", tmp)); | |
213 | return 0; | |
214 | } | |
215 | mad_write(MC7_PORT, 0xcb); | |
216 | if ((tmp = mad_read(MC7_PORT)) != 0xcb) | |
217 | { | |
218 | DDB(printk("MC7 not writable2 (%x)\n", tmp)); | |
219 | return 0; | |
220 | } | |
221 | ||
222 | tmp = mad_read(MC0_PORT+18); | |
223 | if (tmp == 0xff || tmp == 0x00) | |
224 | return 1; | |
225 | /* We probably have a C931 */ | |
226 | DDB(printk("Detected C931 config=0x%02x\n", tmp)); | |
227 | c931_detected = 1; | |
228 | ||
229 | /* | |
230 | * We cannot configure the chip if it is in PnP mode. | |
231 | * If we have a CSN assigned (bit 8 in MC13) we first try | |
232 | * a software reset, then a software power off, finally | |
233 | * Clearing PnP mode. The last option is not | |
234 | * Bit 8 in MC13 | |
235 | */ | |
236 | if ((mad_read(MC0_PORT+13) & 0x80) == 0) | |
237 | return 1; | |
238 | ||
239 | /* Software reset */ | |
240 | mad_write(MC9_PORT, 0x02); | |
241 | mad_write(MC9_PORT, 0x00); | |
242 | ||
243 | if ((mad_read(MC0_PORT+13) & 0x80) == 0) | |
244 | return 1; | |
245 | ||
246 | /* Power off, and on again */ | |
247 | mad_write(MC9_PORT, 0xc2); | |
248 | mad_write(MC9_PORT, 0xc0); | |
249 | ||
250 | if ((mad_read(MC0_PORT+13) & 0x80) == 0) | |
251 | return 1; | |
252 | ||
253 | #if 0 | |
254 | /* Force off PnP mode. This is not recommended because | |
255 | * the PnP bios will not recognize the chip on the next | |
256 | * warm boot and may assignd different resources to other | |
257 | * PnP/PCI cards. | |
258 | */ | |
259 | mad_write(MC0_PORT+17, 0x04); | |
260 | #endif | |
261 | return 1; | |
262 | } | |
263 | ||
264 | static int __init detect_mad16(void) | |
265 | { | |
266 | unsigned char tmp, tmp2, bit; | |
267 | int i, port; | |
268 | ||
269 | /* | |
270 | * Check that reading a register doesn't return bus float (0xff) | |
271 | * when the card is accessed using password. This may fail in case | |
272 | * the card is in low power mode. Normally at least the power saving | |
273 | * mode bit should be 0. | |
274 | */ | |
275 | ||
276 | if ((tmp = mad_read(MC1_PORT)) == 0xff) | |
277 | { | |
278 | DDB(printk("MC1_PORT returned 0xff\n")); | |
279 | return 0; | |
280 | } | |
281 | for (i = 0xf8d; i <= 0xf98; i++) | |
282 | if (!c924pnp) | |
283 | DDB(printk("Port %0x (init value) = %0x\n", i, mad_read(i))); | |
284 | else | |
285 | DDB(printk("Port %0x (init value) = %0x\n", i-0x80, mad_read(i))); | |
286 | ||
287 | if (board_type == C930) | |
288 | return detect_c930(); | |
289 | ||
290 | /* | |
291 | * Now check that the gate is closed on first I/O after writing | |
292 | * the password. (This is how a MAD16 compatible card works). | |
293 | */ | |
294 | ||
295 | if ((tmp2 = inb(MC1_PORT)) == tmp) /* It didn't close */ | |
296 | { | |
297 | DDB(printk("MC1_PORT didn't close after read (0x%02x)\n", tmp2)); | |
298 | return 0; | |
299 | } | |
300 | ||
301 | bit = (c924pnp) ? 0x20 : 0x80; | |
302 | port = (c924pnp) ? MC2_PORT : MC1_PORT; | |
303 | ||
304 | tmp = mad_read(port); | |
305 | mad_write(port, tmp ^ bit); /* Toggle a bit */ | |
306 | if ((tmp2 = mad_read(port)) != (tmp ^ bit)) /* Compare the bit */ | |
307 | { | |
308 | mad_write(port, tmp); /* Restore */ | |
309 | DDB(printk("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2)); | |
310 | return 0; | |
311 | } | |
312 | mad_write(port, tmp); /* Restore */ | |
313 | return 1; /* Bingo */ | |
314 | } | |
315 | ||
316 | static int __init wss_init(struct address_info *hw_config) | |
317 | { | |
318 | /* | |
319 | * Check if the IO port returns valid signature. The original MS Sound | |
320 | * system returns 0x04 while some cards (AudioTrix Pro for example) | |
321 | * return 0x00. | |
322 | */ | |
323 | ||
324 | if ((inb(hw_config->io_base + 3) & 0x3f) != 0x04 && | |
325 | (inb(hw_config->io_base + 3) & 0x3f) != 0x00) | |
326 | { | |
327 | DDB(printk("No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, inb(hw_config->io_base + 3))); | |
328 | return 0; | |
329 | } | |
330 | /* | |
331 | * Check that DMA0 is not in use with a 8 bit board. | |
332 | */ | |
333 | if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80) | |
334 | { | |
335 | printk("MSS: Can't use DMA0 with a 8 bit card/slot\n"); | |
336 | return 0; | |
337 | } | |
338 | if (hw_config->irq > 9 && inb(hw_config->io_base + 3) & 0x80) | |
339 | printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq); | |
340 | return 1; | |
341 | } | |
342 | ||
343 | static void __init init_c930(struct address_info *hw_config, int base) | |
344 | { | |
345 | unsigned char cfg = 0; | |
346 | ||
347 | cfg |= (0x0f & mad16_conf); | |
348 | ||
349 | if(c931_detected) | |
350 | { | |
351 | /* Bit 0 has reversd meaning. Bits 1 and 2 sese | |
352 | reversed on write. | |
353 | Support only IDE cdrom. IDE port programmed | |
354 | somewhere else. */ | |
355 | cfg = (cfg & 0x09) ^ 0x07; | |
356 | } | |
357 | cfg |= base << 4; | |
358 | mad_write(MC1_PORT, cfg); | |
359 | ||
360 | /* MC2 is CD configuration. Don't touch it. */ | |
361 | ||
362 | mad_write(MC3_PORT, 0); /* Disable SB mode IRQ and DMA */ | |
363 | ||
364 | /* bit 2 of MC4 reverses it's meaning between the C930 | |
365 | and the C931. */ | |
366 | cfg = c931_detected ? 0x04 : 0x00; | |
367 | ||
368 | if(mad16_cdsel & 0x20) | |
369 | mad_write(MC4_PORT, 0x62|cfg); /* opl4 */ | |
370 | else | |
371 | mad_write(MC4_PORT, 0x52|cfg); /* opl3 */ | |
372 | ||
373 | mad_write(MC5_PORT, 0x3C); /* Init it into mode2 */ | |
374 | mad_write(MC6_PORT, 0x02); /* Enable WSS, Disable MPU and SB */ | |
375 | mad_write(MC7_PORT, 0xCB); | |
376 | mad_write(MC10_PORT, 0x11); | |
377 | } | |
378 | ||
379 | static int __init chip_detect(void) | |
380 | { | |
381 | int i; | |
382 | ||
383 | /* | |
384 | * Then try to detect with the old password | |
385 | */ | |
386 | board_type = C924; | |
387 | ||
388 | DDB(printk("Detect using password = 0xE5\n")); | |
389 | ||
390 | if (detect_mad16()) { | |
391 | return 1; | |
392 | } | |
393 | ||
394 | board_type = C928; | |
395 | ||
396 | DDB(printk("Detect using password = 0xE2\n")); | |
397 | ||
398 | if (detect_mad16()) | |
399 | { | |
400 | unsigned char model; | |
401 | ||
402 | if (((model = mad_read(MC3_PORT)) & 0x03) == 0x03) { | |
403 | DDB(printk("mad16.c: Mozart detected\n")); | |
404 | board_type = MOZART; | |
405 | } else { | |
406 | DDB(printk("mad16.c: 82C928 detected???\n")); | |
407 | board_type = C928; | |
408 | } | |
409 | return 1; | |
410 | } | |
411 | ||
412 | board_type = C929; | |
413 | ||
414 | DDB(printk("Detect using password = 0xE3\n")); | |
415 | ||
416 | if (detect_mad16()) | |
417 | { | |
418 | DDB(printk("mad16.c: 82C929 detected\n")); | |
419 | return 1; | |
420 | } | |
421 | ||
422 | if (inb(PASSWD_REG) != 0xff) | |
423 | return 0; | |
424 | ||
425 | /* | |
426 | * First relocate MC# registers to 0xe0e/0xe0f, disable password | |
427 | */ | |
428 | ||
429 | outb((0xE4), PASSWD_REG); | |
430 | outb((0x80), PASSWD_REG); | |
431 | ||
432 | board_type = C930; | |
433 | ||
434 | DDB(printk("Detect using password = 0xE4\n")); | |
435 | ||
436 | for (i = 0xf8d; i <= 0xf93; i++) | |
437 | DDB(printk("port %03x = %02x\n", i, mad_read(i))); | |
438 | ||
439 | if(detect_mad16()) { | |
440 | DDB(printk("mad16.c: 82C930 detected\n")); | |
441 | return 1; | |
442 | } | |
443 | ||
444 | /* The C931 has the password reg at F8D */ | |
445 | outb((0xE4), 0xF8D); | |
446 | outb((0x80), 0xF8D); | |
447 | DDB(printk("Detect using password = 0xE4 for C931\n")); | |
448 | ||
449 | if (detect_mad16()) { | |
450 | return 1; | |
451 | } | |
452 | ||
453 | board_type = C924; | |
454 | c924pnp++; | |
455 | DDB(printk("Detect using password = 0xE5 (again), port offset -0x80\n")); | |
456 | if (detect_mad16()) { | |
457 | DDB(printk("mad16.c: 82C924 PnP detected\n")); | |
458 | return 1; | |
459 | } | |
460 | ||
461 | c924pnp=0; | |
462 | ||
463 | return 0; | |
464 | } | |
465 | ||
466 | static int __init probe_mad16(struct address_info *hw_config) | |
467 | { | |
468 | int i; | |
469 | unsigned char tmp; | |
470 | unsigned char cs4231_mode = 0; | |
471 | ||
472 | int ad_flags = 0; | |
473 | ||
474 | signed char bits; | |
475 | ||
476 | static char dma_bits[4] = { | |
477 | 1, 2, 0, 3 | |
478 | }; | |
479 | ||
480 | int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3; | |
481 | int dma = hw_config->dma, dma2 = hw_config->dma2; | |
482 | unsigned char dma2_bit = 0; | |
483 | int base; | |
484 | struct resource *ports; | |
485 | ||
486 | mad16_osp = hw_config->osp; | |
487 | ||
488 | switch (hw_config->io_base) { | |
489 | case 0x530: | |
490 | base = 0; | |
491 | break; | |
492 | case 0xe80: | |
493 | base = 1; | |
494 | break; | |
495 | case 0xf40: | |
496 | base = 2; | |
497 | break; | |
498 | case 0x604: | |
499 | base = 3; | |
500 | break; | |
501 | default: | |
502 | printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base); | |
503 | return 0; | |
504 | } | |
505 | ||
506 | if (dma != 0 && dma != 1 && dma != 3) { | |
507 | printk(KERN_ERR "MSS: Bad DMA %d\n", dma); | |
508 | return 0; | |
509 | } | |
510 | ||
511 | /* | |
512 | * Check that all ports return 0xff (bus float) when no password | |
513 | * is written to the password register. | |
514 | */ | |
515 | ||
516 | DDB(printk("--- Detecting MAD16 / Mozart ---\n")); | |
517 | if (!chip_detect()) | |
518 | return 0; | |
519 | ||
520 | switch (hw_config->irq) { | |
521 | case 7: | |
522 | bits = 8; | |
523 | break; | |
524 | case 9: | |
525 | bits = 0x10; | |
526 | break; | |
527 | case 10: | |
528 | bits = 0x18; | |
529 | break; | |
530 | case 12: | |
531 | bits = 0x20; | |
532 | break; | |
533 | case 5: /* Also IRQ5 is possible on C930 */ | |
534 | if (board_type == C930 || c924pnp) { | |
535 | bits = 0x28; | |
536 | break; | |
537 | } | |
538 | default: | |
539 | printk(KERN_ERR "MAD16/Mozart: Bad IRQ %d\n", hw_config->irq); | |
540 | return 0; | |
541 | } | |
542 | ||
543 | ports = request_region(hw_config->io_base + 4, 4, "ad1848"); | |
544 | if (!ports) { | |
545 | printk(KERN_ERR "MSS: I/O port conflict\n"); | |
546 | return 0; | |
547 | } | |
548 | if (!request_region(hw_config->io_base, 4, "mad16 WSS config")) { | |
549 | release_region(hw_config->io_base + 4, 4); | |
550 | printk(KERN_ERR "MSS: I/O port conflict\n"); | |
551 | return 0; | |
552 | } | |
553 | ||
554 | if (board_type == C930) { | |
555 | init_c930(hw_config, base); | |
556 | goto got_it; | |
557 | } | |
558 | ||
559 | for (i = 0xf8d; i <= 0xf93; i++) { | |
560 | if (!c924pnp) | |
561 | DDB(printk("port %03x = %02x\n", i, mad_read(i))); | |
562 | else | |
563 | DDB(printk("port %03x = %02x\n", i-0x80, mad_read(i))); | |
564 | } | |
565 | ||
566 | /* | |
567 | * Set the WSS address | |
568 | */ | |
569 | ||
570 | tmp = (mad_read(MC1_PORT) & 0x0f) | 0x80; /* Enable WSS, Disable SB */ | |
571 | tmp |= base << 4; /* WSS port select bits */ | |
572 | ||
573 | /* | |
574 | * Set optional CD-ROM and joystick settings. | |
575 | */ | |
576 | ||
577 | tmp &= ~0x0f; | |
578 | tmp |= (mad16_conf & 0x0f); /* CD-ROM and joystick bits */ | |
579 | mad_write(MC1_PORT, tmp); | |
580 | ||
581 | tmp = mad16_cdsel; | |
582 | mad_write(MC2_PORT, tmp); | |
583 | mad_write(MC3_PORT, 0xf0); /* Disable SB */ | |
584 | ||
585 | if (board_type == C924) /* Specific C924 init values */ | |
586 | { | |
587 | mad_write(MC4_PORT, 0xA0); | |
588 | mad_write(MC5_PORT, 0x05); | |
589 | mad_write(MC6_PORT, 0x03); | |
590 | } | |
591 | if (!ad1848_detect(ports, &ad_flags, mad16_osp)) | |
592 | goto fail; | |
593 | ||
594 | if (ad_flags & (AD_F_CS4231 | AD_F_CS4248)) | |
595 | cs4231_mode = 0x02; /* CS4248/CS4231 sync delay switch */ | |
596 | ||
597 | if (board_type == C929) | |
598 | { | |
599 | mad_write(MC4_PORT, 0xa2); | |
600 | mad_write(MC5_PORT, 0xA5 | cs4231_mode); | |
601 | mad_write(MC6_PORT, 0x03); /* Disable MPU401 */ | |
602 | } | |
603 | else | |
604 | { | |
605 | mad_write(MC4_PORT, 0x02); | |
606 | mad_write(MC5_PORT, 0x30 | cs4231_mode); | |
607 | } | |
608 | ||
609 | for (i = 0xf8d; i <= 0xf93; i++) { | |
610 | if (!c924pnp) | |
611 | DDB(printk("port %03x after init = %02x\n", i, mad_read(i))); | |
612 | else | |
613 | DDB(printk("port %03x after init = %02x\n", i-0x80, mad_read(i))); | |
614 | } | |
615 | ||
616 | got_it: | |
617 | ad_flags = 0; | |
618 | if (!ad1848_detect(ports, &ad_flags, mad16_osp)) | |
619 | goto fail; | |
620 | ||
621 | if (!wss_init(hw_config)) | |
622 | goto fail; | |
623 | ||
624 | /* | |
625 | * Set the IRQ and DMA addresses. | |
626 | */ | |
627 | ||
628 | outb((bits | 0x40), config_port); | |
629 | if ((inb(version_port) & 0x40) == 0) | |
630 | printk(KERN_ERR "[IRQ Conflict?]\n"); | |
631 | ||
632 | /* | |
633 | * Handle the capture DMA channel | |
634 | */ | |
635 | ||
636 | if (ad_flags & AD_F_CS4231 && dma2 != -1 && dma2 != dma) | |
637 | { | |
638 | if (!((dma == 0 && dma2 == 1) || | |
639 | (dma == 1 && dma2 == 0) || | |
640 | (dma == 3 && dma2 == 0))) | |
641 | { /* Unsupported combination. Try to swap channels */ | |
642 | int tmp = dma; | |
643 | ||
644 | dma = dma2; | |
645 | dma2 = tmp; | |
646 | } | |
647 | if ((dma == 0 && dma2 == 1) || (dma == 1 && dma2 == 0) || | |
648 | (dma == 3 && dma2 == 0)) | |
649 | { | |
650 | dma2_bit = 0x04; /* Enable capture DMA */ | |
651 | } | |
652 | else | |
653 | { | |
654 | printk("MAD16: Invalid capture DMA\n"); | |
655 | dma2 = dma; | |
656 | } | |
657 | } | |
658 | else dma2 = dma; | |
659 | ||
660 | outb((bits | dma_bits[dma] | dma2_bit), config_port); /* Write IRQ+DMA setup */ | |
661 | ||
662 | hw_config->slots[0] = ad1848_init("mad16 WSS", ports, | |
663 | hw_config->irq, | |
664 | dma, | |
665 | dma2, 0, | |
666 | hw_config->osp, | |
667 | THIS_MODULE); | |
668 | return 1; | |
669 | ||
670 | fail: | |
671 | release_region(hw_config->io_base + 4, 4); | |
672 | release_region(hw_config->io_base, 4); | |
673 | return 0; | |
674 | } | |
675 | ||
676 | static int __init probe_mad16_mpu(struct address_info *hw_config) | |
677 | { | |
678 | unsigned char tmp; | |
679 | ||
680 | if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */ | |
681 | { | |
682 | ||
683 | #ifdef CONFIG_MAD16_OLDCARD | |
684 | ||
685 | tmp = mad_read(MC3_PORT); | |
686 | ||
687 | /* | |
688 | * MAD16 SB base is defined by the WSS base. It cannot be changed | |
689 | * alone. | |
690 | * Ignore configured I/O base. Use the active setting. | |
691 | */ | |
692 | ||
693 | if (mad_read(MC1_PORT) & 0x20) | |
694 | hw_config->io_base = 0x240; | |
695 | else | |
696 | hw_config->io_base = 0x220; | |
697 | ||
698 | switch (hw_config->irq) | |
699 | { | |
700 | case 5: | |
701 | tmp = (tmp & 0x3f) | 0x80; | |
702 | break; | |
703 | case 7: | |
704 | tmp = (tmp & 0x3f); | |
705 | break; | |
706 | case 11: | |
707 | tmp = (tmp & 0x3f) | 0x40; | |
708 | break; | |
709 | default: | |
710 | printk(KERN_ERR "mad16/Mozart: Invalid MIDI IRQ\n"); | |
711 | return 0; | |
712 | } | |
713 | ||
714 | mad_write(MC3_PORT, tmp | 0x04); | |
715 | hw_config->driver_use_1 = SB_MIDI_ONLY; | |
716 | if (!request_region(hw_config->io_base, 16, "soundblaster")) | |
717 | return 0; | |
718 | if (!sb_dsp_detect(hw_config, 0, 0, NULL)) { | |
719 | release_region(hw_config->io_base, 16); | |
720 | return 0; | |
721 | } | |
722 | ||
723 | if (mad_read(MC1_PORT) & 0x20) | |
724 | hw_config->io_base = 0x240; | |
725 | else | |
726 | hw_config->io_base = 0x220; | |
727 | ||
728 | hw_config->name = "Mad16/Mozart"; | |
729 | sb_dsp_init(hw_config, THIS_MODULE); | |
730 | return 1; | |
731 | #else | |
732 | /* assuming all later Mozart cards are identified as | |
733 | * either 82C928 or Mozart. If so, following code attempts | |
734 | * to set MPU register. TODO - add probing | |
735 | */ | |
736 | ||
737 | tmp = mad_read(MC8_PORT); | |
738 | ||
739 | switch (hw_config->irq) | |
740 | { | |
741 | case 5: | |
742 | tmp |= 0x08; | |
743 | break; | |
744 | case 7: | |
745 | tmp |= 0x10; | |
746 | break; | |
747 | case 9: | |
748 | tmp |= 0x18; | |
749 | break; | |
750 | case 10: | |
751 | tmp |= 0x20; | |
752 | break; | |
753 | case 11: | |
754 | tmp |= 0x28; | |
755 | break; | |
756 | default: | |
757 | printk(KERN_ERR "mad16/MOZART: invalid mpu_irq\n"); | |
758 | return 0; | |
759 | } | |
760 | ||
761 | switch (hw_config->io_base) | |
762 | { | |
763 | case 0x300: | |
764 | tmp |= 0x01; | |
765 | break; | |
766 | case 0x310: | |
767 | tmp |= 0x03; | |
768 | break; | |
769 | case 0x320: | |
770 | tmp |= 0x05; | |
771 | break; | |
772 | case 0x330: | |
773 | tmp |= 0x07; | |
774 | break; | |
775 | default: | |
776 | printk(KERN_ERR "mad16/MOZART: invalid mpu_io\n"); | |
777 | return 0; | |
778 | } | |
779 | ||
780 | mad_write(MC8_PORT, tmp); /* write MPU port parameters */ | |
781 | goto probe_401; | |
782 | #endif | |
783 | } | |
784 | tmp = mad_read(MC6_PORT) & 0x83; | |
785 | tmp |= 0x80; /* MPU-401 enable */ | |
786 | ||
787 | /* Set the MPU base bits */ | |
788 | ||
789 | switch (hw_config->io_base) | |
790 | { | |
791 | case 0x300: | |
792 | tmp |= 0x60; | |
793 | break; | |
794 | case 0x310: | |
795 | tmp |= 0x40; | |
796 | break; | |
797 | case 0x320: | |
798 | tmp |= 0x20; | |
799 | break; | |
800 | case 0x330: | |
801 | tmp |= 0x00; | |
802 | break; | |
803 | default: | |
804 | printk(KERN_ERR "MAD16: Invalid MIDI port 0x%x\n", hw_config->io_base); | |
805 | return 0; | |
806 | } | |
807 | ||
808 | /* Set the MPU IRQ bits */ | |
809 | ||
810 | switch (hw_config->irq) | |
811 | { | |
812 | case 5: | |
813 | tmp |= 0x10; | |
814 | break; | |
815 | case 7: | |
816 | tmp |= 0x18; | |
817 | break; | |
818 | case 9: | |
819 | tmp |= 0x00; | |
820 | break; | |
821 | case 10: | |
822 | tmp |= 0x08; | |
823 | break; | |
824 | default: | |
825 | printk(KERN_ERR "MAD16: Invalid MIDI IRQ %d\n", hw_config->irq); | |
826 | break; | |
827 | } | |
828 | ||
829 | mad_write(MC6_PORT, tmp); /* Write MPU401 config */ | |
830 | ||
831 | #ifndef CONFIG_MAD16_OLDCARD | |
832 | probe_401: | |
833 | #endif | |
834 | hw_config->driver_use_1 = SB_MIDI_ONLY; | |
835 | hw_config->name = "Mad16/Mozart"; | |
836 | return probe_uart401(hw_config, THIS_MODULE); | |
837 | } | |
838 | ||
839 | static void __exit unload_mad16(struct address_info *hw_config) | |
840 | { | |
841 | ad1848_unload(hw_config->io_base + 4, | |
842 | hw_config->irq, | |
843 | hw_config->dma, | |
844 | hw_config->dma2, 0); | |
845 | release_region(hw_config->io_base, 4); | |
846 | sound_unload_audiodev(hw_config->slots[0]); | |
847 | } | |
848 | ||
849 | static void __exit unload_mad16_mpu(struct address_info *hw_config) | |
850 | { | |
851 | #ifdef CONFIG_MAD16_OLDCARD | |
852 | if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */ | |
853 | { | |
854 | sb_dsp_unload(hw_config, 0); | |
855 | return; | |
856 | } | |
857 | #endif | |
858 | ||
859 | unload_uart401(hw_config); | |
860 | } | |
861 | ||
862 | static struct address_info cfg; | |
863 | static struct address_info cfg_mpu; | |
864 | ||
865 | static int found_mpu; | |
866 | ||
867 | static int __initdata mpu_io = 0; | |
868 | static int __initdata mpu_irq = 0; | |
869 | static int __initdata io = -1; | |
870 | static int __initdata dma = -1; | |
871 | static int __initdata dma16 = -1; /* Set this for modules that need it */ | |
872 | static int __initdata irq = -1; | |
873 | static int __initdata cdtype = 0; | |
874 | static int __initdata cdirq = 0; | |
875 | static int __initdata cdport = 0x340; | |
876 | static int __initdata cddma = -1; | |
877 | static int __initdata opl4 = 0; | |
878 | static int __initdata joystick = 0; | |
879 | ||
880 | module_param(mpu_io, int, 0); | |
881 | module_param(mpu_irq, int, 0); | |
882 | module_param(io, int, 0); | |
883 | module_param(dma, int, 0); | |
884 | module_param(dma16, int, 0); | |
885 | module_param(irq, int, 0); | |
886 | module_param(cdtype, int, 0); | |
887 | module_param(cdirq, int, 0); | |
888 | module_param(cdport, int, 0); | |
889 | module_param(cddma, int, 0); | |
890 | module_param(opl4, int, 0); | |
891 | module_param(joystick, bool, 0); | |
892 | module_param(debug, bool, 0644); | |
893 | ||
894 | static int __initdata dma_map[2][8] = | |
895 | { | |
896 | {0x03, -1, -1, -1, -1, 0x00, 0x01, 0x02}, | |
897 | {0x03, -1, 0x01, 0x00, -1, -1, -1, -1} | |
898 | }; | |
899 | ||
900 | static int __initdata irq_map[16] = | |
901 | { | |
902 | 0x00, -1, -1, 0x0A, | |
903 | -1, 0x04, -1, 0x08, | |
904 | -1, 0x10, 0x14, 0x18, | |
905 | -1, -1, -1, -1 | |
906 | }; | |
907 | ||
e608460d DT |
908 | #ifdef SUPPORT_JOYSTICK |
909 | ||
910 | static struct gameport *gameport; | |
911 | ||
1da177e4 LT |
912 | static int __devinit mad16_register_gameport(int io_port) |
913 | { | |
914 | if (!request_region(io_port, 1, "mad16 gameport")) { | |
915 | printk(KERN_ERR "mad16: gameport address 0x%#x already in use\n", io_port); | |
916 | return -EBUSY; | |
917 | } | |
918 | ||
919 | gameport = gameport_allocate_port(); | |
920 | if (!gameport) { | |
921 | printk(KERN_ERR "mad16: can not allocate memory for gameport\n"); | |
922 | release_region(io_port, 1); | |
923 | return -ENOMEM; | |
924 | } | |
925 | ||
926 | gameport_set_name(gameport, "MAD16 Gameport"); | |
927 | gameport_set_phys(gameport, "isa%04x/gameport0", io_port); | |
928 | gameport->io = io_port; | |
929 | ||
930 | gameport_register_port(gameport); | |
931 | ||
932 | return 0; | |
933 | } | |
934 | ||
e608460d DT |
935 | static inline void mad16_unregister_gameport(void) |
936 | { | |
937 | if (gameport) { | |
938 | /* the gameport was initialized so we must free it up */ | |
939 | gameport_unregister_port(gameport); | |
940 | gameport = NULL; | |
941 | release_region(0x201, 1); | |
942 | } | |
943 | } | |
944 | #else | |
945 | static inline int mad16_register_gameport(int io_port) { return -ENOSYS; } | |
946 | static inline void mad16_unregister_gameport(void) { } | |
947 | #endif | |
948 | ||
1da177e4 LT |
949 | static int __devinit init_mad16(void) |
950 | { | |
951 | int dmatype = 0; | |
952 | ||
953 | printk(KERN_INFO "MAD16 audio driver Copyright (C) by Hannu Savolainen 1993-1996\n"); | |
954 | ||
955 | printk(KERN_INFO "CDROM "); | |
956 | switch (cdtype) | |
957 | { | |
958 | case 0x00: | |
959 | printk("Disabled"); | |
960 | cdirq = 0; | |
961 | break; | |
962 | case 0x02: | |
963 | printk("Sony CDU31A"); | |
964 | dmatype = 1; | |
965 | if(cddma == -1) cddma = 3; | |
966 | break; | |
967 | case 0x04: | |
968 | printk("Mitsumi"); | |
969 | dmatype = 0; | |
970 | if(cddma == -1) cddma = 5; | |
971 | break; | |
972 | case 0x06: | |
973 | printk("Panasonic Lasermate"); | |
974 | dmatype = 1; | |
975 | if(cddma == -1) cddma = 3; | |
976 | break; | |
977 | case 0x08: | |
978 | printk("Secondary IDE"); | |
979 | dmatype = 0; | |
980 | if(cddma == -1) cddma = 5; | |
981 | break; | |
982 | case 0x0A: | |
983 | printk("Primary IDE"); | |
984 | dmatype = 0; | |
985 | if(cddma == -1) cddma = 5; | |
986 | break; | |
987 | default: | |
988 | printk("\n"); | |
989 | printk(KERN_ERR "Invalid CDROM type\n"); | |
990 | return -EINVAL; | |
991 | } | |
992 | ||
993 | /* | |
994 | * Build the config words | |
995 | */ | |
996 | ||
997 | mad16_conf = (joystick ^ 1) | cdtype; | |
998 | mad16_cdsel = 0; | |
999 | if (opl4) | |
1000 | mad16_cdsel |= 0x20; | |
1001 | ||
1002 | if(cdtype){ | |
1003 | if (cddma > 7 || cddma < 0 || dma_map[dmatype][cddma] == -1) | |
1004 | { | |
1005 | printk("\n"); | |
1006 | printk(KERN_ERR "Invalid CDROM DMA\n"); | |
1007 | return -EINVAL; | |
1008 | } | |
1009 | if (cddma) | |
1010 | printk(", DMA %d", cddma); | |
1011 | else | |
1012 | printk(", no DMA"); | |
1013 | ||
1014 | if (!cdirq) | |
1015 | printk(", no IRQ"); | |
1016 | else if (cdirq < 0 || cdirq > 15 || irq_map[cdirq] == -1) | |
1017 | { | |
1018 | printk(", invalid IRQ (disabling)"); | |
1019 | cdirq = 0; | |
1020 | } | |
1021 | else printk(", IRQ %d", cdirq); | |
1022 | ||
1023 | mad16_cdsel |= dma_map[dmatype][cddma]; | |
1024 | ||
1025 | if (cdtype < 0x08) | |
1026 | { | |
1027 | switch (cdport) | |
1028 | { | |
1029 | case 0x340: | |
1030 | mad16_cdsel |= 0x00; | |
1031 | break; | |
1032 | case 0x330: | |
1033 | mad16_cdsel |= 0x40; | |
1034 | break; | |
1035 | case 0x360: | |
1036 | mad16_cdsel |= 0x80; | |
1037 | break; | |
1038 | case 0x320: | |
1039 | mad16_cdsel |= 0xC0; | |
1040 | break; | |
1041 | default: | |
1042 | printk(KERN_ERR "Unknown CDROM I/O base %d\n", cdport); | |
1043 | return -EINVAL; | |
1044 | } | |
1045 | } | |
1046 | mad16_cdsel |= irq_map[cdirq]; | |
1047 | } | |
1048 | ||
1049 | printk(".\n"); | |
1050 | ||
1051 | cfg.io_base = io; | |
1052 | cfg.irq = irq; | |
1053 | cfg.dma = dma; | |
1054 | cfg.dma2 = dma16; | |
1055 | ||
1056 | if (cfg.io_base == -1 || cfg.dma == -1 || cfg.irq == -1) { | |
1057 | printk(KERN_ERR "I/O, DMA and irq are mandatory\n"); | |
1058 | return -EINVAL; | |
1059 | } | |
1060 | ||
1061 | if (!request_region(MC0_PORT, 12, "mad16")) | |
1062 | return -EBUSY; | |
1063 | ||
1064 | if (!probe_mad16(&cfg)) { | |
1065 | release_region(MC0_PORT, 12); | |
1066 | return -ENODEV; | |
1067 | } | |
1068 | ||
1069 | cfg_mpu.io_base = mpu_io; | |
1070 | cfg_mpu.irq = mpu_irq; | |
1071 | ||
1072 | found_mpu = probe_mad16_mpu(&cfg_mpu); | |
1073 | ||
1074 | if (joystick) | |
1075 | mad16_register_gameport(0x201); | |
1076 | ||
1077 | return 0; | |
1078 | } | |
1079 | ||
1080 | static void __exit cleanup_mad16(void) | |
1081 | { | |
1082 | if (found_mpu) | |
1083 | unload_mad16_mpu(&cfg_mpu); | |
e608460d | 1084 | mad16_unregister_gameport(); |
1da177e4 LT |
1085 | unload_mad16(&cfg); |
1086 | release_region(MC0_PORT, 12); | |
1087 | } | |
1088 | ||
1089 | module_init(init_mad16); | |
1090 | module_exit(cleanup_mad16); | |
1091 | ||
1092 | #ifndef MODULE | |
1093 | static int __init setup_mad16(char *str) | |
1094 | { | |
1095 | /* io, irq */ | |
1096 | int ints[8]; | |
1097 | ||
1098 | str = get_options(str, ARRAY_SIZE(ints), ints); | |
1099 | ||
1100 | io = ints[1]; | |
1101 | irq = ints[2]; | |
1102 | dma = ints[3]; | |
1103 | dma16 = ints[4]; | |
1104 | mpu_io = ints[5]; | |
1105 | mpu_irq = ints[6]; | |
1106 | joystick = ints[7]; | |
1107 | ||
1108 | return 1; | |
1109 | } | |
1110 | ||
1111 | __setup("mad16=", setup_mad16); | |
1112 | #endif | |
1113 | MODULE_LICENSE("GPL"); |