git: aa83e9b189d6 - main - Retire snd_ess ISA sound card driver
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 21 Jun 2022 19:11:36 UTC
The branch main has been updated by emaste: URL: https://cgit.FreeBSD.org/src/commit/?id=aa83e9b189d67c8aa772fed4f9dd26cbcbff4e3f commit aa83e9b189d67c8aa772fed4f9dd26cbcbff4e3f Author: Ed Maste <emaste@FreeBSD.org> AuthorDate: 2022-06-21 18:50:04 +0000 Commit: Ed Maste <emaste@FreeBSD.org> CommitDate: 2022-06-21 18:50:04 +0000 Retire snd_ess ISA sound card driver snd_ess supported sound cards using the ESS 18xx chipset. ISA sound card drivers are deprecated as discussed on the current[1] and stable[2] mailing lists. Deprecation notices were added in e39ec8933be4 and MFCd to stable branches. Driver removals are being committed individually so that specific drivers can be restored if necessary (either in FreeBSD or by downstream projects). [1] https://lists.freebsd.org/archives/freebsd-current/2022-March/001680.html [2] https://lists.freebsd.org/archives/freebsd-stable/2022-March/000585.html Reviewed by: mav Relnotes: Yes Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D34671 --- ObsoleteFiles.inc | 1 + share/man/man4/Makefile | 1 - share/man/man4/pcm.4 | 3 - share/man/man4/snd_ess.4 | 75 --- sys/conf/files | 1 - sys/dev/sound/driver.c | 1 - sys/dev/sound/isa/ess.c | 1013 --------------------------------- sys/modules/sound/driver/Makefile | 2 +- sys/modules/sound/driver/ess/Makefile | 9 - 9 files changed, 2 insertions(+), 1104 deletions(-) diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 8a13d6d71182..f5fd1f3cd3ae 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -55,6 +55,7 @@ # 20220621: ISA sound card drivers removed OLD_FILES+=usr/share/man/man4/snd_ad1816.4 +OLD_FILES+=usr/share/man/man4/snd_ess.4 # 20220612: new clang import which bumps version from 14.0.4 to 14.0.5 OLD_FILES+=usr/lib/clang/14.0.4/include/cuda_wrappers/algorithm diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 80b6f5fb1cf0..cff2d4f99241 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -511,7 +511,6 @@ MAN= aac.4 \ snd_envy24.4 \ snd_envy24ht.4 \ snd_es137x.4 \ - snd_ess.4 \ snd_fm801.4 \ snd_gusc.4 \ snd_hda.4 \ diff --git a/share/man/man4/pcm.4 b/share/man/man4/pcm.4 index 8021e4d1a692..143282eaa32b 100644 --- a/share/man/man4/pcm.4 +++ b/share/man/man4/pcm.4 @@ -99,8 +99,6 @@ The following bridge device drivers are available: .It .Xr snd_es137x 4 (enabled by default on amd64, i386) .It -.Xr snd_ess 4 -.It .Xr snd_fm801 4 .It .Xr snd_gusc 4 @@ -708,7 +706,6 @@ A device node is not created properly. .Xr snd_envy24 4 , .Xr snd_envy24ht 4 , .Xr snd_es137x 4 , -.Xr snd_ess 4 , .Xr snd_fm801 4 , .Xr snd_gusc 4 , .Xr snd_hda 4 , diff --git a/share/man/man4/snd_ess.4 b/share/man/man4/snd_ess.4 deleted file mode 100644 index d4ac1520becf..000000000000 --- a/share/man/man4/snd_ess.4 +++ /dev/null @@ -1,75 +0,0 @@ -.\" Copyright (c) 2004 Atte Peltomaki -.\" 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$ -.\" -.Dd March 19, 2022 -.Dt SND_ESS 4 -.Os -.Sh NAME -.Nm snd_ess -.Nd "Ensoniq ESS ISA PnP/non-PnP bridge device driver" -.Sh DEPRECATION NOTICE -This driver is scheduled for removal prior to the release of -.Fx 14.0 . -.Sh SYNOPSIS -To compile this driver into the kernel, place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device sound" -.Cd "device snd_ess" -.Cd "device snd_sbc" -.Ed -.Pp -Alternatively, to load the driver as a module at boot time, place the -following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -snd_ess_load="YES" -.Ed -.Sh DESCRIPTION -The -.Nm -bridge driver allows the generic audio driver -.Xr sound 4 -to attach to the ESS ISA sound cards. -.Sh HARDWARE -The -.Nm -driver supports the following sound cards: -.Pp -.Bl -bullet -compact -.It -Ensoniq ESS ISA PnP/non-PnP -.El -.Sh SEE ALSO -.Xr sound 4 -.Sh HISTORY -The -.Nm -device driver first appeared in -.Fx 4.1 . -.Sh AUTHORS -.An Cameron Grant Aq Mt cg@FreeBSD.org -.An Luigi Rizzo Aq Mt luigi@FreeBSD.org diff --git a/sys/conf/files b/sys/conf/files index bf18a649da6f..c94f08ea962f 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -3089,7 +3089,6 @@ dev/smc/if_smc_fdt.c optional smc fdt dev/snp/snp.c optional snp dev/sound/clone.c optional sound dev/sound/unit.c optional sound -dev/sound/isa/ess.c optional snd_ess isa dev/sound/isa/gusc.c optional snd_gusc isa dev/sound/isa/mss.c optional snd_mss isa dev/sound/isa/sb16.c optional snd_sb16 isa diff --git a/sys/dev/sound/driver.c b/sys/dev/sound/driver.c index 575567f5a3c2..21fb6c01cd46 100644 --- a/sys/dev/sound/driver.c +++ b/sys/dev/sound/driver.c @@ -68,7 +68,6 @@ MODULE_DEPEND(snd_driver, snd_emu10kx, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_envy24, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_envy24ht, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_es137x, 1, 1, 1); -MODULE_DEPEND(snd_driver, snd_ess, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_fm801, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_gusc, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_hda, 1, 1, 1); diff --git a/sys/dev/sound/isa/ess.c b/sys/dev/sound/isa/ess.c deleted file mode 100644 index efe08143424d..000000000000 --- a/sys/dev/sound/isa/ess.c +++ /dev/null @@ -1,1013 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> - * Copyright (c) 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. - */ - -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include "opt_snd.h" -#endif - -#include <dev/sound/pcm/sound.h> - -#include <dev/sound/isa/sb.h> -#include <dev/sound/chip.h> - -#include <isa/isavar.h> - -#include "mixer_if.h" - -SND_DECLARE_FILE("$FreeBSD$"); - -#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 - -static u_int32_t ess_pfmt[] = { - SND_FORMAT(AFMT_U8, 1, 0), - SND_FORMAT(AFMT_U8, 2, 0), - SND_FORMAT(AFMT_S8, 1, 0), - SND_FORMAT(AFMT_S8, 2, 0), - SND_FORMAT(AFMT_S16_LE, 1, 0), - SND_FORMAT(AFMT_S16_LE, 2, 0), - SND_FORMAT(AFMT_U16_LE, 1, 0), - SND_FORMAT(AFMT_U16_LE, 2, 0), - 0 -}; - -static struct pcmchan_caps ess_playcaps = {6000, 48000, ess_pfmt, 0}; - -static u_int32_t ess_rfmt[] = { - SND_FORMAT(AFMT_U8, 1, 0), - SND_FORMAT(AFMT_U8, 2, 0), - SND_FORMAT(AFMT_S8, 1, 0), - SND_FORMAT(AFMT_S8, 2, 0), - SND_FORMAT(AFMT_S16_LE, 1, 0), - SND_FORMAT(AFMT_S16_LE, 2, 0), - SND_FORMAT(AFMT_U16_LE, 1, 0), - SND_FORMAT(AFMT_U16_LE, 2, 0), - 0 -}; - -static struct pcmchan_caps ess_reccaps = {6000, 48000, ess_rfmt, 0}; - -struct ess_info; - -struct ess_chinfo { - struct ess_info *parent; - struct pcm_channel *channel; - struct snd_dbuf *buffer; - int dir, hwch, stopping, run; - u_int32_t fmt, spd, blksz; -}; - -struct ess_info { - device_t parent_dev; - struct resource *io_base; /* I/O address for the board */ - struct resource *irq; - struct resource *drq1; - struct resource *drq2; - void *ih; - bus_dma_tag_t parent_dmat; - - unsigned int bufsize; - int type; - unsigned int duplex:1, newspeed:1; - u_long bd_flags; /* board-specific flags */ - struct ess_chinfo pch, rch; -}; - -#if 0 -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); -#endif - -/* - * 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 void -ess_lock(struct ess_info *sc) { - sbc_lock(device_get_softc(sc->parent_dev)); -} - -static void -ess_unlock(struct ess_info *sc) { - sbc_unlock(device_get_softc(sc->parent_dev)); -} - -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) -{ - 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) -{ - DEB(printf("ess_setmixer: reg=%x, val=%x\n", port, value);) - 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); -} - -static int -ess_getmixer(struct ess_info *sc, u_int port) -{ - int val; - ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ - DELAY(10); - val = ess_rd(sc, SB_MIX_DATA); - DELAY(10); - - 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(sc->io_base))); - return ENXIO; /* Sorry */ - } - ess_cmd(sc, 0xc6); - return 0; -} - -static void -ess_release_resources(struct ess_info *sc, device_t dev) -{ - if (sc->irq) { - if (sc->ih) - bus_teardown_intr(dev, sc->irq, sc->ih); - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); - sc->irq = NULL; - } - if (sc->drq1) { - isa_dma_release(rman_get_start(sc->drq1)); - bus_release_resource(dev, SYS_RES_DRQ, 0, sc->drq1); - sc->drq1 = NULL; - } - if (sc->drq2) { - isa_dma_release(rman_get_start(sc->drq2)); - bus_release_resource(dev, SYS_RES_DRQ, 1, sc->drq2); - sc->drq2 = NULL; - } - if (sc->io_base) { - bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->io_base); - sc->io_base = NULL; - } - if (sc->parent_dmat) { - bus_dma_tag_destroy(sc->parent_dmat); - sc->parent_dmat = 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_any(dev, SYS_RES_IOPORT, - &rid, RF_ACTIVE); - rid = 0; - if (!sc->irq) - sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &rid, RF_ACTIVE); - rid = 0; - if (!sc->drq1) - sc->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ, - &rid, RF_ACTIVE); - rid = 1; - if (!sc->drq2) - sc->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ, - &rid, 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), sc->bufsize); - - if (sc->drq2) { - isa_dma_acquire(rman_get_start(sc->drq2)); - isa_dmainit(rman_get_start(sc->drq2), sc->bufsize); - } - - return 0; - } else return ENXIO; -} - -static void -ess_intr(void *arg) -{ - struct ess_info *sc = (struct ess_info *)arg; - int src, pirq, rirq; - - ess_lock(sc); - 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.run) { - ess_unlock(sc); - chn_intr(sc->pch.channel); - ess_lock(sc); - } - if (sc->pch.stopping) { - sc->pch.run = 0; - sndbuf_dma(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); - } - } - - if (rirq) { - if (sc->rch.run) { - ess_unlock(sc); - chn_intr(sc->rch.channel); - ess_lock(sc); - } - if (sc->rch.stopping) { - sc->rch.run = 0; - sndbuf_dma(sc->rch.buffer, PCMTRIG_STOP); - sc->rch.stopping = 0; - /* XXX: will this stop audio2? */ - ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01); - } - } - - if (src & 2) - ess_setmixer(sc, 0x7a, ess_getmixer(sc, 0x7a) & ~0x80); - if (src & 1) - ess_rd(sc, DSP_DATA_AVAIL); - ess_unlock(sc); -} - -/* 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 = 128 - (793800 / speed); - s0 = 793800 / (128 - t0); - - t1 = 128 - (768000 / speed); - s1 = 768000 / (128 - t1); - t1 |= 0x80; - - 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 = (AFMT_CHANNEL(fmt) > 1)? 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_lock(sc); - ess_setupch(sc, ch->hwch, ch->dir, ch->spd, ch->fmt, ch->blksz); - 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); - ess_unlock(sc); - return 0; -} - -static int -ess_stop(struct ess_chinfo *ch) -{ - struct ess_info *sc = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - - ess_lock(sc); - 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); - ess_unlock(sc); - return 0; -} - -/* -------------------------------------------------------------------- */ -/* channel interface for ESS18xx */ -static void * -esschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct 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; - if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsize) != 0) - return NULL; - ch->dir = dir; - ch->hwch = 1; - if ((dir == PCMDIR_PLAY) && (sc->duplex)) - ch->hwch = 2; - sndbuf_dmasetup(ch->buffer, (ch->hwch == 1)? sc->drq1 : sc->drq2); - return ch; -} - -static int -esschan_setformat(kobj_t obj, void *data, u_int32_t format) -{ - struct ess_chinfo *ch = data; - - ch->fmt = format; - return 0; -} - -static u_int32_t -esschan_setspeed(kobj_t obj, 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 u_int32_t -esschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) -{ - struct ess_chinfo *ch = data; - - ch->blksz = blocksize; - return ch->blksz; -} - -static int -esschan_trigger(kobj_t obj, void *data, int go) -{ - struct ess_chinfo *ch = data; - - if (!PCMTRIG_COMMON(go)) - return 0; - - switch (go) { - case PCMTRIG_START: - ch->run = 1; - sndbuf_dma(ch->buffer, go); - ess_start(ch); - break; - - case PCMTRIG_STOP: - case PCMTRIG_ABORT: - default: - ess_stop(ch); - break; - } - return 0; -} - -static u_int32_t -esschan_getptr(kobj_t obj, void *data) -{ - struct ess_chinfo *ch = data; - - return sndbuf_dmaptr(ch->buffer); -} - -static struct pcmchan_caps * -esschan_getcaps(kobj_t obj, void *data) -{ - struct ess_chinfo *ch = data; - - return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps; -} - -static kobj_method_t esschan_methods[] = { - KOBJMETHOD(channel_init, esschan_init), - KOBJMETHOD(channel_setformat, esschan_setformat), - KOBJMETHOD(channel_setspeed, esschan_setspeed), - KOBJMETHOD(channel_setblocksize, esschan_setblocksize), - KOBJMETHOD(channel_trigger, esschan_trigger), - KOBJMETHOD(channel_getptr, esschan_getptr), - KOBJMETHOD(channel_getcaps, esschan_getcaps), - KOBJMETHOD_END -}; -CHANNEL_DECLARE(esschan); - -/************************************************************/ - -static int -essmix_init(struct 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 | SOUND_MASK_SPEAKER); - - ess_setmixer(sc, 0, 0); /* reset */ - - return 0; -} - -static int -essmix_set(struct 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_SPEAKER: - preg = 0x3c; - 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 u_int32_t -essmix_setrecsrc(struct 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 kobj_method_t essmixer_methods[] = { - KOBJMETHOD(mixer_init, essmix_init), - KOBJMETHOD(mixer_set, essmix_set), - KOBJMETHOD(mixer_setrecsrc, essmix_setrecsrc), - KOBJMETHOD_END -}; -MIXER_DECLARE(essmixer); - -/************************************************************/ - -static int -ess_probe(device_t dev) -{ *** 251 LINES SKIPPED ***