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-hackers" 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>