1 #define MAD16_OPL4 /* Disable this if you have problems with OPL3 */
2 /*
3 * sound/mad16.c
4 *
5 * Initialization code for OPTi MAD16 compatible audio chips. Including
6 *
7 * OPTi 82C928 MAD16 (replaced by C929)
8 * OAK OTI-601D Mozart
9 * OPTi 82C929 MAD16 Pro
10 *
11 * These audio interface chips don't prduce sound themselves. They just
12 * connect some other components (OPL-[234] and a WSS compatible codec)
13 * to the PC bus and perform I/O, DMA and IRQ address decoding. There is
14 * also a UART for the MPU-401 mode (not 82C928/Mozart).
15 * The Mozart chip appears to be compatible with the 82C928 (can anybody
16 * confirm this?).
17 *
18 * NOTE! If you want to set CD-ROM address and/or joystick enable, define
19 * MAD16_CONF in local.h as combination of the following bits:
20 *
21 * 0x01 - joystick disabled
22 *
23 * CD-ROM type selection (select just one):
24 * 0x00 - none
25 * 0x02 - Sony 31A
26 * 0x04 - Mitsumi
27 * 0x06 - Panasonic (type "LaserMate", not "SoundBlaster")
28 * 0x08 - Secondary IDE (address 0x170)
29 * 0x0a - Primary IDE (address 0x1F0)
30 *
31 * For example Mitsumi with joystick disabled = 0x04|0x01 = 0x05
32 * For example LaserMate (for use with sbpcd) plus joystick = 0x06
33 *
34 * MAD16_CDSEL:
35 * This defaults to CD I/O 0x340, no IRQ and DMA3
36 * (DMA5 with Mitsumi or IDE). If you like to change these, define
37 * MAD16_CDSEL with the following bits:
38 *
39 * CD-ROM port: 0x00=340, 0x40=330, 0x80=360 or 0xc0=320
40 * OPL4 select: 0x20=OPL4, 0x00=OPL3
41 * CD-ROM irq: 0x00=disabled, 0x04=IRQ5, 0x08=IRQ7, 0x0a=IRQ3, 0x10=IRQ9,
42 * 0x14=IRQ10 and 0x18=IRQ11.
43 *
44 * CD-ROM DMA (Sony or Panasonic): 0x00=DMA3, 0x01=DMA2, 0x02=DMA1 or 0x03=disabled
45 * or
46 * CD-ROM DMA (Mitsumi or IDE): 0x00=DMA5, 0x01=DMA6, 0x02=DMA7 or 0x03=disabled
47 *
48 * For use with sbpcd, address 0x340, set MAD16_CDSEL to 0x03 or 0x23.
49 *
50 * Copyright by Hannu Savolainen 1995
51 *
52 * Redistribution and use in source and binary forms, with or without
53 * modification, are permitted provided that the following conditions are
54 * met: 1. Redistributions of source code must retain the above copyright
55 * notice, this list of conditions and the following disclaimer. 2.
56 * Redistributions in binary form must reproduce the above copyright notice,
57 * this list of conditions and the following disclaimer in the documentation
58 * and/or other materials provided with the distribution.
59 *
60 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
61 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
62 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
63 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
64 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
66 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
67 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70 * SUCH DAMAGE.
71 *
72 */
73
74 #include "sound_config.h"
75
76 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MAD16)
77
78 static int already_initialized = 0;
79
80 #define C928 1
81 #define MOZART 2
82 #define C929 3
83
84 /*
85 * Registers
86 *
87 * The MAD16 occupies I/O ports 0xf8d to 0xf93 (fixed locations).
88 * All ports are inactive by default. They can be activated by
89 * writing 0xE2 or 0xE3 to the password register. The password is valid
90 * only until the next I/O read or write.
91 */
92
93 #define MC1_PORT 0xf8d /* SB address, CDROM interface type, joystick */
94 #define MC2_PORT 0xf8e /* CDROM address, IRQ, DMA, plus OPL4 bit */
95 #define MC3_PORT 0xf8f
96 #define PASSWD_REG 0xf8f
97 #define MC4_PORT 0xf90
98 #define MC5_PORT 0xf91
99 #define MC6_PORT 0xf92
100 #define MC7_PORT 0xf93
101
102 static int board_type = C928;
103
104 #ifndef DDB
105 #define DDB(x)
106 #endif
107
108 static unsigned char
109 mad_read (int port)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
110 {
111 unsigned long flags;
112 unsigned char tmp;
113
114 DISABLE_INTR (flags);
115
116 switch (board_type) /* Output password */
117 {
118 case C928:
119 case MOZART:
120 OUTB (0xE2, PASSWD_REG);
121 break;
122
123 case C929:
124 OUTB (0xE3, PASSWD_REG);
125 break;
126 }
127
128 tmp = INB (port);
129 RESTORE_INTR (flags);
130
131 return tmp;
132 }
133
134 static void
135 mad_write (int port, int value)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
136 {
137 unsigned long flags;
138
139 DISABLE_INTR (flags);
140
141 switch (board_type) /* Output password */
142 {
143 case C928:
144 case MOZART:
145 OUTB (0xE2, PASSWD_REG);
146 break;
147
148 case C929:
149 OUTB (0xE3, PASSWD_REG);
150 break;
151 }
152
153 OUTB ((unsigned char) (value & 0xff), port);
154 RESTORE_INTR (flags);
155 }
156
157 static int
158 detect_mad16 (void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
159 {
160 unsigned char tmp, tmp2;
161
162 /*
163 * Check that reading a register doesn't return bus float (0xff)
164 * when the card is accessed using password. This may fail in case
165 * the card is in low power mode. Normally at least the power saving mode
166 * bit should be 0.
167 */
168 if ((tmp = mad_read (MC1_PORT)) == 0xff)
169 {
170 DDB (printk ("MC1_PORT returned 0xff\n"));
171 return 0;
172 }
173 /*
174 * Now check that the gate is closed on first I/O after writing
175 * the password. (This is how a MAD16 compatible card works).
176 */
177
178 if ((tmp2 = INB (MC1_PORT)) == tmp) /* It didn't close */
179 {
180 DDB (printk ("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
181 return 0;
182 }
183
184 mad_write (MC1_PORT, tmp ^ 0x80); /* Togge a bit */
185
186 if ((tmp2 = mad_read (MC1_PORT)) != (tmp ^ 0x80)) /* Compare the bit */
187 {
188 mad_write (MC1_PORT, tmp); /* Restore */
189 DDB (printk ("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
190 return 0;
191 }
192
193 mad_write (MC1_PORT, tmp); /* Restore */
194 return 1; /* Bingo */
195
196 }
197
198 int
199 probe_mad16 (struct address_info *hw_config)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
200 {
201 int i;
202 static int valid_ports[] =
203 {0x530, 0xe80, 0xf40, 0x604};
204 unsigned char tmp;
205
206 if (already_initialized)
207 return 0;
208
209 /*
210 * Check that all ports return 0xff (bus float) when no password
211 * is written to the password register.
212 */
213
214 DDB (printk ("--- Detecting MAD16 / Mozart ---\n"));
215
216 #if 0
217 for (i = 0xf8d; i <= 0xf93; i++)
218 if (INB (i) != 0xff)
219 {
220 DDB (printk ("port 0x%03x != 0xff (0x%02x)\n", i, INB (i)));
221 return 0;
222 }
223 #endif
224
225 /*
226 * Then try to detect with the old password
227 */
228 board_type = C928;
229
230 DDB (printk ("Detect using password = 0xE2\n"));
231
232 if (!detect_mad16 ()) /* No luck. Try different model */
233 {
234 board_type = C929;
235
236 DDB (printk ("Detect using password = 0xE3\n"));
237
238 if (!detect_mad16 ())
239 return 0;
240
241 printk ("mad16.c: 82C929 detected???\n");
242 }
243 else
244 {
245 unsigned char model;
246
247 if (((model = mad_read (MC3_PORT)) & 0x03) == 0x03)
248 {
249 printk ("mad16.c: Mozart detected???\n");
250 board_type = MOZART;
251 }
252 else
253 {
254 printk ("mad16.c: 82C928 detected???\n");
255 board_type = C928;
256 }
257 }
258
259 for (i = 0xf8d; i <= 0xf93; i++)
260 DDB (printk ("port %03x = %03x\n", i, mad_read (i)));
261
262 /*
263 * Set the WSS address
264 */
265
266 tmp = 0x80; /* Enable WSS, Disable SB */
267
268 for (i = 0; i < 5; i++)
269 {
270 if (i > 3) /* Not a valid port */
271 {
272 printk ("MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base);
273 return 0;
274 }
275
276 if (valid_ports[i] == hw_config->io_base)
277 {
278 tmp |= i << 4; /* WSS port select bits */
279 break;
280 }
281 }
282
283 /*
284 * Set optional CD-ROM and joystick settings.
285 */
286 #define MAD16_CONF 0x06
287 #define MAD16_CDSEL 0x03
288
289 #ifdef MAD16_CONF
290 tmp |= ((MAD16_CONF) & 0x0f); /* CD-ROM and joystick bits */
291 #endif
292 mad_write (MC1_PORT, tmp);
293
294 #if defined(MAD16_CONF) && defined(MAD16_CDSEL)
295 tmp = MAD16_CDSEL;
296 #else
297 tmp = 0x03;
298 #endif
299
300 #ifdef MAD16_OPL4
301 tmp |= 0x20; /* Enable OPL4 access */
302 #endif
303
304 mad_write (MC2_PORT, tmp);
305 mad_write (MC3_PORT, 0xf0); /* Disable SB */
306
307 if (board_type == C929)
308 {
309 mad_write (MC4_PORT, 0xa2);
310 mad_write (MC5_PORT, 0x95); /* AD184x mode (0x9f for CS42xx) */
311 mad_write (MC6_PORT, 0x03); /* Disable MPU401 */
312 }
313 else
314 {
315 mad_write (MC4_PORT, 0x02);
316 mad_write (MC5_PORT, 0x10); /* AD184x mode (0x12 for CS42xx) */
317 }
318
319 for (i = 0xf8d; i <= 0xf93; i++)
320 DDB (printk ("port %03x after init = %03x\n", i, mad_read (i)));
321
322 return probe_ms_sound (hw_config);
323 }
324
325 long
326 attach_mad16 (long mem_start, struct address_info *hw_config)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
327 {
328
329 already_initialized = 1;
330
331 return attach_ms_sound (mem_start, hw_config);
332 }
333
334 long
335 attach_mad16_mpu (long mem_start, struct address_info *hw_config)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
336 {
337
338 #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
339 if (!already_initialized)
340 return mem_start;
341
342 return attach_mpu401 (mem_start, hw_config);
343 #else
344 return mem_start;
345 #endif
346 }
347
348 int
349 probe_mad16_mpu (struct address_info *hw_config)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
350 {
351 #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
352 static int mpu_attached = 0;
353 static int valid_ports[] =
354 {0x330, 0x320, 0x310, 0x300};
355 static short valid_irqs[] =
356 {9, 10, 5, 7};
357 unsigned char tmp;
358
359 int i; /* A variable with secret power */
360
361 if (!already_initialized) /* The MSS port must be initialized first */
362 return 0;
363
364 if (mpu_attached) /* Don't let them call this twice */
365 return 0;
366 mpu_attached = 1;
367
368 if (board_type < C929) /* Early chip. No MPU support */
369 {
370 printk ("Mozart and OPTi 82C928 based cards don't support MPU401. Sorry\n");
371 return 0;
372 }
373
374 tmp = 0x83; /* MPU-401 enable */
375
376 /*
377 * Set the MPU base bits
378 */
379
380 for (i = 0; i < 5; i++)
381 {
382 if (i > 3) /* Out of array bounds */
383 {
384 printk ("MAD16 / Mozart: Invalid MIDI port 0x%x\n", hw_config->io_base);
385 return 0;
386 }
387
388 if (valid_ports[i] == hw_config->io_base)
389 {
390 tmp |= i << 5;
391 break;
392 }
393 }
394
395 /*
396 * Set the MPU IRQ bits
397 */
398
399 for (i = 0; i < 5; i++)
400 {
401 if (i > 3) /* Out of array bounds */
402 {
403 printk ("MAD16 / Mozart: Invalid MIDI IRQ %d\n", hw_config->irq);
404 return 0;
405 }
406
407 if (valid_irqs[i] == hw_config->irq)
408 {
409 tmp |= i << 3;
410 break;
411 }
412 }
413 mad_write (MC6_PORT, tmp); /* Write MPU401 config */
414
415 return probe_mpu401 (hw_config);
416 #else
417 return 0;
418 #endif
419 }
420
421 /* That's all folks */
422 #endif