patch-2.0.1 linux/drivers/sound/mad16.c
Next file: linux/drivers/sound/mad16_sb_midi.c
Previous file: linux/drivers/sound/lowlevel/init.c
Back to the patch index
Back to the overall index
- Lines: 397
- Date:
Sun Jun 30 11:44:02 1996
- Orig file:
v2.0.0/linux/drivers/sound/mad16.c
- Orig date:
Fri Apr 12 15:52:03 1996
diff -u --recursive --new-file v2.0.0/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c
@@ -1,25 +1,9 @@
/*
- * Copyright by Hannu Savolainen 1993-1996
+ * Copyright (C) by Hannu Savolainen 1993-1996
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer. 2.
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this software
+ * for more info.
*/
#include <linux/config.h>
@@ -31,9 +15,9 @@
* OPTi 82C928 MAD16 (replaced by C929)
* OAK OTI-601D Mozart
* OPTi 82C929 MAD16 Pro
- * OPTi 82C930 (Not supported yet)
+ * OPTi 82C930
*
- * These audio interface chips don't produce sound themselves. They just
+ * These audio interface chips don't prduce sound themselves. They just
* connect some other components (OPL-[234] and a WSS compatible codec)
* to the PC bus and perform I/O, DMA and IRQ address decoding. There is
* also a UART for the MPU-401 mode (not 82C928/Mozart).
@@ -77,6 +61,8 @@
#if defined(CONFIG_MAD16)
+#include "sb.h"
+
static int already_initialized = 0;
#define C928 1
@@ -91,6 +77,9 @@
* All ports are inactive by default. They can be activated by
* writing 0xE2 or 0xE3 to the password register. The password is valid
* only until the next I/O read or write.
+ *
+ * 82C930 uses 0xE4 as the password and indirect addressing to access
+ * the config registers.
*/
#define MC0_PORT 0xf8c /* Dummy port */
@@ -136,9 +125,18 @@
outb (0xE3, PASSWD_REG);
break;
+ case C930:
+ /* outb( 0xE4, PASSWD_REG); */
+ break;
}
- tmp = inb (port);
+ if (board_type == C930)
+ {
+ outb (port - MC0_PORT, 0xe0e); /* Write to index reg */
+ tmp = inb (0xe0f); /* Read from data reg */
+ }
+ else
+ tmp = inb (port);
restore_flags (flags);
return tmp;
@@ -163,13 +161,60 @@
outb (0xE3, PASSWD_REG);
break;
+ case C930:
+ /* outb( 0xE4, PASSWD_REG); */
+ break;
}
- outb ((unsigned char) (value & 0xff), port);
+ if (board_type == C930)
+ {
+ outb (port - MC0_PORT, 0xe0e); /* Write to index reg */
+ outb ((unsigned char) (value & 0xff), 0xe0f);
+ }
+ else
+ outb ((unsigned char) (value & 0xff), port);
restore_flags (flags);
}
static int
+detect_c930 (void)
+{
+ unsigned char tmp = mad_read (MC1_PORT);
+
+ if ((tmp & 0x06) != 0x06)
+ {
+ DDB (printk ("Wrong C930 signature (%x)\n", tmp));
+ /* return 0; */
+ }
+
+ mad_write (MC1_PORT, 0);
+
+ if (mad_read (MC1_PORT) != 0x06)
+ {
+ DDB (printk ("Wrong C930 signature2 (%x)\n", tmp));
+ /* return 0; */
+ }
+
+ mad_write (MC1_PORT, tmp); /* Restore bits */
+
+ mad_write (MC7_PORT, 0);
+ if ((tmp = mad_read (MC7_PORT)) != 0)
+ {
+ DDB (printk ("MC7 not writeable (%x)\n", tmp));
+ return 0;
+ }
+
+ mad_write (MC7_PORT, 0xcb);
+ if ((tmp = mad_read (MC7_PORT)) != 0xcb)
+ {
+ DDB (printk ("MC7 not writeable2 (%x)\n", tmp));
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
detect_mad16 (void)
{
unsigned char tmp, tmp2;
@@ -190,6 +235,8 @@
for (i = 0xf8d; i <= 0xf98; i++)
DDB (printk ("Port %0x (init value) = %0x\n", i, mad_read (i)));
+ if (board_type == C930)
+ return detect_c930 ();
/*
* Now check that the gate is closed on first I/O after writing
* the password. (This is how a MAD16 compatible card works).
@@ -201,7 +248,7 @@
return 0;
}
- mad_write (MC1_PORT, tmp ^ 0x80); /* Toggle a bit */
+ mad_write (MC1_PORT, tmp ^ 0x80); /* Togge a bit */
if ((tmp2 = mad_read (MC1_PORT)) != (tmp ^ 0x80)) /* Compare the bit */
{
mad_write (MC1_PORT, tmp); /* Restore */
@@ -233,7 +280,7 @@
return 0;
/*
* Check if the IO port returns valid signature. The original MS Sound
- * system returns 0x04 while some cards (AudioTriX Pro for example)
+ * system returns 0x04 while some cards (AudioTrix Pro for example)
* return 0x00.
*/
@@ -275,6 +322,57 @@
return 1;
}
+static int
+init_c930 (struct address_info *hw_config)
+{
+ unsigned char cfg;
+
+ cfg = (mad_read (MC1_PORT) & ~0x30);
+ /* mad_write(MC1_PORT, 0); */
+
+ switch (hw_config->io_base)
+ {
+ case 0x530:
+ cfg |= 0x00;
+ break;
+ case 0xe80:
+ cfg |= 0x10;
+ break;
+ case 0xf40:
+ cfg |= 0x20;
+ break;
+ case 0x604:
+ cfg |= 0x30;
+ break;
+
+ default:
+ printk ("MAD16: Invalid codec port %x\n", hw_config->io_base);
+ return 0;
+ }
+ mad_write (MC1_PORT, cfg);
+
+ /* MC2 is CD configuration. Don't touch it. */
+
+ mad_write (MC3_PORT, 0); /* Disable SB mode IRQ and DMA */
+
+ mad_write (MC4_PORT, 0x52); /* ??? */
+ mad_write (MC5_PORT, 0x3D); /* Init it into mode2 */
+ mad_write (MC6_PORT, 0x02); /* Enable WSS, Disable MPU and SB */
+ mad_write (MC7_PORT, 0xCB);
+ mad_write (MC10_PORT, 0x11);
+
+ if (!wss_init (hw_config))
+ return 0;
+
+/*
+ * A temporarary kludge which drops the device back to mode1.
+ * This removes problems with interrupts but disables full duplex.
+ * A better solution should be introduced later.
+ */
+ mad_write (MC5_PORT, 0x1D); /* Disable mode2 */
+ return wss_init (hw_config);
+}
+
int
probe_mad16 (struct address_info *hw_config)
{
@@ -313,7 +411,28 @@
if (!detect_mad16 ())
{
- return 0;
+ if (inb (PASSWD_REG) != 0xff)
+ return 0;
+
+/*
+ * First relocate MC# registers to 0xe0e/0xe0f, disable password
+ */
+
+ outb (0xE4, PASSWD_REG);
+ outb (0x80, PASSWD_REG);
+
+ board_type = C930;
+
+ DDB (printk ("Detect using password = 0xE4\n"));
+
+ for (i = 0xf8d; i <= 0xf93; i++)
+ DDB (printk ("port %03x = %02x\n", i, mad_read (i)));
+
+ if (!detect_mad16 ())
+ return 0;
+
+ DDB (printk ("mad16.c: 82C930 detected\n"));
+ return init_c930 (hw_config);
}
else
{
@@ -408,8 +527,8 @@
return 1;
}
-long
-attach_mad16 (long mem_start, struct address_info *hw_config)
+void
+attach_mad16 (struct address_info *hw_config)
{
static char interrupt_bits[12] =
@@ -430,7 +549,7 @@
already_initialized = 1;
if (!ad1848_detect (hw_config->io_base + 4, &ad_flags, mad16_osp))
- return mem_start;
+ return;
/*
* Set the IRQ and DMA addresses.
@@ -438,7 +557,7 @@
bits = interrupt_bits[hw_config->irq];
if (bits == -1)
- return mem_start;
+ return;
outb (bits | 0x40, config_port);
if ((inb (version_port) & 0x40) == 0)
@@ -450,12 +569,21 @@
if (ad_flags & AD_F_CS4231 && dma2 != -1 && dma2 != dma)
{
+ if (!((dma == 0 && dma2 == 1) ||
+ (dma == 1 && dma2 == 0) ||
+ (dma == 3 && dma2 == 0)))
+ { /* Unsupported combination. Try to swap channels */
+ int tmp = dma;
+
+ dma = dma2;
+ dma2 = tmp;
+ }
+
if ((dma == 0 && dma2 == 1) ||
(dma == 1 && dma2 == 0) ||
(dma == 3 && dma2 == 0))
{
dma2_bit = 0x04; /* Enable capture DMA */
-
}
else
{
@@ -474,12 +602,10 @@
dma2, 0,
hw_config->osp);
request_region (hw_config->io_base, 4, "MAD16 WSS config");
-
- return mem_start;
}
-long
-attach_mad16_mpu (long mem_start, struct address_info *hw_config)
+void
+attach_mad16_mpu (struct address_info *hw_config)
{
if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */
{
@@ -490,19 +616,20 @@
else
hw_config->io_base = 0x220;
- return mad16_sb_dsp_init (mem_start, hw_config);
-#else
- return 0;
+ hw_config->name = "Mad16/Mozart";
+ sb_dsp_init (hw_config);
#endif
+
+ return;
}
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
if (!already_initialized)
- return mem_start;
+ return;
- return attach_mpu401 (mem_start, hw_config);
-#else
- return mem_start;
+ hw_config->driver_use_1 = SB_MIDI_ONLY;
+ hw_config->name = "Mad16/Mozart";
+ attach_uart401 (hw_config);
#endif
}
@@ -562,13 +689,15 @@
}
mad_write (MC3_PORT, tmp | 0x04);
- return mad16_sb_dsp_detect (hw_config);
+ hw_config->driver_use_1 = SB_MIDI_ONLY;
+ return sb_dsp_detect (hw_config);
#else
return 0;
#endif
}
- tmp = 0x83; /* MPU-401 enable */
+ tmp = mad_read (MC6_PORT) & 0x83;
+ tmp |= 0x80; /* MPU-401 enable */
/*
* Set the MPU base bits
@@ -609,7 +738,7 @@
}
mad_write (MC6_PORT, tmp); /* Write MPU401 config */
- return probe_mpu401 (hw_config);
+ return probe_uart401 (hw_config);
#else
return 0;
#endif
@@ -632,13 +761,13 @@
#ifdef CONFIG_MIDI
if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */
{
- mad16_sb_dsp_unload (hw_config);
+ sb_dsp_unload (hw_config);
return;
}
#endif
-#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
- unload_mpu401 (hw_config);
+#if (defined(CONFIG_UART401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+ unload_uart401 (hw_config);
#endif
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov