Subject: kern/2011: No support for MAD16 audio chips.
To: None <gnats-bugs@NetBSD.ORG>
From: Lennart Augustsson <augustss@cs.chalmers.se>
List: netbsd-bugs
Date: 02/01/1996 13:31:12
>Number:         2011
>Category:       kern
>Synopsis:       No support for MAD16 audio chips.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Feb  1 07:50:01 1996
>Last-Modified:
>Originator:     Lennart Augustsson
>Organization:
CS at Chalmers University of Technology
>Release:        NetBSD 1.1 current, 1996 Jan 31
>Environment:
System: NetBSD calvin.cs.chalmers.se 1.1A NetBSD 1.1A (CALVIN) #29: Thu Feb 1 12:52:52 MET 1996 augustss@calvin.cs.chalmers.se:/usr/src/sys/arch/i386/compile/CALVIN i386


>Description:
	There is no support for the MAD16 (82C929 etc) audio chip sets.
	They can emulate both SoundBlaster and Windows Sound System.
	WSS is better.
>How-To-Repeat:
	Just try using a card with one of those chips (I've tried miro PCM10).
>Fix:
	This fix adds code to the wss driver to look for MAD16 chips.
	To make the driver probe for it you need a "flag 1" on the config
	line for wss.   I.e.
		device wss0 at isa? port 0x530 irq 10 drq 0 flag 1

	The code is based on the VoxWare driver.

*** dev/isa/madreg.h.orig	Thu Feb  1 12:51:22 1996
--- dev/isa/madreg.h	Thu Feb  1 12:51:06 1996
***************
*** 0 ****
--- 1,75 ----
+ /*
+  * Copyright (c) 1996 Lennart Augustsson
+  * Copyright (c) 1995 Hannu Savolainen
+  * Copyright (c) 1991-1993 Regents of the University of California.
+  * All rights reserved.
+  *
+  * 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.
+  * 3. All advertising materials mentioning features or use of this software
+  *    must display the following acknowledgement:
+  *	This product includes software developed by the Computer Systems
+  *	Engineering Group at Lawrence Berkeley Laboratory.
+  * 4. Neither the name of the University nor of the Laboratory may be used
+  *    to endorse or promote products derived from this software without
+  *    specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+  *
+  */
+ 
+ /*
+  * Variations of the supported chips.
+  */
+ 
+ #define MAD_NONE	0
+ #define MAD_82C928	1		/* OPTi 82C928     MAD16 */
+ #define MAD_OTI601D	2		/* OAK OTI-601D    Mozart */
+ #define MAD_82C929	3		/* OPTi 82C929     MAD16 Pro */
+ 
+ /*
+  *    Registers
+  *
+  *      The MAD16 occupies I/O ports 0xf8d to 0xf93 (fixed locations).
+  *      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.
+  */
+ 
+ #define MC1_PORT	0xf8d	/* SB address, CDROM interface type, joystick */
+ #define MC2_PORT	0xf8e	/* CDROM address, IRQ, DMA, plus OPL4 bit */
+ #define MC3_PORT	0xf8f
+ #define MC_PASSWD_REG	MC3_PORT
+ #define MC4_PORT	0xf90
+ #define MC5_PORT	0xf91
+ #define MC6_PORT	0xf92
+ #define MC7_PORT	0xf93
+ 
+ /* Possible WSS emulation ports */
+ #define M_WSS_PORT0 0x530
+ #define M_WSS_PORT1 0xe80
+ #define M_WSS_PORT2 0xf40
+ #define M_WSS_PORT3 0x604
+ #define M_WSS_NPORTS 4
+ 
+ /* Port 1 */
+ #define M_WSS_PORT_SELECT(i) (0x80 | ((i) << 4))
+ 
+ #define M_PASSWD_928	0xe2
+ #define M_PASSWD_929	0xe3
*** dev/isa/wss.c.orig	Thu Feb  1 12:39:47 1996
--- dev/isa/wss.c	Thu Feb  1 12:50:50 1996
***************
*** 5,10 ****
--- 5,15 ----
   * Copyright (c) 1991-1993 Regents of the University of California.
   * All rights reserved.
   *
+  * MAD support:
+  * Copyright (c) 1996 Lennart Augustsson
+  * Based on code which is
+  * Copyright (c) 1995 Hannu Savolainen
+  *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
***************
*** 34,39 ****
--- 39,68 ----
   * SUCH DAMAGE.
   *
   */
+ /*
+  * Copyright by Hannu Savolainen 1994
+  *
+  * 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.
+  *
+  */
  
  #include <sys/param.h>
  #include <sys/systm.h>
***************
*** 56,61 ****
--- 85,91 ----
  #include <dev/ic/ad1848reg.h>
  #include <dev/isa/ad1848var.h>
  #include <dev/isa/wssreg.h>
+ #include <dev/isa/madreg.h>
  
  /*
   * Mixer devices
***************
*** 93,98 ****
--- 123,129 ----
  #define wss_drq    sc_ad1848.sc_drq
  
  	int 	mic_mute, cd_mute, dac_mute;
+ 	int	mad_chip_type;		/* chip type if MAD emulation of WSS */
  };
  
  struct audio_device wss_device = {
***************
*** 116,121 ****
--- 147,155 ----
  int	wss_mixer_get_port __P((void *, mixer_ctrl_t *));
  int	wss_query_devinfo __P((void *, mixer_devinfo_t *));
  
+ static int 	madprobe __P((int));
+ static void	madprobedone __P((struct wss_softc *));
+ 
  /*
   * Define our interface to the higher level audio driver.
   */
***************
*** 184,189 ****
--- 218,231 ----
      };
      static u_char dma_bits[4] = {1, 2, 0, 3};
      
+     if (sc->sc_dev.dv_cfdata->cf_flags & 1) {
+ 	sc->mad_chip_type = madprobe(iobase);
+ 	if (sc->mad_chip_type == MAD_NONE)
+ 	    return 0;
+     } else {
+ 	sc->mad_chip_type = MAD_NONE;
+     }
+ 
      if (!WSS_BASE_VALID(ia->ia_iobase)) {
  	printf("wss: configured iobase %x invalid\n", ia->ia_iobase);
  	return 0;
***************
*** 227,232 ****
--- 269,277 ----
      outb(iobase+WSS_CONFIG,
  	 (interrupt_bits[ia->ia_irq] | dma_bits[ia->ia_drq]));
  
+     if (sc->mad_chip_type != MAD_NONE)
+ 	madprobedone(sc);
+ 
      return 1;
  }
  
***************
*** 249,259 ****
  #ifdef NEWCONFIG
      isa_establish(&sc->sc_id, &sc->sc_dev);
  #endif
!     sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_AUDIO, ad1848_intr,	&sc->sc_ad1848);
  
      ad1848_attach(&sc->sc_ad1848);
      
      printf(" (vers %d)", inb(iobase+WSS_STATUS) & WSS_VERSMASK);
      printf("\n");
  
      sc->sc_ad1848.parent = sc;
--- 294,310 ----
  #ifdef NEWCONFIG
      isa_establish(&sc->sc_id, &sc->sc_dev);
  #endif
!     sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_AUDIO, ad1848_intr,
! 				   &sc->sc_ad1848);
  
      ad1848_attach(&sc->sc_ad1848);
      
      printf(" (vers %d)", inb(iobase+WSS_STATUS) & WSS_VERSMASK);
+     if (sc->mad_chip_type != MAD_NONE)
+ 	printf(", %s", 
+ 	       sc->mad_chip_type == MAD_82C929 ? "82C929" : 
+ 	       sc->mad_chip_type == MAD_82C928 ? "82C928" :
+ 	       "OTI-601D");
      printf("\n");
  
      sc->sc_ad1848.parent = sc;
***************
*** 711,714 ****
--- 762,931 ----
      DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
  
      return 0;
