From 57376530f018db4c771d3d8b8c150f037cc4eb07 Mon Sep 17 00:00:00 2001 From: Cameron Grant Date: Tue, 28 Mar 2000 18:31:01 +0000 Subject: [PATCH] split up ess and sb code rewrite ess mixer to use native registers rewrite play/rec code to use more accurate timer when available add code to use audio2 for playback, but disable it as no irqs are generated --- sys/conf/files | 3 + sys/dev/sound/isa/ess.c | 930 +++++++++++++++++++++++++++++++++++++++ sys/dev/sound/isa/sb.c | 330 +------------- sys/dev/sound/isa/sb16.c | 330 +------------- sys/dev/sound/isa/sb8.c | 330 +------------- 5 files changed, 972 insertions(+), 951 deletions(-) create mode 100644 sys/dev/sound/isa/ess.c diff --git a/sys/conf/files b/sys/conf/files index 08d40daf2d7b..b38ff6a7619a 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -327,6 +327,7 @@ dev/sn/if_sn_isa.c optional sn isa dev/sn/if_sn_pccard.c optional sn card dev/sound/isa/ad1816.c optional pcm isa dev/sound/isa/es1888.c optional pcm isa +dev/sound/isa/ess.c optional pcm isa dev/sound/isa/gusc.c optional gusc isa dev/sound/isa/gusc.c optional pcm isa dev/sound/isa/mss.c optional pcm isa @@ -337,9 +338,11 @@ dev/sound/isa/sbc.c optional sbc isa dev/sound/pci/csa.c optional csa pci dev/sound/pci/csa.c optional pcm pci dev/sound/pci/csapcm.c optional pcm pci +#dev/sound/pci/emu10k1.c optional pcm pci dev/sound/pci/es137x.c optional pcm pci dev/sound/pci/neomagic.c optional pcm pci dev/sound/pci/t4dwave.c optional pcm pci +#dev/sound/pci/via82c686.c optional pcm pci dev/sound/pcm/ac97.c optional pcm dev/sound/pcm/channel.c optional pcm dev/sound/pcm/dsp.c optional pcm diff --git a/sys/dev/sound/isa/ess.c b/sys/dev/sound/isa/ess.c new file mode 100644 index 000000000000..60727644cd84 --- /dev/null +++ b/sys/dev/sound/isa/ess.c @@ -0,0 +1,930 @@ +/* + * Copyright (c) 1999 Cameron Grant + * Copyright 1997,1998 Luigi Rizzo. + * + * Derived from files in the Voxware 3.5 distribution, + * Copyright by Hannu Savolainen 1994, under the same copyright + * conditions. + * 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. + * + * 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. + * + * $FreeBSD$ + */ + +#include + +#include "sbc.h" + +#include +#include + +#define ESS_BUFFSIZE (4096) +#define ABS(x) (((x) < 0)? -(x) : (x)) + +/* audio2 never generates irqs and sounds very noisy */ +#undef ESS18XX_DUPLEX + +/* more accurate clocks and split audio1/audio2 rates */ +#define ESS18XX_NEWSPEED + +/* channel interface for ESS */ +static void *esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); +static int esschan_setdir(void *data, int dir); +static int esschan_setformat(void *data, u_int32_t format); +static int esschan_setspeed(void *data, u_int32_t speed); +static int esschan_setblocksize(void *data, u_int32_t blocksize); +static int esschan_trigger(void *data, int go); +static int esschan_getptr(void *data); +static pcmchan_caps *esschan_getcaps(void *data); + +static pcmchan_caps ess_playcaps = { + 5000, 49000, + AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_U16_LE | AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE +}; + +static pcmchan_caps ess_reccaps = { + 5000, 49000, + AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_U16_LE | AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE +}; + +static pcm_channel ess_chantemplate = { + esschan_init, + esschan_setdir, + esschan_setformat, + esschan_setspeed, + esschan_setblocksize, + esschan_trigger, + esschan_getptr, + esschan_getcaps, +}; + +struct ess_info; + +struct ess_chinfo { + struct ess_info *parent; + pcm_channel *channel; + snd_dbuf *buffer; + int dir, hwch, stopping; + u_int32_t fmt, spd; +}; + +struct ess_info { + struct resource *io_base; /* I/O address for the board */ + struct resource *irq; + struct resource *drq1; + struct resource *drq2; + bus_dma_tag_t parent_dmat; + + int type, duplex:1, newspeed:1; + u_long bd_flags; /* board-specific flags */ + struct ess_chinfo pch, rch; +}; + +static int ess_rd(struct ess_info *sc, int reg); +static void ess_wr(struct ess_info *sc, int reg, u_int8_t val); +static int ess_dspready(struct ess_info *sc); +static int ess_cmd(struct ess_info *sc, u_char val); +static int ess_cmd1(struct ess_info *sc, u_char cmd, int val); +static int ess_get_byte(struct ess_info *sc); +static void ess_setmixer(struct ess_info *sc, u_int port, u_int value); +static int ess_getmixer(struct ess_info *sc, u_int port); +static int ess_reset_dsp(struct ess_info *sc); + +static int ess_write(struct ess_info *sc, u_char reg, int val); +static int ess_read(struct ess_info *sc, u_char reg); + +static void ess_intr(void *arg); +static int ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len); +static int ess_start(struct ess_chinfo *ch); +static int ess_stop(struct ess_chinfo *ch); + +static int essmix_init(snd_mixer *m); +static int essmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right); +static int essmix_setrecsrc(snd_mixer *m, u_int32_t src); + +static snd_mixer ess_mixer = { + "ESS mixer", + essmix_init, + essmix_set, + essmix_setrecsrc, +}; + +static devclass_t pcm_devclass; + +/* + * Common code for the midi and pcm functions + * + * ess_cmd write a single byte to the CMD port. + * ess_cmd1 write a CMD + 1 byte arg + * ess_cmd2 write a CMD + 2 byte arg + * ess_get_byte returns a single byte from the DSP data port + * + * ess_write is actually ess_cmd1 + * ess_read access ext. regs via ess_cmd(0xc0, reg) followed by ess_get_byte + */ + +static int +port_rd(struct resource *port, int off) +{ + return bus_space_read_1(rman_get_bustag(port), + rman_get_bushandle(port), + off); +} + +static void +port_wr(struct resource *port, int off, u_int8_t data) +{ + return bus_space_write_1(rman_get_bustag(port), + rman_get_bushandle(port), + off, data); +} + +static int +ess_rd(struct ess_info *sc, int reg) +{ + return port_rd(sc->io_base, reg); +} + +static void +ess_wr(struct ess_info *sc, int reg, u_int8_t val) +{ + port_wr(sc->io_base, reg, val); +} + +static int +ess_dspready(struct ess_info *sc) +{ + return ((ess_rd(sc, SBDSP_STATUS) & 0x80) == 0); +} + +static int +ess_dspwr(struct ess_info *sc, u_char val) +{ + int i; + + for (i = 0; i < 1000; i++) { + if (ess_dspready(sc)) { + ess_wr(sc, SBDSP_CMD, val); + return 1; + } + if (i > 10) DELAY((i > 100)? 1000 : 10); + } + printf("ess_dspwr(0x%02x) timed out.\n", val); + return 0; +} + +static int +ess_cmd(struct ess_info *sc, u_char val) +{ +#if 0 + printf("ess_cmd: %x\n", val); +#endif + return ess_dspwr(sc, val); +} + +static int +ess_cmd1(struct ess_info *sc, u_char cmd, int val) +{ +#if 0 + printf("ess_cmd1: %x, %x\n", cmd, val); +#endif + if (ess_dspwr(sc, cmd)) { + return ess_dspwr(sc, val & 0xff); + } else return 0; +} + +static void +ess_setmixer(struct ess_info *sc, u_int port, u_int value) +{ + u_long flags; + + DEB(printf("ess_setmixer: reg=%x, val=%x\n", port, value);) + flags = spltty(); + ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ + DELAY(10); + ess_wr(sc, SB_MIX_DATA, (u_char) (value & 0xff)); + DELAY(10); + splx(flags); +} + +static int +ess_getmixer(struct ess_info *sc, u_int port) +{ + int val; + u_long flags; + + flags = spltty(); + ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ + DELAY(10); + val = ess_rd(sc, SB_MIX_DATA); + DELAY(10); + splx(flags); + + return val; +} + +static int +ess_get_byte(struct ess_info *sc) +{ + int i; + + for (i = 1000; i > 0; i--) { + if (ess_rd(sc, DSP_DATA_AVAIL) & 0x80) + return ess_rd(sc, DSP_READ); + else + DELAY(20); + } + return -1; +} + +static int +ess_write(struct ess_info *sc, u_char reg, int val) +{ + return ess_cmd1(sc, reg, val); +} + +static int +ess_read(struct ess_info *sc, u_char reg) +{ + return (ess_cmd(sc, 0xc0) && ess_cmd(sc, reg))? ess_get_byte(sc) : -1; +} + +static int +ess_reset_dsp(struct ess_info *sc) +{ + ess_wr(sc, SBDSP_RST, 3); + DELAY(100); + ess_wr(sc, SBDSP_RST, 0); + if (ess_get_byte(sc) != 0xAA) { + DEB(printf("ess_reset_dsp 0x%lx failed\n", + rman_get_start(d->io_base))); + return ENXIO; /* Sorry */ + } + ess_cmd(sc, 0xc6); + return 0; +} + +static void +ess_release_resources(struct ess_info *sc, device_t dev) +{ + /* should we bus_teardown_intr here? */ + if (sc->irq) { + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); + sc->irq = 0; + } + if (sc->drq1) { + bus_release_resource(dev, SYS_RES_DRQ, 0, sc->drq1); + sc->drq1 = 0; + } + if (sc->drq2) { + bus_release_resource(dev, SYS_RES_DRQ, 1, sc->drq2); + sc->drq2 = 0; + } + if (sc->io_base) { + bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->io_base); + sc->io_base = 0; + } + free(sc, M_DEVBUF); +} + +static int +ess_alloc_resources(struct ess_info *sc, device_t dev) +{ + int rid; + + rid = 0; + if (!sc->io_base) + sc->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, + &rid, 0, ~0, 1, + RF_ACTIVE); + rid = 0; + if (!sc->irq) + sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, + &rid, 0, ~0, 1, + RF_ACTIVE); + rid = 0; + if (!sc->drq1) + sc->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ, + &rid, 0, ~0, 1, + RF_ACTIVE); + rid = 1; + if (!sc->drq2) + sc->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, + &rid, 0, ~0, 1, + RF_ACTIVE); + + if (sc->io_base && sc->drq1 && sc->irq) { + isa_dma_acquire(rman_get_start(sc->drq1)); + isa_dmainit(rman_get_start(sc->drq1), ESS_BUFFSIZE); + + if (sc->drq2) { + isa_dma_acquire(rman_get_start(sc->drq2)); + isa_dmainit(rman_get_start(sc->drq2), ESS_BUFFSIZE); + } + + return 0; + } else return ENXIO; +} + +static int +ess_doattach(device_t dev, struct ess_info *sc) +{ + snddev_info *d = device_get_softc(dev); + void *ih; + char status[SND_STATUSLEN], buf[64]; + int ver; + + if (ess_alloc_resources(sc, dev)) + goto no; + if (ess_reset_dsp(sc)) + goto no; + mixer_init(d, &ess_mixer, sc); + + sc->duplex = 0; + sc->newspeed = 0; + ver = (ess_getmixer(sc, 0x40) << 8) | ess_rd(sc, SB_MIX_DATA); + snprintf(buf, sizeof buf, "ESS %x DSP", ver); + device_set_desc_copy(dev, buf); + if (bootverbose) + device_printf(dev, "ESS%x detected", ver); + + switch (ver) { + case 0x1869: + case 0x1879: +#ifdef ESS18XX_DUPLEX + sc->duplex = sc->drq2? 1 : 0; +#endif +#ifdef ESS18XX_NEWSPEED + sc->newspeed = 1; +#endif + break; + } + if (bootverbose) + printf("%s%s\n", sc->duplex? ", duplex" : "", + sc->newspeed? ", newspeed" : ""); + + if (sc->newspeed) + ess_setmixer(sc, 0x71, 0x22); + + bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, ess_intr, sc, &ih); + if (!sc->duplex) + pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); + + if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, + /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, + /*highaddr*/BUS_SPACE_MAXADDR, + /*filter*/NULL, /*filterarg*/NULL, + /*maxsize*/ESS_BUFFSIZE, /*nsegments*/1, + /*maxsegz*/0x3ffff, + /*flags*/0, &sc->parent_dmat) != 0) { + device_printf(dev, "unable to create dma tag\n"); + goto no; + } + + snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld", + rman_get_start(sc->io_base), rman_get_start(sc->irq), + rman_get_start(sc->drq1)); + if (sc->drq2) + snprintf(status + strlen(status), SND_STATUSLEN - strlen(status), + ":%ld", rman_get_start(sc->drq2)); + + if (pcm_register(dev, sc, 1, 1)) + goto no; + pcm_addchan(dev, PCMDIR_REC, &ess_chantemplate, sc); + pcm_addchan(dev, PCMDIR_PLAY, &ess_chantemplate, sc); + pcm_setstatus(dev, status); + + return 0; + +no: + ess_release_resources(sc, dev); + return ENXIO; +} + +static void +ess_intr(void *arg) +{ + struct ess_info *sc = (struct ess_info *)arg; + int src, pirq, rirq; + + src = 0; + if (ess_getmixer(sc, 0x7a) & 0x80) + src |= 2; + if (ess_rd(sc, 0x0c) & 0x01) + src |= 1; + + pirq = (src & sc->pch.hwch)? 1 : 0; + rirq = (src & sc->rch.hwch)? 1 : 0; + + if (pirq) { + if (sc->pch.stopping) { + buf_isadma(sc->pch.buffer, PCMTRIG_STOP); + sc->pch.stopping = 0; + if (sc->pch.hwch == 1) + ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01); + else + ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x03); + } + chn_intr(sc->pch.channel); + } + + if (rirq) { + if (sc->rch.stopping) { + buf_isadma(sc->rch.buffer, PCMTRIG_STOP); + sc->rch.stopping = 0; + /* XXX: will this stop audio2? */ + ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01); + } + chn_intr(sc->rch.channel); + } + + if (src & 2) + ess_setmixer(sc, 0x7a, ess_getmixer(sc, 0x7a) & ~0x80); + if (src & 1) + ess_rd(sc, DSP_DATA_AVAIL); +} + +/* utility functions for ESS */ +static u_int8_t +ess_calcspeed8(int *spd) +{ + int speed = *spd; + u_int32_t t; + + if (speed > 22000) { + t = (795500 + speed / 2) / speed; + speed = (795500 + t / 2) / t; + t = (256 - t) | 0x80; + } else { + t = (397700 + speed / 2) / speed; + speed = (397700 + t / 2) / t; + t = 128 - t; + } + *spd = speed; + return t & 0x000000ff; +} + +static u_int8_t +ess_calcspeed9(int *spd) +{ + int speed, s0, s1, use0; + u_int8_t t0, t1; + + /* rate = source / (256 - divisor) */ + /* divisor = 256 - (source / rate) */ + speed = *spd; + t0 = 256 - (793800 / speed); + s0 = 793800 / (256 - t0); + + t1 = 0x80 | (256 - (768000 / speed)); + s1 = 768000 / (256 - t1); + + use0 = (ABS(speed - s0) < ABS(speed - s1))? 1 : 0; + + *spd = use0? s0 : s1; + return use0? t0 : t1; +} + +static u_int8_t +ess_calcfilter(int spd) +{ + int cutoff; + + /* cutoff = 7160000 / (256 - divisor) */ + /* divisor = 256 - (7160000 / cutoff) */ + cutoff = (spd * 9 * 82) / 20; + return (256 - (7160000 / cutoff)); +} + +static int +ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len) +{ + int play = (dir == PCMDIR_PLAY)? 1 : 0; + int b16 = (fmt & AFMT_16BIT)? 1 : 0; + int stereo = (fmt & AFMT_STEREO)? 1 : 0; + int unsign = (fmt == AFMT_U8 || fmt == AFMT_U16_LE)? 1 : 0; + u_int8_t spdval, fmtval; + + + spdval = (sc->newspeed)? ess_calcspeed9(&spd) : ess_calcspeed8(&spd); + len = -len; + + if (ch == 1) { + KASSERT((dir == PCMDIR_PLAY) || (dir == PCMDIR_REC), ("ess_setupch: dir1 bad")); + /* transfer length low */ + ess_write(sc, 0xa4, len & 0x00ff); + /* transfer length high */ + ess_write(sc, 0xa5, (len & 0xff00) >> 8); + /* autoinit, dma dir */ + ess_write(sc, 0xb8, 0x04 | (play? 0x00 : 0x0a)); + /* mono/stereo */ + ess_write(sc, 0xa8, (ess_read(sc, 0xa8) & ~0x03) | (stereo? 0x01 : 0x02)); + /* demand mode, 4 bytes/xfer */ + ess_write(sc, 0xb9, 0x02); + /* sample rate */ + ess_write(sc, 0xa1, spdval); + /* filter cutoff */ + ess_write(sc, 0xa2, ess_calcfilter(spd)); + /* setup dac/adc */ + if (play) + ess_write(sc, 0xb6, unsign? 0x80 : 0x00); + /* mono, b16: signed, load signal */ + ess_write(sc, 0xb7, 0x51 | (unsign? 0x00 : 0x20)); + /* setup fifo */ + ess_write(sc, 0xb7, 0x90 | (unsign? 0x00 : 0x20) | + (b16? 0x04 : 0x00) | + (stereo? 0x08 : 0x40)); + /* irq control */ + ess_write(sc, 0xb1, (ess_read(sc, 0xb1) & 0x0f) | 0x50); + /* drq control */ + ess_write(sc, 0xb2, (ess_read(sc, 0xb2) & 0x0f) | 0x50); + } else if (ch == 2) { + KASSERT(dir == PCMDIR_PLAY, ("ess_setupch: dir2 bad")); + /* transfer length low */ + ess_setmixer(sc, 0x74, len & 0x00ff); + /* transfer length high */ + ess_setmixer(sc, 0x76, (len & 0xff00) >> 8); + /* autoinit, 4 bytes/req */ + ess_setmixer(sc, 0x78, 0x90); + fmtval = b16 | (stereo << 1) | (unsign << 2); + /* enable irq, set format */ + ess_setmixer(sc, 0x7a, 0x40 | fmtval); + if (sc->newspeed) { + /* sample rate */ + ess_setmixer(sc, 0x70, spdval); + /* filter cutoff */ + ess_setmixer(sc, 0x72, ess_calcfilter(spd)); + } + + } + return 0; +} +static int +ess_start(struct ess_chinfo *ch) +{ + struct ess_info *sc = ch->parent; + int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; + + ess_setupch(sc, ch->hwch, ch->dir, ch->spd, ch->fmt, ch->buffer->dl); + ch->stopping = 0; + if (ch->hwch == 1) + ess_write(sc, 0xb8, ess_read(sc, 0xb8) | 0x01); + else + ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) | 0x03); + if (play) + ess_cmd(sc, DSP_CMD_SPKON); + return 0; +} + +static int +ess_stop(struct ess_chinfo *ch) +{ + struct ess_info *sc = ch->parent; + int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; + + ch->stopping = 1; + if (ch->hwch == 1) + ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x04); + else + ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x10); + if (play) + ess_cmd(sc, DSP_CMD_SPKOFF); + return 0; +} + +/* channel interface for ESS18xx */ +static void * +esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) +{ + struct ess_info *sc = devinfo; + struct ess_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; + + ch->parent = sc; + ch->channel = c; + ch->buffer = b; + ch->buffer->bufsize = ESS_BUFFSIZE; + if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1) + return NULL; + ch->hwch = 1; + if ((dir == PCMDIR_PLAY) && (sc->duplex)) + ch->hwch = 2; + ch->buffer->chan = rman_get_start((ch->hwch == 1)? sc->drq1 : sc->drq2); + return ch; +} + +static int +esschan_setdir(void *data, int dir) +{ + struct ess_chinfo *ch = data; + + ch->dir = dir; + return 0; +} + +static int +esschan_setformat(void *data, u_int32_t format) +{ + struct ess_chinfo *ch = data; + + ch->fmt = format; + return 0; +} + +static int +esschan_setspeed(void *data, u_int32_t speed) +{ + struct ess_chinfo *ch = data; + struct ess_info *sc = ch->parent; + + ch->spd = speed; + if (sc->newspeed) + ess_calcspeed9(&ch->spd); + else + ess_calcspeed8(&ch->spd); + return ch->spd; +} + +static int +esschan_setblocksize(void *data, u_int32_t blocksize) +{ + return blocksize; +} + +static int +esschan_trigger(void *data, int go) +{ + struct ess_chinfo *ch = data; + + if (go == PCMTRIG_EMLDMAWR) + return 0; + + switch (go) { + case PCMTRIG_START: + buf_isadma(ch->buffer, go); + ess_start(ch); + break; + + case PCMTRIG_STOP: + case PCMTRIG_ABORT: + default: + ess_stop(ch); + break; + } + return 0; +} + +static int +esschan_getptr(void *data) +{ + struct ess_chinfo *ch = data; + + return buf_isadmaptr(ch->buffer); +} + +static pcmchan_caps * +esschan_getcaps(void *data) +{ + struct ess_chinfo *ch = data; + + return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps; +} + +/************************************************************/ + +static int +essmix_init(snd_mixer *m) +{ + struct ess_info *sc = mix_getdevinfo(m); + + mix_setrecdevs(m, SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE | + SOUND_MASK_IMIX); + + mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | + SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME | + SOUND_MASK_LINE1); + + ess_setmixer(sc, 0, 0); /* reset */ + + return 0; +} + +static int +essmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right) +{ + struct ess_info *sc = mix_getdevinfo(m); + int preg = 0, rreg = 0, l, r; + + l = (left * 15) / 100; + r = (right * 15) / 100; + switch (dev) { + case SOUND_MIXER_SYNTH: + preg = 0x36; + rreg = 0x6b; + break; + + case SOUND_MIXER_PCM: + preg = 0x14; + rreg = 0x7c; + break; + + case SOUND_MIXER_LINE: + preg = 0x3e; + rreg = 0x6e; + break; + + case SOUND_MIXER_MIC: + preg = 0x1a; + rreg = 0x68; + break; + + case SOUND_MIXER_LINE1: + preg = 0x3a; + rreg = 0x6c; + break; + + case SOUND_MIXER_CD: + preg = 0x38; + rreg = 0x6a; + break; + + case SOUND_MIXER_VOLUME: + l = left? (left * 63) / 100 : 64; + r = right? (right * 63) / 100 : 64; + ess_setmixer(sc, 0x60, l); + ess_setmixer(sc, 0x62, r); + left = (l == 64)? 0 : (l * 100) / 63; + right = (r == 64)? 0 : (r * 100) / 63; + return left | (right << 8); + } + + if (preg) + ess_setmixer(sc, preg, (l << 4) | r); + if (rreg) + ess_setmixer(sc, rreg, (l << 4) | r); + + left = (l * 100) / 15; + right = (r * 100) / 15; + + return left | (right << 8); +} + +static int +essmix_setrecsrc(snd_mixer *m, u_int32_t src) +{ + struct ess_info *sc = mix_getdevinfo(m); + u_char recdev; + + switch (src) { + case SOUND_MASK_CD: + recdev = 0x02; + break; + + case SOUND_MASK_LINE: + recdev = 0x06; + break; + + case SOUND_MASK_IMIX: + recdev = 0x05; + break; + + case SOUND_MASK_MIC: + default: + recdev = 0x00; + src = SOUND_MASK_MIC; + break; + } + + ess_setmixer(sc, 0x1c, recdev); + + return src; +} + +static int +ess_probe(device_t dev) +{ + uintptr_t func, ver, r, f; + + /* The parent device has already been probed. */ + r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func); + if (func != SCF_PCM) + return (ENXIO); + + r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); + f = (ver & 0xffff0000) >> 16; + if (!(f & BD_F_ESS)) + return (ENXIO); + + device_set_desc(dev, "ESS 18xx DSP"); + + return 0; +} + +static int +ess_attach(device_t dev) +{ + struct ess_info *sc; + + sc = (struct ess_info *)malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); + if (!sc) + return ENXIO; + bzero(sc, sizeof *sc); + + return ess_doattach(dev, sc); +} + +static device_method_t ess_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ess_probe), + DEVMETHOD(device_attach, ess_attach), + + { 0, 0 } +}; + +static driver_t ess_driver = { + "pcm", + ess_methods, + sizeof(snddev_info), +}; + +DRIVER_MODULE(ess, sbc, ess_driver, pcm_devclass, 0, 0); + +static devclass_t esscontrol_devclass; + +static struct isa_pnp_id essc_ids[] = { + {0x06007316, "ESS Control"}, + {0} +}; + +static int +esscontrol_probe(device_t dev) +{ + return ISA_PNP_PROBE(device_get_parent(dev), dev, essc_ids); +} + +static int +esscontrol_attach(device_t dev) +{ +#ifdef notyet + struct resource *io; + int rid, i, x; + + rid = 0; + io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); + x = 0; + for (i = 0; i < 0x100; i++) { + port_wr(io, 0, i); + x = port_rd(io, 1); + if ((i & 0x0f) == 0) + printf("%3.3x: ", i); + printf("%2.2x ", x); + if ((i & 0x0f) == 0x0f) + printf("\n"); + } + bus_release_resource(dev, SYS_RES_IOPORT, 0, io); + io = NULL; +#endif + + return 0; +} + +static device_method_t esscontrol_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, esscontrol_probe), + DEVMETHOD(device_attach, esscontrol_attach), + + { 0, 0 } +}; + +static driver_t esscontrol_driver = { + "esscontrol", + esscontrol_methods, + sizeof(snddev_info), +}; + +DRIVER_MODULE(esscontrol, isa, esscontrol_driver, esscontrol_devclass, 0, 0); + + + + diff --git a/sys/dev/sound/isa/sb.c b/sys/dev/sound/isa/sb.c index 5bfce3452000..6b1aa4b46705 100644 --- a/sys/dev/sound/isa/sb.c +++ b/sys/dev/sound/isa/sb.c @@ -39,7 +39,6 @@ #include #include -#define ESS_BUFFSIZE (65536 - 256) #define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16) /* channel interface */ @@ -52,16 +51,6 @@ static int sbchan_trigger(void *data, int go); static int sbchan_getptr(void *data); static pcmchan_caps *sbchan_getcaps(void *data); -/* channel interface for ESS */ -static void *esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -static int esschan_setdir(void *data, int dir); -static int esschan_setformat(void *data, u_int32_t format); -static int esschan_setspeed(void *data, u_int32_t speed); -static int esschan_setblocksize(void *data, u_int32_t blocksize); -static int esschan_trigger(void *data, int go); -static int esschan_getptr(void *data); -static pcmchan_caps *esschan_getcaps(void *data); - static pcmchan_caps sb_playcaps = { 4000, 22050, AFMT_U8, @@ -104,18 +93,6 @@ static pcmchan_caps sb16x_caps = { AFMT_STEREO | AFMT_S16_LE }; -static pcmchan_caps ess_playcaps = { - 5000, 49000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcmchan_caps ess_reccaps = { - 5000, 49000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - static pcm_channel sb_chantemplate = { sbchan_init, sbchan_setdir, @@ -127,17 +104,6 @@ static pcm_channel sb_chantemplate = { sbchan_getcaps, }; -static pcm_channel ess_chantemplate = { - esschan_init, - esschan_setdir, - esschan_setformat, - esschan_setspeed, - esschan_setblocksize, - esschan_trigger, - esschan_getptr, - esschan_getcaps, -}; - struct sb_info; struct sb_chinfo { @@ -146,7 +112,6 @@ struct sb_chinfo { snd_dbuf *buffer; int dir; u_int32_t fmt, spd; - int ess_dma_started; }; struct sb_info { @@ -177,15 +142,6 @@ static int sb_speed(struct sb_chinfo *ch); static int sb_start(struct sb_chinfo *ch); static int sb_stop(struct sb_chinfo *ch); -static int ess_write(struct sb_info *sb, u_char reg, int val); -static int ess_read(struct sb_info *sb, u_char reg); -static void ess_intr(void *arg); -static int ess_format(struct sb_chinfo *ch, u_int32_t format); -static int ess_speed(struct sb_chinfo *ch, int speed); -static int ess_start(struct sb_chinfo *ch); -static int ess_stop(struct sb_chinfo *ch); -static int ess_abort(struct sb_chinfo *ch); - static int sbmix_init(snd_mixer *m); static int sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right); static int sbmix_setrecsrc(snd_mixer *m, u_int32_t src); @@ -340,18 +296,6 @@ sb_get_byte(struct sb_info *sb) return 0xffff; } -static int -ess_write(struct sb_info *sb, u_char reg, int val) -{ - return sb_cmd1(sb, reg, val); -} - -static int -ess_read(struct sb_info *sb, u_char reg) -{ - return (sb_cmd(sb, 0xc0) && sb_cmd(sb, reg))? sb_get_byte(sb) : 0xffff; -} - static int sb_reset_dsp(struct sb_info *sb) { @@ -412,13 +356,13 @@ sb_alloc_resources(struct sb_info *sb, device_t dev) &rid, 0, ~0, 1, RF_ACTIVE); rid = 1; - if (!sb->drq2 && !(sb->bd_flags & BD_F_ESS)) + if (!sb->drq2) sb->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, &rid, 0, ~0, 1, RF_ACTIVE); if (sb->io_base && sb->drq1 && sb->irq) { - int bs = (sb->bd_flags & BD_F_ESS)? ESS_BUFFSIZE : DSP_BUFFSIZE; + int bs = DSP_BUFFSIZE; isa_dma_acquire(rman_get_start(sb->drq1)); isa_dmainit(rman_get_start(sb->drq1), bs); @@ -448,9 +392,7 @@ sb16_swap(void *v, int dir) else if (dir == PCMDIR_REC && rc < 4) swp = 1; - if (sb->bd_flags & BD_F_SB16X) - swp = !swp; - if (swp) { + if (swp) { int t; t = sb->pch.buffer->chan; @@ -468,7 +410,7 @@ sb_doattach(device_t dev, struct sb_info *sb) snddev_info *d = device_get_softc(dev); void *ih; char status[SND_STATUSLEN]; - int bs = (sb->bd_flags & BD_F_ESS)? ESS_BUFFSIZE : DSP_BUFFSIZE; + int bs = DSP_BUFFSIZE; if (sb_alloc_resources(sb, dev)) goto no; @@ -476,10 +418,7 @@ sb_doattach(device_t dev, struct sb_info *sb) goto no; mixer_init(d, &sb_mixer, sb); - if (sb->bd_flags & BD_F_ESS) - bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, ess_intr, sb, &ih); - else - bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih); + bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih); if ((sb->bd_flags & BD_F_SB16) && !(sb->bd_flags & BD_F_SB16X)) pcm_setswap(dev, sb16_swap); if (!sb->drq2) @@ -505,13 +444,8 @@ sb_doattach(device_t dev, struct sb_info *sb) if (pcm_register(dev, sb, 1, 1)) goto no; - if (sb->bd_flags & BD_F_ESS) { - pcm_addchan(dev, PCMDIR_REC, &ess_chantemplate, sb); - pcm_addchan(dev, PCMDIR_PLAY, &ess_chantemplate, sb); - } else { - pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb); - pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb); - } + pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb); + pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb); pcm_setstatus(dev, status); return 0; @@ -566,29 +500,6 @@ sb_intr(void *arg) sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */ } -static void -ess_intr(void *arg) -{ - struct sb_info *sb = (struct sb_info *)arg; - - sb_rd(sb, DSP_DATA_AVAIL); /* int ack */ -#ifdef notyet - /* - * XXX - * for full-duplex mode: - * should read port 0x6 to identify where interrupt came from. - */ -#endif - /* - * We are transferring data in DSP normal mode, - * so clear the dl to indicate the DMA is stopped. - */ - if (sb->pch.buffer->dl > 0) - chn_intr(sb->pch.channel); - if (sb->rch.buffer->dl > 0) - chn_intr(sb->rch.channel); -} - static int sb_speed(struct sb_chinfo *ch) { @@ -813,219 +724,6 @@ sbchan_getcaps(void *data) return (ch->buffer->chan >= 4)? &sb16_hcaps : &sb16_lcaps; } -/* utility functions for ESS */ -static int -ess_format(struct sb_chinfo *ch, u_int32_t format) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - int b16 = (format & AFMT_S16_LE)? 1 : 0; - int stereo = (format & AFMT_STEREO)? 1 : 0; - u_char c; - - ch->fmt = format; - sb_reset_dsp(sb); - /* auto-init DMA mode */ - ess_write(sb, 0xb8, play ? 0x04 : 0x0e); - /* mono/stereo */ - c = (ess_read(sb, 0xa8) & ~0x03) | 1; - if (!stereo) - c++; - ess_write(sb, 0xa8, c); - /* demand mode, 4 bytes/xfer */ - ess_write(sb, 0xb9, 2); - /* setup dac/adc */ - if (play) - ess_write(sb, 0xb6, b16? 0x00 : 0x80); - ess_write(sb, 0xb7, 0x51 | (b16? 0x20 : 0x00)); - ess_write(sb, 0xb7, 0x98 + (b16? 0x24 : 0x00) + (stereo? 0x00 : 0x38)); - /* irq/drq control */ - ess_write(sb, 0xb1, (ess_read(sb, 0xb1) & 0x0f) | 0x50); - ess_write(sb, 0xb2, (ess_read(sb, 0xb2) & 0x0f) | 0x50); - return 0; -} - -static int -ess_speed(struct sb_chinfo *ch, int speed) -{ - struct sb_info *sb = ch->parent; - int t; - - RANGE (speed, 5000, 49000); - if (speed > 22000) { - t = (795500 + speed / 2) / speed; - speed = (795500 + t / 2) / t; - t = (256 - t ) | 0x80; - } else { - t = (397700 + speed / 2) / speed; - speed = (397700 + t / 2) / t; - t = 128 - t; - } - ess_write(sb, 0xa1, t); /* set time constant */ -#if 0 - d->play_speed = d->rec_speed = speed; - speed = (speed * 9 ) / 20; -#endif - t = 256 - 7160000 / ((speed * 9 / 20) * 82); - ess_write(sb, 0xa2, t); - return speed; -} - -static int -ess_start(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - short c = - ch->buffer->dl; - u_char c1; - - /* - * clear bit 0 of register B8h - */ -#if 1 - c1 = play ? 0x04 : 0x0e; - ess_write(sb, 0xb8, c1++); -#else - c1 = ess_read(sb, 0xb8) & 0xfe; - ess_write(sb, 0xb8, c1++); -#endif - /* - * update ESS Transfer Count Register - */ - ess_write(sb, 0xa4, (u_char)((u_short)c & 0xff)); - ess_write(sb, 0xa5, (u_char)(((u_short)c >> 8) & 0xff)); - /* - * set bit 0 of register B8h - */ - ess_write(sb, 0xb8, c1); - if (play) - sb_cmd(sb, DSP_CMD_SPKON); - return 0; -} - -static int -ess_stop(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - /* - * no need to send a stop command if the DMA has already stopped. - */ - if (ch->buffer->dl > 0) { - sb_cmd(sb, DSP_CMD_DMAPAUSE_8); /* pause dma. */ - } - return 0; -} - -static int -ess_abort(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - - if (play) - sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */ - sb_reset_dsp(sb); - ess_format(ch, ch->fmt); - ess_speed(ch, ch->channel->speed); - return 0; -} - -/* channel interface for ESS18xx */ -static void * -esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) -{ - struct sb_info *sb = devinfo; - struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch; - - ch->parent = sb; - ch->channel = c; - ch->buffer = b; - ch->buffer->bufsize = ESS_BUFFSIZE; - if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1) - return NULL; - ch->buffer->chan = rman_get_start(sb->drq1); - return ch; -} - -static int -esschan_setdir(void *data, int dir) -{ - struct sb_chinfo *ch = data; - - ch->dir = dir; - return 0; -} - -static int -esschan_setformat(void *data, u_int32_t format) -{ - struct sb_chinfo *ch = data; - - ess_format(ch, format); - return 0; -} - -static int -esschan_setspeed(void *data, u_int32_t speed) -{ - struct sb_chinfo *ch = data; - - return ess_speed(ch, speed); -} - -static int -esschan_setblocksize(void *data, u_int32_t blocksize) -{ - return blocksize; -} - -static int -esschan_trigger(void *data, int go) -{ - struct sb_chinfo *ch = data; - - if (go == PCMTRIG_EMLDMAWR) - return 0; - switch (go) { - case PCMTRIG_START: - if (!ch->ess_dma_started) - buf_isadma(ch->buffer, go); - ch->ess_dma_started = 1; - ess_start(ch); - break; - case PCMTRIG_STOP: - if (ch->buffer->dl >= 0) { - buf_isadma(ch->buffer, go); - ch->ess_dma_started = 0; - ess_stop(ch); - } - break; - case PCMTRIG_ABORT: - default: - ch->ess_dma_started = 0; - ess_abort(ch); - buf_isadma(ch->buffer, go); - break; - } - return 0; -} - -static int -esschan_getptr(void *data) -{ - struct sb_chinfo *ch = data; - - return buf_isadmaptr(ch->buffer); -} - -static pcmchan_caps * -esschan_getcaps(void *data) -{ - struct sb_chinfo *ch = data; - - return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps; -} - /************************************************************/ static int @@ -1038,8 +736,7 @@ sbmix_init(snd_mixer *m) mix_setdevs(m, SBPRO_MIXER_DEVICES); mix_setrecdevs(m, SBPRO_RECORDING_DEVICES); sb_setmixer(sb, 0, 1); /* reset mixer */ - if (!(sb->bd_flags & BD_F_ESS)) - sb_setmixer(sb, MIC_VOL, 0x6); /* mic volume max */ + sb_setmixer(sb, MIC_VOL, 0x6); /* mic volume max */ sb_setmixer(sb, RECORD_SRC, 0x0); /* mic source */ sb_setmixer(sb, FM_VOL, 0x0); /* no midi */ break; @@ -1064,10 +761,7 @@ sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right) switch (sb->bd_flags & BD_F_MIX_MASK) { case BD_F_MIX_CT1345: - if (sb->bd_flags & BD_F_ESS) - iomap = &ess_mix; - else - iomap = &sbpro_mix; + iomap = &sbpro_mix; break; case BD_F_MIX_CT1745: @@ -1158,8 +852,10 @@ sbsbc_probe(device_t dev) r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); f = (ver & 0xffff0000) >> 16; ver &= 0x0000ffff; - snprintf(buf, sizeof buf, "SB DSP %d.%02d%s%s", (int) ver >> 8, (int) ver & 0xff, - (f & BD_F_ESS)? " (ESS mode)" : "", + if (f & BD_F_ESS) + return (ENXIO); + + snprintf(buf, sizeof buf, "SB DSP %d.%02d%s", (int) ver >> 8, (int) ver & 0xff, (f & BD_F_SB16X)? " (ViBRA16X)" : ""); device_set_desc_copy(dev, buf); diff --git a/sys/dev/sound/isa/sb16.c b/sys/dev/sound/isa/sb16.c index 5bfce3452000..6b1aa4b46705 100644 --- a/sys/dev/sound/isa/sb16.c +++ b/sys/dev/sound/isa/sb16.c @@ -39,7 +39,6 @@ #include #include -#define ESS_BUFFSIZE (65536 - 256) #define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16) /* channel interface */ @@ -52,16 +51,6 @@ static int sbchan_trigger(void *data, int go); static int sbchan_getptr(void *data); static pcmchan_caps *sbchan_getcaps(void *data); -/* channel interface for ESS */ -static void *esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -static int esschan_setdir(void *data, int dir); -static int esschan_setformat(void *data, u_int32_t format); -static int esschan_setspeed(void *data, u_int32_t speed); -static int esschan_setblocksize(void *data, u_int32_t blocksize); -static int esschan_trigger(void *data, int go); -static int esschan_getptr(void *data); -static pcmchan_caps *esschan_getcaps(void *data); - static pcmchan_caps sb_playcaps = { 4000, 22050, AFMT_U8, @@ -104,18 +93,6 @@ static pcmchan_caps sb16x_caps = { AFMT_STEREO | AFMT_S16_LE }; -static pcmchan_caps ess_playcaps = { - 5000, 49000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcmchan_caps ess_reccaps = { - 5000, 49000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - static pcm_channel sb_chantemplate = { sbchan_init, sbchan_setdir, @@ -127,17 +104,6 @@ static pcm_channel sb_chantemplate = { sbchan_getcaps, }; -static pcm_channel ess_chantemplate = { - esschan_init, - esschan_setdir, - esschan_setformat, - esschan_setspeed, - esschan_setblocksize, - esschan_trigger, - esschan_getptr, - esschan_getcaps, -}; - struct sb_info; struct sb_chinfo { @@ -146,7 +112,6 @@ struct sb_chinfo { snd_dbuf *buffer; int dir; u_int32_t fmt, spd; - int ess_dma_started; }; struct sb_info { @@ -177,15 +142,6 @@ static int sb_speed(struct sb_chinfo *ch); static int sb_start(struct sb_chinfo *ch); static int sb_stop(struct sb_chinfo *ch); -static int ess_write(struct sb_info *sb, u_char reg, int val); -static int ess_read(struct sb_info *sb, u_char reg); -static void ess_intr(void *arg); -static int ess_format(struct sb_chinfo *ch, u_int32_t format); -static int ess_speed(struct sb_chinfo *ch, int speed); -static int ess_start(struct sb_chinfo *ch); -static int ess_stop(struct sb_chinfo *ch); -static int ess_abort(struct sb_chinfo *ch); - static int sbmix_init(snd_mixer *m); static int sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right); static int sbmix_setrecsrc(snd_mixer *m, u_int32_t src); @@ -340,18 +296,6 @@ sb_get_byte(struct sb_info *sb) return 0xffff; } -static int -ess_write(struct sb_info *sb, u_char reg, int val) -{ - return sb_cmd1(sb, reg, val); -} - -static int -ess_read(struct sb_info *sb, u_char reg) -{ - return (sb_cmd(sb, 0xc0) && sb_cmd(sb, reg))? sb_get_byte(sb) : 0xffff; -} - static int sb_reset_dsp(struct sb_info *sb) { @@ -412,13 +356,13 @@ sb_alloc_resources(struct sb_info *sb, device_t dev) &rid, 0, ~0, 1, RF_ACTIVE); rid = 1; - if (!sb->drq2 && !(sb->bd_flags & BD_F_ESS)) + if (!sb->drq2) sb->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, &rid, 0, ~0, 1, RF_ACTIVE); if (sb->io_base && sb->drq1 && sb->irq) { - int bs = (sb->bd_flags & BD_F_ESS)? ESS_BUFFSIZE : DSP_BUFFSIZE; + int bs = DSP_BUFFSIZE; isa_dma_acquire(rman_get_start(sb->drq1)); isa_dmainit(rman_get_start(sb->drq1), bs); @@ -448,9 +392,7 @@ sb16_swap(void *v, int dir) else if (dir == PCMDIR_REC && rc < 4) swp = 1; - if (sb->bd_flags & BD_F_SB16X) - swp = !swp; - if (swp) { + if (swp) { int t; t = sb->pch.buffer->chan; @@ -468,7 +410,7 @@ sb_doattach(device_t dev, struct sb_info *sb) snddev_info *d = device_get_softc(dev); void *ih; char status[SND_STATUSLEN]; - int bs = (sb->bd_flags & BD_F_ESS)? ESS_BUFFSIZE : DSP_BUFFSIZE; + int bs = DSP_BUFFSIZE; if (sb_alloc_resources(sb, dev)) goto no; @@ -476,10 +418,7 @@ sb_doattach(device_t dev, struct sb_info *sb) goto no; mixer_init(d, &sb_mixer, sb); - if (sb->bd_flags & BD_F_ESS) - bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, ess_intr, sb, &ih); - else - bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih); + bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih); if ((sb->bd_flags & BD_F_SB16) && !(sb->bd_flags & BD_F_SB16X)) pcm_setswap(dev, sb16_swap); if (!sb->drq2) @@ -505,13 +444,8 @@ sb_doattach(device_t dev, struct sb_info *sb) if (pcm_register(dev, sb, 1, 1)) goto no; - if (sb->bd_flags & BD_F_ESS) { - pcm_addchan(dev, PCMDIR_REC, &ess_chantemplate, sb); - pcm_addchan(dev, PCMDIR_PLAY, &ess_chantemplate, sb); - } else { - pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb); - pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb); - } + pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb); + pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb); pcm_setstatus(dev, status); return 0; @@ -566,29 +500,6 @@ sb_intr(void *arg) sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */ } -static void -ess_intr(void *arg) -{ - struct sb_info *sb = (struct sb_info *)arg; - - sb_rd(sb, DSP_DATA_AVAIL); /* int ack */ -#ifdef notyet - /* - * XXX - * for full-duplex mode: - * should read port 0x6 to identify where interrupt came from. - */ -#endif - /* - * We are transferring data in DSP normal mode, - * so clear the dl to indicate the DMA is stopped. - */ - if (sb->pch.buffer->dl > 0) - chn_intr(sb->pch.channel); - if (sb->rch.buffer->dl > 0) - chn_intr(sb->rch.channel); -} - static int sb_speed(struct sb_chinfo *ch) { @@ -813,219 +724,6 @@ sbchan_getcaps(void *data) return (ch->buffer->chan >= 4)? &sb16_hcaps : &sb16_lcaps; } -/* utility functions for ESS */ -static int -ess_format(struct sb_chinfo *ch, u_int32_t format) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - int b16 = (format & AFMT_S16_LE)? 1 : 0; - int stereo = (format & AFMT_STEREO)? 1 : 0; - u_char c; - - ch->fmt = format; - sb_reset_dsp(sb); - /* auto-init DMA mode */ - ess_write(sb, 0xb8, play ? 0x04 : 0x0e); - /* mono/stereo */ - c = (ess_read(sb, 0xa8) & ~0x03) | 1; - if (!stereo) - c++; - ess_write(sb, 0xa8, c); - /* demand mode, 4 bytes/xfer */ - ess_write(sb, 0xb9, 2); - /* setup dac/adc */ - if (play) - ess_write(sb, 0xb6, b16? 0x00 : 0x80); - ess_write(sb, 0xb7, 0x51 | (b16? 0x20 : 0x00)); - ess_write(sb, 0xb7, 0x98 + (b16? 0x24 : 0x00) + (stereo? 0x00 : 0x38)); - /* irq/drq control */ - ess_write(sb, 0xb1, (ess_read(sb, 0xb1) & 0x0f) | 0x50); - ess_write(sb, 0xb2, (ess_read(sb, 0xb2) & 0x0f) | 0x50); - return 0; -} - -static int -ess_speed(struct sb_chinfo *ch, int speed) -{ - struct sb_info *sb = ch->parent; - int t; - - RANGE (speed, 5000, 49000); - if (speed > 22000) { - t = (795500 + speed / 2) / speed; - speed = (795500 + t / 2) / t; - t = (256 - t ) | 0x80; - } else { - t = (397700 + speed / 2) / speed; - speed = (397700 + t / 2) / t; - t = 128 - t; - } - ess_write(sb, 0xa1, t); /* set time constant */ -#if 0 - d->play_speed = d->rec_speed = speed; - speed = (speed * 9 ) / 20; -#endif - t = 256 - 7160000 / ((speed * 9 / 20) * 82); - ess_write(sb, 0xa2, t); - return speed; -} - -static int -ess_start(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - short c = - ch->buffer->dl; - u_char c1; - - /* - * clear bit 0 of register B8h - */ -#if 1 - c1 = play ? 0x04 : 0x0e; - ess_write(sb, 0xb8, c1++); -#else - c1 = ess_read(sb, 0xb8) & 0xfe; - ess_write(sb, 0xb8, c1++); -#endif - /* - * update ESS Transfer Count Register - */ - ess_write(sb, 0xa4, (u_char)((u_short)c & 0xff)); - ess_write(sb, 0xa5, (u_char)(((u_short)c >> 8) & 0xff)); - /* - * set bit 0 of register B8h - */ - ess_write(sb, 0xb8, c1); - if (play) - sb_cmd(sb, DSP_CMD_SPKON); - return 0; -} - -static int -ess_stop(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - /* - * no need to send a stop command if the DMA has already stopped. - */ - if (ch->buffer->dl > 0) { - sb_cmd(sb, DSP_CMD_DMAPAUSE_8); /* pause dma. */ - } - return 0; -} - -static int -ess_abort(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - - if (play) - sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */ - sb_reset_dsp(sb); - ess_format(ch, ch->fmt); - ess_speed(ch, ch->channel->speed); - return 0; -} - -/* channel interface for ESS18xx */ -static void * -esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) -{ - struct sb_info *sb = devinfo; - struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch; - - ch->parent = sb; - ch->channel = c; - ch->buffer = b; - ch->buffer->bufsize = ESS_BUFFSIZE; - if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1) - return NULL; - ch->buffer->chan = rman_get_start(sb->drq1); - return ch; -} - -static int -esschan_setdir(void *data, int dir) -{ - struct sb_chinfo *ch = data; - - ch->dir = dir; - return 0; -} - -static int -esschan_setformat(void *data, u_int32_t format) -{ - struct sb_chinfo *ch = data; - - ess_format(ch, format); - return 0; -} - -static int -esschan_setspeed(void *data, u_int32_t speed) -{ - struct sb_chinfo *ch = data; - - return ess_speed(ch, speed); -} - -static int -esschan_setblocksize(void *data, u_int32_t blocksize) -{ - return blocksize; -} - -static int -esschan_trigger(void *data, int go) -{ - struct sb_chinfo *ch = data; - - if (go == PCMTRIG_EMLDMAWR) - return 0; - switch (go) { - case PCMTRIG_START: - if (!ch->ess_dma_started) - buf_isadma(ch->buffer, go); - ch->ess_dma_started = 1; - ess_start(ch); - break; - case PCMTRIG_STOP: - if (ch->buffer->dl >= 0) { - buf_isadma(ch->buffer, go); - ch->ess_dma_started = 0; - ess_stop(ch); - } - break; - case PCMTRIG_ABORT: - default: - ch->ess_dma_started = 0; - ess_abort(ch); - buf_isadma(ch->buffer, go); - break; - } - return 0; -} - -static int -esschan_getptr(void *data) -{ - struct sb_chinfo *ch = data; - - return buf_isadmaptr(ch->buffer); -} - -static pcmchan_caps * -esschan_getcaps(void *data) -{ - struct sb_chinfo *ch = data; - - return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps; -} - /************************************************************/ static int @@ -1038,8 +736,7 @@ sbmix_init(snd_mixer *m) mix_setdevs(m, SBPRO_MIXER_DEVICES); mix_setrecdevs(m, SBPRO_RECORDING_DEVICES); sb_setmixer(sb, 0, 1); /* reset mixer */ - if (!(sb->bd_flags & BD_F_ESS)) - sb_setmixer(sb, MIC_VOL, 0x6); /* mic volume max */ + sb_setmixer(sb, MIC_VOL, 0x6); /* mic volume max */ sb_setmixer(sb, RECORD_SRC, 0x0); /* mic source */ sb_setmixer(sb, FM_VOL, 0x0); /* no midi */ break; @@ -1064,10 +761,7 @@ sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right) switch (sb->bd_flags & BD_F_MIX_MASK) { case BD_F_MIX_CT1345: - if (sb->bd_flags & BD_F_ESS) - iomap = &ess_mix; - else - iomap = &sbpro_mix; + iomap = &sbpro_mix; break; case BD_F_MIX_CT1745: @@ -1158,8 +852,10 @@ sbsbc_probe(device_t dev) r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); f = (ver & 0xffff0000) >> 16; ver &= 0x0000ffff; - snprintf(buf, sizeof buf, "SB DSP %d.%02d%s%s", (int) ver >> 8, (int) ver & 0xff, - (f & BD_F_ESS)? " (ESS mode)" : "", + if (f & BD_F_ESS) + return (ENXIO); + + snprintf(buf, sizeof buf, "SB DSP %d.%02d%s", (int) ver >> 8, (int) ver & 0xff, (f & BD_F_SB16X)? " (ViBRA16X)" : ""); device_set_desc_copy(dev, buf); diff --git a/sys/dev/sound/isa/sb8.c b/sys/dev/sound/isa/sb8.c index 5bfce3452000..6b1aa4b46705 100644 --- a/sys/dev/sound/isa/sb8.c +++ b/sys/dev/sound/isa/sb8.c @@ -39,7 +39,6 @@ #include #include -#define ESS_BUFFSIZE (65536 - 256) #define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16) /* channel interface */ @@ -52,16 +51,6 @@ static int sbchan_trigger(void *data, int go); static int sbchan_getptr(void *data); static pcmchan_caps *sbchan_getcaps(void *data); -/* channel interface for ESS */ -static void *esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -static int esschan_setdir(void *data, int dir); -static int esschan_setformat(void *data, u_int32_t format); -static int esschan_setspeed(void *data, u_int32_t speed); -static int esschan_setblocksize(void *data, u_int32_t blocksize); -static int esschan_trigger(void *data, int go); -static int esschan_getptr(void *data); -static pcmchan_caps *esschan_getcaps(void *data); - static pcmchan_caps sb_playcaps = { 4000, 22050, AFMT_U8, @@ -104,18 +93,6 @@ static pcmchan_caps sb16x_caps = { AFMT_STEREO | AFMT_S16_LE }; -static pcmchan_caps ess_playcaps = { - 5000, 49000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcmchan_caps ess_reccaps = { - 5000, 49000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - static pcm_channel sb_chantemplate = { sbchan_init, sbchan_setdir, @@ -127,17 +104,6 @@ static pcm_channel sb_chantemplate = { sbchan_getcaps, }; -static pcm_channel ess_chantemplate = { - esschan_init, - esschan_setdir, - esschan_setformat, - esschan_setspeed, - esschan_setblocksize, - esschan_trigger, - esschan_getptr, - esschan_getcaps, -}; - struct sb_info; struct sb_chinfo { @@ -146,7 +112,6 @@ struct sb_chinfo { snd_dbuf *buffer; int dir; u_int32_t fmt, spd; - int ess_dma_started; }; struct sb_info { @@ -177,15 +142,6 @@ static int sb_speed(struct sb_chinfo *ch); static int sb_start(struct sb_chinfo *ch); static int sb_stop(struct sb_chinfo *ch); -static int ess_write(struct sb_info *sb, u_char reg, int val); -static int ess_read(struct sb_info *sb, u_char reg); -static void ess_intr(void *arg); -static int ess_format(struct sb_chinfo *ch, u_int32_t format); -static int ess_speed(struct sb_chinfo *ch, int speed); -static int ess_start(struct sb_chinfo *ch); -static int ess_stop(struct sb_chinfo *ch); -static int ess_abort(struct sb_chinfo *ch); - static int sbmix_init(snd_mixer *m); static int sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right); static int sbmix_setrecsrc(snd_mixer *m, u_int32_t src); @@ -340,18 +296,6 @@ sb_get_byte(struct sb_info *sb) return 0xffff; } -static int -ess_write(struct sb_info *sb, u_char reg, int val) -{ - return sb_cmd1(sb, reg, val); -} - -static int -ess_read(struct sb_info *sb, u_char reg) -{ - return (sb_cmd(sb, 0xc0) && sb_cmd(sb, reg))? sb_get_byte(sb) : 0xffff; -} - static int sb_reset_dsp(struct sb_info *sb) { @@ -412,13 +356,13 @@ sb_alloc_resources(struct sb_info *sb, device_t dev) &rid, 0, ~0, 1, RF_ACTIVE); rid = 1; - if (!sb->drq2 && !(sb->bd_flags & BD_F_ESS)) + if (!sb->drq2) sb->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, &rid, 0, ~0, 1, RF_ACTIVE); if (sb->io_base && sb->drq1 && sb->irq) { - int bs = (sb->bd_flags & BD_F_ESS)? ESS_BUFFSIZE : DSP_BUFFSIZE; + int bs = DSP_BUFFSIZE; isa_dma_acquire(rman_get_start(sb->drq1)); isa_dmainit(rman_get_start(sb->drq1), bs); @@ -448,9 +392,7 @@ sb16_swap(void *v, int dir) else if (dir == PCMDIR_REC && rc < 4) swp = 1; - if (sb->bd_flags & BD_F_SB16X) - swp = !swp; - if (swp) { + if (swp) { int t; t = sb->pch.buffer->chan; @@ -468,7 +410,7 @@ sb_doattach(device_t dev, struct sb_info *sb) snddev_info *d = device_get_softc(dev); void *ih; char status[SND_STATUSLEN]; - int bs = (sb->bd_flags & BD_F_ESS)? ESS_BUFFSIZE : DSP_BUFFSIZE; + int bs = DSP_BUFFSIZE; if (sb_alloc_resources(sb, dev)) goto no; @@ -476,10 +418,7 @@ sb_doattach(device_t dev, struct sb_info *sb) goto no; mixer_init(d, &sb_mixer, sb); - if (sb->bd_flags & BD_F_ESS) - bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, ess_intr, sb, &ih); - else - bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih); + bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih); if ((sb->bd_flags & BD_F_SB16) && !(sb->bd_flags & BD_F_SB16X)) pcm_setswap(dev, sb16_swap); if (!sb->drq2) @@ -505,13 +444,8 @@ sb_doattach(device_t dev, struct sb_info *sb) if (pcm_register(dev, sb, 1, 1)) goto no; - if (sb->bd_flags & BD_F_ESS) { - pcm_addchan(dev, PCMDIR_REC, &ess_chantemplate, sb); - pcm_addchan(dev, PCMDIR_PLAY, &ess_chantemplate, sb); - } else { - pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb); - pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb); - } + pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb); + pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb); pcm_setstatus(dev, status); return 0; @@ -566,29 +500,6 @@ sb_intr(void *arg) sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */ } -static void -ess_intr(void *arg) -{ - struct sb_info *sb = (struct sb_info *)arg; - - sb_rd(sb, DSP_DATA_AVAIL); /* int ack */ -#ifdef notyet - /* - * XXX - * for full-duplex mode: - * should read port 0x6 to identify where interrupt came from. - */ -#endif - /* - * We are transferring data in DSP normal mode, - * so clear the dl to indicate the DMA is stopped. - */ - if (sb->pch.buffer->dl > 0) - chn_intr(sb->pch.channel); - if (sb->rch.buffer->dl > 0) - chn_intr(sb->rch.channel); -} - static int sb_speed(struct sb_chinfo *ch) { @@ -813,219 +724,6 @@ sbchan_getcaps(void *data) return (ch->buffer->chan >= 4)? &sb16_hcaps : &sb16_lcaps; } -/* utility functions for ESS */ -static int -ess_format(struct sb_chinfo *ch, u_int32_t format) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - int b16 = (format & AFMT_S16_LE)? 1 : 0; - int stereo = (format & AFMT_STEREO)? 1 : 0; - u_char c; - - ch->fmt = format; - sb_reset_dsp(sb); - /* auto-init DMA mode */ - ess_write(sb, 0xb8, play ? 0x04 : 0x0e); - /* mono/stereo */ - c = (ess_read(sb, 0xa8) & ~0x03) | 1; - if (!stereo) - c++; - ess_write(sb, 0xa8, c); - /* demand mode, 4 bytes/xfer */ - ess_write(sb, 0xb9, 2); - /* setup dac/adc */ - if (play) - ess_write(sb, 0xb6, b16? 0x00 : 0x80); - ess_write(sb, 0xb7, 0x51 | (b16? 0x20 : 0x00)); - ess_write(sb, 0xb7, 0x98 + (b16? 0x24 : 0x00) + (stereo? 0x00 : 0x38)); - /* irq/drq control */ - ess_write(sb, 0xb1, (ess_read(sb, 0xb1) & 0x0f) | 0x50); - ess_write(sb, 0xb2, (ess_read(sb, 0xb2) & 0x0f) | 0x50); - return 0; -} - -static int -ess_speed(struct sb_chinfo *ch, int speed) -{ - struct sb_info *sb = ch->parent; - int t; - - RANGE (speed, 5000, 49000); - if (speed > 22000) { - t = (795500 + speed / 2) / speed; - speed = (795500 + t / 2) / t; - t = (256 - t ) | 0x80; - } else { - t = (397700 + speed / 2) / speed; - speed = (397700 + t / 2) / t; - t = 128 - t; - } - ess_write(sb, 0xa1, t); /* set time constant */ -#if 0 - d->play_speed = d->rec_speed = speed; - speed = (speed * 9 ) / 20; -#endif - t = 256 - 7160000 / ((speed * 9 / 20) * 82); - ess_write(sb, 0xa2, t); - return speed; -} - -static int -ess_start(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - short c = - ch->buffer->dl; - u_char c1; - - /* - * clear bit 0 of register B8h - */ -#if 1 - c1 = play ? 0x04 : 0x0e; - ess_write(sb, 0xb8, c1++); -#else - c1 = ess_read(sb, 0xb8) & 0xfe; - ess_write(sb, 0xb8, c1++); -#endif - /* - * update ESS Transfer Count Register - */ - ess_write(sb, 0xa4, (u_char)((u_short)c & 0xff)); - ess_write(sb, 0xa5, (u_char)(((u_short)c >> 8) & 0xff)); - /* - * set bit 0 of register B8h - */ - ess_write(sb, 0xb8, c1); - if (play) - sb_cmd(sb, DSP_CMD_SPKON); - return 0; -} - -static int -ess_stop(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - /* - * no need to send a stop command if the DMA has already stopped. - */ - if (ch->buffer->dl > 0) { - sb_cmd(sb, DSP_CMD_DMAPAUSE_8); /* pause dma. */ - } - return 0; -} - -static int -ess_abort(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - - if (play) - sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */ - sb_reset_dsp(sb); - ess_format(ch, ch->fmt); - ess_speed(ch, ch->channel->speed); - return 0; -} - -/* channel interface for ESS18xx */ -static void * -esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) -{ - struct sb_info *sb = devinfo; - struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch; - - ch->parent = sb; - ch->channel = c; - ch->buffer = b; - ch->buffer->bufsize = ESS_BUFFSIZE; - if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1) - return NULL; - ch->buffer->chan = rman_get_start(sb->drq1); - return ch; -} - -static int -esschan_setdir(void *data, int dir) -{ - struct sb_chinfo *ch = data; - - ch->dir = dir; - return 0; -} - -static int -esschan_setformat(void *data, u_int32_t format) -{ - struct sb_chinfo *ch = data; - - ess_format(ch, format); - return 0; -} - -static int -esschan_setspeed(void *data, u_int32_t speed) -{ - struct sb_chinfo *ch = data; - - return ess_speed(ch, speed); -} - -static int -esschan_setblocksize(void *data, u_int32_t blocksize) -{ - return blocksize; -} - -static int -esschan_trigger(void *data, int go) -{ - struct sb_chinfo *ch = data; - - if (go == PCMTRIG_EMLDMAWR) - return 0; - switch (go) { - case PCMTRIG_START: - if (!ch->ess_dma_started) - buf_isadma(ch->buffer, go); - ch->ess_dma_started = 1; - ess_start(ch); - break; - case PCMTRIG_STOP: - if (ch->buffer->dl >= 0) { - buf_isadma(ch->buffer, go); - ch->ess_dma_started = 0; - ess_stop(ch); - } - break; - case PCMTRIG_ABORT: - default: - ch->ess_dma_started = 0; - ess_abort(ch); - buf_isadma(ch->buffer, go); - break; - } - return 0; -} - -static int -esschan_getptr(void *data) -{ - struct sb_chinfo *ch = data; - - return buf_isadmaptr(ch->buffer); -} - -static pcmchan_caps * -esschan_getcaps(void *data) -{ - struct sb_chinfo *ch = data; - - return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps; -} - /************************************************************/ static int @@ -1038,8 +736,7 @@ sbmix_init(snd_mixer *m) mix_setdevs(m, SBPRO_MIXER_DEVICES); mix_setrecdevs(m, SBPRO_RECORDING_DEVICES); sb_setmixer(sb, 0, 1); /* reset mixer */ - if (!(sb->bd_flags & BD_F_ESS)) - sb_setmixer(sb, MIC_VOL, 0x6); /* mic volume max */ + sb_setmixer(sb, MIC_VOL, 0x6); /* mic volume max */ sb_setmixer(sb, RECORD_SRC, 0x0); /* mic source */ sb_setmixer(sb, FM_VOL, 0x0); /* no midi */ break; @@ -1064,10 +761,7 @@ sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right) switch (sb->bd_flags & BD_F_MIX_MASK) { case BD_F_MIX_CT1345: - if (sb->bd_flags & BD_F_ESS) - iomap = &ess_mix; - else - iomap = &sbpro_mix; + iomap = &sbpro_mix; break; case BD_F_MIX_CT1745: @@ -1158,8 +852,10 @@ sbsbc_probe(device_t dev) r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); f = (ver & 0xffff0000) >> 16; ver &= 0x0000ffff; - snprintf(buf, sizeof buf, "SB DSP %d.%02d%s%s", (int) ver >> 8, (int) ver & 0xff, - (f & BD_F_ESS)? " (ESS mode)" : "", + if (f & BD_F_ESS) + return (ENXIO); + + snprintf(buf, sizeof buf, "SB DSP %d.%02d%s", (int) ver >> 8, (int) ver & 0xff, (f & BD_F_SB16X)? " (ViBRA16X)" : ""); device_set_desc_copy(dev, buf);