>> 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"
>> <[EMAIL PROTECTED]> 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 [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message