Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Aug 1999 12:58:54 +0900
From:      MIHIRA Sanpei Yoshiro <sanpei@sanpei.org>
To:        hackers@FreeBSD.ORG
Cc:        freebsd-multimedia@FreeBSD.ORG
Subject:   Re: Is there any plan to newbuslize for 3-stable?
Message-ID:  <199908130358.MAA05559@lavender.yy.cs.keio.ac.jp>
In-Reply-To: Your message of "Thu, 12 Aug 1999 16:14:26 JST". <199908120714.QAA04064@lavender.yy.cs.keio.ac.jp>

next in thread | previous in thread | raw e-mail | index | archive | help
>>   If my patch for pcm/ESS sound chip apply to FreeBSD, may I send-pr
>> with old-config style?
>>   Yes, current pcm sound driver is old-config, but "Cameron Grant"
>> <gandalf@vilnya.demon.co.uk> is working to newbuslize.

  I create patch for 4-current sys/i386/isa/snd. It fix for
pcm/ESS-ISA sound driver.

  All ESS-ISA specific changes are quoted in (d->bd_flags & BD_F_ESS).

MIHIRA Sanpei Yoshiro

diff -uNr snd.org/CARDS snd/CARDS
--- snd.org/CARDS	Wed Aug 11 10:36:53 1999
+++ snd/CARDS	Wed Aug 11 10:21:33 1999
@@ -357,3 +357,4 @@
 
 
 --------------------------------------------------------------------
+$Id$
diff -uNr snd.org/README snd/README
--- snd.org/README	Wed Aug 11 10:36:53 1999
+++ snd/README	Wed Aug 11 10:21:33 1999
@@ -222,3 +222,5 @@
 the product. Too bad that no one of the chip/card manufacturers I
 have contacted by email regarding missing or inconsistent documentation
 on their products did even care to reply to my messages.
+
+$Id$
diff -uNr snd.org/ad1848.c snd/ad1848.c
--- snd.org/ad1848.c	Wed Aug 11 10:36:53 1999
+++ snd/ad1848.c	Wed Aug 11 10:21:33 1999
@@ -40,6 +40,10 @@
  *	http://www.opti.com/	for the OPTi931
  */
 
+/*
+ *	$Id$
+ */
+
 #include <i386/isa/snd/sound.h>
 #if NPCM > 0
 
diff -uNr snd.org/clones.c snd/clones.c
--- snd.org/clones.c	Wed Aug 11 10:36:53 1999
+++ snd/clones.c	Wed Aug 11 10:21:33 1999
@@ -33,6 +33,10 @@
  * in the Voxware 3.5 distribution.
  */
 
+/*
+ *	$Id$
+ */
+
 #include <i386/isa/snd/sound.h>
 #if NPCM > 0
 
diff -uNr snd.org/dmabuf.c snd/dmabuf.c
--- snd.org/dmabuf.c	Wed Aug 11 10:36:53 1999
+++ snd/dmabuf.c	Wed Aug 11 10:21:33 1999
@@ -31,7 +31,12 @@
  *
  */
 
+/*
+ *    $Id$
+ */
+
 #include <i386/isa/snd/sound.h>
+#include <i386/isa/snd/sbcard.h>
 #include <i386/isa/snd/ulaw.h>
 
 #define MIN_CHUNK_SIZE 256	/* for uiomove etc. */
@@ -183,12 +188,13 @@
 	 * This happens if the size has changed _and_ the new size
 	 * is smaller, or it matches the blocksize.
 	 */
-	if (l != b->dl && (b->dl == 0 || l<b->dl || l == d->play_blocksize) ) {
+	if ((l != b->dl && (b->dl == 0 || l<b->dl || l == d->play_blocksize))
+	    || (d->bd_flags & BD_F_ESS)) {
 	    /* for any reason, size has changed. Stop and restart */
 	    DEB(printf("wrintr: bsz change from %d to %d, rp %d rl %d\n",
 		b->dl, l, b->rp, b->rl));
 	    DEB(printf("wrintr: dl %d -> %d\n", b->dl, l);)
-	    if (b->dl != 0)
+	    if (b->dl != 0 && ! (d->bd_flags & BD_F_ESS))
 		d->callback(d, SND_CB_WR | SND_CB_STOP );
 	    /*
 	     * at high speed, it might well be that the count
@@ -281,12 +287,16 @@
 	    else
 		timeout = 1 ;
             ret = tsleep( (caddr_t)b, PRIBIO|PCATCH, "dspwr", timeout);
-	    if (ret == EINTR)
-		d->flags |= SND_F_ABORTING ;
+	    if (ret == EINTR || ((d->bd_flags & BD_F_ESS) && timeout != 1 &&
+	    			ret == EWOULDBLOCK && b->rl == b->bufsize)) {
+                d->flags |= SND_F_ABORTING ;
+	    	splx(s);
+		break;
+	    }
 	    splx(s);
-	    if (ret == EINTR || ret == ERESTART)
+	    if (ret == ERESTART)
 		break ;
-            continue;
+	    continue;
         }
         splx(s);
 
@@ -319,7 +329,8 @@
         if ( b->dl == 0 ) /* dma was idle, restart it */
             dsp_wrintr(d) ;
         splx(s) ;
-	if (buf->uio_resid == 0 && (b->fp & (b->sample_size - 1)) == 0) {
+	if (buf->uio_resid == 0 && (b->fp & (b->sample_size - 1)) == 0 &&
+	    ! (d->bd_flags & BD_F_ESS)) {
 	    /*
 	     * If data is correctly aligned, pad the region with
 	     * replicas of the last sample. l0 goes from current to
@@ -472,9 +483,13 @@
 	int l = min(b->fl - 0x100, d->rec_blocksize);
 	l &= DMA_ALIGN_MASK ; /* realign sizes */
 	DEB(printf("rdintr: dl %d -> %d\n", b->dl, l);)
+#ifdef ESS_RECORD_WITH_NORMAL_DMA
+	if (l != b->dl || d->bd_flags & BD_F_ESS) {
+#else
 	if (l != b->dl) {
+#endif
 	    /* for any reason, size has changed. Stop and restart */
-	    if (b->dl > 0 )
+	    if (b->dl > 0)
 		d->callback(d, SND_CB_RD | SND_CB_STOP );
 	    b->dl = l ;
 	    d->callback(d, SND_CB_RD | SND_CB_START );
@@ -572,10 +587,14 @@
 	    else
 		timeout = 1; /* maybe data will be ready earlier */
             ret = tsleep( (caddr_t)b, PRIBIO | PCATCH , "dsprd", timeout ) ;
-	    if (ret == EINTR)
+	    if (ret == EINTR || ((d->bd_flags & BD_F_ESS) && timeout != 1 &&
+				ret == EWOULDBLOCK && b->fl == b->bufsize)) {
 		d->flags |= SND_F_ABORTING ;
+		splx(s);
+		break;
+	    }
 	    splx(s);
-	    if (ret == EINTR || ret == ERESTART)
+	    if (ret == ERESTART)
 		break ;
             continue;
         }
@@ -719,8 +738,12 @@
     if ( b->dl ) {
 	b->dl = 0 ;
 	d->flags &= ~ SND_F_WRITING ;
-	if (d->callback)
+	if (d->callback) {
 	    d->callback(d, SND_CB_WR | SND_CB_ABORT);
+	    if ((d->bd_flags & BD_F_ESS) && restart) {
+		d->callback(d, SND_CB_INIT);
+	    }
+	}
 	if (!d->special_dma)
 	    isa_dmastop(b->chan) ;
 	dsp_wr_dmadone(d);
@@ -746,15 +769,19 @@
     if ( b->dl ) {
 	b->dl = 0 ;
 	d->flags &= ~ SND_F_READING ;
-	if (d->callback)
+	if (d->callback) {
 	    d->callback(d, SND_CB_RD | SND_CB_ABORT);
+	    if ((d->bd_flags & BD_F_ESS) && restart) {
+		d->callback(d, SND_CB_INIT);
+	    }
+	}
 	if (!d->special_dma) 
 	    isa_dmastop(b->chan) ;
 	dsp_rd_dmadone(d);
     }
     missing = b->rl ;
     if (!d->special_dma)
-        isa_dmadone(B_READ, b->buf, b->bufsize, b->chan);
+	isa_dmadone(B_READ, b->buf, b->bufsize, b->chan);
     reset_dbuf(b, restart ? SND_CHAN_RD : SND_CHAN_NONE);
     splx(s);
     return missing;
@@ -775,7 +802,9 @@
     snd_dbuf *b = &(d->dbuf_out) ;
 
     DEB(printf("snd_flush d->flags 0x%08x\n", d->flags));
-    dsp_rdabort(d, 0 /* no restart */);
+    if (! (d->bd_flags & BD_F_ESS) || (d->rec_fmt &&
+		(FULL_DUPLEX(d) || d->play_fmt == 0)))
+	dsp_rdabort(d, 0 /* no restart */);
     /* close write */
     while ( b->dl ) {
 	/*
@@ -800,7 +829,8 @@
     }
     s = spltty(); /* should not be necessary... */
     d->flags &= ~SND_F_CLOSING ;
-    dsp_wrabort(d, 0 /* no restart */);
+    if (! (d->bd_flags & BD_F_ESS) || d->play_fmt)
+	dsp_wrabort(d, 0 /* no restart */);
     splx(s);
     return 0 ;
 }
diff -uNr snd.org/mss.h snd/mss.h
--- snd.org/mss.h	Wed Aug 11 10:36:53 1999
+++ snd/mss.h	Wed Aug 11 10:21:33 1999
@@ -9,6 +9,10 @@
  */
 
 /*
+ *	$Id$
+ */
+
+/*
  *
 
 The codec part of the board is seen as a set of 4 registers mapped
diff -uNr snd.org/sb_dsp.c snd/sb_dsp.c
--- snd.org/sb_dsp.c	Wed Aug 11 10:36:53 1999
+++ snd/sb_dsp.c	Wed Aug 11 10:21:33 1999
@@ -35,6 +35,10 @@
  */
 
 /*
+ *	$Id$
+ */
+
+/*
  * use this as a template file for board-specific drivers.
  * The next two lines (and the final #endif) are in all drivers:
  */
@@ -69,13 +73,14 @@
 
 static	void sb_dsp_init(snddev_info *d, struct isa_device *dev);
 static	void sb_mix_init(snddev_info *d);
-static int sb_mixer_set(snddev_info *d, int dev, int value);
+/* static int sb_mixer_set(snddev_info *d, int dev, int value); */
 static int dsp_speed(snddev_info *d);
 static void sb_mixer_reset(snddev_info *d);
 
 u_int sb_get_byte(int io_base);
 int ess_write(int io_base, u_char reg, int val);
 int ess_read(int io_base, u_char reg);
+void ess_cont_getmixer(int io_base, u_int port, u_char *buf, int num);
 
 /*
  * Then put here the descriptors for the various boards supported
@@ -322,6 +327,17 @@
 	}
     }
     /* XXX previous location of ack... */
+    if (d->bd_flags & BD_F_ESS) {
+	/*
+	 * A read from port 2xEh(following ack command) will reset
+	 * any IRQ request on ESS chip. And dsp_??intr runs slow.
+	 * Therefore interrupt will be dropped in original location.
+	 */
+	if ( c & 2 )
+	    inb(DSP_DATA_AVL16); /* 16-bit int ack */
+	if (c & 1)
+	    inb(DSP_DATA_AVAIL);	/* 8-bit int ack */
+    }
     DEB(printf("sb_intr, flags 0x%08lx reason %d c 0x%x\n",
 	d->flags, reason, c));
     if ( reason & 1 ) { /* possibly a write interrupt */
@@ -332,11 +348,12 @@
 	if ( d->dbuf_in.dl )
 	    dsp_rdintr(d);
     }
-    if ( c & 2 )
-	inb(DSP_DATA_AVL16); /* 16-bit int ack */
-    if (c & 1)
-	inb(DSP_DATA_AVAIL);	/* 8-bit int ack */
-
+    if (! (d->bd_flags & BD_F_ESS)) {
+	if ( c & 2 )
+	    inb(DSP_DATA_AVL16); /* 16-bit int ack */
+	if (c & 1)
+	    inb(DSP_DATA_AVAIL);	/* 8-bit int ack */
+    }
     /*
      * the sb16 might have multiple sources etc.
      */
@@ -364,6 +381,10 @@
 
     switch (reason & SND_CB_REASON_MASK) {
     case SND_CB_INIT : /* called with int enabled and no pending io */
+	if (d->bd_flags & BD_F_ESS) {
+	    sb_reset_dsp(d->io_base);
+	    sb_cmd(d->io_base, 0xc6); /* enable extended ESS mode */
+	}
 	/*
 	 * set the speed
 	 */
@@ -430,66 +451,79 @@
 		d->dbuf_in.chan = d->dbuf_out.chan;
 		d->dbuf_out.chan = c ;
 	    }
-	}
-	else if (d->bd_flags & BD_F_ESS) {
-		u_char c;
-
-		DEB(printf("SND_CB_INIT, play_fmt == 0x%x, rec_fmt == 0x%x\n",
-			(int) d->play_fmt, (int) d->rec_fmt));
-
-		/* autoinit DMA mode */
-		if (d->play_fmt)
-			ess_write(d->io_base, 0xb8, 0x04);
-		else
-			ess_write(d->io_base, 0xb8, 0x0e);
+	} else if (d->bd_flags & BD_F_ESS) {
+	    u_char c ;
+	    u_char *cmd_ofs;
+	    if (d->play_fmt == 0) {
+		/* initialize for record */
+		static u_char cmd[] = {
+		    0x51,0xd0,0x71,0xf4,0x51,0x98,0x71,0xbc
+		};
+#if ESS_RECORD_WITH_NORMAL_DMA
+		ess_write(d->io_base, 0xb8, 0x0a); /* normal DMA */
+#else
+		ess_write(d->io_base, 0xb8, 0x0e);
+#endif
+		c = ( ess_read(d->io_base, 0xa8) & 0xfc ) | 1 ;
+		if (! (d->flags & SND_F_STEREO))
+		    c++ ;
+		ess_write(d->io_base, 0xa8, c);
+		ess_write(d->io_base, 0xb9, 2); /* 4bytes/transfer */
+		/*
+		 * set format in b6, b7
+		 */
+		cmd_ofs = cmd + ((d->flags & SND_F_STEREO) ? 4 : 0)
+		    + ((d->rec_fmt == AFMT_S16_LE) ? 2 : 0);
+		ess_write(d->io_base, 0xb7, cmd_ofs[0]);
+		ess_write(d->io_base, 0xb7, cmd_ofs[1]);
+		ess_write(d->io_base, 0xb1,
+			  (ess_read(d->io_base, 0xb1) & 0x0f) | 0x50);
+		ess_write(d->io_base, 0xb2,
+			  (ess_read(d->io_base, 0xb2) & 0x0f) | 0x50);
+	    } else {
+		/* initialize for play */
+		static u_char cmd[] = {
+		    0x80,0x51,0xd0,0x00,0x71,0xf4,
+		    0x80,0x51,0x98,0x00,0x71,0xbc
+		};
+		ess_write(d->io_base, 0xb8, 0); /* normal DMA */
+		c = ( ess_read(d->io_base, 0xa8) & 0xfc ) | 1 ;
+		if (! (d->flags & SND_F_STEREO))
+		    c++;
+		ess_write(d->io_base, 0xa8, c);
+		ess_write(d->io_base, 0xb9, 2); /* 4bytes/transfer */
+		
+		cmd_ofs = cmd + ((d->flags & SND_F_STEREO) ? 6 : 0) 
+		    + ((d->play_fmt == AFMT_S16_LE) ? 3 : 0);
+		ess_write(d->io_base, 0xb6, cmd_ofs[0]);
+		ess_write(d->io_base, 0xb7, cmd_ofs[1]);
+		ess_write(d->io_base, 0xb7, cmd_ofs[2]);
 
-		c = (ess_read(d->io_base, 0xa8) & ~0x03) | 0x01;
-		if ((d->flags & SND_F_STEREO) == 0)
-			c++;
-		ess_write(d->io_base, 0xa8, c);	/* select mono/stereo */
-		ess_write(d->io_base, 0xb9, 2);	/* demand 4 bytes/transfer */
-
-		switch (d->play_fmt ? d->play_fmt : d->rec_fmt) {
-		case AFMT_S16_LE:
-			if (d->flags & SND_F_STEREO) {
-				/* 16 bit stereo */
-				if (d->play_fmt)
-					ess_write(d->io_base, 0xb6, 0x00);
-				ess_write(d->io_base, 0xb7, 0x71);
-				ess_write(d->io_base, 0xb7, 0xbc);
-			}
-			else {
-				/* 16 bit mono */
-				if (d->play_fmt)
-					ess_write(d->io_base, 0xb6, 0x00);
-				ess_write(d->io_base, 0xb7, 0x71);
-				ess_write(d->io_base, 0xb7, 0xf4);
-			}
-			break;
-		case AFMT_U8:
-			if (d->flags & SND_F_STEREO) {
-				/* 8 bit stereo */
-				if (d->play_fmt)
-					ess_write(d->io_base, 0xb6, 0x80);
-				ess_write(d->io_base, 0xb7, 0x51);
-				ess_write(d->io_base, 0xb7, 0x98);
-			}
-			else {
-				/* 8 bit mono */
-				if (d->play_fmt)
-					ess_write(d->io_base, 0xb6, 0x80);
-				ess_write(d->io_base, 0xb7, 0x51);
-				ess_write(d->io_base, 0xb7, 0xd0);
-			}
-			break;
-		}
 		ess_write(d->io_base, 0xb1,
-			  ess_read(d->io_base, 0xb1) | 0x50);
+			  (ess_read(d->io_base, 0xb1) & 0x0f) | 0x50);
 		ess_write(d->io_base, 0xb2,
-			  ess_read(d->io_base, 0xb1) | 0x50);
+			  (ess_read(d->io_base, 0xb2) & 0x0f) | 0x50);
+	    }
+	}
+	if (! (d->bd_flags & BD_F_ESS)) {
+	    /*
+	     * isa_dmastart will be called on the same channel
+	     * with a half duplex device.
+	     */
+	    reset_dbuf(& (d->dbuf_in), SND_CHAN_RD );
+	    reset_dbuf(& (d->dbuf_out), SND_CHAN_WR );
+	} else {
+	    if (FULL_DUPLEX(d)) {
+		reset_dbuf(& (d->dbuf_in), SND_CHAN_RD );
+		reset_dbuf(& (d->dbuf_out), SND_CHAN_WR );
+	    } else {
+		if (d->play_fmt) {
+		    reset_dbuf(& (d->dbuf_out), SND_CHAN_WR );
+		} else if (d->rec_fmt) {
+		    reset_dbuf(& (d->dbuf_in), SND_CHAN_RD );
+		}
+	    }
 	}
-	reset_dbuf(& (d->dbuf_in), SND_CHAN_RD );
-	reset_dbuf(& (d->dbuf_out), SND_CHAN_WR );
 	break ;
 
     case SND_CB_START : /* called with int disabled */
@@ -547,18 +581,25 @@
 	    sb_cmd(d->io_base, c );
 	    sb_cmd3(d->io_base, c1 , l - 1) ;
 	} else if (d->bd_flags & BD_F_ESS) {
-		u_long fmt = rd ? d->rec_fmt : d->play_fmt;
+	    short c = -l;
+	    u_char c1;
 
-		DEB(printf("SND_CB_START: %s (%d)\n", rd ? "rd" : "wr", l));
-		if (fmt == AFMT_S16_LE)
-			l >>= 1;
-		l--;
-		if (!rd)
-			sb_cmd(d->io_base, DSP_CMD_SPKON);
-		ess_write(d->io_base, 0xa4, l);
-		ess_write(d->io_base, 0xa5, l >> 8);
-		ess_write(d->io_base, 0xb8,
-			  ess_read(d->io_base, 0xb8) | (rd ? 0x0f : 0x05));
+	    /*
+	     * clear bit 0 of register B8h
+	     */
+	    c1 = ess_read(d->io_base, 0xb8) & 0xfe ;
+	    ess_write(d->io_base, 0xb8, c1++);
+	    /*
+	     * update ESS Transfer Count Register
+	     */
+	    ess_write(d->io_base, 0xa4, (u_char)((u_short)c & 0xff));
+	    ess_write(d->io_base, 0xa5, (u_char)((u_short)(c >> 8) & 0xff));
+	    /*
+	     * set bit 0 of register B8h
+	     */
+	    ess_write(d->io_base, 0xb8, c1);
+	    if (! rd)
+		sb_cmd(d->io_base, DSP_CMD_SPKON);
 	} else { /* SBPro -- stereo not supported */
 	    u_char c ;
 	    if (!rd)
@@ -589,10 +630,10 @@
     case SND_CB_STOP :
 	{
 	    int cmd = DSP_CMD_DMAPAUSE_8 ; /* default: halt 8 bit chan */
-		DEB(printf("SND_CB_XXX: reason 0x%x\n", reason));
-	    if ( b->chan > 4
-		 || (rd && d->rec_fmt == AFMT_S16_LE)
-		 || (!rd && d->play_fmt == AFMT_S16_LE)
+	    if (!(d->bd_flags & BD_F_ESS)
+		&& (b->chan > 4
+		|| (rd && d->rec_fmt == AFMT_S16_LE)
+		|| (!rd && d->play_fmt == AFMT_S16_LE))
 	       )
 		cmd = DSP_CMD_DMAPAUSE_16 ;
 	    if (d->bd_flags & BD_F_HISPEED) {
@@ -601,7 +642,22 @@
 		    sb_cmd(d->io_base, 0xc6 ); /* enable extended ESS mode */
 		d->flags |= SND_F_INIT ;
 	    } else {
-		sb_cmd(d->io_base, cmd); /* pause dma. */
+#ifdef ESS_IGNORE_PAUSE_COMMAND
+		if (d->bd_flags & BD_F_ESS) {
+		    DEB(u_char c1 ;
+	    	        c1 = ess_read(d->io_base, 0xb8) ;
+		        printf("CB_STOP: b8 0x%x\n", (u_int) c1);)
+		    if (rd) {
+#if ESS_RECORD_WITH_NORMAL_DMA
+			ess_write(d->io_base, 0xb8, 0x0a);
+#else
+			ess_write(d->io_base, 0xb8, 0x0e);
+#endif
+		    } else
+			ess_write(d->io_base, 0xb8, 0x00);
+		} else
+#endif
+		    sb_cmd(d->io_base, cmd); /* pause dma. */
 	       /*
 		* The above seems to have the undocumented side effect of
 		* blocking the other side as well. If the other
@@ -669,6 +725,7 @@
     int i, x;
     char *fmt = NULL ;
     int	io_base = dev->id_iobase ;
+    u_char ess_ident[4];
 
     d->bd_id = 0 ;
 
@@ -761,25 +818,32 @@
 		} else
 		    DELAY(20);
 	    }
-
 	    if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) {
 		/* the ESS488 can be treated as an SBPRO */
 		printf("ESS488 (rev %d)\n", ess_minor & 0x0f);
 		break ;
-	    }
-		else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) {
-			int rev = ess_minor & 0xf;
-
-			if (rev >= 8)
-				printf("ESS1868 (rev %d)\n", rev);
-			else
-				printf("ESS688 (rev %d)\n", rev);
-			d->bd_flags |= BD_F_ESS;
-			d->audio_fmt |= AFMT_S16_LE;
-
-			/* enable extended ESS mode */
-			sb_cmd(d->io_base, 0xc6);
-			break;
+	    } else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) {
+		int rev = ess_minor & 0xf ;
+		if ( rev >= 8 ) {
+		    ess_cont_getmixer(io_base, 0x40, ess_ident, sizeof(ess_ident));
+		    if (ess_ident[0] == 0x18) {
+			sprintf(fmt, "ESS18%x %%d.%%d", ess_ident[1]);
+			printf("ESS18%x (rev %d, native mode)\n", ess_ident[1], rev);
+		    } else {
+			sprintf(fmt, "ESS Chip %%d.%%d");
+		        printf("ESS Chip (rev %d, %x%x, native mode)\n", rev, ess_ident[0], ess_ident[1]);
+		    }
+		} else {
+		    sprintf(fmt, "ESS688 %%d.%%d");
+		    printf("ESS688 (rev %d, native mode)\n", rev);
+		}
+		d->audio_fmt |= AFMT_S16_LE;
+		d->bd_flags |= BD_F_ESS;
+		d->bd_flags &= ~BD_F_MIX_MASK ;
+		d->bd_flags |= BD_F_MIX_ESS688 ;
+		sb_reset_dsp(io_base);
+		sb_cmd(io_base, 0xc6);
+		break ;
 	    } else {
 		printf("Unknown card 0x%x 0x%x -- hope it is SBPRO\n",
 			ess_major, ess_minor);
@@ -798,6 +862,7 @@
 static void
 sb_mix_init(snddev_info *d)
 {
+    u_int mixval;
     switch (d->bd_flags & BD_F_MIX_MASK) {
     case BD_F_MIX_CT1345 : /* SB 3.0 has 1345 mixer */
 
@@ -816,6 +881,20 @@
 	d->mix_devs = SB16_MIXER_DEVICES ;
 	d->mix_rec_devs = SB16_RECORDING_DEVICES ;
 	d->mix_recsrc = SOUND_MASK_MIC ;
+	break ;
+
+    case BD_F_MIX_ESS688 : /* ESS688/ESS1868 mixer */
+
+	mixval = (u_int)sb_getmixer(d->io_base, ESS_VOLCTL);
+	if (mixval & 1) {
+	    printf("%s: setting master volume control register"
+		"(compatibility mode)\n", d->name);
+	    sb_setmixer(d->io_base, ESS_VOLCTL, mixval & ~1);
+	}
+	d->mix_devs = ESS_MIXER_DEVICES ;
+	d->mix_rec_devs = ESS_RECORDING_DEVICES ;
+	d->mix_recsrc = SOUND_MASK_MIC ;
+	break ;
     }
     sb_mixer_reset(d);
 }
@@ -931,6 +1010,20 @@
     return sb_get_byte(io_base);
 }
 
+void
+ess_cont_getmixer(int io_base, u_int port, u_char *buf, int num)
+{
+    int	    val;
+    int     i;
+    u_long  flags;
+
+    flags = spltty();
+    outb(io_base + SB_MIX_ADDR, (u_char) (port & 0xff));   /* Select register */
+    for (i = 0; i < num; buf++, i++) {
+        *buf = inb(io_base + SB_MIX_DATA);
+    }
+    splx(flags);
+}
 
 /*
  * various utility functions for the DSP
@@ -1067,6 +1160,7 @@
     mask &= d->mix_rec_devs;
     switch (d->bd_flags & BD_F_MIX_MASK) {
     case BD_F_MIX_CT1345 :
+    case BD_F_MIX_ESS688 :
 	if (mask == SOUND_MASK_LINE)
 	    recdev = 6 ;
 	else if (mask == SOUND_MASK_CD)
@@ -1121,7 +1215,7 @@
     sb_set_recsrc(d, SOUND_MASK_MIC);
 }
 
-static int
+int
 sb_mixer_set(snddev_info *d, int dev, int value)
 {
     int left = value & 0x000000ff;
@@ -1159,6 +1253,9 @@
 	break;
     case BD_F_MIX_CT1745 :
 	iomap = &sb16_mix ;
+	break;
+    case BD_F_MIX_ESS688 :
+	iomap = &ess688_mix ;
 	break;
     /* XXX how about the SG NX Pro, iomap = sgnxpro_mix */
     }
diff -uNr snd.org/sbcard.h snd/sbcard.h
--- snd.org/sbcard.h	Wed Aug 11 10:36:53 1999
+++ snd/sbcard.h	Wed Aug 11 10:21:33 1999
@@ -2,6 +2,10 @@
  * file: sbcard.h
  */
 
+/*
+ *	$Id$
+ */
+
 typedef struct _sbdev_info {
 
 } sbdev_info ;
@@ -136,6 +140,7 @@
 #define	BD_F_MIX_CT1335	0x0010	/* CT1335		*/
 #define	BD_F_MIX_CT1345	0x0020	/* CT1345		*/
 #define	BD_F_MIX_CT1745	0x0030	/* CT1745		*/
+#define	BD_F_MIX_ESS688	0x0040	/* ESS688/ESS1868 mixer	*/
 
 #define	BD_F_SB16	0x0100	/* this is a SB16 */
 #define	BD_F_SB16X	0x0200	/* this is a vibra16X or clone */
@@ -208,6 +213,14 @@
      SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
      SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE)
 
+#define ESS_MIXER_DEVICES	\
+    (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | \
+     SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | \
+     SOUND_MASK_VOLUME)
+
+/* XXX	I don't know;-) */
+#define ESS_RECORDING_DEVICES	SB16_RECORDING_DEVICES
+
 /*
  * Mixer registers
  * 
@@ -253,6 +266,10 @@
 #define SB16_IMASK_R	0x3e
 #define SB16_OMASK	0x3c
 
+/*
+ * ESS mixer cnotrol extension registers
+ */
+#define	ESS_VOLCTL	0x64
 
 #ifndef __SB_MIXER_C__
 mixer_tab       sbpro_mix;
@@ -314,6 +331,23 @@
     PMIX_ENT(SOUND_MIXER_OGAIN,   0x41, 6, 2, 0x42, 6, 2)
 };
 