+ }
+ 
+ /*
+  * Initialization code for OPTi MAD16 compatible audio chips. Including
+  *
+  *      OPTi 82C928     MAD16           (replaced by C929)
+  *      OAK OTI-601D    Mozart
+  *      OPTi 82C929     MAD16 Pro
+  *
+  */
+ 
+ static unsigned int
+ mad_read(chip_type, port)
+     int chip_type;
+     int port;
+ {
+     unsigned int tmp;
+     int s = splaudio();		/* don't want an interrupt between outb&inb */
+     
+     switch (chip_type) {	/* Output password */
+     case MAD_82C928:
+     case MAD_OTI601D:
+ 	outb(MC_PASSWD_REG, M_PASSWD_928);
+ 	break;
+     case MAD_82C929:
+ 	outb(MC_PASSWD_REG, M_PASSWD_929);
+ 	break;
+     }
+     tmp = inb(port);
+     splx(s);
+     return tmp;
+ }
+ 
+ static void
+ mad_write(chip_type, port, value)
+     int chip_type;
+     int port;
+     int value;
+ {
+     int s = splaudio();		/* don't want an interrupt between outb&outb */
+ 
+     switch (chip_type) {	/* Output password */
+     case MAD_82C928:
+     case MAD_OTI601D:
+ 	outb(MC_PASSWD_REG, M_PASSWD_928);
+ 	break;
+     case MAD_82C929:
+ 	outb(MC_PASSWD_REG, M_PASSWD_929);
+ 	break;
+     }
+     outb(port, value & 0xff);
+     splx(s);
+ }
+ 
+ static int
+ detect_mad16(chip_type)
+     int chip_type;
+ {
+     unsigned char tmp, tmp2;
+ 
+     /*
+      * Check that reading a register doesn't return bus float (0xff)
+      * when the card is accessed using password. This may fail in case
+      * the card is in low power mode. Normally at least the power saving mode
+      * bit should be 0.
+      */
+     if ((tmp = mad_read(chip_type, MC1_PORT)) == 0xff) {
+ 	DPRINTF(("MC1_PORT returned 0xff\n"));
+ 	return 0;
+     }
+ 
+     /*
+      * Now check that the gate is closed on first I/O after writing
+      * the password. (This is how a MAD16 compatible card works).
+      */
+     if ((tmp2 = inb(MC1_PORT)) == tmp)	{ /* It didn't close */
+ 	DPRINTF(("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
+ 	return 0;
+     }
+ 
+     mad_write(chip_type, MC1_PORT, tmp ^ 0x80);	/* Toggle a bit */
+ 
+     /* Compare the bit */
+     if ((tmp2 = mad_read(chip_type, MC1_PORT)) != (tmp ^ 0x80)) {
+ 	mad_write(chip_type, MC1_PORT, tmp);	/* Restore */
+ 	DPRINTF(("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
+ 	return 0;
+     }
+ 
+     mad_write(chip_type, MC1_PORT, tmp);	/* Restore */
+     return 1;			/* Bingo */
+ }
+ 
+ static int
+ madprobe(iobase)
+     int iobase;
+ {
+     static int valid_ports[M_WSS_NPORTS] = 
+         { M_WSS_PORT0, M_WSS_PORT1, M_WSS_PORT2, M_WSS_PORT3 };
+     int i;
+     int chip_type;
+ 
+     DPRINTF(("mad: Detect using password = 0xE2\n"));
+     if (!detect_mad16(MAD_82C928)) {
+ 	/* No luck. Try different model */
+ 	DPRINTF(("mad: Detect using password = 0xE3\n"));
+ 	if (!detect_mad16(MAD_82C929))
+ 	    return MAD_NONE;
+ 	chip_type = MAD_82C929;
+ 	DPRINTF(("mad: 82C929 detected\n"));
+     } else {
+ 	if ((mad_read(MAD_82C928, MC3_PORT) & 0x03) == 0x03) {
+ 	    DPRINTF(("mad: Mozart detected\n"));
+ 	    chip_type = MAD_OTI601D;
+ 	} else {
+ 	    DPRINTF(("mad: 82C928 detected?\n"));
+ 	    chip_type = MAD_82C928;
+ 	}
+     }
+ 
+ #ifdef AUDIO_DEBUG
+     for (i = MC1_PORT; i <= MC7_PORT; i++)
+ 	printf("mad: port %03x = %02x\n", i, mad_read(chip_type, i));
+ #endif
+ 
+     /* Set the WSS address. */
+     for (i = 0; i < 4; i++)
+ 	if (valid_ports[i] == iobase)
+ 	    break;
+     if (i > 3) {		/* Not a valid port */
+ 	printf("mad: Bad WSS base address 0x%x\n", iobase);
+ 	return MAD_NONE;
+     }
+     /* enable WSS emulation at the I/O port */
+     mad_write(chip_type, MC1_PORT, M_WSS_PORT_SELECT(i));
+ 
+     mad_write(chip_type, MC2_PORT, 0x03); /* ? */
+     mad_write(chip_type, MC3_PORT, 0xf0); /* Disable SB */
+ 
+     return chip_type;
+ }
+ 
+ static void
+ madprobedone(sc)
+     struct wss_softc *sc;
+ {
+     int chip_type = sc->mad_chip_type;
+     unsigned char cs4231_mode;
+ 
+     cs4231_mode = 
+ 	strncmp(sc->sc_ad1848.chip_name, "CS4248", 6) == 0 ||
+ 	strncmp(sc->sc_ad1848.chip_name, "CS4231", 6) == 0 ? 0x02 : 0;
+ 
+     if (chip_type == MAD_82C929) {
+ 	mad_write(chip_type, MC4_PORT, 0xa2);
+ 	mad_write(chip_type, MC5_PORT, 0xA5 | cs4231_mode);
+ 	mad_write(chip_type, MC6_PORT, 0x03);	/* Disable MPU401 */
+     } else {
+ 	mad_write(chip_type, MC4_PORT, 0x02);
+ 	mad_write(chip_type, MC5_PORT, 0x30 | cs4231_mode);
+     }
+ 
+ #ifdef AUDIO_DEBUG
+     for (i = MC1_PORT; i <= MC7_PORT; i++)
+ 	DPRINTF(("port %03x after init = %02x\n", i, mad_read(chip_type, i)));
+ #endif
  }
*** /usr/src/share/man/man4/man4.i386/wss.4.orig	Thu Feb  1 13:23:45 1996
--- /usr/src/share/man/man4/man4.i386/wss.4	Thu Feb  1 13:26:24 1996
***************
*** 32,38 ****
  .Nm wss
  .Nd Windows Sound System hardware driver
  .Sh SYNOPSIS
! .Cd "device wss0 at isa? port 0x530 irq 10 drq 0"
  .Sh DESCRIPTION
  The
  .Nm
--- 32,38 ----
  .Nm wss
  .Nd Windows Sound System hardware driver
  .Sh SYNOPSIS
! .Cd "device wss0 at isa? port 0x530 irq 10 drq 0 [flag 1]"
  .Sh DESCRIPTION
  The
  .Nm
***************
*** 44,52 ****
  Both IRQ and DMA channels are software programmable.
  The IRQ may be set to 7, 9, 10, or 11, and
  the DMA channel may be set to 0, 1, or 3.
- .Sh BUGS
- This driver doesn't work yet.
  .Pp
  The FM synthesizer is not supported.
  .Sh SEE ALSO
  .Xr audio 4 ,
--- 44,53 ----
  Both IRQ and DMA channels are software programmable.
  The IRQ may be set to 7, 9, 10, or 11, and
  the DMA channel may be set to 0, 1, or 3.
  .Pp
+ If the flag value is 1 the driver will look for MAD16 chips and
+ initialize it.  This chip is used in, e.g., some Turtle Beach cards.
+ .Sh BUGS
  The FM synthesizer is not supported.
  .Sh SEE ALSO
  .Xr audio 4 ,
>Audit-Trail:
>Unformatted: