diff options
author | peter <peter@FreeBSD.org> | 1999-09-26 22:15:49 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1999-09-26 22:15:49 +0000 |
commit | cc8f297f6d23489f5232ad0ad8ea8c4f2a650153 (patch) | |
tree | f17788c34aae2413b1e327d9b7928f770a3f75e3 | |
parent | f75ff36ffa0a7fe82ad748500b71eea23ba54859 (diff) | |
download | FreeBSD-src-cc8f297f6d23489f5232ad0ad8ea8c4f2a650153.zip FreeBSD-src-cc8f297f6d23489f5232ad0ad8ea8c4f2a650153.tar.gz |
These files live on in sys/dev/pcm/pci/es1370*
-rw-r--r-- | sys/pci/es1370.c | 1123 | ||||
-rw-r--r-- | sys/pci/es1370_reg.h | 134 |
2 files changed, 0 insertions, 1257 deletions
diff --git a/sys/pci/es1370.c b/sys/pci/es1370.c deleted file mode 100644 index d1370aa..0000000 --- a/sys/pci/es1370.c +++ /dev/null @@ -1,1123 +0,0 @@ -/* - * Support the ENSONIQ AudioPCI board based on the ES1370 and Codec - * AK4531. - * - * Copyright (c) 1998 by Joachim Kuebart. 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. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgement: - * This product includes software developed by Joachim Kuebart. - * - * 4. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``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 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 "pcm.h" - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/kernel.h> -#include <machine/bus_pio.h> -#include <machine/bus_memio.h> -#include <machine/bus.h> -#include <pci/pcireg.h> -#include <pci/pcivar.h> - -#include <pci/es1370_reg.h> -#include <i386/isa/snd/sound.h> -#define DSP_ULAW_NOT_WANTED -#include <i386/isa/snd/ulaw.h> - - -/* -------------------------------------------------------------------- */ - -/* - * #defines - */ - -#ifdef __alpha__ -#define IO_SPACE_MAPPING ALPHA_BUS_SPACE_IO -#define MEM_SPACE_MAPPING ALPHA_BUS_SPACE_MEM -#else /* not __alpha__ */ -#define IO_SPACE_MAPPING I386_BUS_SPACE_IO -#define MEM_SPACE_MAPPING I386_BUS_SPACE_MEM -#endif /* not __alpha__ */ - -#define DMA_ALIGN_THRESHOLD 4 -#define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1)) -#define DMA_READ_THRESHOLD 0x200 - -#define MEM_MAP_REG 0x14 - -#define UNIT(minor) ((minor) >> 4) -#define DEV(minor) ((minor) & 0xf) - - -/* -------------------------------------------------------------------- */ - -/* - * PCI IDs of supported chips - */ - -#define ES1370_PCI_ID 0x50001274 - - -/* -------------------------------------------------------------------- */ - -/* - * device private data - */ - -struct es_info { - bus_space_tag_t st; - bus_space_handle_t sh; - - bus_dma_tag_t parent_dmat; - bus_dmamap_t dmam_in, dmam_out; - - /* Contents of board's registers */ - u_long ctrl; - u_long sctrl; -}; - - -/* -------------------------------------------------------------------- */ - -/* - * prototypes - */ - -static void dma_wrintr(snddev_info *); -static void dma_rdintr(snddev_info *); -static int es_init(snddev_info *); -static snd_callback_t es_callback; -static d_open_t es_dsp_open; -static d_close_t es_dsp_close; -static d_ioctl_t es_dsp_ioctl; -static d_read_t es_dsp_read; -static d_write_t es_dsp_write; -static void es_intr(void *); -static int es_rdabort(snddev_info *); -static void es_rd_map(void *, bus_dma_segment_t *, int, int); -static int es_wrabort(snddev_info *); -static void es_wr_map(void *, bus_dma_segment_t *, int, int); -static const char *es_pci_probe __P((pcici_t, pcidi_t)); -static void es_pci_attach __P((pcici_t, int)); -static int es_rd_dmaupdate(snddev_info *); -static d_select_t es_select; -static int es_wr_dmaupdate(snddev_info *); -static int alloc_dmabuf(snddev_info *, int); -static int write_codec(snddev_info *, u_char, u_char); - - -/* -------------------------------------------------------------------- */ - -/* - * PCI driver and PCM driver method tables - */ - -static struct pci_device es_pci_driver = { - "pcm", - es_pci_probe, - es_pci_attach, - &nsnd, - NULL -}; - -COMPAT_PCI_DRIVER(es_pci, es_pci_driver); - -static snddev_info es_op_desc = { - "ENSONIQ AudioPCI", - - 0, /* type, apparently unused */ - NULL, /* ISA probe */ - NULL, /* ISA attach */ - - es_dsp_open, - es_dsp_close, - es_dsp_read, - es_dsp_write, - es_dsp_ioctl, - es_select, - - NULL, /* Interrupt Service Routine */ - es_callback, - - ES_BUFFSIZE, - - AFMT_FULLDUPLEX | AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, /* brag :-) */ -}; - - -/* -------------------------------------------------------------------- */ - -/* - * The mixer interface - */ - -static const struct { - unsigned volidx:4; - unsigned left:4; - unsigned right:4; - unsigned stereo:1; - unsigned recmask:13; - unsigned avail:1; -} mixtable[SOUND_MIXER_NRDEVICES] = { - [SOUND_MIXER_VOLUME] = { 0, 0x0, 0x1, 1, 0x0000, 1 }, - [SOUND_MIXER_PCM] = { 1, 0x2, 0x3, 1, 0x0400, 1 }, - [SOUND_MIXER_SYNTH] = { 2, 0x4, 0x5, 1, 0x0060, 1 }, - [SOUND_MIXER_CD] = { 3, 0x6, 0x7, 1, 0x0006, 1 }, - [SOUND_MIXER_LINE] = { 4, 0x8, 0x9, 1, 0x0018, 1 }, - [SOUND_MIXER_LINE1] = { 5, 0xa, 0xb, 1, 0x1800, 1 }, - [SOUND_MIXER_LINE2] = { 6, 0xc, 0x0, 0, 0x0100, 1 }, - [SOUND_MIXER_LINE3] = { 7, 0xd, 0x0, 0, 0x0200, 1 }, - [SOUND_MIXER_MIC] = { 8, 0xe, 0x0, 0, 0x0001, 1 }, - [SOUND_MIXER_OGAIN] = { 9, 0xf, 0x0, 0, 0x0000, 1 } }; - -static int -mixer_ioctl(snddev_info *d, u_long cmd, caddr_t data, int fflag, struct proc *p) -{ - int i, j, *val, ret = 0; - - val = (int *)data; - i = cmd & 0xff; - - switch (cmd & IOC_DIRMASK) { - case IOC_IN | IOC_OUT: /* _IOWR */ - switch (i) { - case SOUND_MIXER_RECSRC: - for (i = j = 0; i != SOUND_MIXER_NRDEVICES; i++) - if ((*val & (1 << i)) != 0) { - if (!mixtable[i].recmask) - *val &= ~(1 << i); - else - j |= mixtable[i].recmask; - } - d->mix_recsrc = *val; - write_codec(d, CODEC_LIMIX1, j & 0x55); - write_codec(d, CODEC_RIMIX1, j & 0xaa); - write_codec(d, CODEC_LIMIX2, (j >> 8) & 0x17); - write_codec(d, CODEC_RIMIX2, (j >> 8) & 0x0f); - write_codec(d, CODEC_OMIX1, 0x7f); - write_codec(d, CODEC_OMIX2, 0x3f); - break; - - default: - if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].avail) - ret = EINVAL; - else { - int l, r, rl, rr; - - l = *val & 0xff; - if (l > 100) - l = 100; - if (mixtable[i].left == 0xf) { - if (l < 2) - rl = 0x80; - else - rl = 7 - (l - 2) / 14; - } else { - if (l < 10) - rl = 0x80; - else - rl = 15 - (l - 10) / 6; - } - if (mixtable[i].stereo) { - r = (*val >> 8) & 0xff; - if (r > 100) - r = 100; - if (r < 10) - rr = 0x80; - else - rr = 15 - (r - 10) / 6; - write_codec(d, mixtable[i].right, rr); - } else - r = l; - write_codec(d, mixtable[i].left, rl); - *val = d->mix_levels[i] = ((u_int) r << 8) | l; - } - break; - } - break; - - default: - ret = ENOSYS; - break; - } - - return (ret); -} - - -/* -------------------------------------------------------------------- */ - -/* - * File operations - */ - -static int -es_dsp_open(dev_t dev, int oflags, int devtype, struct proc *p) -{ - int unit = UNIT(minor(dev)); - snddev_info *d = &pcm_info[unit]; - - if (d->flags & SND_F_BUSY) - return (EBUSY); - d->flags = 0; - - d->dbuf_out.total = d->dbuf_out.prev_total = - d->dbuf_in.total = d->dbuf_in.prev_total = 0; - - switch (DEV(minor(dev))) { - case SND_DEV_DSP16: - d->play_fmt = d->rec_fmt = AFMT_S16_LE; - break; - - case SND_DEV_DSP: - d->play_fmt = d->rec_fmt = AFMT_U8; - break; - - case SND_DEV_AUDIO: - d->play_fmt = d->rec_fmt = AFMT_MU_LAW; - break; - - default: - return (ENXIO); - } - - if ((oflags & FREAD) == 0) - d->rec_fmt = 0; - else if ((oflags & FWRITE) == 0) - d->play_fmt = 0; - - d->play_speed = d->rec_speed = DSP_DEFAULT_SPEED; - - d->flags |= SND_F_BUSY; - if (oflags & O_NONBLOCK) - d->flags |= SND_F_NBIO; - - ask_init(d); - - return (0); -} - -static int -es_dsp_close(dev_t dev, int cflags, int devtype, struct proc *p) -{ - int unit = UNIT(minor(dev)); - snddev_info *d = &pcm_info[unit]; - - d->flags &= ~SND_F_BUSY; - - es_rdabort(d); - - return (0); -} - -static int -es_dsp_read(dev_t dev, struct uio *buf, int flag) -{ - int l, l1, limit, ret = 0, unit = UNIT(minor(dev)); - long s; - snddev_info *d = &pcm_info[unit]; - snd_dbuf *b = &d->dbuf_in; - - if (d->flags & SND_F_READING) { - /* This shouldn't happen and is actually silly */ - tsleep(&s, PZERO, "sndar", hz); - return (EBUSY); - } - d->flags |= SND_F_READING; - - /* - * XXX Check for SND_F_INIT. If set, wait for DMA to run empty and - * re-initialize the board - */ - - if (buf->uio_resid - d->rec_blocksize > 0) - limit = buf->uio_resid - d->rec_blocksize; - else - limit = 0; - - while ((l = buf->uio_resid) > limit) { - s = spltty(); - es_rd_dmaupdate(d); - if ((l = min(l, b->rl)) == 0) { - int timeout; - if (b->dl == 0) - dma_rdintr(d); - if (d->flags & SND_F_NBIO) { - splx(s); - break; - } - if (buf->uio_resid - limit > b->dl) - timeout = hz; - else - timeout = 1; - splx(s); - switch (ret = tsleep((caddr_t)b, PRIBIO | PCATCH, - "dsprd", timeout)) { - case EINTR: - es_rdabort(d); - /* FALLTHROUGH */ - - case ERESTART: - break; - - default: - continue; - } - break; - } - splx(s); - - if ((l1 = b->bufsize - b->rp) < l) { - if (d->flags & SND_F_XLAT8) { - translate_bytes(ulaw_dsp, b->buf + b->rp, l1); - translate_bytes(ulaw_dsp, b->buf, l - l1); - } - uiomove(b->buf + b->rp, l1, buf); - uiomove(b->buf, l - l1, buf); - } else { - if (d->flags & SND_F_XLAT8) - translate_bytes(ulaw_dsp, b->buf + b->rp, l); - uiomove(b->buf + b->rp, l, buf); - } - - s = spltty(); - b->fl += l; - b->rl -= l; - b->rp = (b->rp + l) % b->bufsize; - splx(s); - } - - d->flags &= ~SND_F_READING; - - return (ret); -} - -static int -es_dsp_write(dev_t dev, struct uio *buf, int flag) -{ - int l, l1, ret = 0, unit = UNIT(minor(dev)); - long s; - snddev_info *d = &pcm_info[unit]; - snd_dbuf *b = &d->dbuf_out; - - if (d->flags & SND_F_WRITING) { - /* This shouldn't happen and is actually silly */ - tsleep(&s, PZERO, "sndaw", hz); - return (EBUSY); - } - d->flags |= SND_F_WRITING; - - /* - * XXX Check for SND_F_INIT. If set, wait for DMA to run empty and - * re-initialize the board - */ - - while ((l = buf->uio_resid) != 0) { - s = spltty(); - es_wr_dmaupdate(d); - if ((l = min(l, b->fl)) == 0) { - int timeout; - if (d->flags & SND_F_NBIO) { - splx(s); - break; - } - if (buf->uio_resid >= b->dl) - timeout = hz; - else - timeout = 1; - splx(s); - switch (ret = tsleep((caddr_t)b, PRIBIO | PCATCH, - "dspwr", timeout)) { - case EINTR: - es_wrabort(d); - /* FALLTHROUGH */ - - case ERESTART: - break; - - default: - continue; - } - break; - } - splx(s); - - if ((l1 = b->bufsize - b->fp) < l) { - uiomove(b->buf + b->fp, l1, buf); - uiomove(b->buf, l - l1, buf); - if (d->flags & SND_F_XLAT8) { - translate_bytes(ulaw_dsp, b->buf + b->fp, l1); - translate_bytes(ulaw_dsp, b->buf, l - l1); - } - } else { - uiomove(b->buf + b->fp, l, buf); - if (d->flags & SND_F_XLAT8) - translate_bytes(ulaw_dsp, b->buf + b->fp, l); - } - - s = spltty(); - b->rl += l; - b->fl -= l; - b->fp = (b->fp + l) % b->bufsize; - if (b->dl == 0) - dma_wrintr(d); - splx(s); - } - - d->flags &= ~SND_F_WRITING; - - return (ret); -} - -static int -es_dsp_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) -{ - int ret = 0, unit = UNIT(minor(dev)); - snddev_info *d = &pcm_info[unit]; - long s; - - if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) - return mixer_ioctl(d, cmd, data, fflag, p); - - switch(cmd) { - case AIONWRITE: - if (d->dbuf_out.dl != 0) { - s = spltty(); - es_wr_dmaupdate(d); - splx(s); - } - *(int *)data = d->dbuf_out.fl; - break; - - case FIONREAD: - if (d->dbuf_in.dl != 0) { - s = spltty(); - es_rd_dmaupdate(d); - splx(s); - } - *(int *)data = d->dbuf_in.rl; - break; - - case SNDCTL_DSP_GETISPACE: - { - audio_buf_info *a = (audio_buf_info *)data; - snd_dbuf *b = &d->dbuf_in; - if (b->dl != 0) { - s = spltty(); - es_rd_dmaupdate(d); - splx(s); - } - a->bytes = b->fl; - a->fragments = b->fl / d->rec_blocksize; - a->fragstotal = b->bufsize / d->rec_blocksize; - a->fragsize = d->rec_blocksize; - } - break; - - case SNDCTL_DSP_GETOSPACE: - { - audio_buf_info *a = (audio_buf_info *)data; - snd_dbuf *b = &d->dbuf_out; - if (b->dl != 0) { - s = spltty(); - es_wr_dmaupdate(d); - splx(s); - } - a->bytes = b->fl; - a->fragments = b->fl / d->rec_blocksize; - a->fragstotal = b->bufsize / d->play_blocksize; - a->fragsize = d->play_blocksize; - } - break; - - case SNDCTL_DSP_GETIPTR: - { - count_info *c = (count_info *)data; - snd_dbuf *b = &d->dbuf_in; - if (b->dl != 0) { - s = spltty(); - es_rd_dmaupdate(d); - splx(s); - } - c->bytes = b->total; - c->blocks = (b->total - b->prev_total + - d->rec_blocksize - 1) / d->rec_blocksize; - c->ptr = b->fp; - b->prev_total = b->total; - } - break; - - case SNDCTL_DSP_GETOPTR: - { - count_info *c = (count_info *)data; - snd_dbuf *b = &d->dbuf_out; - if (b->dl != 0) { - s = spltty(); - es_wr_dmaupdate(d); - splx(s); - } - c->bytes = b->total; - c->blocks = (b->total - b->prev_total + - d->play_blocksize - 1) / d->play_blocksize; - c->ptr = b->rp; - b->prev_total = b->total; - } - break; - - case AIOSTOP: - case SNDCTL_DSP_RESET: - case SNDCTL_DSP_SYNC: - ret = EINVAL; - break; - - default: - ret = ENOSYS; - break; - } - return (ret); -} - -static int -es_select(dev_t i_dev, int rw, struct proc * p) -{ - return (ENOSYS); -} - - -/* -------------------------------------------------------------------- */ - -/* - * The interrupt handler - */ - -static void -es_intr (void *p) -{ - snddev_info *d = (snddev_info *)p; - struct es_info *es = (struct es_info *)d->device_data; - unsigned intsrc, sctrl; - - intsrc = bus_space_read_4(es->st, es->sh, ES1370_REG_STATUS); - if ((intsrc & STAT_INTR) == 0) - return; - - sctrl = es->sctrl; - if (intsrc & STAT_ADC) - sctrl &= ~SCTRL_R1INTEN; - if (intsrc & STAT_DAC1) - sctrl &= ~SCTRL_P1INTEN; - if (intsrc & STAT_DAC2) { - sctrl &= ~SCTRL_P2INTEN; - } - bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, sctrl); - bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, - es->sctrl); - if (intsrc & STAT_DAC2) - dma_wrintr(d); - if (intsrc & STAT_ADC) - dma_rdintr(d); -} - - -/* -------------------------------------------------------------------- */ - -/* - * DMA hassle - */ - -static int -alloc_dmabuf(snddev_info *d, int rd) -{ - struct es_info *es = (struct es_info *)d->device_data; - snd_dbuf *b = rd ? &d->dbuf_in : &d->dbuf_out; - bus_dmamap_t *dmam = rd ? &es->dmam_in : &es->dmam_out; - - if (bus_dmamem_alloc(es->parent_dmat, (void **)&b->buf, BUS_DMA_NOWAIT, - dmam) != 0 || - bus_dmamap_load(es->parent_dmat, *dmam, b->buf, d->bufsize, - rd ? es_rd_map : es_wr_map, es, 0) != 0) - return -1; - - b->rp = b->fp = b->dl = b->rl = 0; - b->fl = b->bufsize = d->bufsize; - return (0); -} - -static int -es_wr_dmaupdate(snddev_info *d) -{ - struct es_info *es = (struct es_info *)d->device_data; - unsigned hwptr, delta; - - bus_space_write_4(es->st, es->sh, ES1370_REG_MEMPAGE, - ES1370_REG_DAC2_FRAMECNT >> 8); - hwptr = (bus_space_read_4(es->st, es->sh, - ES1370_REG_DAC2_FRAMECNT & 0xff) >> 14) & 0x3fffc; - delta = (d->dbuf_out.bufsize + hwptr - d->dbuf_out.rp) % - d->dbuf_out.bufsize; - d->dbuf_out.rp = hwptr; - d->dbuf_out.rl -= delta; - d->dbuf_out.fl += delta; - d->dbuf_out.total += delta; - - return delta; -} - -static int -es_rd_dmaupdate(snddev_info *d) -{ - struct es_info *es = (struct es_info *)d->device_data; - unsigned hwptr, delta; - - bus_space_write_4(es->st, es->sh, ES1370_REG_MEMPAGE, - ES1370_REG_ADC_FRAMECNT >> 8); - hwptr = (bus_space_read_4(es->st, es->sh, - ES1370_REG_ADC_FRAMECNT & 0xff) >> 14) & 0x3fffc; - delta = (d->dbuf_in.bufsize + hwptr - d->dbuf_in.fp) % - d->dbuf_in.bufsize; - d->dbuf_in.fp = hwptr; - d->dbuf_in.rl += delta; - d->dbuf_in.fl -= delta; - d->dbuf_in.total += delta; - return delta; -} - - -/* -------------------------------------------------------------------- */ - -/* - * Hardware - */ - -static int -es_callback(snddev_info *d, int reason) -{ - struct es_info *es = (struct es_info *)d->device_data; - int rd = reason & SND_CB_RD; - - switch(reason & SND_CB_REASON_MASK) { - case SND_CB_INIT: - es->ctrl = (es->ctrl & ~CTRL_PCLKDIV) | - (DAC2_SRTODIV(d->play_speed) << CTRL_SH_PCLKDIV); - snd_set_blocksize(d); - - es->sctrl &= ~(SCTRL_R1FMT | SCTRL_P2FMT); - d->flags &= ~SND_F_XLAT8; - switch(d->play_fmt) { - case 0: - case AFMT_U8: - break; - - case AFMT_S16_LE: - es->sctrl |= SCTRL_P2SEB; - break; - - case AFMT_MU_LAW: - d->flags |= SND_F_XLAT8; - break; - - default: - return (-1); - } - - switch(d->rec_fmt) { - case 0: - case AFMT_U8: - break; - - case AFMT_S16_LE: - es->sctrl |= SCTRL_R1SEB; - break; - - case AFMT_MU_LAW: - d->flags |= SND_F_XLAT8; - break; - - default: - return (-1); - } - - if (d->flags & SND_F_STEREO) - es->sctrl |= SCTRL_P2SMB | SCTRL_R1SMB; - - bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, - es->ctrl); - bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, - es->sctrl); - break; - - case SND_CB_START: - if (rd) { - es->ctrl |= CTRL_ADC_EN; - es->sctrl = (es->sctrl & ~SCTRL_R1LOOPSEL) | - SCTRL_R1INTEN; - bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_SCOUNT, - d->dbuf_in.dl / d->dbuf_in.sample_size - 1); - } else { - es->ctrl |= CTRL_DAC2_EN; - es->sctrl = (es->sctrl & ~(SCTRL_P2ENDINC | - SCTRL_P2STINC | SCTRL_P2LOOPSEL | SCTRL_P2PAUSE | - SCTRL_P2DACSEN)) | SCTRL_P2INTEN | - (((d->play_fmt == AFMT_S16_LE) ? 2 : 1) - << SCTRL_SH_P2ENDINC); - bus_space_write_4(es->st, es->sh, - ES1370_REG_DAC2_SCOUNT, - d->dbuf_out.dl / d->dbuf_out.sample_size - 1); - } - bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, - es->sctrl); - bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl); - break; - - case SND_CB_ABORT: - case SND_CB_STOP: - if (rd) - es->ctrl &= ~CTRL_ADC_EN; - else - es->ctrl &= ~CTRL_DAC2_EN; - bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl); - break; - - default: - return (-1); - } - return (0); -} - -static int -write_codec(snddev_info *d, u_char i, u_char data) -{ - struct es_info *es = (struct es_info *)d->device_data; - int wait = 100; /* 100 msec timeout */ - - do { - if ((bus_space_read_4(es->st, es->sh, ES1370_REG_STATUS) & - STAT_CSTAT) == 0) { - bus_space_write_2(es->st, es->sh, ES1370_REG_CODEC, - ((u_short)i << CODEC_INDEX_SHIFT) | data); - return (0); - } - DELAY(1000); - /* tsleep(&wait, PZERO, "sndaw", hz / 1000); */ - } while (--wait); - printf("pcm: write_codec timed out\n"); - return (-1); -} - -static void -es_wr_map(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - struct es_info *es = (struct es_info *)arg; - - bus_space_write_1(es->st, es->sh, ES1370_REG_MEMPAGE, - ES1370_REG_DAC2_FRAMEADR >> 8); - bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_FRAMEADR & 0xff, - segs->ds_addr); - bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_FRAMECNT & 0xff, - (segs->ds_len >> 2) - 1); -} - -static void -es_rd_map(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - struct es_info *es = (struct es_info *)arg; - - bus_space_write_1(es->st, es->sh, ES1370_REG_MEMPAGE, - ES1370_REG_ADC_FRAMEADR >> 8); - bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_FRAMEADR & 0xff, - segs->ds_addr); - bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_FRAMECNT & 0xff, - (segs->ds_len >> 2) - 1); -} - -static void -dma_wrintr(snddev_info *d) -{ - snd_dbuf *b = &d->dbuf_out; - - /* - * According to Linux driver: - * dmaupdate() - * Bei underrun error++ - * wake_up(dac2.wait) - */ - - if (b->dl != 0) { - es_wr_dmaupdate(d); - wakeup(b); - } - - if (b->rl >= DMA_ALIGN_THRESHOLD && - !(d->flags & SND_F_ABORTING)) { - int l = min(b->rl, d->play_blocksize); - l &= DMA_ALIGN_MASK; - - if (l != b->dl) { - if (b->dl != 0) { - d->callback(d, SND_CB_WR | SND_CB_STOP); - es_wr_dmaupdate(d); - l = min(b->rl, d->play_blocksize); - l &= DMA_ALIGN_MASK; - } - b->dl = l; - d->callback(d, SND_CB_WR | SND_CB_START); - } - } else if (b->dl != 0) { - b->dl = 0; - d->callback(d, SND_CB_WR | SND_CB_STOP); - es_wr_dmaupdate(d); - } -} - -static void -dma_rdintr(snddev_info *d) -{ - snd_dbuf *b = &d->dbuf_in; - - if (b->dl != 0) { - es_rd_dmaupdate(d); - wakeup(b); - } - - if (b->fl >= DMA_READ_THRESHOLD && - !(d->flags & SND_F_ABORTING)) { - int l = min(b->fl, d->rec_blocksize); - l &= DMA_ALIGN_MASK; - - if (l != b->dl) { - if (b->dl != 0) { - d->callback(d, SND_CB_RD | SND_CB_STOP); - es_rd_dmaupdate(d); - l = min(b->fl, d->rec_blocksize); - l &= DMA_ALIGN_MASK; - } - b->dl = l; - d->callback(d, SND_CB_RD | SND_CB_START); - } - } else { - if (b->dl != 0) { - b->dl = 0; - d->callback(d, SND_CB_RD | SND_CB_STOP); - es_rd_dmaupdate(d); - } - } -} - -static int -es_wrabort(snddev_info *d) -{ - snd_dbuf *b = &d->dbuf_out; - long s; - int missing; - - s = spltty(); - if (b->dl != 0) { - wakeup(b); - b->dl = 0; - d->callback(d, SND_CB_WR | SND_CB_ABORT); - } - es_wr_dmaupdate(d); - missing = b->rl; - b->rl = 0; - b->fp = b->rp; - b->fl = b->bufsize; - splx(s); - return missing; -} - -static int -es_rdabort(snddev_info *d) -{ - snd_dbuf *b = &d->dbuf_in; - long s; - int missing; - - s = spltty(); - if (b->dl != 0) { - wakeup(b); - b->dl = 0; - d->callback(d, SND_CB_RD | SND_CB_ABORT); - es_rd_dmaupdate(d); - } - missing = b->rl; - b->rl = 0; - b->fp = b->rp; - b->fl = b->bufsize; - splx(s); - return missing; -} - - -/* -------------------------------------------------------------------- */ - -/* - * Probe and attach the card - */ - -static int -es_init(snddev_info *d) -{ - struct es_info *es = (struct es_info *)d->device_data; - u_int i; - - es->ctrl = CTRL_CDC_EN | CTRL_SERR_DIS | - (DAC2_SRTODIV(DSP_DEFAULT_SPEED) << CTRL_SH_PCLKDIV); - bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl); - es->sctrl = 0; - bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl); - write_codec(d, CODEC_RES_PD, 3);/* No RST, PD */ - write_codec(d, CODEC_CSEL, 0); /* CODEC ADC and CODEC DAC use - * {LR,B}CLK2 and run off the LRCLK2 - * PLL; program DAC_SYNC=0! */ - write_codec(d, CODEC_ADSEL, 0); /* Recording source is mixer */ - write_codec(d, CODEC_MGAIN, 0); /* MIC amp is 0db */ - - i = SOUND_MASK_MIC; - mixer_ioctl(d, SOUND_MIXER_WRITE_RECSRC, (caddr_t) &i, 0, NULL); - i = 0; - mixer_ioctl(d, SOUND_MIXER_WRITE_VOLUME, (caddr_t) &i, 0, NULL); - mixer_ioctl(d, SOUND_MIXER_WRITE_PCM, (caddr_t) &i, 0, NULL); - mixer_ioctl(d, SOUND_MIXER_WRITE_SYNTH, (caddr_t) &i, 0, NULL); - mixer_ioctl(d, SOUND_MIXER_WRITE_CD, (caddr_t) &i, 0, NULL); - mixer_ioctl(d, SOUND_MIXER_WRITE_LINE, (caddr_t) &i, 0, NULL); - mixer_ioctl(d, SOUND_MIXER_WRITE_LINE1, (caddr_t) &i, 0, NULL); - mixer_ioctl(d, SOUND_MIXER_WRITE_LINE2, (caddr_t) &i, 0, NULL); - mixer_ioctl(d, SOUND_MIXER_WRITE_LINE3, (caddr_t) &i, 0, NULL); - mixer_ioctl(d, SOUND_MIXER_WRITE_MIC, (caddr_t) &i, 0, NULL); - - return (0); -} - -static const char * -es_pci_probe(pcici_t tag, pcidi_t type) -{ - if (type == ES1370_PCI_ID) - return ("AudioPCI ES1370"); - - return (NULL); -} - -static void -es_pci_attach(pcici_t config_id, int unit) -{ - snddev_info *d; - u_int32_t data; - struct es_info *es; - pci_port_t io_port; - int i, mapped; - vm_offset_t vaddr, paddr; - - if (unit > NPCM_MAX) - return; - - d = &pcm_info[unit]; - *d = es_op_desc; - if ((es = malloc(sizeof(*es), M_DEVBUF, M_NOWAIT)) == NULL) { - printf("pcm%d: cannot allocate softc\n", unit); - return; - } - bzero(es, sizeof(*es)); - d->device_data = es; - - vaddr = paddr = NULL; - mapped = 0; - data = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG); - if (mapped == 0 && (data & PCI_COMMAND_MEM_ENABLE)) { - if (pci_map_mem(config_id, MEM_MAP_REG, &vaddr, &paddr)) { - es->st = MEM_SPACE_MAPPING; - es->sh = vaddr; - mapped++; - } - } - if (mapped == 0 && (data & PCI_COMMAND_IO_ENABLE)) { - if (pci_map_port(config_id, PCI_MAP_REG_START, &io_port)) { - es->st = IO_SPACE_MAPPING; - es->sh = io_port; - mapped++; - } - } - if (mapped == 0) { - printf("pcm%d: unable to map any ports\n", unit); - free(es, M_DEVBUF); - return; - } - printf("pcm%d: using %s space register mapping at %#x\n", unit, - es->st == IO_SPACE_MAPPING ? "I/O" : "Memory", es->sh); - - d->io_base = es->sh; - d->mix_devs = 0; - for (i = 0; i != SOUND_MIXER_NRDEVICES; i++) - if (mixtable[i].avail) - d->mix_devs |= (1 << i); - d->mix_rec_devs = 0; - for (i = 0; i != SOUND_MIXER_NRDEVICES; i++) - if (mixtable[i].recmask) - d->mix_rec_devs |= (1 << i); - - if (es_init(d) == -1) { - printf("pcm%d: unable to initialize the card\n", unit); - free(es, M_DEVBUF); - d->io_base = 0; - return; - } - if (pci_map_int(config_id, es_intr, d, &tty_imask) == 0) { - printf("pcm%d: unable to map interrupt\n", unit); - free(es, M_DEVBUF); - d->io_base = 0; - return; - } - if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/d->bufsize, /*nsegments*/1, /*maxsegz*/0x3ffff, - /*flags*/0, &es->parent_dmat) != 0) { - printf("pcm%d: unable to create dma tag\n", unit); - free(es, M_DEVBUF); - d->io_base = 0; - return; - } - - if (alloc_dmabuf(d, 0) == -1 || - alloc_dmabuf(d, 1) == -1) { - printf("pcm%d: unable to allocate dma buffers\n", unit); - free(es, M_DEVBUF); - d->io_base = 0; - return; - } - - pcminit(d, unit); - - return; -} diff --git a/sys/pci/es1370_reg.h b/sys/pci/es1370_reg.h deleted file mode 100644 index a1adc35..0000000 --- a/sys/pci/es1370_reg.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * This supports the ENSONIQ AudioPCI board based on the ES1370. - * - * Copyright (c) 1998 Joachim Kuebart <joki@kuebart.stuttgart.netsurf.de> - * 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 immediately at the beginning of the file, without modification, - * 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. - * 3. Absolutely no warranty of function or purpose is made by the author - * Joachim Kuebart. - * 4. Modifications may be freely made to this file if the above conditions - * are met. - * - * $FreeBSD$ - */ - -#ifndef _ES1370_REG_H -#define _ES1370_REG_H - -#define ES1370_REG_CONTROL 0x00 -#define ES1370_REG_STATUS 0x04 -#define ES1370_REG_UART_DATA 0x08 -#define ES1370_REG_UART_STATUS 0x09 -#define ES1370_REG_UART_CONTROL 0x09 -#define ES1370_REG_UART_TEST 0x0a -#define ES1370_REG_MEMPAGE 0x0c -#define ES1370_REG_CODEC 0x10 -#define CODEC_INDEX_SHIFT 8 -#define ES1370_REG_SERIAL_CONTROL 0x20 -#define ES1370_REG_DAC1_SCOUNT 0x24 -#define ES1370_REG_DAC2_SCOUNT 0x28 -#define ES1370_REG_ADC_SCOUNT 0x2c - -#define ES1370_REG_DAC1_FRAMEADR 0xc30 -#define ES1370_REG_DAC1_FRAMECNT 0xc34 -#define ES1370_REG_DAC2_FRAMEADR 0xc38 -#define ES1370_REG_DAC2_FRAMECNT 0xc3c -#define ES1370_REG_ADC_FRAMEADR 0xd30 -#define ES1370_REG_ADC_FRAMECNT 0xd34 - -#define DAC2_SRTODIV(x) (((1411200 + (x) / 2) / (x) - 2) & 0x1fff) -#define DAC2_DIVTOSR(x) (1411200 / ((x) + 2)) - -#define CTRL_ADC_STOP 0x80000000 /* 1 = ADC stopped */ -#define CTRL_XCTL1 0x40000000 /* SERR pin if enabled */ -#define CTRL_OPEN 0x20000000 /* no function, can be read and - * written */ -#define CTRL_PCLKDIV 0x1fff0000 /* ADC/DAC2 clock divider */ -#define CTRL_SH_PCLKDIV 16 -#define CTRL_MSFMTSEL 0x00008000 /* MPEG serial data fmt: 0 = Sony, 1 - * = I2S */ -#define CTRL_M_SBB 0x00004000 /* DAC2 clock: 0 = PCLKDIV, 1 = MPEG */ -#define CTRL_WTSRSEL 0x00003000 /* DAC1 clock freq: 0=5512, 1=11025, - * 2=22050, 3=44100 */ -#define CTRL_SH_WTSRSEL 12 -#define CTRL_DAC_SYNC 0x00000800 /* 1 = DAC2 runs off DAC1 clock */ -#define CTRL_CCB_INTRM 0x00000400 /* 1 = CCB "voice" ints enabled */ -#define CTRL_M_CB 0x00000200 /* recording source: 0 = ADC, 1 = - * MPEG */ -#define CTRL_XCTL0 0x00000100 /* 0 = Line in, 1 = Line out */ -#define CTRL_BREQ 0x00000080 /* 1 = test mode (internal mem test) */ -#define CTRL_DAC1_EN 0x00000040 /* enable DAC1 */ -#define CTRL_DAC2_EN 0x00000020 /* enable DAC2 */ -#define CTRL_ADC_EN 0x00000010 /* enable ADC */ -#define CTRL_UART_EN 0x00000008 /* enable MIDI uart */ -#define CTRL_JYSTK_EN 0x00000004 /* enable Joystick port (presumably - * at address 0x200) */ -#define CTRL_CDC_EN 0x00000002 /* enable serial (CODEC) interface */ -#define CTRL_SERR_DIS 0x00000001 /* 1 = disable PCI SERR signal */ - -#define SCTRL_P2ENDINC 0x00380000 /* */ -#define SCTRL_SH_P2ENDINC 19 -#define SCTRL_P2STINC 0x00070000 /* */ -#define SCTRL_SH_P2STINC 16 -#define SCTRL_R1LOOPSEL 0x00008000 /* 0 = loop mode */ -#define SCTRL_P2LOOPSEL 0x00004000 /* 0 = loop mode */ -#define SCTRL_P1LOOPSEL 0x00002000 /* 0 = loop mode */ -#define SCTRL_P2PAUSE 0x00001000 /* 1 = pause mode */ -#define SCTRL_P1PAUSE 0x00000800 /* 1 = pause mode */ -#define SCTRL_R1INTEN 0x00000400 /* enable interrupt */ -#define SCTRL_P2INTEN 0x00000200 /* enable interrupt */ -#define SCTRL_P1INTEN 0x00000100 /* enable interrupt */ -#define SCTRL_P1SCTRLD 0x00000080 /* reload sample count register for - * DAC1 */ -#define SCTRL_P2DACSEN 0x00000040 /* 1 = DAC2 play back last sample - * when disabled */ -#define SCTRL_R1SEB 0x00000020 /* 1 = 16bit */ -#define SCTRL_R1SMB 0x00000010 /* 1 = stereo */ -#define SCTRL_R1FMT 0x00000030 /* format mask */ -#define SCTRL_SH_R1FMT 4 -#define SCTRL_P2SEB 0x00000008 /* 1 = 16bit */ -#define SCTRL_P2SMB 0x00000004 /* 1 = stereo */ -#define SCTRL_P2FMT 0x0000000c /* format mask */ -#define SCTRL_SH_P2FMT 2 -#define SCTRL_P1SEB 0x00000002 /* 1 = 16bit */ -#define SCTRL_P1SMB 0x00000001 /* 1 = stereo */ -#define SCTRL_P1FMT 0x00000003 /* format mask */ -#define SCTRL_SH_P1FMT 0 - -#define STAT_INTR 0x80000000 /* wired or of all interrupt bits */ -#define STAT_CSTAT 0x00000400 /* 1 = codec busy or codec write in - * progress */ -#define STAT_CBUSY 0x00000200 /* 1 = codec busy */ -#define STAT_CWRIP 0x00000100 /* 1 = codec write in progress */ -#define STAT_VC 0x00000060 /* CCB int source, 0=DAC1, 1=DAC2, - * 2=ADC, 3=undef */ -#define STAT_SH_VC 5 -#define STAT_MCCB 0x00000010 /* CCB int pending */ -#define STAT_UART 0x00000008 /* UART int pending */ -#define STAT_DAC1 0x00000004 /* DAC1 int pending */ -#define STAT_DAC2 0x00000002 /* DAC2 int pending */ -#define STAT_ADC 0x00000001 /* ADC int pending */ - -#define CODEC_OMIX1 0x10 -#define CODEC_OMIX2 0x11 -#define CODEC_LIMIX1 0x12 -#define CODEC_RIMIX1 0x13 -#define CODEC_LIMIX2 0x14 -#define CODEC_RIMIX2 0x15 -#define CODEC_RES_PD 0x16 -#define CODEC_CSEL 0x17 -#define CODEC_ADSEL 0x18 -#define CODEC_MGAIN 0x19 - -#define ES_BUFFSIZE 0x20000 /* We're PCI! Use a large buffer */ - -#endif |