+mixer_tab       ess688_mix = {
+    PMIX_ENT(SOUND_MIXER_VOLUME,  0x32, 4, 4, 0x32, 0, 4),
+    PMIX_ENT(SOUND_MIXER_BASS,    0x00, 0, 0, 0x00, 0, 0),
+    PMIX_ENT(SOUND_MIXER_TREBLE,  0x00, 0, 0, 0x00, 0, 0),
+    PMIX_ENT(SOUND_MIXER_SYNTH,   0x36, 4, 4, 0x36, 0, 4),
+    PMIX_ENT(SOUND_MIXER_PCM,     0x14, 4, 4, 0x14, 0, 4),
+    PMIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 0, 3, 0x00, 0, 0),
+    PMIX_ENT(SOUND_MIXER_LINE,    0x3e, 4, 4, 0x3e, 0, 4),
+    PMIX_ENT(SOUND_MIXER_MIC,     0x1a, 4, 4, 0x1a, 0, 4),
+    PMIX_ENT(SOUND_MIXER_CD,      0x38, 4, 4, 0x38, 0, 4),
+    PMIX_ENT(SOUND_MIXER_IMIX,    0x00, 0, 0, 0x00, 0, 0),
+    PMIX_ENT(SOUND_MIXER_ALTPCM,  0x00, 0, 0, 0x00, 0, 0),
+    PMIX_ENT(SOUND_MIXER_RECLEV,  0x00, 0, 0, 0x00, 0, 0),
+    PMIX_ENT(SOUND_MIXER_IGAIN,   0x00, 0, 0, 0x00, 0, 0),
+    PMIX_ENT(SOUND_MIXER_OGAIN,   0x00, 0, 0, 0x00, 0, 0)
+};
+
 #ifdef SM_GAMES			/* Master volume is lower and PCM & FM
 				 * volumes higher than with SB Pro. This
 				 * improves the sound quality */
@@ -346,7 +380,7 @@
 	0x4b4b,			/* PCM */
 	0x4b4b,			/* PC Speaker */
 	0x4b4b,			/* Ext Line */
-	0x1010,			/* Mic */
+	0x0000,			/* Mic */
 	0x4b4b,			/* CD */
 	0x4b4b,			/* Recording monitor */
 	0x4b4b,			/* SB PCM */
diff -uNr snd.org/sound.c snd/sound.c
--- snd.org/sound.c	Wed Aug 11 10:36:53 1999
+++ snd/sound.c	Wed Aug 11 10:21:33 1999
@@ -50,9 +50,14 @@
  *
  */
 
+/*
+ *	$Id$
+ */
+
 #include "opt_devfs.h"
 
 #include <i386/isa/snd/sound.h>
+#include <i386/isa/snd/sbcard.h>
 #ifdef DEVFS
 #include <sys/devfsext.h>
 #endif /* DEVFS */
@@ -145,6 +150,20 @@
 	    outb(0x371, 0xa9 ); /* use both dma chans */
 	else
 	    outb(0x371, 0x8b ); /* use low dma chan */
+    } else if (d->bd_flags & BD_F_ESS) {
+	int i ;
+
+	DDB(printf("ESS: resume\n"));
+	sb_reset_dsp(d->io_base);
+	sb_cmd(d->io_base, 0xc6);
+
+	if (d->dbuf_out.dl)
+	    dsp_wrabort(d, 1 /* restart */);
+	if (d->dbuf_in.dl)
+	    dsp_rdabort(d, 1 /* restart */);
+
+	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+	    sb_mixer_set(d, i, d->mix_levels[i]);
     }
 	printf("Called APM sound resume hook for unit %d\n", (int)arg);
 	return 0 ;
@@ -967,8 +986,21 @@
 	break ;
     case SNDCTL_DSP_RESET:
 	DEB(printf("dsp reset\n"));
-	dsp_wrabort(d, 1 /* restart */);
-	dsp_rdabort(d, 1 /* restart */);
+	if (! (d->bd_flags & BD_F_ESS)) {
+	    dsp_wrabort(d, 1 /* restart */);
+	    dsp_rdabort(d, 1 /* restart */);
+	} else {
+	    if (FULL_DUPLEX(d)) {
+	        dsp_wrabort(d, 1 /* restart */);
+	        dsp_rdabort(d, 1 /* restart */);
+	    } else {
+	        if (d->play_fmt) {
+		    dsp_wrabort(d, 1 /* restart */);
+	        } else if (d->rec_fmt) {
+		    dsp_rdabort(d, 1 /* restart */);
+	        }
+	    }
+	}
 	break ;
 
     case SNDCTL_DSP_SYNC:
@@ -1035,8 +1067,19 @@
 	if (d->rec_fmt)
 	    d->rec_fmt = *(int *)arg ;
 	splx(s);
-	if (ask_init(d))
-	    *(int *)arg = d->play_fmt ;
+	if (ask_init(d)) {
+	    /*
+	     * ioctl will fail if (half duplex) ESS is opened RDONLY.
+	     */
+	    if (d->bd_flags & BD_F_ESS) {
+		if (d->play_fmt)
+		    *(int *)arg = d->play_fmt ;
+		else if (d->rec_fmt)    /* XXX */
+		    *(int *)arg = d->rec_fmt ;
+	    } else {
+		*(int *)arg = d->play_fmt ;
+	    }
+	}
 	break ;
 
     case SNDCTL_DSP_SUBDIVIDE:
diff -uNr snd.org/sound.h snd/sound.h
--- snd.org/sound.h	Wed Aug 11 10:36:53 1999
+++ snd/sound.h	Wed Aug 11 10:21:33 1999
@@ -28,6 +28,10 @@
  *
  */
 
+/*
+ *	$Id$
+ */
+
 #ifdef KERNEL
 #include "pcm.h"
 #else
@@ -498,6 +502,7 @@
 int sb_reset_dsp (int io_base);
 void sb_setmixer (int io_base, u_int port, u_int value);
 int sb_getmixer (int io_base, u_int port);
+int sb_mixer_set (snddev_info *d, int dev, int value);
 
 #endif /* KERNEL */
 
@@ -526,3 +531,7 @@
 #define DV_PNP_SBCODEC 0x1
 
 #endif
+/*
+ *
+ */
+#define ESS_RECORD_WITH_NORMAL_DMA 0


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-multimedia" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199908130358.MAA05559>