Index: head/sys/dev/pcm/mixer.h =================================================================== --- head/sys/dev/pcm/mixer.h (revision 53505) +++ head/sys/dev/pcm/mixer.h (nonexistent) @@ -1,42 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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$ - */ - -extern int mixer_init(snddev_info *d, snd_mixer *m, void *devinfo); -extern int mixer_set(snddev_info *d, unsigned dev, unsigned lev); -extern int mixer_get(snddev_info *d, int dev); -extern int mixer_setrecsrc(snddev_info *d, u_int32_t src); -extern int mixer_getrecsrc(snddev_info *d); -extern int mixer_ioctl(snddev_info *d, u_long cmd, caddr_t arg); - -extern void change_bits(mixer_tab *t, u_char *regval, int dev, int chn, int newval); - -void mix_setdevs(snd_mixer *m, u_int32_t v); -void mix_setrecdevs(snd_mixer *m, u_int32_t v); -u_int32_t mix_getdevs(snd_mixer *m); -u_int32_t mix_getrecdevs(snd_mixer *m); -void *mix_getdevinfo(snd_mixer *m); Property changes on: head/sys/dev/pcm/mixer.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/sound.c =================================================================== --- head/sys/dev/pcm/sound.c (revision 53505) +++ head/sys/dev/pcm/sound.c (nonexistent) @@ -1,448 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * (C) 1997 Luigi Rizzo (luigi@iet.unipi.it) - * 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 "opt_devfs.h" - -#include -#ifdef DEVFS -#include -#endif /* DEVFS */ - -#if NPCM > 0 /* from "pcm.h" via disgusting #include in snd/sound.h */ - -extern struct isa_driver pcmdriver; - -static int status_isopen = 0; -static int status_init(char *buf, int size); -static int status_read(struct uio *buf); - -static d_open_t sndopen; -static d_close_t sndclose; -static d_ioctl_t sndioctl; -static d_read_t sndread; -static d_write_t sndwrite; -static d_mmap_t sndmmap; -static d_poll_t sndpoll; - -#define CDEV_MAJOR 30 -static struct cdevsw snd_cdevsw = { - /* open */ sndopen, - /* close */ sndclose, - /* read */ sndread, - /* write */ sndwrite, - /* ioctl */ sndioctl, - /* poll */ sndpoll, - /* mmap */ sndmmap, - /* strategy */ nostrategy, - /* name */ "snd", - /* maj */ CDEV_MAJOR, - /* dump */ nodump, - /* psize */ nopsize, - /* flags */ 0, - /* bmaj */ -1 -}; - -/* PROPOSAL: -each unit needs: -status, mixer, dsp, dspW, audio, sequencer, midi-in, seq2, sndproc = 9 devices -dspW and audio are deprecated. -dsp needs min 64 channels, will give it 256 - -minor = (unit << 12) + (dev << 8) + channel -currently minor = (channel << 8) + (unit << 4) + dev - -nomenclature: - /dev/pcmX/dsp.(0..255) - /dev/pcmX/dspW - /dev/pcmX/audio - /dev/pcmX/status - /dev/pcmX/mixer - [etc.] - -currently: -minor = (channel << 8) + (unit << 4) + dev -*/ - -#define PCMMINOR(x) (minor(x)) -#define PCMCHAN(x) ((PCMMINOR(x) & 0x0000ff00) >> 8) -#define PCMUNIT(x) ((PCMMINOR(x) & 0x000000f0) >> 4) -#define PCMDEV(x) (PCMMINOR(x) & 0x0000000f) -#define PCMMKMINOR(u, d) (((u) & 0x0f) << 4 | ((d) & 0x0f)) - -static devclass_t pcm_devclass; - -static snddev_info * -gsd(int unit) -{ - return devclass_get_softc(pcm_devclass, unit); -} - -int -pcm_addchan(device_t dev, int dir, pcm_channel *templ, void *devinfo) -{ - snddev_info *d = device_get_softc(dev); - pcm_channel *ch; - - ch = (dir == PCMDIR_PLAY)? &d->play[d->playcount++] : &d->rec[d->reccount++]; - *ch = *templ; - chn_init(ch, devinfo, dir); - d->chancount++; - return 0; -} - -int -pcm_setstatus(device_t dev, char *str) -{ - snddev_info *d = device_get_softc(dev); - strncpy(d->status, str, SND_STATUSLEN); - return 0; -} - -u_int32_t -pcm_getflags(device_t dev) -{ - snddev_info *d = device_get_softc(dev); - return d->flags; -} - -void -pcm_setflags(device_t dev, u_int32_t val) -{ - snddev_info *d = device_get_softc(dev); - d->flags = val; -} - -/* This is the generic init routine */ -int -pcm_register(device_t dev, void *devinfo, int numplay, int numrec) -{ - int sz, unit = device_get_unit(dev); - snddev_info *d = device_get_softc(dev); - - if (!pcm_devclass) { - pcm_devclass = device_get_devclass(dev); - make_dev(&snd_cdevsw, PCMMKMINOR(0, SND_DEV_STATUS), - UID_ROOT, GID_WHEEL, 0444, "sndstat"); - } - make_dev(&snd_cdevsw, PCMMKMINOR(unit, SND_DEV_CTL), - UID_ROOT, GID_WHEEL, 0666, "mixer%d", unit); - make_dev(&snd_cdevsw, PCMMKMINOR(unit, SND_DEV_DSP), - UID_ROOT, GID_WHEEL, 0666, "dsp%d", unit); - make_dev(&snd_cdevsw, PCMMKMINOR(unit, SND_DEV_AUDIO), - UID_ROOT, GID_WHEEL, 0666, "audio%d", unit); - make_dev(&snd_cdevsw, PCMMKMINOR(unit, SND_DEV_DSP16), - UID_ROOT, GID_WHEEL, 0666, "dspW%d", unit); - /* XXX SND_DEV_NORESET? */ - d->devinfo = devinfo; - d->chancount = d->playcount = d->reccount = 0; - sz = (numplay + numrec) * sizeof(pcm_channel *); - d->aplay = (pcm_channel **)malloc(sz, M_DEVBUF, M_NOWAIT); - if (!d->aplay) goto no; - d->arec = (pcm_channel **)malloc(sz, M_DEVBUF, M_NOWAIT); - if (!d->arec) goto no; - bzero(d->aplay, sz); - bzero(d->arec, sz); - - d->play = (pcm_channel *)malloc(numplay * sizeof(pcm_channel), - M_DEVBUF, M_NOWAIT); - if (!d->play) goto no; - d->rec = (pcm_channel *)malloc(numrec * sizeof(pcm_channel), - M_DEVBUF, M_NOWAIT); - if (!d->rec) goto no; - bzero(d->play, numplay * sizeof(pcm_channel)); - bzero(d->rec, numrec * sizeof(pcm_channel)); - - fkchan_setup(&d->fakechan); - chn_init(&d->fakechan, NULL, 0); - d->magic = MAGIC(unit); /* debugging... */ - - return 0; -no: - if (d->aplay) free(d->aplay, M_DEVBUF); - if (d->play) free(d->play, M_DEVBUF); - if (d->arec) free(d->arec, M_DEVBUF); - if (d->rec) free(d->rec, M_DEVBUF); - return ENXIO; -} - -/* - * a small utility function which, given a device number, returns - * a pointer to the associated snddev_info struct, and sets the unit - * number. - */ -static snddev_info * -get_snddev_info(dev_t i_dev, int *unit, int *dev, int *chan) -{ - int u, d, c; - - u = PCMUNIT(i_dev); - d = PCMDEV(i_dev); - c = PCMCHAN(i_dev); - if (u > devclass_get_maxunit(pcm_devclass)) u = -1; - if (unit) *unit = u; - if (dev) *dev = d; - if (chan) *chan = c; - if (u < 0) return NULL; - - switch(d) { - case SND_DEV_CTL: /* /dev/mixer handled by pcm */ - case SND_DEV_STATUS: /* /dev/sndstat handled by pcm */ - case SND_DEV_DSP: - case SND_DEV_DSP16: - case SND_DEV_AUDIO: - return gsd(u); - - case SND_DEV_SEQ: /* XXX when enabled... */ - case SND_DEV_SEQ2: - case SND_DEV_MIDIN: - case SND_DEV_SNDPROC: /* /dev/sndproc handled by pcm */ - default: - printf("unsupported subdevice %d\n", d); - return NULL; - } -} - -static int -sndopen(dev_t i_dev, int flags, int mode, struct proc *p) -{ - int dev, unit, chan; - snddev_info *d = get_snddev_info(i_dev, &unit, &dev, &chan); - - DEB(printf("open snd%d subdev %d flags 0x%08x mode 0x%08x\n", - unit, dev, flags, mode)); - - switch(dev) { - case SND_DEV_STATUS: - if (status_isopen) return EBUSY; - status_isopen = 1; - return 0; - - case SND_DEV_CTL: - return d? 0 : ENXIO; - - case SND_DEV_AUDIO: - case SND_DEV_DSP: - case SND_DEV_DSP16: - case SND_DEV_NORESET: - return d? dsp_open(d, chan, flags, dev) : ENXIO; - - default: - return ENXIO; - } -} - -static int -sndclose(dev_t i_dev, int flags, int mode, struct proc *p) -{ - int dev, unit, chan; - snddev_info *d = get_snddev_info(i_dev, &unit, &dev, &chan); - - DEB(printf("close snd%d subdev %d\n", unit, dev)); - - switch(dev) { /* only those for which close makes sense */ - case SND_DEV_STATUS: - if (!status_isopen) return EBADF; - status_isopen = 0; - return 0; - - case SND_DEV_CTL: - return d? 0 : ENXIO; - - case SND_DEV_AUDIO: - case SND_DEV_DSP: - case SND_DEV_DSP16: - return d? dsp_close(d, chan, dev) : ENXIO; - - default: - return ENXIO; - } -} - -static int -sndread(dev_t i_dev, struct uio *buf, int flag) -{ - int dev, unit, chan; - snddev_info *d = get_snddev_info(i_dev, &unit, &dev, &chan); - DEB(printf("read snd%d subdev %d flag 0x%08x\n", unit, dev, flag)); - - switch(dev) { - case SND_DEV_STATUS: - return status_isopen? status_read(buf) : EBADF; - - case SND_DEV_AUDIO: - case SND_DEV_DSP: - case SND_DEV_DSP16: - return d? dsp_read(d, chan, buf, flag) : EBADF; - - default: - return ENXIO; - } -} - -static int -sndwrite(dev_t i_dev, struct uio *buf, int flag) -{ - int dev, unit, chan; - snddev_info *d = get_snddev_info(i_dev, &unit, &dev, &chan); - - DEB(printf("write snd%d subdev %d flag 0x%08x\n", unit, dev & 0xf, flag)); - - switch(dev) { /* only writeable devices */ - case SND_DEV_DSP: - case SND_DEV_DSP16: - case SND_DEV_AUDIO: - return d? dsp_write(d, chan, buf, flag) : EBADF; - - default: - return EPERM; /* for non-writeable devices ; */ - } -} - -static int -sndioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc * p) -{ - int dev, chan; - snddev_info *d = get_snddev_info(i_dev, NULL, &dev, &chan); - - if (d == NULL) return ENXIO; - - switch(dev) { - case SND_DEV_CTL: - return mixer_ioctl(d, cmd, arg); - - case SND_DEV_AUDIO: - case SND_DEV_DSP: - case SND_DEV_DSP16: - return dsp_ioctl(d, chan, cmd, arg); - - default: - return ENXIO; - } -} - -static int -sndpoll(dev_t i_dev, int events, struct proc *p) -{ - int dev, chan; - snddev_info *d = get_snddev_info(i_dev, NULL, &dev, &chan); - - DEB(printf("sndpoll dev 0x%04x events 0x%08x\n", i_dev, events)); - - if (d == NULL) return ENXIO; - - switch(dev) { - case SND_DEV_AUDIO: - case SND_DEV_DSP: - case SND_DEV_DSP16: - return dsp_poll(d, chan, events, p); - - default: - return (events & - (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)) | POLLHUP; - } -} - -/* - * The mmap interface allows access to the play and read buffer, - * plus the device descriptor. - * The various blocks are accessible at the following offsets: - * - * 0x00000000 ( 0 ) : write buffer ; - * 0x01000000 (16 MB) : read buffer ; - * 0x02000000 (32 MB) : device descriptor (dangerous!) - * - * WARNING: the mmap routines assume memory areas are aligned. This - * is true (probably) for the dma buffers, but likely false for the - * device descriptor. As a consequence, we do not know where it is - * located in the requested area. - */ -static int -sndmmap(dev_t i_dev, vm_offset_t offset, int nprot) -{ - int unit, dev, chan; - snddev_info *d = get_snddev_info(i_dev, &unit, &dev, &chan); - - DEB(printf("sndmmap d 0x%p dev 0x%04x ofs 0x%08x nprot 0x%08x\n", - d, dev, offset, nprot)); - - if (d == NULL || nprot & PROT_EXEC) return -1; /* forbidden */ - - switch(dev) { - case SND_DEV_AUDIO: - case SND_DEV_DSP: - case SND_DEV_DSP16: - return dsp_mmap(d, chan, offset, nprot); - - default: - return -1; - } -} - -static int -status_init(char *buf, int size) -{ - int i; - device_t dev; - snddev_info *d; - - snprintf(buf, size, "FreeBSD Audio Driver (newpcm) %s %s\n" - "Installed devices:\n", __DATE__, __TIME__); - - for (i = 0; i <= devclass_get_maxunit(pcm_devclass); i++) { - d = gsd(i); - if (!d) continue; - dev = devclass_get_device(pcm_devclass, i); - if (1) snprintf(buf + strlen(buf), size - strlen(buf), - "pcm%d: <%s> %s (%d/%d channels%s)\n", - i, device_get_desc(dev), d->status, - d->playcount, d->reccount, - (!(d->flags & SD_F_SIMPLEX))? " duplex" : ""); - } - return strlen(buf); -} - -static int -status_read(struct uio *buf) -{ - static char status_buf[4096]; - static int bufptr = 0, buflen = 0; - int l; - - if (status_isopen == 1) { - status_isopen++; - bufptr = 0; - buflen = status_init(status_buf, sizeof status_buf); - } - - l = min(buf->uio_resid, buflen - bufptr); - bufptr += l; - return (l > 0)? uiomove(status_buf + bufptr - l, l, buf) : 0; -} - -#endif /* NPCM > 0 */ Property changes on: head/sys/dev/pcm/sound.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/ac97.h =================================================================== --- head/sys/dev/pcm/ac97.h (revision 53505) +++ head/sys/dev/pcm/ac97.h (nonexistent) @@ -1,35 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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$ - */ - -typedef u_int32_t (ac97_read)(void *devinfo, int regno); -typedef void (ac97_write)(void *devinfo, int regno, u_int32_t data); - -extern snd_mixer ac97_mixer; -struct ac97_info; - -struct ac97_info *ac97_create(void *devinfo, ac97_read *rd, ac97_write *wr); Property changes on: head/sys/dev/pcm/ac97.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/datatypes.h =================================================================== --- head/sys/dev/pcm/datatypes.h (revision 53505) +++ head/sys/dev/pcm/datatypes.h (nonexistent) @@ -1,162 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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$ - */ - -typedef struct _snd_mixer snd_mixer; -typedef struct _snd_dbuf snd_dbuf; -typedef struct _snddev_info snddev_info; -typedef struct _pcmchan_caps pcmchan_caps; -typedef struct _pcm_feeder pcm_feeder; -typedef struct _pcm_channel pcm_channel; - -typedef int (mix_set_t)(snd_mixer *m, unsigned dev, unsigned left, unsigned right); -typedef int (mix_recsrc_t)(snd_mixer *m, u_int32_t src); -typedef int (mix_init_t)(snd_mixer *m); - -struct _snd_mixer { - char name[64]; - mix_init_t *init; - mix_set_t *set; - mix_recsrc_t *setrecsrc; - - void *devinfo; - u_int32_t devs; - u_int32_t recdevs; - u_int32_t recsrc; - u_int16_t level[32]; -}; - -/* - * descriptor of a dma buffer. See dmabuf.c for documentation. - * (rp,rl) and (fp,fl) identify the READY and FREE regions of the - * buffer. dl contains the length used for dma transfer, dl>0 also - * means that the channel is busy and there is a DMA transfer in progress. - */ - -struct _snd_dbuf { - char *buf; - int bufsize; - volatile int rp, fp; /* pointers to the ready and free area */ - volatile int dl; /* transfer size */ - volatile int rl, fl; /* lenght of ready and free areas. */ - volatile u_int32_t int_count, prev_int_count; - int chan, dir; /* dma channel */ - int sample_size; /* 1, 2, 4 */ - struct selinfo sel; - u_long total; /* total bytes processed */ - u_long prev_total; /* copy of the above when GETxPTR called */ - int first_poll; - bus_dmamap_t dmamap; -}; - -typedef int (pcmfeed_init_t)(pcm_feeder *feeder); -typedef int (pcmfeed_free_t)(pcm_feeder *feeder); -typedef int (pcmfeed_feed_t)(pcm_feeder *feeder, pcm_channel *c, u_int8_t *buffer, - u_int32_t count, struct uio *stream); - -struct _pcm_feeder { - char name[16]; - int align; - pcmfeed_init_t *init; - pcmfeed_free_t *free; - pcmfeed_feed_t *feed; - void *data; - pcm_feeder *source; -}; - -struct _pcmchan_caps { - u_int32_t minspeed, maxspeed; - u_int32_t formats, bestfmt; -}; - -typedef void *(pcmchan_init_t)(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -typedef int (pcmchan_setdir_t)(void *data, int dir); -typedef int (pcmchan_setformat_t)(void *data, u_int32_t format); -typedef int (pcmchan_setspeed_t)(void *data, u_int32_t speed); -typedef int (pcmchan_setblocksize_t)(void *data, u_int32_t blocksize); -typedef int (pcmchan_trigger_t)(void *data, int go); -typedef int (pcmchan_getptr_t)(void *data); -typedef pcmchan_caps *(pcmchan_getcaps_t)(void *data); - -struct _pcm_channel { - pcmchan_init_t *init; - pcmchan_setdir_t *setdir; - pcmchan_setformat_t *setformat; - pcmchan_setspeed_t *setspeed; - pcmchan_setblocksize_t *setblocksize; - pcmchan_trigger_t *trigger; - pcmchan_getptr_t *getptr; - pcmchan_getcaps_t *getcaps; - pcm_feeder *feeder; - u_int32_t align; - - int volume; - u_int32_t speed; - u_int32_t flags; - u_int32_t format, hwfmt; - u_int32_t blocksize; - - int direction; - snd_dbuf buffer; -#define SMEGBUFSZ 4 - u_int8_t smegbuf[SMEGBUFSZ]; - u_int32_t smegcnt; - void *devinfo; -}; - -#define SND_STATUSLEN 64 -/* descriptor of audio device */ -struct _snddev_info { - pcm_channel *play, *rec, **aplay, **arec, fakechan; - unsigned playcount, reccount, chancount; - snd_mixer mixer; - u_long magic; - unsigned flags; - void *devinfo; - char status[SND_STATUSLEN]; -}; - -/* mixer description structure and macros - these should go away, - * only sb.[ch] and mss.[ch] use them - */ -struct mixer_def { - u_int regno:7; - u_int polarity:1; /* 1 means reversed */ - u_int bitoffs:4; - u_int nbits:4; -}; -typedef struct mixer_def mixer_ent; -typedef struct mixer_def mixer_tab[32][2]; - -#define MIX_ENT(name, reg_l, pol_l, pos_l, len_l, reg_r, pol_r, pos_r, len_r) \ - {{reg_l, pol_l, pos_l, len_l}, {reg_r, pol_r, pos_r, len_r}} - -#define PMIX_ENT(name, reg_l, pos_l, len_l, reg_r, pos_r, len_r) \ - {{reg_l, 0, pos_l, len_l}, {reg_r, 0, pos_r, len_r}} - -#define MIX_NONE(name) MIX_ENT(name, 0,0,0,0, 0,0,0,0) - Property changes on: head/sys/dev/pcm/datatypes.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/dsp.h =================================================================== --- head/sys/dev/pcm/dsp.h (revision 53505) +++ head/sys/dev/pcm/dsp.h (nonexistent) @@ -1,37 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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$ - */ - -int dsp_open(snddev_info *d, int chan, int oflags, int devtype); -int dsp_close(snddev_info *d, int chan, int devtype); -int dsp_read(snddev_info *d, int chan, struct uio *buf, int flag); -int dsp_write(snddev_info *d, int chan, struct uio *buf, int flag); -int dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg); -int dsp_poll(snddev_info *d, int chan, int events, struct proc *p); -int dsp_mmap(snddev_info *d, int chan, vm_offset_t offset, int nprot); - - Property changes on: head/sys/dev/pcm/dsp.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/feeder.c =================================================================== --- head/sys/dev/pcm/feeder.c (revision 53505) +++ head/sys/dev/pcm/feeder.c (nonexistent) @@ -1,416 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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 - -static int chn_addfeeder(pcm_channel *c, pcm_feeder *f); -static int chn_removefeeder(pcm_channel *c); - -#define FEEDBUFSZ 8192 - -static unsigned char ulaw_to_u8[] = { - 3, 7, 11, 15, 19, 23, 27, 31, - 35, 39, 43, 47, 51, 55, 59, 63, - 66, 68, 70, 72, 74, 76, 78, 80, - 82, 84, 86, 88, 90, 92, 94, 96, - 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, - 113, 114, 114, 115, 115, 116, 116, 117, - 117, 118, 118, 119, 119, 120, 120, 121, - 121, 121, 122, 122, 122, 122, 123, 123, - 123, 123, 124, 124, 124, 124, 125, 125, - 125, 125, 125, 125, 126, 126, 126, 126, - 126, 126, 126, 126, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 253, 249, 245, 241, 237, 233, 229, 225, - 221, 217, 213, 209, 205, 201, 197, 193, - 190, 188, 186, 184, 182, 180, 178, 176, - 174, 172, 170, 168, 166, 164, 162, 160, - 158, 157, 156, 155, 154, 153, 152, 151, - 150, 149, 148, 147, 146, 145, 144, 143, - 143, 142, 142, 141, 141, 140, 140, 139, - 139, 138, 138, 137, 137, 136, 136, 135, - 135, 135, 134, 134, 134, 134, 133, 133, - 133, 133, 132, 132, 132, 132, 131, 131, - 131, 131, 131, 131, 130, 130, 130, 130, - 130, 130, 130, 130, 129, 129, 129, 129, - 129, 129, 129, 129, 129, 129, 129, 129, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, -}; - -static unsigned char u8_to_ulaw[] = { - 0, 0, 0, 0, 0, 1, 1, 1, - 1, 2, 2, 2, 2, 3, 3, 3, - 3, 4, 4, 4, 4, 5, 5, 5, - 5, 6, 6, 6, 6, 7, 7, 7, - 7, 8, 8, 8, 8, 9, 9, 9, - 9, 10, 10, 10, 10, 11, 11, 11, - 11, 12, 12, 12, 12, 13, 13, 13, - 13, 14, 14, 14, 14, 15, 15, 15, - 15, 16, 16, 17, 17, 18, 18, 19, - 19, 20, 20, 21, 21, 22, 22, 23, - 23, 24, 24, 25, 25, 26, 26, 27, - 27, 28, 28, 29, 29, 30, 30, 31, - 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, - 47, 49, 51, 53, 55, 57, 59, 61, - 63, 66, 70, 74, 78, 84, 92, 104, - 254, 231, 219, 211, 205, 201, 197, 193, - 190, 188, 186, 184, 182, 180, 178, 176, - 175, 174, 173, 172, 171, 170, 169, 168, - 167, 166, 165, 164, 163, 162, 161, 160, - 159, 159, 158, 158, 157, 157, 156, 156, - 155, 155, 154, 154, 153, 153, 152, 152, - 151, 151, 150, 150, 149, 149, 148, 148, - 147, 147, 146, 146, 145, 145, 144, 144, - 143, 143, 143, 143, 142, 142, 142, 142, - 141, 141, 141, 141, 140, 140, 140, 140, - 139, 139, 139, 139, 138, 138, 138, 138, - 137, 137, 137, 137, 136, 136, 136, 136, - 135, 135, 135, 135, 134, 134, 134, 134, - 133, 133, 133, 133, 132, 132, 132, 132, - 131, 131, 131, 131, 130, 130, 130, 130, - 129, 129, 129, 129, 128, 128, 128, 128, -}; - -/*****************************************************************************/ - -static int -feed_root(pcm_feeder *feeder, pcm_channel *ch, u_int8_t *buffer, u_int32_t count, struct uio *stream) -{ - int ret, tmp = 0, c = 0; - if (!count) panic("feed_root: count == 0"); - count &= ~((1 << ch->align) - 1); - if (!count) panic("feed_root: aligned count == 0"); - if (ch->smegcnt > 0) { - c = min(ch->smegcnt, count); - bcopy(ch->smegbuf, buffer, c); - ch->smegcnt -= c; - } - while ((stream->uio_resid > 0) && (c < count)) { - tmp = stream->uio_resid; - ret = uiomove(buffer + c, count - c, stream); - if (ret) panic("feed_root: uiomove failed"); - tmp -= stream->uio_resid; - c += tmp; - } - if (!c) panic("feed_root: uiomove didn't"); - return c; -} -pcm_feeder feeder_root = { "root", 0, NULL, NULL, feed_root }; - -/*****************************************************************************/ - -static int -feed_8to16(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream) -{ - int i, j, k; - k = f->source->feed(f->source, c, b, count / 2, stream); - j = k - 1; - i = j * 2 + 1; - while (i > 0 && j >= 0) { - b[i--] = b[j--]; - b[i--] = 0; - } - return k * 2; -} -static pcm_feeder feeder_8to16 = { "8to16", 0, NULL, NULL, feed_8to16 }; - -/*****************************************************************************/ - -static int -feed_16to8_init(pcm_feeder *f) -{ - f->data = malloc(FEEDBUFSZ, M_DEVBUF, M_NOWAIT); - return (f->data == NULL); -} - -static int -feed_16to8_free(pcm_feeder *f) -{ - if (f->data) free(f->data, M_DEVBUF); - f->data = NULL; - return 0; -} - -static int -feed_16to8le(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream) -{ - u_int32_t i = 0, toget = count * 2; - int j = 1, k; - k = f->source->feed(f->source, c, f->data, min(toget, FEEDBUFSZ), stream); - while (j < k) { - b[i++] = ((u_int8_t *)f->data)[j]; - j += 2; - } - return i; -} -static pcm_feeder feeder_16to8le = - { "16to8le", 1, feed_16to8_init, feed_16to8_free, feed_16to8le }; - -/*****************************************************************************/ - -static int -feed_monotostereo8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream) -{ - int i, j, k = f->source->feed(f->source, c, b, count / 2, stream); - j = k - 1; - i = j * 2 + 1; - while (i > 0 && j >= 0) { - b[i--] = b[j]; - b[i--] = b[j]; - j--; - } - return k * 2; -} -static pcm_feeder feeder_monotostereo8 = - { "monotostereo8", 0, NULL, NULL, feed_monotostereo8 }; - -/*****************************************************************************/ - -static int -feed_stereotomono8_init(pcm_feeder *f) -{ - f->data = malloc(FEEDBUFSZ, M_DEVBUF, M_NOWAIT); - return (f->data == NULL); -} - -static int -feed_stereotomono8_free(pcm_feeder *f) -{ - if (f->data) free(f->data, M_DEVBUF); - f->data = NULL; - return 0; -} - -static int -feed_stereotomono8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream) -{ - u_int32_t i = 0, toget = count * 2; - int j = 0, k; - k = f->source->feed(f->source, c, f->data, min(toget, FEEDBUFSZ), stream); - while (j < k) { - b[i++] = ((u_int8_t *)f->data)[j]; - j += 2; - } - return i; -} -static pcm_feeder feeder_stereotomono8 = - { "stereotomono8", 1, feed_stereotomono8_init, feed_stereotomono8_free, - feed_stereotomono8 }; - -/*****************************************************************************/ - -static int -feed_endian(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream) -{ - u_int8_t t; - int i = 0, j = f->source->feed(f->source, c, b, count, stream); - while (i < j) { - t = b[i]; - b[i] = b[i + 1]; - b[i + 1] = t; - i += 2; - } - return i; -} -static pcm_feeder feeder_endian = { "endian", -1, NULL, NULL, feed_endian }; - -/*****************************************************************************/ - -static int -feed_sign(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream) -{ - int i = 0, j = f->source->feed(f->source, c, b, count, stream); - int ssz = (int)f->data, ofs = ssz - 1; - while (i < j) { - b[i + ofs] ^= 0x80; - i += ssz; - } - return i; -} -static pcm_feeder feeder_sign8 = - { "sign8", 0, NULL, NULL, feed_sign, (void *)1 }; -static pcm_feeder feeder_sign16 = - { "sign16", -1, NULL, NULL, feed_sign, (void *)2 }; - -/*****************************************************************************/ - -static int -feed_table(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream) -{ - int i = 0, j = f->source->feed(f->source, c, b, count, stream); - while (i < j) { - b[i] = ((u_int8_t *)f->data)[b[i]]; - i++; - } - return i; -} -static pcm_feeder feeder_ulawtou8 = - { "ulawtou8", 0, NULL, NULL, feed_table, ulaw_to_u8 }; -static pcm_feeder feeder_u8toulaw = - { "u8toulaw", 0, NULL, NULL, feed_table, u8_to_ulaw }; - -/*****************************************************************************/ - -struct fmtspec { - int stereo; - int sign; - int bit16; - int bigendian; - int ulaw; - int bad; -}; - -struct fmtcvt { - pcm_feeder *f; - struct fmtspec ispec, ospec; -}; - -struct fmtcvt cvttab[] = { - {&feeder_ulawtou8, {-1, 0, 0, 0, 1}, {-1, 0, 0, 0, 0}}, - {&feeder_u8toulaw, {-1, 0, 0, 0, 0}, {-1, 0, 0, 0, 1}}, - {&feeder_sign8, {-1, 0, 0, 0, 0}, {-1, 1, 0, 0, 0}}, - {&feeder_sign8, {-1, 1, 0, 0, 0}, {-1, 0, 0, 0, 0}}, - {&feeder_monotostereo8, { 0, -1, 0, 0, -1}, { 1, -1, 0, 0, -1}}, - {&feeder_stereotomono8, { 1, -1, 0, 0, -1}, { 0, -1, 0, 0, -1}}, - {&feeder_sign16, {-1, 0, 1, 0, 0}, {-1, 1, 1, 0, 0}}, - {&feeder_sign16, {-1, 1, 1, 0, 0}, {-1, 0, 1, 0, 0}}, - {&feeder_8to16, {-1, -1, 0, 0, 0}, {-1, -1, 1, 0, 0}}, - {&feeder_16to8le, {-1, -1, 1, 0, 0}, {-1, -1, 0, 0, 0}}, - {&feeder_endian, {-1, -1, 1, 0, 0}, {-1, -1, 1, 1, 0}}, - {&feeder_endian, {-1, -1, 1, 1, 0}, {-1, -1, 1, 0, 0}}, -}; -#define FEEDERTABSZ (sizeof(cvttab) / sizeof(struct fmtcvt)) - -static int -getspec(u_int32_t fmt, struct fmtspec *spec) -{ - spec->stereo = (fmt & AFMT_STEREO)? 1 : 0; - spec->sign = (fmt & AFMT_SIGNED)? 1 : 0; - spec->bit16 = (fmt & AFMT_16BIT)? 1 : 0; - spec->bigendian = (fmt & AFMT_BIGENDIAN)? 1 : 0; - spec->ulaw = (fmt & AFMT_MU_LAW)? 1 : 0; - spec->bad = (fmt & (AFMT_A_LAW | AFMT_MPEG))? 1 : 0; - return 0; -} - -static int -cmp(int x, int y) -{ - return (x == -1 || x == y || y == -1)? 1 : 0; -} - -static int -cmpspec(struct fmtspec *x, struct fmtspec *y) -{ - int i = 0; - if (cmp(x->stereo, y->stereo)) i |= 0x01; - if (cmp(x->sign, y->sign)) i |= 0x02; - if (cmp(x->bit16, y->bit16)) i |= 0x04; - if (cmp(x->bigendian, y->bigendian)) i |= 0x08; - if (cmp(x->ulaw, y->ulaw)) i |= 0x10; - return i; -} - -static int -cvtapply(pcm_channel *c, struct fmtcvt *cvt, struct fmtspec *s) -{ - int i = cmpspec(s, &cvt->ospec); - chn_addfeeder(c, cvt->f); - if (cvt->ospec.stereo != -1) s->stereo = cvt->ospec.stereo; - if (cvt->ospec.sign != -1) s->sign = cvt->ospec.sign; - if (cvt->ospec.bit16 != -1) s->bit16 = cvt->ospec.bit16; - if (cvt->ospec.bigendian != -1) s->bigendian = cvt->ospec.bigendian; - if (cvt->ospec.ulaw != -1) s->ulaw = cvt->ospec.ulaw; - return i; -} - -int -chn_feedchain(pcm_channel *c) -{ - int i, chosen, iter; - u_int32_t mask; - struct fmtspec s, t; - struct fmtcvt *e; - - while (chn_removefeeder(c) != -1); - c->align = 0; - if ((c->format & chn_getcaps(c)->formats) == c->format) - return c->format; - getspec(c->format, &s); - if (s.bad) return -1; - getspec(chn_getcaps(c)->bestfmt, &t); - mask = (~cmpspec(&s, &t)) & 0x1f; - iter = 0; - do { - if (mask == 0 || iter >= 8) break; - chosen = -1; - for (i = 0; i < FEEDERTABSZ && chosen == -1; i++) { - e = &cvttab[i]; - if ((cmpspec(&s, &e->ispec) == 0x1f) && - ((~cmpspec(&e->ispec, &e->ospec)) & mask)) - chosen = i; - } - if (chosen != -1) mask &= cvtapply(c, &cvttab[chosen], &s); - iter++; - } while (chosen != -1); - return (iter < 8)? chn_getcaps(c)->bestfmt : -1; -} - -static int -chn_addfeeder(pcm_channel *c, pcm_feeder *f) -{ - pcm_feeder *n; - n = malloc(sizeof(pcm_feeder), M_DEVBUF, M_NOWAIT); - *n = *f; - n->source = c->feeder; - c->feeder = n; - if (n->init) n->init(n); - if (n->align > 0) c->align += n->align; - else if (n->align < 0 && c->align < -n->align) c->align -= n->align; - return 0; -} - -static int -chn_removefeeder(pcm_channel *c) -{ - pcm_feeder *f; - if (c->feeder == &feeder_root) return -1; - f = c->feeder->source; - if (c->feeder->free) c->feeder->free(c->feeder); - free(c->feeder, M_DEVBUF); - c->feeder = f; - return 0; -} - Property changes on: head/sys/dev/pcm/feeder.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/sound.h =================================================================== --- head/sys/dev/pcm/sound.h (revision 53505) +++ head/sys/dev/pcm/sound.h (nonexistent) @@ -1,182 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * Copyright by Hannu Savolainen 1995 - * 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$ - */ - -#ifdef KERNEL -#include "pcm.h" -#else -#error why? -#define NPCM 1 -#endif -#if NPCM > 0 - -/* - * first, include kernel header files. - */ - -#ifndef _OS_H_ -#define _OS_H_ - -#ifdef KERNEL -#include -#include -#include - -#include -#include -#include -#include -#include - -#include /* for DATA_SET */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for DELAY */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#else -struct isa_device { int dummy; }; -#define d_open_t void -#define d_close_t void -#define d_read_t void -#define d_write_t void -#define d_ioctl_t void -#define d_select_t void -#endif /* KERNEL */ - -#endif /* _OS_H_ */ - -#include -#include -#include -#include - -#define MAGIC(unit) (0xa4d10de0 + unit) - -#define SD_F_SIMPLEX 0x00000001 -#define SD_F_EVILSB16 0x00000002 -#define SD_F_PRIO_RD 0x10000000 -#define SD_F_PRIO_WR 0x20000000 -#define SD_F_PRIO_SET (SD_F_PRIO_RD | SD_F_PRIO_WR) -#define SD_F_DIR_SET 0x40000000 -#define SD_F_TRANSIENT 0xf0000000 - -/* many variables should be reduced to a range. Here define a macro */ -#define RANGE(var, low, high) (var) = \ - (((var)<(low))? (low) : ((var)>(high))? (high) : (var)) - -#define DSP_BUFFSIZE (65536 - 256) /* XXX */ -/* the last 256 bytes are room for buggy soundcard to overflow. */ - -/* make figuring out what a format is easier. got AFMT_STEREO already */ -#define AFMT_16BIT (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE) -#define AFMT_SIGNED (AFMT_S16_LE | AFMT_S16_BE | AFMT_S8) -#define AFMT_BIGENDIAN (AFMT_S16_BE | AFMT_U16_BE) - -int fkchan_setup(pcm_channel *c); - -#ifdef KERNEL -#include "pnp.h" -#endif /* KERNEL */ - -/* - * Minor numbers for the sound driver. - * - * Unfortunately Creative called the codec chip of SB as a DSP. For this - * reason the /dev/dsp is reserved for digitized audio use. There is a - * device for true DSP processors but it will be called something else. - * In v3.0 it's /dev/sndproc but this could be a temporary solution. - */ - -#define SND_DEV_CTL 0 /* Control port /dev/mixer */ -#define SND_DEV_SEQ 1 /* Sequencer /dev/sequencer */ -#define SND_DEV_MIDIN 2 /* Raw midi access */ -#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */ -#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */ -#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */ -#define SND_DEV_STATUS 6 /* /dev/sndstat */ - /* #7 not in use now. */ -#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */ -#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */ -#define SND_DEV_PSS SND_DEV_SNDPROC /* ? */ -#define SND_DEV_NORESET 10 - -#define DSP_DEFAULT_SPEED 8000 - -#define ON 1 -#define OFF 0 - -#ifdef KERNEL - -/* - * some macros for debugging purposes - * DDB/DEB to enable/disable debugging stuff - * BVDDB to enable debugging when bootverbose - */ -#define DDB(x) x /* XXX */ -#define BVDDB(x) if (bootverbose) x - -#ifndef DEB -#define DEB(x) -#endif - -int pcm_addchan(device_t dev, int dir, pcm_channel *templ, void *devinfo); -int pcm_register(device_t dev, void *devinfo, int numplay, int numrec); -int pcm_setstatus(device_t dev, char *str); -u_int32_t pcm_getflags(device_t dev); -void pcm_setflags(device_t dev, u_int32_t val); - -#endif /* KERNEL */ - -/* usage of flags in device config entry (config file) */ -#define DV_F_DRQ_MASK 0x00000007 /* mask for secondary drq */ -#define DV_F_DUAL_DMA 0x00000010 /* set to use secondary dma channel */ - -/* ought to be made obsolete */ -#define DV_F_DEV_MASK 0x0000ff00 /* force device type/class */ -#define DV_F_DEV_SHIFT 8 /* force device type/class */ - -#endif Property changes on: head/sys/dev/pcm/sound.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/channel.c =================================================================== --- head/sys/dev/pcm/channel.c (revision 53505) +++ head/sys/dev/pcm/channel.c (nonexistent) @@ -1,746 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * Portions Copyright by Luigi Rizzo - 1997-99 - * 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 - -#define MIN_CHUNK_SIZE 256 /* for uiomove etc. */ -#define DMA_ALIGN_THRESHOLD 4 -#define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1)) - -#define ISA_DMA(b) (((b)->chan >= 0 && (b)->chan != 4 && (b)->chan < 8)) -#define CANCHANGE(c) (!(c)->buffer.dl) - -static void chn_stintr(pcm_channel *c); -/* - * SOUND OUTPUT - -We use a circular buffer to store samples directed to the DAC. -The buffer is split into two variable-size regions, each identified -by an offset in the buffer (rp,fp) and a length (rl,fl): - - 0 rp,rl fp,fl bufsize - |__________>____________>________| - FREE d READY w FREE - - READY: data written from the process and ready to be sent to the DAC; - FREE: free part of the buffer. - -Both regions can wrap around the end of the buffer. At initialization, -READY is empty, FREE takes all the available space, and dma is -idle. dl contains the length of the current DMA transfer, dl=0 -means that the dma is idle. - -The two boundaries (rp,fp) in the buffers are advanced by DMA [d] -and write() [w] operations. The first portion of the READY region -is used for DMA transfers. The transfer is started at rp and with -chunks of length dl. During DMA operations, dsp_wr_dmaupdate() -updates rp, rl and fl tracking the ISA DMA engine as the transfer -makes progress. -When a new block is written, fp advances and rl,fl are updated -accordingly. - -The code works as follows: the user write routine dsp_write_body() -fills up the READY region with new data (reclaiming space from the -FREE region) and starts the write DMA engine if inactive. When a -DMA transfer is complete, an interrupt causes dsp_wrintr() to be -called which extends the FREE region and possibly starts the next -transfer. - -In some cases, the code tries to track the current status of DMA -operations by calling dsp_wr_dmaupdate() which changes rp, rl and fl. - -The sistem tries to make all DMA transfers use the same size, -play_blocksize or rec_blocksize. The size is either selected by -the user, or computed by the system to correspond to about .25s of -audio. The blocksize must be within a range which is currently: - - min(5ms, 40 bytes) ... 1/2 buffer size. - -When there aren't enough data (write) or space (read), a transfer -is started with a reduced size. - -To reduce problems in case of overruns, the routine which fills up -the buffer should initialize (e.g. by repeating the last value) a -reasonably long area after the last block so that no noise is -produced on overruns. - - * - */ - - -/* XXX this is broken: in the event a bounce buffer is used, data never - * gets copied in or out of the real buffer. fix requires mods to isa_dma.c - * and possibly fixes to other autodma mode clients - */ -static void -chn_isadmabounce(pcm_channel *c) -{ - if (ISA_DMA(&c->buffer)) { - /* tell isa_dma to bounce data in/out */ - } else panic("chn_isadmabounce called on invalid channel"); -} - -static int -chn_polltrigger(pcm_channel *c) -{ - snd_dbuf *b = &c->buffer; - unsigned lim = (c->flags & CHN_F_HAS_SIZE)? c->blocksize : 1; - int trig = 0; - - if (c->flags & CHN_F_MAPPED) - trig = ((b->int_count > b->prev_int_count) || b->first_poll); - else trig = (((c->direction == PCMDIR_PLAY)? b->fl : b->rl) >= lim); - return trig; -} - -static int -chn_pollreset(pcm_channel *c) -{ - snd_dbuf *b = &c->buffer; - - if (c->flags & CHN_F_MAPPED) b->prev_int_count = b->int_count; - b->first_poll = 0; - return 1; -} - -/* - * chn_dmadone() updates pointers and wakes up any process sleeping - * or waiting on a select(). - * Must be called at spltty(). - */ -static void -chn_dmadone(pcm_channel *c) -{ - snd_dbuf *b = &c->buffer; - - chn_dmaupdate(c); - if (ISA_DMA(b)) chn_isadmabounce(c); /* sync bounce buffer */ - wakeup(b); - b->int_count++; - if (b->sel.si_pid && chn_polltrigger(c)) selwakeup(&b->sel); -} - -/* - * chn_dmaupdate() tracks the status of a dma transfer, - * updating pointers. It must be called at spltty(). - * - * NOTE: when we are using auto dma in the device, rl might become - * negative. - */ -void -chn_dmaupdate(pcm_channel *c) -{ - snd_dbuf *b = &c->buffer; - int delta, hwptr = chn_getptr(c); - - if (c->direction == PCMDIR_PLAY) { - delta = (b->bufsize + hwptr - b->rp) % b->bufsize; - b->rp = hwptr; - b->rl -= delta; - b->fl += delta; - } else { - delta = (b->bufsize + hwptr - b->fp) % b->bufsize; - b->fp = hwptr; - b->rl += delta; - b->fl -= delta; - } - b->total += delta; -} - -/* - * Write interrupt routine. Can be called from other places (e.g. - * to start a paused transfer), but with interrupts disabled. - */ -static void -chn_wrintr(pcm_channel *c) -{ - snd_dbuf *b = &c->buffer; - int start; - - if (b->dl) chn_dmadone(c); - - /* - * start another dma operation only if have ready data in the buffer, - * there is no pending abort, have a full-duplex device, or have a - * half duplex device and there is no pending op on the other side. - * - * Force transfers to be aligned to a boundary of 4, which is - * needed when doing stereo and 16-bit. - */ - if (c->flags & CHN_F_MAPPED) start = c->flags & CHN_F_TRIGGERED; - else start = (b->rl >= DMA_ALIGN_THRESHOLD && !(c->flags & CHN_F_ABORTING)); - if (start) { - int l; - chn_dmaupdate(c); - l = min(b->rl, c->blocksize) & DMA_ALIGN_MASK; - if (c->flags & CHN_F_MAPPED) l = c->blocksize; - /* - * check if we need to reprogram the DMA on the sound card. - * This happens if the size has changed _and_ the new size - * is smaller, or it matches the blocksize. - * - * 0 <= l <= blocksize - * 0 <= dl <= blocksize - * reprog if (dl == 0 || l != dl) - * was: - * l != b->dl && (b->dl == 0 || l < b->dl || l == c->blocksize) - */ - if (b->dl == 0 || l != b->dl) { - /* size has changed. Stop and restart */ - DEB(printf("wrintr: bsz %d -> %d, rp %d rl %d\n", - b->dl, l, b->rp, b->rl)); - if (b->dl) chn_trigger(c, PCMTRIG_STOP); - b->dl = l; /* record new transfer size */ - chn_trigger(c, PCMTRIG_START); - } - } else { - /* cannot start a new dma transfer */ - DEB(printf("cannot start wr-dma flags 0x%08x rp %d rl %d\n", - c->flags, b->rp, b->rl)); - if (b->dl) { /* was active */ - b->dl = 0; - chn_trigger(c, PCMTRIG_STOP); -#if 0 - if (c->flags & CHN_F_WRITING) - DEB(printf("got wrint while reloading\n")); - else if (b->rl <= 0) /* XXX added 980110 lr */ - chn_resetbuf(c); -#endif - } - } -} - -/* - * user write routine - * - * advance the boundary between READY and FREE, fill the space with - * uiomove(), and possibly start DMA. Do the above until the transfer - * is complete. - * - * To minimize latency in case a pending DMA transfer is about to end, - * we do the transfer in pieces of increasing sizes, extending the - * READY area at every checkpoint. In the (necessary) assumption that - * memory bandwidth is larger than the rate at which the dma consumes - * data, we reduce the latency to something proportional to the length - * of the first piece, while keeping the overhead low and being able - * to feed the DMA with large blocks. - */ - -int -chn_write(pcm_channel *c, struct uio *buf) -{ - int a, l, w, timeout, ret = 0; - long s; - snd_dbuf *b = &c->buffer; - - if (c->flags & CHN_F_WRITING) { - /* This shouldn't happen and is actually silly - * - will never wake up, just timeout; why not sleep on b? - */ - tsleep(&s, PZERO, "pcmwrW", hz); - return EBUSY; - } - a = (1 << c->align) - 1; - c->flags |= CHN_F_WRITING; - while ((c->smegcnt + buf->uio_resid) > a) { - s = spltty(); - chn_dmaupdate(c); - splx(s); - if (b->fl < DMA_ALIGN_THRESHOLD) { - if (c->flags & CHN_F_NBIO) break; - timeout = (buf->uio_resid >= b->dl)? hz : 1; - ret = tsleep(b, PRIBIO | PCATCH, "pcmwr", timeout); - if (ret == EINTR) chn_abort(c); - if (ret == EINTR || ret == ERESTART) break; - ret = 0; - continue; - } - /* ensure we always have a whole number of samples */ - l = min(b->fl, b->bufsize - b->fp) & ~a; - if (l == 0) break; - w = c->feeder->feed(c->feeder, c, b->buf + b->fp, l, buf); - if (w == 0) panic("no feed"); - s = spltty(); - b->rl += w; - b->fl -= w; - b->fp = (b->fp + w) % b->bufsize; - splx(s); - if (b->rl && !b->dl) chn_stintr(c); - } - if ((ret == 0) && (buf->uio_resid > 0)) { - l = buf->uio_resid; - if ((c->smegcnt + l) >= SMEGBUFSZ) panic("resid overflow %d", l); - uiomove(c->smegbuf + c->smegcnt, l, buf); - c->smegcnt += l; - } - c->flags &= ~CHN_F_WRITING; - return ret; -} - -/* - * SOUND INPUT - * - -The input part is similar to the output one, with a circular buffer -split in two regions, and boundaries advancing because of read() calls -[r] or dma operation [d]. At initialization, as for the write -routine, READY is empty, and FREE takes all the space. - - 0 rp,rl fp,fl bufsize - |__________>____________>________| - FREE r READY d FREE - -Operation is as follows: upon user read (dsp_read_body()) a DMA read -is started if not already active (marked by b->dl > 0), -then as soon as data are available in the READY region they are -transferred to the user buffer, thus advancing the boundary between FREE -and READY. Upon interrupts, caused by a completion of a DMA transfer, -the READY region is extended and possibly a new transfer is started. - -When necessary, dsp_rd_dmaupdate() is called to advance fp (and update -rl,fl accordingly). Upon user reads, rp is advanced and rl,fl are -updated accordingly. - -The rules to choose the size of the new DMA area are similar to -the other case, with a preferred constant transfer size equal to -rec_blocksize, and fallback to smaller sizes if no space is available. - - */ - -/* read interrupt routine. Must be called with interrupts blocked. */ -static void -chn_rdintr(pcm_channel *c) -{ - snd_dbuf *b = &c->buffer; - int start; - - if (b->dl) chn_dmadone(c); - - DEB(printf("rdintr: start dl %d, rp:rl %d:%d, fp:fl %d:%d\n", - b->dl, b->rp, b->rl, b->fp, b->fl)); - /* Restart if have enough free space to absorb overruns */ - if (c->flags & CHN_F_MAPPED) start = c->flags & CHN_F_TRIGGERED; - else start = (b->fl > 0x200 && !(c->flags & CHN_F_ABORTING)); - if (start) { - int l = min(b->fl - 0x100, c->blocksize); - if (c->flags & CHN_F_MAPPED) l = c->blocksize; - l &= DMA_ALIGN_MASK ; /* realign sizes */ - - DEB(printf("rdintr: dl %d -> %d\n", b->dl, l);) - if (l != b->dl) { - /* size has changed. Stop and restart */ - if (b->dl) { - chn_trigger(c, PCMTRIG_STOP); - chn_dmaupdate(c); - l = min(b->fl - 0x100, c->blocksize); - l &= DMA_ALIGN_MASK ; /* realign sizes */ - } - b->dl = l; - chn_trigger(c, PCMTRIG_START); - } - } else { - if (b->dl) { /* was active */ - b->dl = 0; - chn_dmaupdate(c); - chn_trigger(c, PCMTRIG_STOP); - } - } -} - -/* - * body of user-read routine - * - * Start DMA if not active; wait for READY not empty. - * Transfer data from READY region using uiomove(), advance boundary - * between FREE and READY. Repeat until transfer is complete. - * - * To avoid excessive latency in freeing up space for the DMA - * engine, transfers are done in blocks of increasing size, so that - * the latency is proportional to the size of the smallest block, but - * we have a low overhead and are able to feed the dma engine with - * large blocks. - * - * NOTE: in the current version, read will not return more than - * blocksize bytes at once (unless more are already available), to - * avoid that requests using very large buffers block for too long. - */ - -int -chn_read(pcm_channel *c, struct uio *buf) -{ - int w, l, timeout, limit, ret = 0; - long s; - snd_dbuf *b = &c->buffer; - - if (c->flags & CHN_F_READING) { - /* This shouldn't happen and is actually silly */ - tsleep(&s, PZERO, "pcmrdR", hz); - return (EBUSY); - } - - if (!b->rl & !b->dl) chn_stintr(c); - c->flags |= CHN_F_READING; - limit = buf->uio_resid - c->blocksize; - if (limit < 0) limit = 0; - while (buf->uio_resid > limit) { - s = spltty(); - chn_dmaupdate(c); - splx(s); - if (b->rl < DMA_ALIGN_THRESHOLD) { - if (c->flags & CHN_F_NBIO) break; - timeout = (buf->uio_resid - limit >= b->dl)? hz : 1; - ret = tsleep(b, PRIBIO | PCATCH, "pcmrd", timeout); - if (ret == EINTR) chn_abort(c); - if (ret == EINTR || ret == ERESTART) break; - ret = 0; - continue; - } - /* ensure we always have a whole number of samples */ - l = min(b->rl, b->bufsize - b->rp) & DMA_ALIGN_MASK; - w = c->feeder->feed(c->feeder, c, b->buf + b->rp, l, buf); - s = spltty(); - b->rl -= w; - b->fl += w; - b->rp = (b->rp + w) % b->bufsize; - splx(s); - } - c->flags &= ~CHN_F_READING; - return ret; -} - -void -chn_intr(pcm_channel *c) -{ -/* if (!c->buffer.dl) chn_reinit(c); -*/ if (c->direction == PCMDIR_PLAY) chn_wrintr(c); else chn_rdintr(c); -} - -static void -chn_stintr(pcm_channel *c) -{ - u_long s; - s = spltty(); - chn_intr(c); - splx(s); -} - -static void -chn_dma_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - snd_dbuf *b = (snd_dbuf *)arg; - - if (bootverbose) { - printf("pcm: setmap %lx, %lx; ", (unsigned long)segs->ds_addr, - (unsigned long)segs->ds_len); - printf("%p -> %lx\n", b->buf, (unsigned long)vtophys(b->buf)); - } -} - -int -chn_allocbuf(snd_dbuf *b, bus_dma_tag_t parent_dmat) -{ - if (bus_dmamem_alloc(parent_dmat, (void **)&b->buf, - BUS_DMA_NOWAIT, &b->dmamap)) return -1; - if (bus_dmamap_load(parent_dmat, b->dmamap, b->buf, - b->bufsize, chn_dma_setmap, b, 0)) return -1; - return 0; -} - -void -chn_resetbuf(pcm_channel *c) -{ - snd_dbuf *b = &c->buffer; - u_int16_t data, *p; - u_int32_t i; - - c->smegcnt = 0; - c->buffer.sample_size = 1; - c->buffer.sample_size <<= (c->hwfmt & AFMT_STEREO)? 1 : 0; - c->buffer.sample_size <<= (c->hwfmt & AFMT_16BIT)? 1 : 0; - /* rely on bufsize & 3 == 0 */ - if (c->hwfmt & AFMT_SIGNED) data = 0x00; else data = 0x80; - if (c->hwfmt & AFMT_16BIT) data <<= 8; else data |= data << 8; - if (c->hwfmt & AFMT_BIGENDIAN) - data = ((data >> 8) & 0x00ff) | ((data << 8) & 0xff00); - for (i = 0, p = (u_int16_t *)b->buf; i < b->bufsize; i += 2) - *p++ = data; - b->rp = b->fp = 0; - b->dl = b->rl = 0; - b->prev_total = b->total = 0; - b->prev_int_count = b->int_count = 0; - b->first_poll = 1; - b->fl = b->bufsize; -} - -void -buf_isadma(snd_dbuf *b, int go) -{ - if (ISA_DMA(b)) { - if (go == PCMTRIG_START) isa_dmastart(b->dir | B_RAW, b->buf, - b->bufsize, b->chan); - else { - isa_dmastop(b->chan); - isa_dmadone(b->dir | B_RAW, b->buf, b->bufsize, - b->chan); - } - } else panic("buf_isadma called on invalid channel"); -} - -int -buf_isadmaptr(snd_dbuf *b) -{ - if (ISA_DMA(b)) { - int i = b->dl? isa_dmastatus(b->chan) : b->bufsize; - if (i < 0) i = 0; - return b->bufsize - i; - } else panic("buf_isadmaptr called on invalid channel"); - return -1; -} - -/* - * snd_sync waits until the space in the given channel goes above - * a threshold. The threshold is checked against fl or rl respectively. - * Assume that the condition can become true, do not check here... - */ -int -chn_sync(pcm_channel *c, int threshold) -{ - u_long s, rdy; - int ret; - snd_dbuf *b = &c->buffer; - - for (;;) { - s = spltty(); - chn_dmaupdate(c); - rdy = (c->direction == PCMDIR_PLAY)? b->fl : b->rl; - if (rdy <= threshold) { - ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmsyn", 1); - splx(s); - if (ret == ERESTART || ret == EINTR) { - printf("tsleep returns %d\n", ret); - return -1; - } - } else break; - } - splx(s); - return 0; -} - -int -chn_poll(pcm_channel *c, int ev, struct proc *p) -{ - snd_dbuf *b = &c->buffer; - u_long s = spltty(); - if (b->dl) chn_dmaupdate(c); - splx(s); - if (chn_polltrigger(c) && chn_pollreset(c)) return ev; - else { - selrecord(p, &b->sel); - return 0; - } -} - -/* - * chn_abort is a non-blocking function which aborts a pending - * DMA transfer and flushes the buffers. - * It returns the number of bytes that have not been transferred. - */ -int -chn_abort(pcm_channel *c) -{ - long s; - int missing = 0; - snd_dbuf *b = &c->buffer; - - s = spltty(); - if (b->dl) { - b->dl = 0; - c->flags &= ~((c->direction == PCMDIR_PLAY)? CHN_F_WRITING : CHN_F_READING); - chn_trigger(c, PCMTRIG_ABORT); - chn_dmadone(c); - } - missing = b->rl; - splx(s); - return missing; -} - -/* - * this routine tries to flush the dma transfer. It is called - * on a close. We immediately abort any read DMA - * operation, and then wait for the play buffer to drain. - */ - -int -chn_flush(pcm_channel *c) -{ - int ret, count = 10; - snd_dbuf *b = &c->buffer; - - DEB(printf("snd_flush c->flags 0x%08x\n", c->flags)); - c->flags |= CHN_F_CLOSING; - if (c->direction != PCMDIR_PLAY) chn_abort(c); - else while (b->dl) { - /* still pending output data. */ - ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmflu", hz); - chn_dmaupdate(c); - DEB(printf("snd_sync: now rl : fl %d : %d\n", b->rl, b->fl)); - if (ret == EINTR) { - printf("tsleep returns %d\n", ret); - return -1; - } - if (ret && --count == 0) { - printf("timeout flushing dbuf_out, cnt 0x%x flags 0x%x\n", - b->rl, c->flags); - break; - } - } - c->flags &= ~CHN_F_CLOSING; - if (c->direction == PCMDIR_PLAY) chn_abort(c); - return 0; -} - -int -chn_reset(pcm_channel *c) -{ - chn_abort(c); - c->flags &= CHN_F_RESET; - chn_resetbuf(c); - c->flags |= CHN_F_INIT; - return 0; -} - -int -chn_reinit(pcm_channel *c) -{ - if ((c->flags & CHN_F_INIT) && CANCHANGE(c)) { - chn_setformat(c, c->format); - chn_setspeed(c, c->speed); - chn_setblocksize(c, c->blocksize); - chn_setvolume(c, (c->volume >> 8) & 0xff, c->volume & 0xff); - c->flags &= ~CHN_F_INIT; - return 1; - } - return 0; -} - -int -chn_init(pcm_channel *c, void *devinfo, int dir) -{ - c->flags = 0; - c->feeder = &feeder_root; - c->buffer.chan = -1; - c->devinfo = c->init(devinfo, &c->buffer, c, dir); - chn_setdir(c, dir); - return 0; -} - -int -chn_setdir(pcm_channel *c, int dir) -{ - c->direction = dir; - if (ISA_DMA(&c->buffer)) - c->buffer.dir = (dir == PCMDIR_PLAY)? B_WRITE : B_READ; - return c->setdir(c->devinfo, c->direction); -} - -int -chn_setvolume(pcm_channel *c, int left, int right) -{ - /* could add a feeder for volume changing if channel returns -1 */ - if (CANCHANGE(c)) { - return -1; - } - c->volume = (left << 8) | right; - c->flags |= CHN_F_INIT; - return 0; -} - -int -chn_setspeed(pcm_channel *c, int speed) -{ - /* could add a feeder for rate conversion */ - if (CANCHANGE(c)) { - c->speed = c->setspeed(c->devinfo, speed); - return c->speed; - } - c->speed = speed; - c->flags |= CHN_F_INIT; - return 0; -} - -int -chn_setformat(pcm_channel *c, u_int32_t fmt) -{ - if (CANCHANGE(c)) { - c->hwfmt = c->format = fmt; - c->hwfmt = chn_feedchain(c); - chn_resetbuf(c); - c->setformat(c->devinfo, c->hwfmt); - return fmt; - } - c->format = fmt; - c->flags |= CHN_F_INIT; - return 0; -} - -int -chn_setblocksize(pcm_channel *c, int blksz) -{ - if (CANCHANGE(c)) { - c->flags &= ~CHN_F_HAS_SIZE; - if (blksz >= 2) c->flags |= CHN_F_HAS_SIZE; - blksz = abs(blksz); - if (blksz < 2) blksz = (c->buffer.sample_size * c->speed) >> 2; - RANGE(blksz, 1024, c->buffer.bufsize / 4); - blksz &= ~3; - c->blocksize = c->setblocksize(c->devinfo, blksz); - return c->blocksize; - } - c->blocksize = blksz; - c->flags |= CHN_F_INIT; - return 0; -} - -int -chn_trigger(pcm_channel *c, int go) -{ - return c->trigger(c->devinfo, go); -} - -int -chn_getptr(pcm_channel *c) -{ - return c->getptr(c->devinfo); -} - -pcmchan_caps * -chn_getcaps(pcm_channel *c) -{ - return c->getcaps(c->devinfo); -} Property changes on: head/sys/dev/pcm/channel.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/fake.c =================================================================== --- head/sys/dev/pcm/fake.c (revision 53505) +++ head/sys/dev/pcm/fake.c (nonexistent) @@ -1,115 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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 "pcm.h" - -#include - -/* channel interface */ -static void *fkchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -static int fkchan_setdir(void *data, int dir); -static int fkchan_setformat(void *data, u_int32_t format); -static int fkchan_setspeed(void *data, u_int32_t speed); -static int fkchan_setblocksize(void *data, u_int32_t blocksize); -static int fkchan_trigger(void *data, int go); -static int fkchan_getptr(void *data); -static pcmchan_caps *fkchan_getcaps(void *data); - -static pcmchan_caps fk_caps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE -}; - -static pcm_channel fk_chantemplate = { - fkchan_init, - fkchan_setdir, - fkchan_setformat, - fkchan_setspeed, - fkchan_setblocksize, - fkchan_trigger, - fkchan_getptr, - fkchan_getcaps, -}; - -/* channel interface */ -static void * -fkchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) -{ - b->bufsize = 16384; - b->buf = malloc(b->bufsize, M_DEVBUF, M_NOWAIT); - return (void *)0xbabef00d; -} - -static int -fkchan_setdir(void *data, int dir) -{ - return 0; -} - -static int -fkchan_setformat(void *data, u_int32_t format) -{ - return 0; -} - -static int -fkchan_setspeed(void *data, u_int32_t speed) -{ - return speed; -} - -static int -fkchan_setblocksize(void *data, u_int32_t blocksize) -{ - return blocksize; -} - -static int -fkchan_trigger(void *data, int go) -{ - return 0; -} - -static int -fkchan_getptr(void *data) -{ - return 0; -} - -static pcmchan_caps * -fkchan_getcaps(void *data) -{ - return &fk_caps; -} - -int -fkchan_setup(pcm_channel *c) -{ - *c = fk_chantemplate; - return 0; -} Property changes on: head/sys/dev/pcm/fake.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/mixer.c =================================================================== --- head/sys/dev/pcm/mixer.c (revision 53505) +++ head/sys/dev/pcm/mixer.c (nonexistent) @@ -1,203 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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 - -static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = { - [SOUND_MIXER_VOLUME] = 75, - [SOUND_MIXER_BASS] = 50, - [SOUND_MIXER_TREBLE] = 50, - [SOUND_MIXER_PCM] = 75, - [SOUND_MIXER_SPEAKER] = 75, - [SOUND_MIXER_LINE] = 75, - [SOUND_MIXER_MIC] = 0, - [SOUND_MIXER_CD] = 75, - [SOUND_MIXER_LINE1] = 75, - [SOUND_MIXER_VIDEO] = 75, - [SOUND_MIXER_RECLEV] = 0, - [SOUND_MIXER_OGAIN] = 50, -}; - -int -mixer_init(snddev_info *d, snd_mixer *m, void *devinfo) -{ - if (d == NULL) return -1; - d->mixer = *m; - d->mixer.devinfo = devinfo; - bzero(&d->mixer.level, sizeof d->mixer.level); - if (d->mixer.init != NULL && d->mixer.init(&d->mixer) == 0) { - int i; - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { - u_int16_t v = snd_mixerdefaults[i]; - mixer_set(d, i, v | (v << 8)); - } - mixer_setrecsrc(d, SOUND_MASK_MIC); - return 0; - } else return -1; -} - -int -mixer_set(snddev_info *d, unsigned dev, unsigned lev) -{ - if (d == NULL || d->mixer.set == NULL) return -1; - if ((dev < SOUND_MIXER_NRDEVICES) && (d->mixer.devs & (1 << dev))) { - unsigned l = min((lev & 0x00ff), 100); - unsigned r = min(((lev & 0xff00) >> 8), 100); - int v = d->mixer.set(&d->mixer, dev, l, r); - if (v >= 0) d->mixer.level[dev] = v; - return 0; - } else return -1; -} - -int -mixer_get(snddev_info *d, int dev) -{ - if (d == NULL) return -1; - if (dev < SOUND_MIXER_NRDEVICES && (d->mixer.devs & (1 << dev))) - return d->mixer.level[dev]; - else return -1; -} - -int -mixer_setrecsrc(snddev_info *d, u_int32_t src) -{ - if (d == NULL || d->mixer.setrecsrc == NULL) return -1; - src &= d->mixer.recdevs; - if (src == 0) src = SOUND_MASK_MIC; - d->mixer.recsrc = d->mixer.setrecsrc(&d->mixer, src); - return 0; -} - -int -mixer_getrecsrc(snddev_info *d) -{ - if (d == NULL) return -1; - return d->mixer.recsrc; -} - -int -mixer_ioctl(snddev_info *d, u_long cmd, caddr_t arg) -{ - int ret, *arg_i = (int *)arg; - - if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) { - int j = cmd & 0xff; - - if (j == SOUND_MIXER_RECSRC) ret = mixer_setrecsrc(d, *arg_i); - else ret = mixer_set(d, j, *arg_i); - return (ret == 0)? 0 : ENXIO; - } - - if ((cmd & MIXER_READ(0)) == MIXER_READ(0)) { - int v = -1, j = cmd & 0xff; - - switch (j) { - case SOUND_MIXER_DEVMASK: - case SOUND_MIXER_CAPS: - case SOUND_MIXER_STEREODEVS: - v = d->mixer.devs; - break; - - case SOUND_MIXER_RECMASK: - v = d->mixer.recdevs; - break; - - case SOUND_MIXER_RECSRC: - v = mixer_getrecsrc(d); - break; - - default: - v = mixer_get(d, j); - } - *arg_i = v; - return (v != -1)? 0 : ENXIO; - } - return ENXIO; -} - -void -mix_setdevs(snd_mixer *m, u_int32_t v) -{ - m->devs = v; -} - -void -mix_setrecdevs(snd_mixer *m, u_int32_t v) -{ - m->recdevs = v; -} - -u_int32_t -mix_getdevs(snd_mixer *m) -{ - return m->devs; -} - -u_int32_t -mix_getrecdevs(snd_mixer *m) -{ - return m->recdevs; -} - -void * -mix_getdevinfo(snd_mixer *m) -{ - return m->devinfo; -} - -/* - * The various mixers use a variety of bitmasks etc. The Voxware - * driver had a very nice technique to describe a mixer and interface - * to it. A table defines, for each channel, which register, bits, - * offset, polarity to use. This procedure creates the new value - * using the table and the old value. - */ - -void -change_bits(mixer_tab *t, u_char *regval, int dev, int chn, int newval) -{ - u_char mask; - int shift; - - DEB(printf("ch_bits dev %d ch %d val %d old 0x%02x " - "r %d p %d bit %d off %d\n", - dev, chn, newval, *regval, - (*t)[dev][chn].regno, (*t)[dev][chn].polarity, - (*t)[dev][chn].nbits, (*t)[dev][chn].bitoffs ) ); - - if ( (*t)[dev][chn].polarity == 1) /* reverse */ - newval = 100 - newval ; - - mask = (1 << (*t)[dev][chn].nbits) - 1; - newval = (int) ((newval * mask) + 50) / 100; /* Scale it */ - shift = (*t)[dev][chn].bitoffs /*- (*t)[dev][LEFT_CHN].nbits + 1*/; - - *regval &= ~(mask << shift); /* Filter out the previous value */ - *regval |= (newval & mask) << shift; /* Set the new value */ -} - Property changes on: head/sys/dev/pcm/mixer.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/pci/t4dwave.h =================================================================== --- head/sys/dev/pcm/pci/t4dwave.h (revision 53505) +++ head/sys/dev/pcm/pci/t4dwave.h (nonexistent) @@ -1,103 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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$ - */ - -#ifndef _T4DWAVE_REG_H -#define _T4DWAVE_REG_H - -#define TDX_PCI_ID 0x20001023 -#define TNX_PCI_ID 0x20011023 - -#define TR_BUFFSIZE 0x8000 -#define TR_TIMEOUT_CDC 0xffff -#define TR_INTSAMPLES 0x2000 -#define TR_MAXPLAYCH 64 - -#define TR_REG_CIR 0xa0 -#define TR_CIR_MASK 0x0000003f -#define TR_CIR_ADDRENA 0x00001000 -#define TR_CIR_MIDENA 0x00002000 -#define TR_REG_MISCINT 0xb0 -#define TR_INT_ADDR 0x00000020 -#define TR_INT_SB 0x00000004 - -#define TR_REG_DMAR0 0x00 -#define TR_REG_DMAR4 0x04 -#define TR_REG_DMAR11 0x0b -#define TR_REG_DMAR15 0x0f -#define TR_REG_SBR4 0x14 -#define TR_REG_SBR5 0x15 -#define TR_SB_INTSTATUS 0x82 -#define TR_REG_SBR9 0x1e -#define TR_REG_SBR10 0x1f -#define TR_REG_SBBL 0xc0 -#define TR_REG_SBCTRL 0xc4 -#define TR_REG_SBDELTA 0xac - -#define TR_CDC_DATA 16 -#define TDX_REG_CODECWR 0x40 -#define TDX_REG_CODECRD 0x44 -#define TDX_CDC_RWSTAT 0x00008000 -#define TDX_REG_CODECST 0x48 -#define TDX_CDC_SBCTRL 0x40 -#define TDX_CDC_ACTIVE 0x20 -#define TDX_CDC_READY 0x10 -#define TDX_CDC_ADCON 0x08 -#define TDX_CDC_DACON 0x02 -#define TDX_CDC_RESET 0x01 -#define TDX_CDC_ON (TDX_CDC_ADCON|TDX_CDC_DACON) - -#define TNX_REG_CODECWR 0x44 -#define TNX_REG_CODEC1RD 0x48 -#define TNX_REG_CODEC2RD 0x4c -#define TNX_CDC_RWSTAT 0x00000c00 -#define TNX_CDC_SEC 0x00000100 -#define TNX_REG_CODECST 0x40 -#define TNX_CDC_READY2 0x40 -#define TNX_CDC_ADC2ON 0x20 -#define TNX_CDC_DAC2ON 0x10 -#define TNX_CDC_READY1 0x08 -#define TNX_CDC_ADC1ON 0x04 -#define TNX_CDC_DAC1ON 0x02 -#define TNX_CDC_RESET 0x01 -#define TNX_CDC_ON (TNX_CDC_ADC1ON|TNX_CDC_DAC1ON) - - -#define TR_REG_STARTA 0x80 -#define TR_REG_STOPA 0x84 -#define TR_REG_ADDRINTA 0x98 -#define TR_REG_INTENA 0xa4 - -#define TR_REG_STARTB 0xb4 -#define TR_REG_STOPB 0xb8 -#define TR_REG_ADDRINTB 0xd8 -#define TR_REG_INTENB 0xdc - -#define TR_REG_CHNBASE 0xe0 -#define TR_CHN_REGS 5 - -#endif Property changes on: head/sys/dev/pcm/pci/t4dwave.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/pci/aureal.c =================================================================== --- head/sys/dev/pcm/pci/aureal.c (revision 53505) +++ head/sys/dev/pcm/pci/aureal.c (nonexistent) @@ -1,693 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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 "pci.h" -#include "pcm.h" - -#include -#include -#include - -#include -#include - -#if NPCI != 0 - -/* PCI IDs of supported chips */ -#define AU8820_PCI_ID 0x000112eb - -/* channel interface */ -static void *auchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -static int auchan_setdir(void *data, int dir); -static int auchan_setformat(void *data, u_int32_t format); -static int auchan_setspeed(void *data, u_int32_t speed); -static int auchan_setblocksize(void *data, u_int32_t blocksize); -static int auchan_trigger(void *data, int go); -static int auchan_getptr(void *data); -static pcmchan_caps *auchan_getcaps(void *data); - -static pcmchan_caps au_playcaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcmchan_caps au_reccaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcm_channel au_chantemplate = { - auchan_init, - auchan_setdir, - auchan_setformat, - auchan_setspeed, - auchan_setblocksize, - auchan_trigger, - auchan_getptr, - auchan_getcaps, -}; - -/* -------------------------------------------------------------------- */ - -static u_int32_t au_rdcd(void *arg, int regno); -static void au_wrcd(void *arg, int regno, u_int32_t data); - -struct au_info; - -struct au_chinfo { - struct au_info *parent; - pcm_channel *channel; - snd_dbuf *buffer; - int dir; -}; - -struct au_info { - int unit; - - bus_space_tag_t st[3]; - bus_space_handle_t sh[3]; - - bus_dma_tag_t parent_dmat; - - u_int32_t x[32], y[128]; - char z[128]; - u_int32_t routes[4], interrupts; - struct au_chinfo pch; -}; - -static int au_init(device_t dev, struct au_info *au); -static void au_intr(void *); - -/* -------------------------------------------------------------------- */ - -static u_int32_t -au_rd(struct au_info *au, int mapno, int regno, int size) -{ - switch(size) { - case 1: - return bus_space_read_1(au->st[mapno], au->sh[mapno], regno); - case 2: - return bus_space_read_2(au->st[mapno], au->sh[mapno], regno); - case 4: - return bus_space_read_4(au->st[mapno], au->sh[mapno], regno); - default: - return 0xffffffff; - } -} - -static void -au_wr(struct au_info *au, int mapno, int regno, u_int32_t data, int size) -{ - switch(size) { - case 1: - bus_space_write_1(au->st[mapno], au->sh[mapno], regno, data); - break; - case 2: - bus_space_write_2(au->st[mapno], au->sh[mapno], regno, data); - break; - case 4: - bus_space_write_4(au->st[mapno], au->sh[mapno], regno, data); - break; - } -} - -static u_int32_t -au_rdcd(void *arg, int regno) -{ - struct au_info *au = (struct au_info *)arg; - int i=0, j=0; - - regno<<=16; - au_wr(au, 0, AU_REG_CODECIO, regno, 4); - while (j<50) { - i=au_rd(au, 0, AU_REG_CODECIO, 4); - if ((i & 0x00ff0000) == (regno | 0x00800000)) break; - DELAY(j * 200 + 2000); - j++; - } - if (j==50) printf("pcm%d: codec timeout reading register %x (%x)\n", - au->unit, (regno & AU_CDC_REGMASK)>>16, i); - return i & AU_CDC_DATAMASK; -} - -static void -au_wrcd(void *arg, int regno, u_int32_t data) -{ - struct au_info *au = (struct au_info *)arg; - int i, j, tries; - i=j=tries=0; - do { - while (j<50 && (i & AU_CDC_WROK) == 0) { - i=au_rd(au, 0, AU_REG_CODECST, 4); - DELAY(2000); - j++; - } - if (j==50) printf("codec timeout during write of register %x, data %x\n", - regno, data); - au_wr(au, 0, AU_REG_CODECIO, (regno<<16) | AU_CDC_REGSET | data, 4); -/* DELAY(20000); - i=au_rdcd(au, regno); -*/ tries++; - } while (0); /* (i != data && tries < 3); */ - /* - if (tries == 3) printf("giving up writing 0x%4x to codec reg %2x\n", data, regno); - */ -} - -static void -au_setbit(u_int32_t *p, char bit, u_int32_t value) -{ - p += bit >> 5; - bit &= 0x1f; - *p &= ~ (1 << bit); - *p |= (value << bit); -} - -static void -au_addroute(struct au_info *au, int a, int b, int route) -{ - int j = 0x1099c+(a<<2); - if (au->x[a] != a+0x67) j = AU_REG_RTBASE+(au->x[a]<<2); - - au_wr(au, 0, AU_REG_RTBASE+(route<<2), 0xffffffff, 4); - au_wr(au, 0, j, route | (b<<7), 4); - au->y[route]=au->x[a]; - au->x[a]=route; - au->z[route]=a & 0x000000ff; - au_setbit(au->routes, route, 1); -} - -static void -au_delroute(struct au_info *au, int route) -{ - int i; - int j=au->z[route]; - - au_setbit(au->routes, route, 0); - au->z[route]=0x1f; - i=au_rd(au, 0, AU_REG_RTBASE+(route<<2), 4); - au_wr(au, 0, AU_REG_RTBASE+(au->y[route]<<2), i, 4); - au->y[i & 0x7f]=au->y[route]; - au_wr(au, 0, AU_REG_RTBASE+(route<<2), 0xfffffffe, 4); - if (au->x[j] == route) au->x[j]=au->y[route]; - au->y[route]=0x7f; -} - -static void -au_encodec(struct au_info *au, char channel) -{ - au_wr(au, 0, AU_REG_CODECEN, - au_rd(au, 0, AU_REG_CODECEN, 4) | (1 << (channel + 8)), 4); -} - -static void -au_clrfifo(struct au_info *au, u_int32_t c) -{ - u_int32_t i; - - for (i=0; i<32; i++) au_wr(au, 0, AU_REG_FIFOBASE+(c<<7)+(i<<2), 0, 4); -} - -static void -au_setadb(struct au_info *au, u_int32_t c, u_int32_t enable) -{ - int x; - - x = au_rd(au, 0, AU_REG_ADB, 4); - x &= ~(1 << c); - x |= (enable << c); - au_wr(au, 0, AU_REG_ADB, x, 4); -} - -static void -au_prepareoutput(struct au_chinfo *ch, u_int32_t format) -{ - struct au_info *au = ch->parent; - int i, stereo = (format & AFMT_STEREO)? 1 : 0; - u_int32_t baseaddr = vtophys(ch->buffer->buf); - - au_wr(au, 0, 0x1061c, 0, 4); - au_wr(au, 0, 0x10620, 0, 4); - au_wr(au, 0, 0x10624, 0, 4); - switch(format & ~AFMT_STEREO) { - case 1: - i=0xb000; - break; - case 2: - i=0xf000; - break; - case 8: - i=0x7000; - break; - case 16: - i=0x23000; - break; - default: - i=0x3000; - } - au_wr(au, 0, 0x10200, baseaddr, 4); - au_wr(au, 0, 0x10204, baseaddr+0x1000, 4); - au_wr(au, 0, 0x10208, baseaddr+0x2000, 4); - au_wr(au, 0, 0x1020c, baseaddr+0x3000, 4); - - au_wr(au, 0, 0x10400, 0xdeffffff, 4); - au_wr(au, 0, 0x10404, 0xfcffffff, 4); - - au_wr(au, 0, 0x10580, i, 4); - - au_wr(au, 0, 0x10210, baseaddr, 4); - au_wr(au, 0, 0x10214, baseaddr+0x1000, 4); - au_wr(au, 0, 0x10218, baseaddr+0x2000, 4); - au_wr(au, 0, 0x1021c, baseaddr+0x3000, 4); - - au_wr(au, 0, 0x10408, 0x00fff000 | 0x56000000 | 0x00000fff, 4); - au_wr(au, 0, 0x1040c, 0x00fff000 | 0x74000000 | 0x00000fff, 4); - - au_wr(au, 0, 0x10584, i, 4); - - au_wr(au, 0, 0x0f800, stereo? 0x00030032 : 0x00030030, 4); - au_wr(au, 0, 0x0f804, stereo? 0x00030032 : 0x00030030, 4); - - au_addroute(au, 0x11, 0, 0x58); - au_addroute(au, 0x11, stereo? 0 : 1, 0x59); -} - -/* channel interface */ -static void * -auchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) -{ - struct au_info *au = devinfo; - struct au_chinfo *ch = (dir == PCMDIR_PLAY)? &au->pch : NULL; - - ch->parent = au; - ch->channel = c; - ch->buffer = b; - ch->buffer->bufsize = AU_BUFFSIZE; - if (chn_allocbuf(ch->buffer, au->parent_dmat) == -1) return NULL; - return ch; -} - -static int -auchan_setdir(void *data, int dir) -{ - struct au_chinfo *ch = data; - if (dir == PCMDIR_PLAY) { - } else { - } - ch->dir = dir; - return 0; -} - -static int -auchan_setformat(void *data, u_int32_t format) -{ - struct au_chinfo *ch = data; - - if (ch->dir == PCMDIR_PLAY) au_prepareoutput(ch, format); - return 0; -} - -static int -auchan_setspeed(void *data, u_int32_t speed) -{ - struct au_chinfo *ch = data; - if (ch->dir == PCMDIR_PLAY) { - } else { - } - return speed; -} - -static int -auchan_setblocksize(void *data, u_int32_t blocksize) -{ - return blocksize; -} - -static int -auchan_trigger(void *data, int go) -{ - struct au_chinfo *ch = data; - struct au_info *au = ch->parent; - if (ch->dir == PCMDIR_PLAY) { - au_setadb(au, 0x11, (go)? 1 : 0); - if (!go) { - au_wr(au, 0, 0xf800, 0, 4); - au_wr(au, 0, 0xf804, 0, 4); - au_delroute(au, 0x58); - au_delroute(au, 0x59); - } - } else { - } - return 0; -} - -static int -auchan_getptr(void *data) -{ - struct au_chinfo *ch = data; - struct au_info *au = ch->parent; - if (ch->dir == PCMDIR_PLAY) { - return au_rd(au, 0, AU_REG_UNK2, 4) & (AU_BUFFSIZE-1); - } else { - return 0; - } -} - -static pcmchan_caps * -auchan_getcaps(void *data) -{ - struct au_chinfo *ch = data; - return (ch->dir == PCMDIR_PLAY)? &au_playcaps : &au_reccaps; -} - -/* The interrupt handler */ -static void -au_intr (void *p) -{ - struct au_info *au = p; - u_int32_t intsrc, i; - - au->interrupts++; - intsrc=au_rd(au, 0, AU_REG_IRQSRC, 4); - printf("pcm%d: interrupt with src %x\n", au->unit, intsrc); - if (intsrc & AU_IRQ_FATAL) printf("pcm%d: fatal error irq\n", au->unit); - if (intsrc & AU_IRQ_PARITY) printf("pcm%d: parity error irq\n", au->unit); - if (intsrc & AU_IRQ_UNKNOWN) { - (void)au_rd(au, 0, AU_REG_UNK1, 4); - au_wr(au, 0, AU_REG_UNK1, 0, 4); - au_wr(au, 0, AU_REG_UNK1, 0x10000, 4); - } - if (intsrc & AU_IRQ_PCMOUT) { - i=au_rd(au, 0, AU_REG_UNK2, 4) & (AU_BUFFSIZE-1); - chn_intr(au->pch.channel); - (void)au_rd(au, 0, AU_REG_UNK3, 4); - (void)au_rd(au, 0, AU_REG_UNK4, 4); - (void)au_rd(au, 0, AU_REG_UNK5, 4); - } -/* don't support midi - if (intsrc & AU_IRQ_MIDI) { - i=au_rd(au, 0, 0x11004, 4); - j=10; - while (i & 0xff) { - if (j-- <= 0) break; - i=au_rd(au, 0, 0x11000, 4); - if ((au->midi_stat & 1) && (au->midi_out)) - au->midi_out(au->midi_devno, i); - i=au_rd(au, 0, 0x11004); - } - } -*/ - au_wr(au, 0, AU_REG_IRQSRC, intsrc & 0x7ff, 4); - au_rd(au, 0, AU_REG_IRQSRC, 4); -} - - -/* -------------------------------------------------------------------- */ - -/* Probe and attach the card */ - -static int -au_init(device_t dev, struct au_info *au) -{ - u_int32_t i, j; - - au_wr(au, 0, AU_REG_IRQGLOB, 0xffffffff, 4); - DELAY(100000); - - /* init codec */ - /* cold reset */ - for (i=0; i<32; i++) { - au_wr(au, 0, AU_REG_CODECCHN+(i<<2), 0, 4); - DELAY(10000); - } - if (1) { - au_wr(au, 0, AU_REG_CODECST, 0x8068, 4); - DELAY(10000); - au_wr(au, 0, AU_REG_CODECST, 0x00e8, 4); - DELAY(10000); - } else { - au_wr(au, 0, AU_REG_CODECST, 0x00a8, 4); - DELAY(100000); - au_wr(au, 0, AU_REG_CODECST, 0x80a8, 4); - DELAY(100000); - au_wr(au, 0, AU_REG_CODECST, 0x80e8, 4); - DELAY(100000); - au_wr(au, 0, AU_REG_CODECST, 0x80a8, 4); - DELAY(100000); - au_wr(au, 0, AU_REG_CODECST, 0x00a8, 4); - DELAY(100000); - au_wr(au, 0, AU_REG_CODECST, 0x00e8, 4); - DELAY(100000); - } - - /* init */ - for (i=0; i<32; i++) { - au_wr(au, 0, AU_REG_CODECCHN+(i<<2), 0, 4); - DELAY(10000); - } - au_wr(au, 0, AU_REG_CODECST, 0xe8, 4); - DELAY(10000); - au_wr(au, 0, AU_REG_CODECEN, 0, 4); - - /* setup codec */ - i=j=0; - while (j<100 && (i & AU_CDC_READY)==0) { - i=au_rd(au, 0, AU_REG_CODECST, 4); - DELAY(1000); - j++; - } - if (j==100) device_printf(dev, "codec not ready, status 0x%x\n", i); - - /* init adb */ - /*au->x5c=0;*/ - for (i=0; i<32; i++) au->x[i]=i+0x67; - for (i=0; i<128; i++) au->y[i]=0x7f; - for (i=0; i<128; i++) au->z[i]=0x1f; - au_wr(au, 0, AU_REG_ADB, 0, 4); - for (i=0; i<124; i++) au_wr(au, 0, AU_REG_RTBASE+(i<<2), 0xffffffff, 4); - - /* test */ - i=au_rd(au, 0, 0x107c0, 4); - if (i!=0xdeadbeef) device_printf(dev, "dma check failed: 0x%x\n", i); - - /* install mixer */ - au_wr(au, 0, AU_REG_IRQGLOB, - au_rd(au, 0, AU_REG_IRQGLOB, 4) | AU_IRQ_ENABLE, 4); - /* braindead but it's what the oss/linux driver does - * for (i=0; i<0x80000000; i++) au_wr(au, 0, i<<2, 0, 4); - */ - au->routes[0]=au->routes[1]=au->routes[2]=au->routes[3]=0; - /*au->x1e4=0;*/ - - /* attach channel */ - au_addroute(au, 0x11, 0x48, 0x02); - au_addroute(au, 0x11, 0x49, 0x03); - au_encodec(au, 0); - au_encodec(au, 1); - - for (i=0; i<48; i++) au_wr(au, 0, 0xf800+(i<<2), 0x20, 4); - for (i=2; i<6; i++) au_wr(au, 0, 0xf800+(i<<2), 0, 4); - au_wr(au, 0, 0xf8c0, 0x0843, 4); - for (i=0; i<4; i++) au_clrfifo(au, i); - - return (0); -} - -static int -au_testirq(struct au_info *au) -{ - au_wr(au, 0, AU_REG_UNK1, 0x80001000, 4); - au_wr(au, 0, AU_REG_IRQEN, 0x00001030, 4); - au_wr(au, 0, AU_REG_IRQSRC, 0x000007ff, 4); - DELAY(1000000); - if (au->interrupts==0) printf("pcm%d: irq test failed\n", au->unit); - /* this apparently generates an irq */ - return 0; -} - -static int -au_pci_probe(device_t dev) -{ - if (pci_get_devid(dev) == AU8820_PCI_ID) { - device_set_desc(dev, "Aureal Vortex 8820"); - return 0; - } - - return ENXIO; -} - -static int -au_pci_attach(device_t dev) -{ - snddev_info *d; - u_int32_t data; - struct au_info *au; - int type[10]; - int regid[10]; - struct resource *reg[10]; - int i, j, mapped = 0; - int irqid; - struct resource *irq = 0; - void *ih = 0; - struct ac97_info *codec; - char status[SND_STATUSLEN]; - - d = device_get_softc(dev); - if ((au = malloc(sizeof(*au), M_DEVBUF, M_NOWAIT)) == NULL) { - device_printf(dev, "cannot allocate softc\n"); - return ENXIO; - } - - bzero(au, sizeof(*au)); - au->unit = device_get_unit(dev); - - data = pci_read_config(dev, PCIR_COMMAND, 2); - data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); - pci_write_config(dev, PCIR_COMMAND, data, 2); - data = pci_read_config(dev, PCIR_COMMAND, 2); - - j=0; - /* XXX dfr: is this strictly necessary? */ - for (i=0; imap[i].ln2size); - printf("%s space ", (config_id->map[i].type & PCI_MAPPORT)? - "io" : "memory"); - printf("at 0x%x...", config_id->map[i].base); - } -#endif - regid[j] = PCIR_MAPS + i*4; - type[j] = SYS_RES_MEMORY; - reg[j] = bus_alloc_resource(dev, type[j], ®id[j], - 0, ~0, 1, RF_ACTIVE); - if (!reg[j]) { - type[j] = SYS_RES_IOPORT; - reg[j] = bus_alloc_resource(dev, type[j], ®id[j], - 0, ~0, 1, RF_ACTIVE); - } - if (reg[j]) { - au->st[i] = rman_get_bustag(reg[j]); - au->sh[i] = rman_get_bushandle(reg[j]); - mapped++; - } -#if 0 - if (bootverbose) printf("%s\n", mapped? "ok" : "failed"); -#endif - if (mapped) j++; - if (j == 10) { - /* XXX */ - device_printf(dev, "too many resources"); - goto bad; - } - } - -#if 0 - if (j < config_id->nummaps) { - printf("pcm%d: unable to map a required resource\n", unit); - free(au, M_DEVBUF); - return; - } -#endif - - au_wr(au, 0, AU_REG_IRQEN, 0, 4); - - irqid = 0; - irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid, - 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); - if (!irq - || bus_setup_intr(dev, irq, INTR_TYPE_TTY, au_intr, au, &ih)) { - device_printf(dev, "unable to map interrupt\n"); - goto bad; - } - - if (au_testirq(au)) device_printf(dev, "irq test failed\n"); - - if (au_init(dev, au) == -1) { - device_printf(dev, "unable to initialize the card\n"); - goto bad; - } - - codec = ac97_create(au, au_rdcd, au_wrcd); - if (codec == NULL) goto bad; - mixer_init(d, &ac97_mixer, codec); - - 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*/AU_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff, - /*flags*/0, &au->parent_dmat) != 0) { - device_printf(dev, "unable to create dma tag\n"); - goto bad; - } - - snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld", - (type[0] == SYS_RES_IOPORT)? "io" : "memory", - rman_get_start(reg[0]), rman_get_start(irq)); - - if (pcm_register(dev, au, 1, 1)) goto bad; - /* pcm_addchan(dev, PCMDIR_REC, &au_chantemplate, au); */ - pcm_addchan(dev, PCMDIR_PLAY, &au_chantemplate, au); - pcm_setstatus(dev, status); - - return 0; - - bad: - if (au) free(au, M_DEVBUF); - for (i = 0; i < j; i++) - bus_release_resource(dev, type[i], regid[i], reg[i]); - if (ih) bus_teardown_intr(dev, irq, ih); - if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq); - return ENXIO; -} - -static device_method_t au_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, au_pci_probe), - DEVMETHOD(device_attach, au_pci_attach), - - { 0, 0 } -}; - -static driver_t au_driver = { - "pcm", - au_methods, - sizeof(snddev_info), -}; - -static devclass_t pcm_devclass; - -DRIVER_MODULE(au, pci, au_driver, pcm_devclass, 0, 0); - -#endif /* NPCI != 0 */ - Property changes on: head/sys/dev/pcm/pci/aureal.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/pci/aureal.h =================================================================== --- head/sys/dev/pcm/pci/aureal.h (revision 53505) +++ head/sys/dev/pcm/pci/aureal.h (nonexistent) @@ -1,99 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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$ - */ - -#ifndef _AU8820_REG_H -#define _AU8820_REG_H - -#define AU_BUFFSIZE 0x4000 - -#define AU_REG_FIFOBASE 0x0e000 - -#define AU_REG_UNK2 0x105c0 -#define AU_REG_UNK3 0x10600 -#define AU_REG_UNK4 0x10604 -#define AU_REG_UNK5 0x10608 - -#define AU_REG_RTBASE 0x10800 - -#define AU_REG_ADB 0x10a00 - -#define AU_REG_CODECCHN 0x11880 - -#define AU_REG_CODECST 0x11984 -#define AU_CDC_RUN 0x00000040 -#define AU_CDC_WROK 0x00000100 -#define AU_CDC_RESET 0x00008000 - -#define AU_REG_CODECIO 0x11988 -#define AU_CDC_DATAMASK 0x0000ffff -#define AU_CDC_REGMASK 0x007f0000 -#define AU_CDC_REGSET 0x00800000 -#define AU_CDC_READY 0x04000000 - -#define AU_REG_CODECEN 0x11990 -#define AU_CDC_CHAN1EN 0x00000100 -#define AU_CDC_CHAN2EN 0x00000200 - -#define AU_REG_UNK1 0x1199c - -#define AU_REG_IRQSRC 0x12800 -#define AU_IRQ_FATAL 0x0001 -#define AU_IRQ_PARITY 0x0002 -#define AU_IRQ_PCMOUT 0x0020 -#define AU_IRQ_UNKNOWN 0x1000 -#define AU_IRQ_MIDI 0x2000 -#define AU_REG_IRQEN 0x12804 - -#define AU_REG_IRQGLOB 0x1280c -#define AU_IRQ_ENABLE 0x4000 - -#define AC97_MUTE 0x8000 -#define AC97_REG_RESET 0x00 -#define AC97_MIX_MASTER 0x02 -#define AC97_MIX_PHONES 0x04 -#define AC97_MIX_MONO 0x06 -#define AC97_MIX_TONE 0x08 -#define AC97_MIX_BEEP 0x0a -#define AC97_MIX_PHONE 0x0c -#define AC97_MIX_MIC 0x0e -#define AC97_MIX_LINE 0x10 -#define AC97_MIX_CD 0x12 -#define AC97_MIX_VIDEO 0x14 -#define AC97_MIX_AUX 0x16 -#define AC97_MIX_PCM 0x18 -#define AC97_REG_RECSEL 0x1a -#define AC97_MIX_RGAIN 0x1c -#define AC97_MIX_MGAIN 0x1e -#define AC97_REG_GEN 0x20 -#define AC97_REG_3D 0x22 -#define AC97_REG_POWER 0x26 -#define AC97_REG_ID1 0x7c -#define AC97_REG_ID2 0x7e - - -#endif Property changes on: head/sys/dev/pcm/pci/aureal.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/pci/es1370.c =================================================================== --- head/sys/dev/pcm/pci/es1370.c (revision 53505) +++ head/sys/dev/pcm/pci/es1370.c (nonexistent) @@ -1,543 +0,0 @@ -/* - * Support the ENSONIQ AudioPCI board based on the ES1370 and Codec - * AK4531. - * - * Copyright (c) 1999 Cameron Grant - * 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 "pci.h" -#include "pcm.h" - -#include -#include - -#include -#include - -#if NPCI != 0 - -#define MEM_MAP_REG 0x14 - -/* PCI IDs of supported chips */ -#define ES1370_PCI_ID 0x50001274 - -/* device private data */ -struct es_info; - -struct es_chinfo { - struct es_info *parent; - pcm_channel *channel; - snd_dbuf *buffer; - int dir; - u_int32_t fmt; -}; - -struct es_info { - bus_space_tag_t st; - bus_space_handle_t sh; - bus_dma_tag_t parent_dmat; - - /* Contents of board's registers */ - u_long ctrl; - u_long sctrl; - struct es_chinfo pch, rch; -}; - -/* -------------------------------------------------------------------- */ - -/* prototypes */ -static int es_init(struct es_info *); -static void es_intr(void *); -static int write_codec(struct es_info *, u_char, u_char); - -/* channel interface */ -static void *eschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -static int eschan_setdir(void *data, int dir); -static int eschan_setformat(void *data, u_int32_t format); -static int eschan_setspeed(void *data, u_int32_t speed); -static int eschan_setblocksize(void *data, u_int32_t blocksize); -static int eschan_trigger(void *data, int go); -static int eschan_getptr(void *data); -static pcmchan_caps *eschan_getcaps(void *data); - -static pcmchan_caps es_playcaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcmchan_caps es_reccaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcm_channel es_chantemplate = { - eschan_init, - eschan_setdir, - eschan_setformat, - eschan_setspeed, - eschan_setblocksize, - eschan_trigger, - eschan_getptr, - eschan_getcaps, -}; - -/* -------------------------------------------------------------------- */ - -/* The mixer interface */ - -static int es_mixinit(snd_mixer *m); -static int es_mixset(snd_mixer *m, unsigned dev, unsigned left, unsigned right); -static int es_mixsetrecsrc(snd_mixer *m, u_int32_t src); - -static snd_mixer es_mixer = { - "Ensoniq AudioPCI 1370 mixer", - es_mixinit, - es_mixset, - es_mixsetrecsrc, -}; - -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 -es_mixinit(snd_mixer *m) -{ - int i; - u_int32_t v; - - v = 0; - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - if (mixtable[i].avail) v |= (1 << i); - mix_setdevs(m, v); - v = 0; - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - if (mixtable[i].recmask) v |= (1 << i); - mix_setrecdevs(m, v); - return 0; -} - -static int -es_mixset(snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - int l, r, rl, rr; - - if (!mixtable[dev].avail) return -1; - l = left; - r = mixtable[dev].stereo? right : l; - if (mixtable[dev].left == 0xf) { - rl = (l < 2)? 0x80 : 7 - (l - 2) / 14; - } else { - rl = (l < 10)? 0x80 : 15 - (l - 10) / 6; - } - if (mixtable[dev].stereo) { - rr = (r < 10)? 0x80 : 15 - (r - 10) / 6; - write_codec(mix_getdevinfo(m), mixtable[dev].right, rr); - } - write_codec(mix_getdevinfo(m), mixtable[dev].left, rl); - return l | (r << 8); -} - -static int -es_mixsetrecsrc(snd_mixer *m, u_int32_t src) -{ - int i, j = 0; - - if (src == 0) src = 1 << SOUND_MIXER_MIC; - src &= mix_getrecdevs(m); - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - if ((src & (1 << i)) != 0) j |= mixtable[i].recmask; - - write_codec(mix_getdevinfo(m), CODEC_LIMIX1, j & 0x55); - write_codec(mix_getdevinfo(m), CODEC_RIMIX1, j & 0xaa); - write_codec(mix_getdevinfo(m), CODEC_LIMIX2, (j >> 8) & 0x17); - write_codec(mix_getdevinfo(m), CODEC_RIMIX2, (j >> 8) & 0x0f); - write_codec(mix_getdevinfo(m), CODEC_OMIX1, 0x7f); - write_codec(mix_getdevinfo(m), CODEC_OMIX2, 0x3f); - return src; -} - -static int -write_codec(struct es_info *es, u_char i, u_char 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); - } while (--wait); - printf("pcm: write_codec timed out\n"); - return -1; -} - -/* -------------------------------------------------------------------- */ - -/* channel interface */ -static void * -eschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) -{ - struct es_info *es = devinfo; - struct es_chinfo *ch = (dir == PCMDIR_PLAY)? &es->pch : &es->rch; - - ch->parent = es; - ch->channel = c; - ch->buffer = b; - ch->buffer->bufsize = ES_BUFFSIZE; - if (chn_allocbuf(ch->buffer, es->parent_dmat) == -1) return NULL; - return ch; -} - -static int -eschan_setdir(void *data, int dir) -{ - struct es_chinfo *ch = data; - struct es_info *es = ch->parent; - - if (dir == PCMDIR_PLAY) { - 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, - vtophys(ch->buffer->buf)); - bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_FRAMECNT & 0xff, - (ch->buffer->bufsize >> 2) - 1); - } else { - 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, - vtophys(ch->buffer->buf)); - bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_FRAMECNT & 0xff, - (ch->buffer->bufsize >> 2) - 1); - } - ch->dir = dir; - return 0; -} - -static int -eschan_setformat(void *data, u_int32_t format) -{ - struct es_chinfo *ch = data; - struct es_info *es = ch->parent; - - if (ch->dir == PCMDIR_PLAY) { - es->sctrl &= ~SCTRL_P2FMT; - if (format & AFMT_S16_LE) es->sctrl |= SCTRL_P2SEB; - if (format & AFMT_STEREO) es->sctrl |= SCTRL_P2SMB; - } else { - es->sctrl &= ~SCTRL_R1FMT; - if (format & AFMT_S16_LE) es->sctrl |= SCTRL_R1SEB; - if (format & AFMT_STEREO) es->sctrl |= SCTRL_R1SMB; - } - bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl); - ch->fmt = format; - return 0; -} - -static int -eschan_setspeed(void *data, u_int32_t speed) -{ - struct es_chinfo *ch = data; - struct es_info *es = ch->parent; - - es->ctrl &= ~CTRL_PCLKDIV; - es->ctrl |= DAC2_SRTODIV(speed) << CTRL_SH_PCLKDIV; - bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl); - /* rec/play speeds locked together - should indicate in flags */ -#if 0 - if (ch->direction == PCMDIR_PLAY) d->rec[0].speed = speed; - else d->play[0].speed = speed; -#endif - return speed; /* XXX calc real speed */ -} - -static int -eschan_setblocksize(void *data, u_int32_t blocksize) -{ - return blocksize; -} - -static int -eschan_trigger(void *data, int go) -{ - struct es_chinfo *ch = data; - struct es_info *es = ch->parent; - unsigned cnt = ch->buffer->dl / ch->buffer->sample_size - 1; - - if (ch->dir == PCMDIR_PLAY) { - if (go == PCMTRIG_START) { - int b = (ch->fmt & AFMT_S16_LE)? 2 : 1; - es->ctrl |= CTRL_DAC2_EN; - es->sctrl &= ~(SCTRL_P2ENDINC | SCTRL_P2STINC | - SCTRL_P2LOOPSEL | SCTRL_P2PAUSE | - SCTRL_P2DACSEN); - es->sctrl |= SCTRL_P2INTEN | (b << SCTRL_SH_P2ENDINC); - bus_space_write_4(es->st, es->sh, - ES1370_REG_DAC2_SCOUNT, cnt); - } else es->ctrl &= ~CTRL_DAC2_EN; - } else { - if (go == PCMTRIG_START) { - es->ctrl |= CTRL_ADC_EN; - es->sctrl &= ~SCTRL_R1LOOPSEL; - es->sctrl |= SCTRL_R1INTEN; - bus_space_write_4(es->st, es->sh, - ES1370_REG_ADC_SCOUNT, cnt); - } else es->ctrl &= ~CTRL_ADC_EN; - } - 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); - return 0; -} - -static int -eschan_getptr(void *data) -{ - struct es_chinfo *ch = data; - struct es_info *es = ch->parent; - if (ch->dir == PCMDIR_PLAY) { - bus_space_write_4(es->st, es->sh, ES1370_REG_MEMPAGE, - ES1370_REG_DAC2_FRAMECNT >> 8); - return (bus_space_read_4(es->st, es->sh, - ES1370_REG_DAC2_FRAMECNT & 0xff) >> 14) & 0x3fffc; - } else { - bus_space_write_4(es->st, es->sh, ES1370_REG_MEMPAGE, - ES1370_REG_ADC_FRAMECNT >> 8); - return (bus_space_read_4(es->st, es->sh, - ES1370_REG_ADC_FRAMECNT & 0xff) >> 14) & 0x3fffc; - } -} - -static pcmchan_caps * -eschan_getcaps(void *data) -{ - struct es_chinfo *ch = data; - return (ch->dir == PCMDIR_PLAY)? &es_playcaps : &es_reccaps; -} - -/* The interrupt handler */ -static void -es_intr (void *p) -{ - struct es_info *es = p; - 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) chn_intr(es->pch.channel); - if (intsrc & STAT_ADC) chn_intr(es->rch.channel); -} - -/* -------------------------------------------------------------------- */ - -/* - * Probe and attach the card - */ - -static int -es_init(struct es_info *es) -{ - 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(es, CODEC_RES_PD, 3);/* No RST, PD */ - write_codec(es, CODEC_CSEL, 0); /* CODEC ADC and CODEC DAC use - * {LR,B}CLK2 and run off the LRCLK2 - * PLL; program DAC_SYNC=0! */ - write_codec(es, CODEC_ADSEL, 0);/* Recording source is mixer */ - write_codec(es, CODEC_MGAIN, 0);/* MIC amp is 0db */ - - return 0; -} - -static int -es_pci_probe(device_t dev) -{ - if (pci_get_devid(dev) == ES1370_PCI_ID) { - device_set_desc(dev, "AudioPCI ES1370"); - return 0; - } - return ENXIO; -} - -static int -es_pci_attach(device_t dev) -{ - snddev_info *d; - u_int32_t data; - struct es_info *es = 0; - int type = 0; - int regid; - struct resource *reg = 0; - int mapped; - int irqid; - struct resource *irq = 0; - void *ih = 0; - char status[SND_STATUSLEN]; - - d = device_get_softc(dev); - if ((es = malloc(sizeof *es, M_DEVBUF, M_NOWAIT)) == NULL) { - device_printf(dev, "cannot allocate softc\n"); - return ENXIO; - } - bzero(es, sizeof *es); - - mapped = 0; - data = pci_read_config(dev, PCIR_COMMAND, 2); - if (mapped == 0 && (data & PCIM_CMD_MEMEN)) { - regid = MEM_MAP_REG; - type = SYS_RES_MEMORY; - reg = bus_alloc_resource(dev, type, ®id, - 0, ~0, 1, RF_ACTIVE); - if (reg) { - es->st = rman_get_bustag(reg); - es->sh = rman_get_bushandle(reg); - mapped++; - } - } - if (mapped == 0 && (data & PCIM_CMD_PORTEN)) { - regid = PCI_MAP_REG_START; - type = SYS_RES_IOPORT; - reg = bus_alloc_resource(dev, type, ®id, - 0, ~0, 1, RF_ACTIVE); - if (reg) { - es->st = rman_get_bustag(reg); - es->sh = rman_get_bushandle(reg); - mapped++; - } - } - if (mapped == 0) { - device_printf(dev, "unable to map register space\n"); - goto bad; - } - - if (es_init(es) == -1) { - device_printf(dev, "unable to initialize the card\n"); - goto bad; - } - mixer_init(d, &es_mixer, es); - - irqid = 0; - irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid, - 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); - if (!irq - || bus_setup_intr(dev, irq, INTR_TYPE_TTY, es_intr, es, &ih)) { - device_printf(dev, "unable to map interrupt\n"); - goto bad; - } - - 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*/ES_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff, - /*flags*/0, &es->parent_dmat) != 0) { - device_printf(dev, "unable to create dma tag\n"); - goto bad; - } - - snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld", - (type == SYS_RES_IOPORT)? "io" : "memory", - rman_get_start(reg), rman_get_start(irq)); - - if (pcm_register(dev, es, 1, 1)) goto bad; - pcm_addchan(dev, PCMDIR_REC, &es_chantemplate, es); - pcm_addchan(dev, PCMDIR_PLAY, &es_chantemplate, es); - pcm_setstatus(dev, status); - - return 0; - - bad: - if (es) free(es, M_DEVBUF); - if (reg) bus_release_resource(dev, type, regid, reg); - if (ih) bus_teardown_intr(dev, irq, ih); - if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq); - return ENXIO; -} - -static device_method_t es_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, es_pci_probe), - DEVMETHOD(device_attach, es_pci_attach), - - { 0, 0 } -}; - -static driver_t es_driver = { - "pcm", - es_methods, - sizeof(snddev_info), -}; - -static devclass_t pcm_devclass; - -DRIVER_MODULE(es, pci, es_driver, pcm_devclass, 0, 0); - -#endif /* NPCI != 0 */ Property changes on: head/sys/dev/pcm/pci/es1370.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/pci/es1370.h =================================================================== --- head/sys/dev/pcm/pci/es1370.h (revision 53505) +++ head/sys/dev/pcm/pci/es1370.h (nonexistent) @@ -1,134 +0,0 @@ -/* - * This supports the ENSONIQ AudioPCI board based on the ES1370. - * - * Copyright (c) 1998 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 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 Property changes on: head/sys/dev/pcm/pci/es1370.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/pci/es137x.c =================================================================== --- head/sys/dev/pcm/pci/es137x.c (revision 53505) +++ head/sys/dev/pcm/pci/es137x.c (nonexistent) @@ -1,916 +0,0 @@ -/* - * Support the ENSONIQ AudioPCI board and Creative Labs SoundBlaster PCI - * boards based on the ES1370, ES1371 and ES1373 chips. - * - * Copyright (c) 1999 Russell Cattelan - * Copyright (c) 1999 Cameron Grant - * 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$ - */ - -/* - * Part of this code was heavily inspired by the linux driver from - * Thomas Sailer (sailer@ife.ee.ethz.ch) - * Just about everything has been touched and reworked in some way but - * the all the underlying sequences/timing/register values are from - * Thomas' code. - * -*/ - -#include "pci.h" -#include "pcm.h" - -#include -#include -#include - -#include -#include - -#include - -#if NPCI != 0 - -static int debug = 0; -SYSCTL_INT(_debug, OID_AUTO, es_debug, CTLFLAG_RW, &debug, 0, ""); - -#define MEM_MAP_REG 0x14 - -/* PCI IDs of supported chips */ -#define ES1370_PCI_ID 0x50001274 -#define ES1371_PCI_ID 0x13711274 - -/* device private data */ -struct es_info; - -typedef struct es_chinfo { - struct es_info *parent; - pcm_channel *channel; - snd_dbuf *buffer; - int dir; - u_int32_t fmt; -} es_chinfo_t; - -typedef struct es_info { - bus_space_tag_t st; - bus_space_handle_t sh; - bus_dma_tag_t parent_dmat; - - /* Contents of board's registers */ - u_long ctrl; - u_long sctrl; - struct es_chinfo pch, rch; -} es_info_t; - -/* -------------------------------------------------------------------- */ -/* prototypes */ - -static u_int es1371_wait_src_ready(es_info_t *); -static void es1371_src_write(es_info_t *, u_short, unsigned short); -static u_int es1371_adc_rate (es_info_t *, u_int, int); -static u_int es1371_dac1_rate(es_info_t *, u_int, int); -static u_int es1371_dac2_rate(es_info_t *, u_int, int); -static void es1371_wrcodec(void *, int, u_int32_t); -static u_int32_t es1371_rdcodec(void *, u_int32_t); -static int es1371_init(es_info_t *es); -static int eschan1371_setspeed(void *data, u_int32_t speed); - -static int es_init(struct es_info *); -static void es_intr(void *); -static int write_codec(struct es_info *, u_char, u_char); - -/* channel interface */ -static void *eschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -static int eschan_setdir(void *data, int dir); -static int eschan_setformat(void *data, u_int32_t format); -static int eschan_setspeed(void *data, u_int32_t speed); -static int eschan_setblocksize(void *data, u_int32_t blocksize); -static int eschan_trigger(void *data, int go); -static int eschan_getptr(void *data); -static pcmchan_caps *eschan_getcaps(void *data); - -static pcmchan_caps es_playcaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcmchan_caps es_reccaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcm_channel es_chantemplate = { - eschan_init, - eschan_setdir, - eschan_setformat, - eschan_setspeed, - eschan_setblocksize, - eschan_trigger, - eschan_getptr, - eschan_getcaps, -}; - -/* -------------------------------------------------------------------- */ - -/* The mixer interface */ - -static int es_mixinit(snd_mixer *m); -static int es_mixset(snd_mixer *m, unsigned dev, unsigned left, unsigned right); -static int es_mixsetrecsrc(snd_mixer *m, u_int32_t src); - -static snd_mixer es_mixer = { - "Ensoniq AudioPCI 1370 mixer", - es_mixinit, - es_mixset, - es_mixsetrecsrc, -}; - -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 -es_mixinit(snd_mixer *m) -{ - int i; - u_int32_t v; - - v = 0; - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - if (mixtable[i].avail) v |= (1 << i); - mix_setdevs(m, v); - v = 0; - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - if (mixtable[i].recmask) v |= (1 << i); - mix_setrecdevs(m, v); - return 0; -} - -static int -es_mixset(snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - int l, r, rl, rr; - - if (!mixtable[dev].avail) return -1; - l = left; - r = mixtable[dev].stereo? right : l; - if (mixtable[dev].left == 0xf) { - rl = (l < 2)? 0x80 : 7 - (l - 2) / 14; - } else { - rl = (l < 10)? 0x80 : 15 - (l - 10) / 6; - } - if (mixtable[dev].stereo) { - rr = (r < 10)? 0x80 : 15 - (r - 10) / 6; - write_codec(mix_getdevinfo(m), mixtable[dev].right, rr); - } - write_codec(mix_getdevinfo(m), mixtable[dev].left, rl); - return l | (r << 8); -} - -static int -es_mixsetrecsrc(snd_mixer *m, u_int32_t src) -{ - int i, j = 0; - - if (src == 0) src = 1 << SOUND_MIXER_MIC; - src &= mix_getrecdevs(m); - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - if ((src & (1 << i)) != 0) j |= mixtable[i].recmask; - - write_codec(mix_getdevinfo(m), CODEC_LIMIX1, j & 0x55); - write_codec(mix_getdevinfo(m), CODEC_RIMIX1, j & 0xaa); - write_codec(mix_getdevinfo(m), CODEC_LIMIX2, (j >> 8) & 0x17); - write_codec(mix_getdevinfo(m), CODEC_RIMIX2, (j >> 8) & 0x0f); - write_codec(mix_getdevinfo(m), CODEC_OMIX1, 0x7f); - write_codec(mix_getdevinfo(m), CODEC_OMIX2, 0x3f); - return src; -} - -static int -write_codec(struct es_info *es, u_char i, u_char 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); - } while (--wait); - printf("pcm: write_codec timed out\n"); - return -1; -} - -/* -------------------------------------------------------------------- */ - -/* channel interface */ -static void * -eschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) -{ - struct es_info *es = devinfo; - struct es_chinfo *ch = (dir == PCMDIR_PLAY)? &es->pch : &es->rch; - - ch->parent = es; - ch->channel = c; - ch->buffer = b; - ch->buffer->bufsize = ES_BUFFSIZE; - if (chn_allocbuf(ch->buffer, es->parent_dmat) == -1) return NULL; - return ch; -} - -static int -eschan_setdir(void *data, int dir) -{ - struct es_chinfo *ch = data; - struct es_info *es = ch->parent; - - if (dir == PCMDIR_PLAY) { - 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, - vtophys(ch->buffer->buf)); - bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_FRAMECNT & 0xff, - (ch->buffer->bufsize >> 2) - 1); - } else { - 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, - vtophys(ch->buffer->buf)); - bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_FRAMECNT & 0xff, - (ch->buffer->bufsize >> 2) - 1); - } - ch->dir = dir; - return 0; -} - -static int -eschan_setformat(void *data, u_int32_t format) -{ - struct es_chinfo *ch = data; - struct es_info *es = ch->parent; - - if (ch->dir == PCMDIR_PLAY) { - es->sctrl &= ~SCTRL_P2FMT; - if (format & AFMT_S16_LE) es->sctrl |= SCTRL_P2SEB; - if (format & AFMT_STEREO) es->sctrl |= SCTRL_P2SMB; - } else { - es->sctrl &= ~SCTRL_R1FMT; - if (format & AFMT_S16_LE) es->sctrl |= SCTRL_R1SEB; - if (format & AFMT_STEREO) es->sctrl |= SCTRL_R1SMB; - } - bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl); - ch->fmt = format; - return 0; -} - -static int -eschan_setspeed(void *data, u_int32_t speed) -{ - struct es_chinfo *ch = data; - struct es_info *es = ch->parent; - - es->ctrl &= ~CTRL_PCLKDIV; - es->ctrl |= DAC2_SRTODIV(speed) << CTRL_SH_PCLKDIV; - bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl); - /* rec/play speeds locked together - should indicate in flags */ -#if 0 - if (ch->direction == PCMDIR_PLAY) d->rec[0].speed = speed; - else d->play[0].speed = speed; -#endif - return speed; /* XXX calc real speed */ -} - -static int -eschan_setblocksize(void *data, u_int32_t blocksize) -{ - return blocksize; -} - -static int -eschan_trigger(void *data, int go) -{ - struct es_chinfo *ch = data; - struct es_info *es = ch->parent; - unsigned cnt = ch->buffer->dl / ch->buffer->sample_size - 1; - - if (ch->dir == PCMDIR_PLAY) { - if (go == PCMTRIG_START) { - int b = (ch->fmt & AFMT_S16_LE)? 2 : 1; - es->ctrl |= CTRL_DAC2_EN; - es->sctrl &= ~(SCTRL_P2ENDINC | SCTRL_P2STINC | - SCTRL_P2LOOPSEL | SCTRL_P2PAUSE | - SCTRL_P2DACSEN); - es->sctrl |= SCTRL_P2INTEN | (b << SCTRL_SH_P2ENDINC); - bus_space_write_4(es->st, es->sh, - ES1370_REG_DAC2_SCOUNT, cnt); - } else es->ctrl &= ~CTRL_DAC2_EN; - } else { - if (go == PCMTRIG_START) { - es->ctrl |= CTRL_ADC_EN; - es->sctrl &= ~SCTRL_R1LOOPSEL; - es->sctrl |= SCTRL_R1INTEN; - bus_space_write_4(es->st, es->sh, - ES1370_REG_ADC_SCOUNT, cnt); - } else es->ctrl &= ~CTRL_ADC_EN; - } - 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); - return 0; -} - -static int -eschan_getptr(void *data) -{ - struct es_chinfo *ch = data; - struct es_info *es = ch->parent; - if (ch->dir == PCMDIR_PLAY) { - bus_space_write_4(es->st, es->sh, ES1370_REG_MEMPAGE, - ES1370_REG_DAC2_FRAMECNT >> 8); - return (bus_space_read_4(es->st, es->sh, - ES1370_REG_DAC2_FRAMECNT & 0xff) >> 14) & 0x3fffc; - } else { - bus_space_write_4(es->st, es->sh, ES1370_REG_MEMPAGE, - ES1370_REG_ADC_FRAMECNT >> 8); - return (bus_space_read_4(es->st, es->sh, - ES1370_REG_ADC_FRAMECNT & 0xff) >> 14) & 0x3fffc; - } -} - -static pcmchan_caps * -eschan_getcaps(void *data) -{ - struct es_chinfo *ch = data; - return (ch->dir == PCMDIR_PLAY)? &es_playcaps : &es_reccaps; -} - -/* The interrupt handler */ -static void -es_intr (void *p) -{ - struct es_info *es = p; - 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) chn_intr(es->pch.channel); - if (intsrc & STAT_ADC) chn_intr(es->rch.channel); -} - - -/* ES1371 specific code */ - -#define CODEC_ID_SESHIFT 10 -#define CODEC_ID_SEMASK 0x1f - -#define CODEC_PIRD 0x00800000 /* 0 = write AC97 register */ -#define CODEC_PIADD_MASK 0x007f0000 -#define CODEC_PIADD_SHIFT 16 -#define CODEC_PIDAT_MASK 0x0000ffff -#define CODEC_PIDAT_SHIFT 0 - -#define CODEC_PORD 0x00800000 /* 0 = write AC97 register */ -#define CODEC_POADD_MASK 0x007f0000 -#define CODEC_POADD_SHIFT 16 -#define CODEC_PODAT_MASK 0x0000ffff -#define CODEC_PODAT_SHIFT 0 - -#define CODEC_RDY 0x80000000 /* AC97 read data valid */ -#define CODEC_WIP 0x40000000 /* AC97 write in progress */ - -#define ES1370_REG_CONTROL 0x00 -#define ES1370_REG_SERIAL_CONTROL 0x20 -#define ES1371_REG_CODEC 0x14 -#define ES1371_REG_LEGACY 0x18 /* W/R: Legacy control/status register */ -#define ES1371_REG_SMPRATE 0x10 /* W/R: Codec rate converter interface register */ - -#define ES1371_SYNC_RES (1<<14) /* Warm AC97 reset */ -#define ES1371_DIS_R1 (1<<19) /* record channel accumulator update disable */ -#define ES1371_DIS_P2 (1<<20) /* playback channel 2 accumulator update disable */ -#define ES1371_DIS_P1 (1<<21) /* playback channel 1 accumulator update disable */ -#define ES1371_DIS_SRC (1<<22) /* sample rate converter disable */ -#define ES1371_SRC_RAM_BUSY (1<<23) /* R/O: sample rate memory is busy */ -#define ES1371_SRC_RAM_WE (1<<24) /* R/W: read/write control for sample rate converter */ -#define ES1371_SRC_RAM_ADDRO(o) (((o)&0x7f)<<25) /* address of the sample rate converter */ -#define ES1371_SRC_RAM_DATAO(o) (((o)&0xffff)<<0) /* current value of the sample rate converter */ -#define ES1371_SRC_RAM_DATAI(i) (((i)>>0)&0xffff) /* current value of the sample rate converter */ - -/* - * Sample rate converter addresses - */ - -#define ES_SMPREG_DAC1 0x70 -#define ES_SMPREG_DAC2 0x74 -#define ES_SMPREG_ADC 0x78 -#define ES_SMPREG_TRUNC_N 0x00 -#define ES_SMPREG_INT_REGS 0x01 -#define ES_SMPREG_VFREQ_FRAC 0x03 -#define ES_SMPREG_VOL_ADC 0x6c -#define ES_SMPREG_VOL_DAC1 0x7c -#define ES_SMPREG_VOL_DAC2 0x7e - - -int -es1371_init(struct es_info *es) -{ - int idx; - - if(debug > 0) printf("es_init\n"); - - es->ctrl = 0; - es->sctrl = 0; - /* initialize the chips */ - 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); - bus_space_write_4(es->st, es->sh, ES1371_REG_LEGACY, 0); - /* AC'97 warm reset to start the bitclk */ - bus_space_write_4(es->st, es->sh, ES1371_REG_LEGACY, es->ctrl | ES1371_SYNC_RES); - DELAY(2000); - bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL,es->ctrl); - /* Init the sample rate converter */ - bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, ES1371_DIS_SRC); - for (idx = 0; idx < 0x80; idx++) - es1371_src_write(es, idx, 0); - es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N, 16 << 4); - es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10); - es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N, 16 << 4); - es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10); - es1371_src_write(es, ES_SMPREG_VOL_ADC, 1 << 12); - es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, 1 << 12); - es1371_src_write(es, ES_SMPREG_VOL_DAC1, 1 << 12); - es1371_src_write(es, ES_SMPREG_VOL_DAC1 + 1, 1 << 12); - es1371_src_write(es, ES_SMPREG_VOL_DAC2, 1 << 12); - es1371_src_write(es, ES_SMPREG_VOL_DAC2 + 1, 1 << 12); - es1371_adc_rate (es, 22050, 1); - es1371_dac1_rate(es, 22050, 1); - es1371_dac2_rate(es, 22050, 1); - /* WARNING: - * enabling the sample rate converter without properly programming - * its parameters causes the chip to lock up (the SRC busy bit will - * be stuck high, and I've found no way to rectify this other than - * power cycle) - */ - bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, 0); - - return (0); -} - -void -es1371_wrcodec(void *s, int addr, u_int32_t data) -{ - /* unsigned long flags; */ - int sl; - unsigned t, x; - struct es_info *es = (struct es_info*)s; - - if(debug > 0) printf("wrcodec addr 0x%x data 0x%x\n",addr,data); - - for (t = 0; t < 0x1000; t++) - if(!(bus_space_read_4(es->st, es->sh,(ES1371_REG_CODEC & CODEC_WIP)))) - break; - sl = spltty(); - /* save the current state for later */ - x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE); - /* enable SRC state data in SRC mux */ - bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, - (es1371_wait_src_ready(s) & - (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1))); - /* wait for a SAFE time to write addr/data and then do it, dammit */ - for (t = 0; t < 0x1000; t++) - if (( bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000) - break; - - if(debug > 2) printf("one b_s_w: 0x%x 0x%x 0x%x\n",es->sh,ES1371_REG_CODEC, - ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | - ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK)); - - bus_space_write_4(es->st, es->sh,ES1371_REG_CODEC, - ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | - ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK)); - /* restore SRC reg */ - es1371_wait_src_ready(s); - if(debug > 2) printf("two b_s_w: 0x%x 0x%x 0x%x\n",es->sh,ES1371_REG_SMPRATE,x); - bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,x); - splx(sl); -} - -u_int32_t -es1371_rdcodec(void *s, u_int32_t addr) -{ - /* unsigned long flags; */ - int sl; - unsigned t, x; - - struct es_info *es = (struct es_info *)s; - - if(debug > 0) printf("rdcodec addr 0x%x ... ",addr); - - for (t = 0; t < 0x1000; t++) - if (!(x = bus_space_read_4(es->st,es->sh,ES1371_REG_CODEC) & CODEC_WIP)) - break; - if(debug >0) printf("loop 1 t 0x%x x 0x%x ",t,x); - - sl = spltty(); - - /* save the current state for later */ - x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE); - /* enable SRC state data in SRC mux */ - bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, - (es1371_wait_src_ready(s) & - (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1))); - /* wait for a SAFE time to write addr/data and then do it, dammit */ - for (t = 0; t < 0x5000; t++) - if (( x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000) - break; - if(debug >0) printf("loop 2 t 0x%x x 0x%x ",t,x); - bus_space_write_4(es->st, es->sh,ES1371_REG_CODEC, - ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | CODEC_PORD); - - /* restore SRC reg */ - es1371_wait_src_ready(s); - bus_space_write_4(es->st,es->sh,ES1371_REG_SMPRATE,x); - - splx(sl); - - /* now wait for the stinkin' data (RDY) */ - for (t = 0; t < 0x1000; t++) - if ((x = bus_space_read_4(es->st,es->sh,ES1371_REG_CODEC)) & CODEC_RDY) - break; - if(debug > 0) printf("loop 3 t 0x%x 0x%x ret 0x%x\n",t,x,((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT)); - return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT); -} - - - - -static u_int -es1371_src_read(es_info_t *es, u_short reg){ - - unsigned int r; - - r = es1371_wait_src_ready(es) & - (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1); - r |= ES1371_SRC_RAM_ADDRO(reg); - bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r); - return ES1371_SRC_RAM_DATAI(es1371_wait_src_ready(es)); -} - -static void -es1371_src_write(es_info_t *es, u_short reg, u_short data){ - u_int r; - - r = es1371_wait_src_ready(es) & - (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1); - r |= ES1371_SRC_RAM_ADDRO(reg) | ES1371_SRC_RAM_DATAO(data); - /* printf("es1371_src_write 0x%x 0x%x\n",ES1371_REG_SMPRATE,r | ES1371_SRC_RAM_WE); */ - bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r | ES1371_SRC_RAM_WE); -} - -static u_int -es1371_adc_rate(es_info_t *es, u_int rate, int set){ - u_int n, truncm, freq, result; - - if (rate > 48000) - rate = 48000; - if (rate < 4000) - rate = 4000; - n = rate / 3000; - if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9))) - n--; - truncm = (21 * n - 1) | 1; - freq = ((48000UL << 15) / rate) * n; - result = (48000UL << 15) / (freq / n); - if (set) { - if (rate >= 24000) { - if (truncm > 239) - truncm = 239; - es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N, - (((239 - truncm) >> 1) << 9) | (n << 4)); - } else { - if (truncm > 119) - truncm = 119; - es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N, - 0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4)); - } - es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS, - (es1371_src_read(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS) & - 0x00ff) | ((freq >> 5) & 0xfc00)); - es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); - es1371_src_write(es, ES_SMPREG_VOL_ADC, n << 8); - es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, n << 8); - } - return result; -} - -static u_int -es1371_dac1_rate(es_info_t *es, u_int rate, int set){ - u_int freq, r, result; - - if (rate > 48000) - rate = 48000; - if (rate < 4000) - rate = 4000; - freq = (rate << 15) / 3000; - result = (freq * 3000) >> 15; - if (set) { - r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)); - bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r); - es1371_src_write(es, ES_SMPREG_DAC1 + - ES_SMPREG_INT_REGS, - (es1371_src_read(es, - ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS) & 0x00ff) | ((freq >> 5) & 0xfc00)); - es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); - r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P2 | ES1371_DIS_R1)); - bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r); - } - return result; -} - -static u_int -es1371_dac2_rate(es_info_t *es, u_int rate, int set){ - u_int freq, r, result; - - if (rate > 48000) - rate = 48000; - if (rate < 4000) - rate = 4000; - freq = (rate << 15) / 3000; - result = (freq * 3000) >> 15; - if (set) { - r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)); - bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r); - /* if(debug > 0) printf("dac2_rate 0x%x\n",bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE)); */ - es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, - (es1371_src_read(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS) & - 0x00ff) | ((freq >> 5) & 0xfc00)); - es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); - r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_R1)); - bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r); - /* if(debug > 0) printf("dac2_rate 0x%x\n",bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE)); */ - } - return result; -} - - -static u_int -es1371_wait_src_ready(es_info_t *es){ - u_int t, r; - - for (t = 0; t < 500; t++) { - if (!((r = bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE)) & ES1371_SRC_RAM_BUSY)){ - return r; - } - DELAY(1000); - } - printf("es1371: wait source ready timeout 0x%x [0x%x]\n", ES1371_REG_SMPRATE, r); - return 0; -} - - -int -eschan1371_setspeed(void *data, u_int32_t speed) -{ - struct es_chinfo *ch = data; - struct es_info *es = ch->parent; - - /* rec/play speeds locked together - should indicate in flags */ - es1371_dac2_rate(es, speed, 1); /* play */ - es1371_adc_rate (es, speed, 1); /* record */ - - return speed; /* XXX calc real speed */ -} - - - -/* -------------------------------------------------------------------- */ - -/* - * Probe and attach the card - */ - -static int -es_init(struct es_info *es) -{ - 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(es, CODEC_RES_PD, 3);/* No RST, PD */ - write_codec(es, CODEC_CSEL, 0); /* CODEC ADC and CODEC DAC use - * {LR,B}CLK2 and run off the LRCLK2 - * PLL; program DAC_SYNC=0! */ - write_codec(es, CODEC_ADSEL, 0);/* Recording source is mixer */ - write_codec(es, CODEC_MGAIN, 0);/* MIC amp is 0db */ - - return 0; -} - -static int -es_pci_probe(device_t dev) -{ - if (pci_get_devid(dev) == ES1370_PCI_ID) { - device_set_desc(dev, "AudioPCI ES1370"); - return 0; - } else if (pci_get_devid(dev) == ES1371_PCI_ID) { - device_set_desc(dev, "AudioPCI ES1371"); - return 0; - } - return ENXIO; -} - -static int -es_pci_attach(device_t dev) -{ - snddev_info *d; - u_int32_t data; - struct es_info *es = 0; - int type = 0; - int regid; - struct resource *reg = 0; - int mapped; - int irqid; - struct resource *irq = 0; - void *ih = 0; - char status[SND_STATUSLEN]; - struct ac97_info *codec; - - d = device_get_softc(dev); - if ((es = malloc(sizeof *es, M_DEVBUF, M_NOWAIT)) == NULL) { - device_printf(dev, "cannot allocate softc\n"); - return ENXIO; - } - bzero(es, sizeof *es); - - mapped = 0; - data = pci_read_config(dev, PCIR_COMMAND, 2); - if (mapped == 0 && (data & PCIM_CMD_MEMEN)) { - regid = MEM_MAP_REG; - type = SYS_RES_MEMORY; - reg = bus_alloc_resource(dev, type, ®id, - 0, ~0, 1, RF_ACTIVE); - if (reg) { - es->st = rman_get_bustag(reg); - es->sh = rman_get_bushandle(reg); - mapped++; - } - } - if (mapped == 0 && (data & PCIM_CMD_PORTEN)) { - regid = PCI_MAP_REG_START; - type = SYS_RES_IOPORT; - reg = bus_alloc_resource(dev, type, ®id, - 0, ~0, 1, RF_ACTIVE); - if (reg) { - es->st = rman_get_bustag(reg); - es->sh = rman_get_bushandle(reg); - mapped++; - } - } - if (mapped == 0) { - device_printf(dev, "unable to map register space\n"); - goto bad; - } - - if (pci_get_devid(dev) == ES1371_PCI_ID) { - if(-1 == es1371_init(es)){ - device_printf(dev, "unable to initialize the card\n"); - goto bad; - } - codec = ac97_create(es,(ac97_read *)es1371_rdcodec,(ac97_write *)es1371_wrcodec); - if (codec == NULL) goto bad; - /* our init routine does everything for us */ - /* set to NULL; flag mixer_init not to run the ac97_init */ - /* ac97_mixer.init = NULL; */ - mixer_init(d, &ac97_mixer, codec); - /* change the routine for setting speed */ - es_chantemplate.setspeed = eschan1371_setspeed; - } else if (pci_get_devid(dev) == ES1370_PCI_ID) { - if (-1 == es_init(es)){ - device_printf(dev, "unable to initialize the card\n"); - goto bad; - } - mixer_init(d, &es_mixer, es); - } - - - irqid = 0; - irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid, - 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); - if (!irq - || bus_setup_intr(dev, irq, INTR_TYPE_TTY, es_intr, es, &ih)) { - device_printf(dev, "unable to map interrupt\n"); - goto bad; - } - - 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*/ES_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff, - /*flags*/0, &es->parent_dmat) != 0) { - device_printf(dev, "unable to create dma tag\n"); - goto bad; - } - - snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld", - (type == SYS_RES_IOPORT)? "io" : "memory", - rman_get_start(reg), rman_get_start(irq)); - - if (pcm_register(dev, es, 1, 1)) goto bad; - pcm_addchan(dev, PCMDIR_REC, &es_chantemplate, es); - pcm_addchan(dev, PCMDIR_PLAY, &es_chantemplate, es); - pcm_setstatus(dev, status); - - return 0; - - bad: - if (es) free(es, M_DEVBUF); - if (reg) bus_release_resource(dev, type, regid, reg); - if (ih) bus_teardown_intr(dev, irq, ih); - if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq); - return ENXIO; -} - -static device_method_t es_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, es_pci_probe), - DEVMETHOD(device_attach, es_pci_attach), - - { 0, 0 } -}; - -static driver_t es_driver = { - "pcm", - es_methods, - sizeof(snddev_info), -}; - -static devclass_t pcm_devclass; - -DRIVER_MODULE(es, pci, es_driver, pcm_devclass, 0, 0); - - -#endif /* NPCI != 0 */ Property changes on: head/sys/dev/pcm/pci/es137x.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/pci/es137x.h =================================================================== --- head/sys/dev/pcm/pci/es137x.h (revision 53505) +++ head/sys/dev/pcm/pci/es137x.h (nonexistent) @@ -1,134 +0,0 @@ -/* - * This supports the ENSONIQ AudioPCI board based on the ES1370. - * - * Copyright (c) 1998 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 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 Property changes on: head/sys/dev/pcm/pci/es137x.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/pci/t4dwave.c =================================================================== --- head/sys/dev/pcm/pci/t4dwave.c (revision 53505) +++ head/sys/dev/pcm/pci/t4dwave.c (nonexistent) @@ -1,688 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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, WHETHERIN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include "pci.h" -#include "pcm.h" - -#include -#include -#include - -#include -#include - -#if NPCI != 0 - -/* -------------------------------------------------------------------- */ - -struct tr_info; - -/* channel registers */ -struct tr_chinfo { - u_int32_t cso, alpha, fms, fmc, ec; - u_int32_t lba; - u_int32_t eso, delta; - u_int32_t rvol, cvol; - u_int32_t gvsel, pan, vol, ctrl; - int index; - snd_dbuf *buffer; - pcm_channel *channel; - struct tr_info *parent; -}; - -/* device private data */ -struct tr_info { - u_int32_t type; - - bus_space_tag_t st; - bus_space_handle_t sh; - bus_dma_tag_t parent_dmat; - - struct resource *reg, *irq; - int regtype, regid, irqid; - void *ih; - - u_int32_t playchns; - struct tr_chinfo chinfo[TR_MAXPLAYCH]; - struct tr_chinfo recchinfo; -}; - -/* -------------------------------------------------------------------- */ - -/* - * prototypes - */ - -/* channel interface */ -static void *trchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -static int trchan_setdir(void *data, int dir); -static int trchan_setformat(void *data, u_int32_t format); -static int trchan_setspeed(void *data, u_int32_t speed); -static int trchan_setblocksize(void *data, u_int32_t blocksize); -static int trchan_trigger(void *data, int go); -static int trchan_getptr(void *data); -static pcmchan_caps *trchan_getcaps(void *data); - -/* talk to the codec - called from ac97.c */ -static u_int32_t tr_rdcd(void *, int); -static void tr_wrcd(void *, int, u_int32_t); - -/* stuff */ -static int tr_init(struct tr_info *); -static void tr_intr(void *); - -/* talk to the card */ -static u_int32_t tr_rd(struct tr_info *, int, int); -static void tr_wr(struct tr_info *, int, u_int32_t, int); - -/* manipulate playback channels */ -static void tr_clrint(struct tr_info *, char); -static void tr_enaint(struct tr_info *, char, int); -static u_int32_t tr_testint(struct tr_info *, char); -static void tr_rdch(struct tr_info *, char, struct tr_chinfo *); -static void tr_wrch(struct tr_info *, char, struct tr_chinfo *); -static void tr_selch(struct tr_info *, char); -static void tr_startch(struct tr_info *, char); -static void tr_stopch(struct tr_info *, char); - -/* -------------------------------------------------------------------- */ - -static pcmchan_caps tr_reccaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_U16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcmchan_caps tr_playcaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_U16_LE, - AFMT_U16_LE -}; - -static pcm_channel tr_chantemplate = { - trchan_init, - trchan_setdir, - trchan_setformat, - trchan_setspeed, - trchan_setblocksize, - trchan_trigger, - trchan_getptr, - trchan_getcaps, -}; - -/* -------------------------------------------------------------------- */ - -static u_int32_t -tr_fmttobits(u_int32_t fmt) -{ - u_int32_t bits = 0; - bits |= (fmt & AFMT_STEREO)? 0x4 : 0; - bits |= (fmt & (AFMT_S8 | AFMT_S16_LE))? 0x2 : 0; - bits |= (fmt & (AFMT_S16_LE | AFMT_U16_LE))? 0x8 : 0; - return bits; -} - -/* Hardware */ - -static u_int32_t -tr_rd(struct tr_info *tr, int regno, int size) -{ - switch(size) { - case 1: - return bus_space_read_1(tr->st, tr->sh, regno); - case 2: - return bus_space_read_2(tr->st, tr->sh, regno); - case 4: - return bus_space_read_4(tr->st, tr->sh, regno); - default: - return 0xffffffff; - } -} - -static void -tr_wr(struct tr_info *tr, int regno, u_int32_t data, int size) -{ - switch(size) { - case 1: - bus_space_write_1(tr->st, tr->sh, regno, data); - break; - case 2: - bus_space_write_2(tr->st, tr->sh, regno, data); - break; - case 4: - bus_space_write_4(tr->st, tr->sh, regno, data); - break; - } -} - -/* ac97 codec */ - -static u_int32_t -tr_rdcd(void *devinfo, int regno) -{ - struct tr_info *tr = (struct tr_info *)devinfo; - int i, j, treg, trw; - - switch (tr->type) { - case TDX_PCI_ID: - treg=TDX_REG_CODECRD; - trw=TDX_CDC_RWSTAT; - break; - case TNX_PCI_ID: - treg=(regno & 0x100)? TNX_REG_CODEC2RD : TNX_REG_CODEC1RD; - trw=TNX_CDC_RWSTAT; - break; - default: - printf("!!! tr_rdcd defaulted !!!\n"); - return 0xffffffff; - } - - regno &= 0x7f; - tr_wr(tr, treg, regno | trw, 4); - j=trw; - for (i=TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--) j=tr_rd(tr, treg, 4); - if (i == 0) printf("codec timeout during read of register %x\n", regno); - return (j >> TR_CDC_DATA) & 0xffff; -} - -static void -tr_wrcd(void *devinfo, int regno, u_int32_t data) -{ - struct tr_info *tr = (struct tr_info *)devinfo; - int i, j, treg, trw; - - switch (tr->type) { - case TDX_PCI_ID: - treg=TDX_REG_CODECWR; - trw=TDX_CDC_RWSTAT; - break; - case TNX_PCI_ID: - treg=TNX_REG_CODECWR; - trw=TNX_CDC_RWSTAT | ((regno & 0x100)? TNX_CDC_SEC : 0); - break; - default: - printf("!!! tr_wrcd defaulted !!!"); - return; - } - - regno &= 0x7f; -#if 0 - printf("tr_wrcd: reg %x was %x", regno, tr_rdcd(devinfo, regno)); -#endif - j=trw; - for (i=TR_TIMEOUT_CDC; (i>0) && (j & trw); i--) j=tr_rd(tr, treg, 4); - tr_wr(tr, treg, (data << TR_CDC_DATA) | regno | trw, 4); -#if 0 - printf(" - wrote %x, now %x\n", data, tr_rdcd(devinfo, regno)); -#endif - if (i==0) printf("codec timeout writing %x, data %x\n", regno, data); -} - -/* playback channel interrupts */ - -static u_int32_t -tr_testint(struct tr_info *tr, char channel) -{ - return tr_rd(tr, (channel & 0x20)? TR_REG_ADDRINTB : TR_REG_ADDRINTA, - 4) & (1<<(channel & 0x1f)); -} - -static void -tr_clrint(struct tr_info *tr, char channel) -{ - tr_wr(tr, (channel & 0x20)? TR_REG_ADDRINTB : TR_REG_ADDRINTA, - 1<<(channel & 0x1f), 4); -} - -static void -tr_enaint(struct tr_info *tr, char channel, int enable) -{ - u_int32_t reg = (channel & 0x20)? TR_REG_INTENB : TR_REG_INTENA; - u_int32_t i = tr_rd(tr, reg, 4); - channel &= 0x1f; - i &= ~(1 << channel); - i |= (enable? 1 : 0) << channel; - tr_clrint(tr, channel); - tr_wr(tr, reg, i, 4); -} - -/* playback channels */ - -static void -tr_selch(struct tr_info *tr, char channel) -{ - int i=tr_rd(tr, TR_REG_CIR, 4); - i &= ~TR_CIR_MASK; - i |= channel & 0x3f; - tr_wr(tr, TR_REG_CIR, i, 4); -} - -static void -tr_startch(struct tr_info *tr, char channel) -{ - tr_wr(tr, (channel & 0x20)? TR_REG_STARTB : TR_REG_STARTA, - 1<<(channel & 0x1f), 4); -} - -static void -tr_stopch(struct tr_info *tr, char channel) -{ - tr_wr(tr, (channel & 0x20)? TR_REG_STOPB : TR_REG_STOPA, - 1<<(channel & 0x1f), 4); -} - -static void -tr_wrch(struct tr_info *tr, char channel, struct tr_chinfo *ch) -{ - u_int32_t cr[TR_CHN_REGS], i; - - ch->gvsel &= 0x00000001; - ch->fmc &= 0x00000003; - ch->fms &= 0x0000000f; - ch->ctrl &= 0x0000000f; - ch->pan &= 0x0000007f; - ch->rvol &= 0x0000007f; - ch->cvol &= 0x0000007f; - ch->vol &= 0x000000ff; - ch->ec &= 0x00000fff; - ch->alpha &= 0x00000fff; - ch->delta &= 0x0000ffff; - ch->lba &= 0x3fffffff; - - cr[1]=ch->lba; - cr[3]=(ch->rvol<<7) | (ch->cvol); - cr[4]=(ch->gvsel<<31)|(ch->pan<<24)|(ch->vol<<16)|(ch->ctrl<<12)|(ch->ec); - - switch (tr->type) { - case TDX_PCI_ID: - ch->cso &= 0x0000ffff; - ch->eso &= 0x0000ffff; - cr[0]=(ch->cso<<16) | (ch->alpha<<4) | (ch->fms); - cr[2]=(ch->eso<<16) | (ch->delta); - cr[3]|=0x0000c000; - break; - case TNX_PCI_ID: - ch->cso &= 0x00ffffff; - ch->eso &= 0x00ffffff; - cr[0]=((ch->delta & 0xff)<<24) | (ch->cso); - cr[2]=((ch->delta>>16)<<24) | (ch->eso); - cr[3]|=(ch->alpha<<20) | (ch->fms<<16) | (ch->fmc<<14); - break; - } - tr_selch(tr, channel); - for (i=0; ilba= (cr[1] & 0x3fffffff); - ch->fmc= (cr[3] & 0x0000c000) >> 14; - ch->rvol= (cr[3] & 0x00003f80) >> 7; - ch->cvol= (cr[3] & 0x0000007f); - ch->gvsel= (cr[4] & 0x80000000) >> 31; - ch->pan= (cr[4] & 0x7f000000) >> 24; - ch->vol= (cr[4] & 0x00ff0000) >> 16; - ch->ctrl= (cr[4] & 0x0000f000) >> 12; - ch->ec= (cr[4] & 0x00000fff); - switch(tr->type) { - case TDX_PCI_ID: - ch->cso= (cr[0] & 0xffff0000) >> 16; - ch->alpha= (cr[0] & 0x0000fff0) >> 4; - ch->fms= (cr[0] & 0x0000000f); - ch->eso= (cr[2] & 0xffff0000) >> 16; - ch->delta= (cr[2] & 0x0000ffff); - break; - case TNX_PCI_ID: - ch->cso= (cr[0] & 0x00ffffff); - ch->eso= (cr[2] & 0x00ffffff); - ch->delta= ((cr[2] & 0xff000000) >> 16) | - ((cr[0] & 0xff000000) >> 24); - ch->alpha= (cr[3] & 0xfff00000) >> 20; - ch->fms= (cr[3] & 0x000f0000) >> 16; - break; - } -} - -/* channel interface */ - -void * -trchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) -{ - struct tr_info *tr = devinfo; - struct tr_chinfo *ch; - if (dir == PCMDIR_PLAY) { - ch = &tr->chinfo[tr->playchns]; - ch->index = tr->playchns++; - } else { - ch = &tr->recchinfo; - ch->index = -1; - } - ch->buffer = b; - ch->buffer->bufsize = TR_BUFFSIZE; - ch->parent = tr; - ch->channel = c; - if (chn_allocbuf(ch->buffer, tr->parent_dmat) == -1) return NULL; - else return ch; -} - -static int -trchan_setdir(void *data, int dir) -{ - struct tr_chinfo *ch = data; - struct tr_info *tr = ch->parent; - if (dir == PCMDIR_PLAY && ch->index >= 0) { - ch->fmc = ch->fms = ch->ec = ch->alpha = 0; - ch->lba = vtophys(ch->buffer->buf); - ch->cso = 0; - ch->eso = ch->buffer->bufsize - 1; - ch->rvol = ch->cvol = 0; - ch->gvsel = 0; - ch->pan = 0; - ch->vol = 0; - ch->ctrl = 0x01; - ch->delta = 0; - tr_wrch(tr, ch->index, ch); - tr_enaint(tr, ch->index, 1); - } else if (dir == PCMDIR_REC && ch->index == -1) { - /* set up dma mode regs */ - u_int32_t i; - tr_wr(tr, TR_REG_DMAR15, 0, 1); - i = tr_rd(tr, TR_REG_DMAR11, 1) & 0x03; - tr_wr(tr, TR_REG_DMAR11, i | 0x54, 1); - /* set up base address */ - tr_wr(tr, TR_REG_DMAR0, vtophys(ch->buffer->buf), 4); - /* set up buffer size */ - i = tr_rd(tr, TR_REG_DMAR4, 4) & ~0x00ffffff; - tr_wr(tr, TR_REG_DMAR4, i | (ch->buffer->bufsize - 1), 4); - } else return -1; - return 0; -} - -static int -trchan_setformat(void *data, u_int32_t format) -{ - struct tr_chinfo *ch = data; - struct tr_info *tr = ch->parent; - u_int32_t bits = tr_fmttobits(format); - - if (ch->index >= 0) { - tr_rdch(tr, ch->index, ch); - ch->eso = (ch->buffer->bufsize / ch->buffer->sample_size) - 1; - ch->ctrl = bits | 0x01; - tr_wrch(tr, ch->index, ch); - } else { - u_int32_t i; - /* set # of samples between interrupts */ - i = (TR_INTSAMPLES >> ((bits & 0x08)? 1 : 0)) - 1; - tr_wr(tr, TR_REG_SBBL, i | (i << 16), 4); - /* set sample format */ - i = 0x18 | (bits << 4); - tr_wr(tr, TR_REG_SBCTRL, i, 1); - } - return 0; -} - -static int -trchan_setspeed(void *data, u_int32_t speed) -{ - struct tr_chinfo *ch = data; - struct tr_info *tr = ch->parent; - - if (ch->index >= 0) { - tr_rdch(tr, ch->index, ch); - ch->delta = (speed << 12) / 48000; - tr_wrch(tr, ch->index, ch); - return (ch->delta * 48000) >> 12; - } else { - /* setup speed */ - ch->delta = (48000 << 12) / speed; - tr_wr(tr, TR_REG_SBDELTA, ch->delta, 2); - return (48000 << 12) / ch->delta; - } - return 0; -} - -static int -trchan_setblocksize(void *data, u_int32_t blocksize) -{ - struct tr_chinfo *ch = data; - return ch->buffer->bufsize / 2; -} - -static int -trchan_trigger(void *data, int go) -{ - struct tr_chinfo *ch = data; - struct tr_info *tr = ch->parent; - if (ch->index >= 0) { - if (go == PCMTRIG_START) tr_startch(tr, ch->index); - else tr_stopch(tr, ch->index); - } else { - u_int32_t i = tr_rd(tr, TR_REG_SBCTRL, 1) & ~7; - tr_wr(tr, TR_REG_SBCTRL, i | (go == PCMTRIG_START)? 1 : 0, 1); - } - return 0; -} - -static int -trchan_getptr(void *data) -{ - struct tr_chinfo *ch = data; - struct tr_info *tr = ch->parent; - if (ch->index >= 0) { - tr_rdch(tr, ch->index, ch); - return ch->cso * ch->buffer->sample_size; - } else return tr_rd(tr, TR_REG_DMAR0, 4) - vtophys(ch->buffer->buf); -} - -static pcmchan_caps * -trchan_getcaps(void *data) -{ - struct tr_chinfo *ch = data; - return (ch->index >= 0)? &tr_playcaps : &tr_reccaps; -} - -/* The interrupt handler */ - -static void -tr_intr(void *p) -{ - struct tr_info *tr = (struct tr_info *)p; - u_int32_t intsrc = tr_rd(tr, TR_REG_MISCINT, 4); - - if (intsrc & TR_INT_ADDR) { - int i; - for (i = 0; i < tr->playchns; i++) { - if (tr_testint(tr, i)) { - chn_intr(tr->chinfo[i].channel); - tr_clrint(tr, i); - } - } - } - if (intsrc & TR_INT_SB) { - chn_intr(tr->recchinfo.channel); - tr_rd(tr, TR_REG_SBR9, 1); - tr_rd(tr, TR_REG_SBR10, 1); - } -} - -/* -------------------------------------------------------------------- */ - -/* - * Probe and attach the card - */ - -static int -tr_init(struct tr_info *tr) -{ - if (tr->type == TDX_PCI_ID) { - tr_wr(tr, TDX_REG_CODECST, TDX_CDC_ON, 4); - } else tr_wr(tr, TNX_REG_CODECST, TNX_CDC_ON, 4); - - tr_wr(tr, TR_REG_CIR, TR_CIR_MIDENA | TR_CIR_ADDRENA, 4); - tr->playchns = 0; - return 0; -} - -static int -tr_pci_probe(device_t dev) -{ - if (pci_get_devid(dev) == TDX_PCI_ID) { - device_set_desc(dev, "Trident 4DWave DX"); - return 0; - } - if (pci_get_devid(dev) == TNX_PCI_ID) { - device_set_desc(dev, "Trident 4DWave NX"); - return 0; - } - - return ENXIO; -} - -static int -tr_pci_attach(device_t dev) -{ - snddev_info *d; - u_int32_t data; - struct tr_info *tr; - struct ac97_info *codec; - int i; - int mapped; - char status[SND_STATUSLEN]; - - d = device_get_softc(dev); - if ((tr = malloc(sizeof(*tr), M_DEVBUF, M_NOWAIT)) == NULL) { - device_printf(dev, "cannot allocate softc\n"); - return ENXIO; - } - - bzero(tr, sizeof(*tr)); - tr->type = pci_get_devid(dev); - - data = pci_read_config(dev, PCIR_COMMAND, 2); - data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); - pci_write_config(dev, PCIR_COMMAND, data, 2); - data = pci_read_config(dev, PCIR_COMMAND, 2); - - mapped = 0; - /* XXX dfr: is this strictly necessary? */ - for (i = 0; (mapped == 0) && (i < PCI_MAXMAPS_0); i++) { - tr->regid = PCIR_MAPS + i*4; - tr->regtype = SYS_RES_MEMORY; - tr->reg = bus_alloc_resource(dev, tr->regtype, &tr->regid, - 0, ~0, 1, RF_ACTIVE); - if (!tr->reg) { - tr->regtype = SYS_RES_IOPORT; - tr->reg = bus_alloc_resource(dev, tr->regtype, - &tr->regid, 0, ~0, 1, - RF_ACTIVE); - } - if (tr->reg) { - tr->st = rman_get_bustag(tr->reg); - tr->sh = rman_get_bushandle(tr->reg); - mapped++; - } - } - - if (mapped == 0) { - device_printf(dev, "unable to map register space\n"); - goto bad; - } - - if (tr_init(tr) == -1) { - device_printf(dev, "unable to initialize the card\n"); - goto bad; - } - - codec = ac97_create(tr, tr_rdcd, tr_wrcd); - if (codec == NULL) goto bad; - mixer_init(d, &ac97_mixer, codec); - - tr->irqid = 0; - tr->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &tr->irqid, - 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); - if (!tr->irq || - bus_setup_intr(dev, tr->irq, INTR_TYPE_TTY, tr_intr, tr, &tr->ih)) { - device_printf(dev, "unable to map interrupt\n"); - goto bad; - } - - 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*/TR_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff, - /*flags*/0, &tr->parent_dmat) != 0) { - device_printf(dev, "unable to create dma tag\n"); - goto bad; - } - - snprintf(status, 64, "at %s 0x%lx irq %ld", - (tr->regtype == SYS_RES_IOPORT)? "io" : "memory", - rman_get_start(tr->reg), rman_get_start(tr->irq)); - - if (pcm_register(dev, tr, TR_MAXPLAYCH, 1)) goto bad; - pcm_addchan(dev, PCMDIR_REC, &tr_chantemplate, tr); - for (i = 0; i < TR_MAXPLAYCH; i++) - pcm_addchan(dev, PCMDIR_PLAY, &tr_chantemplate, tr); - pcm_setstatus(dev, status); - - return 0; - -bad: - if (tr->reg) bus_release_resource(dev, tr->regtype, tr->regid, tr->reg); - if (tr->ih) bus_teardown_intr(dev, tr->irq, tr->ih); - if (tr->irq) bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq); - free(tr, M_DEVBUF); - return ENXIO; -} - -static device_method_t tr_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, tr_pci_probe), - DEVMETHOD(device_attach, tr_pci_attach), - - { 0, 0 } -}; - -static driver_t tr_driver = { - "pcm", - tr_methods, - sizeof(snddev_info), -}; - -static devclass_t pcm_devclass; - -DRIVER_MODULE(tr, pci, tr_driver, pcm_devclass, 0, 0); - -#endif /* NPCI != 0 */ Property changes on: head/sys/dev/pcm/pci/t4dwave.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/isa/ad1816.c =================================================================== --- head/sys/dev/pcm/isa/ad1816.c (revision 53505) +++ head/sys/dev/pcm/isa/ad1816.c (nonexistent) @@ -1,622 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * Copyright Luigi Rizzo, 1997,1998 - * Copyright by Hannu Savolainen 1994, 1995 - * 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 - -#if NPCM > 0 && NPNP > 0 - -#include - -struct ad1816_info; - -struct ad1816_chinfo { - struct ad1816_info *parent; - pcm_channel *channel; - snd_dbuf *buffer; - int dir; -}; - -struct ad1816_info { - struct resource *io_base; /* primary I/O address for the board */ - int io_rid; - struct resource *irq; - int irq_rid; - struct resource *drq1; /* play */ - int drq1_rid; - struct resource *drq2; /* rec */ - int drq2_rid; - bus_dma_tag_t parent_dmat; - - struct ad1816_chinfo pch, rch; -}; - -static driver_intr_t ad1816_intr; -static int ad1816_probe(device_t dev); -static int ad1816_attach(device_t dev); - -/* IO primitives */ -static int ad1816_wait_init(struct ad1816_info *ad1816, int x); -static u_short ad1816_read(struct ad1816_info *ad1816, u_int reg); -static void ad1816_write(struct ad1816_info *ad1816, u_int reg, u_short data); - -static int ad1816mix_init(snd_mixer *m); -static int ad1816mix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right); -static int ad1816mix_setrecsrc(snd_mixer *m, u_int32_t src); -static snd_mixer ad1816_mixer = { - "ad1816 mixer", - ad1816mix_init, - ad1816mix_set, - ad1816mix_setrecsrc, -}; - -static devclass_t pcm_devclass; - -/* channel interface */ -static void *ad1816chan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -static int ad1816chan_setdir(void *data, int dir); -static int ad1816chan_setformat(void *data, u_int32_t format); -static int ad1816chan_setspeed(void *data, u_int32_t speed); -static int ad1816chan_setblocksize(void *data, u_int32_t blocksize); -static int ad1816chan_trigger(void *data, int go); -static int ad1816chan_getptr(void *data); -static pcmchan_caps *ad1816chan_getcaps(void *data); - -static pcmchan_caps ad1816_caps = { - 4000, 55200, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcm_channel ad1816_chantemplate = { - ad1816chan_init, - ad1816chan_setdir, - ad1816chan_setformat, - ad1816chan_setspeed, - ad1816chan_setblocksize, - ad1816chan_trigger, - ad1816chan_getptr, - ad1816chan_getcaps, -}; - -#define FULL_DUPLEX(x) (pcm_getflags(x) & SD_F_SIMPLEX) -#define AD1816_MUTE 31 /* value for mute */ - -static int -port_rd(struct resource *port, int off) -{ - if (port) - return bus_space_read_1(rman_get_bustag(port), - rman_get_bushandle(port), - off); - else - return -1; -} - -static void -port_wr(struct resource *port, int off, u_int8_t data) -{ - if (port) - return bus_space_write_1(rman_get_bustag(port), - rman_get_bushandle(port), - off, data); -} - -static int -io_rd(struct ad1816_info *ad1816, int reg) -{ - return port_rd(ad1816->io_base, reg); -} - -static void -io_wr(struct ad1816_info *ad1816, int reg, u_int8_t data) -{ - return port_wr(ad1816->io_base, reg, data); -} - -static void -ad1816_intr(void *arg) -{ - struct ad1816_info *ad1816 = (struct ad1816_info *)arg; - unsigned char c, served = 0; - - /* get interupt status */ - c = io_rd(ad1816, AD1816_INT); - - /* check for stray interupts */ - if (c & ~(AD1816_INTRCI | AD1816_INTRPI)) { - printf("pcm: stray int (%x)\n", c); - c &= AD1816_INTRCI | AD1816_INTRPI; - } - /* check for capture interupt */ - if (ad1816->rch.buffer->dl && (c & AD1816_INTRCI)) { - chn_intr(ad1816->rch.channel); - served |= AD1816_INTRCI; /* cp served */ - } - /* check for playback interupt */ - if (ad1816->pch.buffer->dl && (c & AD1816_INTRPI)) { - chn_intr(ad1816->pch.channel); - served |= AD1816_INTRPI; /* pb served */ - } - if (served == 0) { - /* this probably means this is not a (working) ad1816 chip, */ - /* or an error in dma handling */ - printf("pcm: int without reason (%x)\n", c); - c = 0; - } else c &= ~served; - io_wr(ad1816, AD1816_INT, c); - c = io_rd(ad1816, AD1816_INT); - if (c != 0) printf("pcm: int clear failed (%x)\n", c); -} - -static int -ad1816_wait_init(struct ad1816_info *ad1816, int x) -{ - int n = 0; /* to shut up the compiler... */ - - for (; x--;) - if ((n = (io_rd(ad1816, AD1816_ALE) & AD1816_BUSY)) == 0) DELAY(10); - else return n; - printf("ad1816_wait_init failed 0x%02x.\n", n); - return -1; -} - -static unsigned short -ad1816_read(struct ad1816_info *ad1816, unsigned int reg) -{ - int flags; - u_short x = 0; - - /* we don't want to be blocked here */ - flags = spltty(); - if (ad1816_wait_init(ad1816, 100) == -1) return 0; - io_wr(ad1816, AD1816_ALE, 0); - io_wr(ad1816, AD1816_ALE, (reg & AD1816_ALEMASK)); - if (ad1816_wait_init(ad1816, 100) == -1) return 0; - x = (io_rd(ad1816, AD1816_HIGH) << 8) | io_rd(ad1816, AD1816_LOW); - splx(flags); - return x; -} - -static void -ad1816_write(struct ad1816_info *ad1816, unsigned int reg, unsigned short data) -{ - int flags; - - flags = spltty(); - if (ad1816_wait_init(ad1816, 100) == -1) return; - io_wr(ad1816, AD1816_ALE, (reg & AD1816_ALEMASK)); - io_wr(ad1816, AD1816_LOW, (data & 0x000000ff)); - io_wr(ad1816, AD1816_HIGH, (data & 0x0000ff00) >> 8); - splx(flags); -} - -static int -ad1816mix_init(snd_mixer *m) -{ - mix_setdevs(m, AD1816_MIXER_DEVICES); - mix_setrecdevs(m, AD1816_REC_DEVICES); - return 0; -} - -static int -ad1816mix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - struct ad1816_info *ad1816 = mix_getdevinfo(m); - u_short reg = 0; - - /* Scale volumes */ - left = AD1816_MUTE - (AD1816_MUTE * left) / 100; - right = AD1816_MUTE - (AD1816_MUTE * right) / 100; - - reg = (left << 8) | right; - - /* do channel selective muting if volume is zero */ - if (left == AD1816_MUTE) reg |= 0x8000; - if (right == AD1816_MUTE) reg |= 0x0080; - - switch (dev) { - case SOUND_MIXER_VOLUME: /* Register 14 master volume */ - ad1816_write(ad1816, 14, reg); - break; - - case SOUND_MIXER_CD: /* Register 15 cd */ - case SOUND_MIXER_LINE1: - ad1816_write(ad1816, 15, reg); - break; - - case SOUND_MIXER_SYNTH: /* Register 16 synth */ - ad1816_write(ad1816, 16, reg); - break; - - case SOUND_MIXER_PCM: /* Register 4 pcm */ - ad1816_write(ad1816, 4, reg); - break; - - case SOUND_MIXER_LINE: - case SOUND_MIXER_LINE3: /* Register 18 line in */ - ad1816_write(ad1816, 18, reg); - break; - - case SOUND_MIXER_MIC: /* Register 19 mic volume */ - ad1816_write(ad1816, 19, reg & ~0xff); /* mic is mono */ - break; - - case SOUND_MIXER_IGAIN: - /* and now to something completely different ... */ - ad1816_write(ad1816, 20, ((ad1816_read(ad1816, 20) & ~0x0f0f) - | (((AD1816_MUTE - left) / 2) << 8) /* four bits of adc gain */ - | ((AD1816_MUTE - right) / 2))); - break; - - default: - printf("ad1816_mixer_set(): unknown device.\n"); - break; - } - - return left | (right << 8); -} - -static int -ad1816mix_setrecsrc(snd_mixer *m, u_int32_t src) -{ - struct ad1816_info *ad1816 = mix_getdevinfo(m); - int dev; - - switch (src) { - case SOUND_MASK_LINE: - case SOUND_MASK_LINE3: - dev = 0x00; - break; - - case SOUND_MASK_CD: - case SOUND_MASK_LINE1: - dev = 0x20; - break; - - case SOUND_MASK_MIC: - default: - dev = 0x50; - src = SOUND_MASK_MIC; - } - - dev |= dev << 8; - ad1816_write(ad1816, 20, (ad1816_read(ad1816, 20) & ~0x7070) | dev); - return src; -} - -/* channel interface */ -static void * -ad1816chan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) -{ - struct ad1816_info *ad1816 = devinfo; - struct ad1816_chinfo *ch = (dir == PCMDIR_PLAY)? &ad1816->pch : &ad1816->rch; - - ch->parent = ad1816; - ch->channel = c; - ch->buffer = b; - ch->buffer->bufsize = DSP_BUFFSIZE; - if (chn_allocbuf(ch->buffer, ad1816->parent_dmat) == -1) return NULL; - return ch; -} - -static int -ad1816chan_setdir(void *data, int dir) -{ - struct ad1816_chinfo *ch = data; - struct ad1816_info *ad1816 = ch->parent; - - ch->buffer->chan = rman_get_start((dir == PCMDIR_PLAY)? - ad1816->drq1 : ad1816->drq2); - ch->dir = dir; - return 0; -} - -static int -ad1816chan_setformat(void *data, u_int32_t format) -{ - struct ad1816_chinfo *ch = data; - struct ad1816_info *ad1816 = ch->parent; - - int fmt = AD1816_U8, reg; - if (ch->dir == PCMDIR_PLAY) { - reg = AD1816_PLAY; - ad1816_write(ad1816, 8, 0x0000); /* reset base and current counter */ - ad1816_write(ad1816, 9, 0x0000); /* for playback and capture */ - } else { - reg = AD1816_CAPT; - ad1816_write(ad1816, 10, 0x0000); - ad1816_write(ad1816, 11, 0x0000); - } - switch (format & ~AFMT_STEREO) { - case AFMT_A_LAW: - fmt = AD1816_ALAW; - break; - - case AFMT_MU_LAW: - fmt = AD1816_MULAW; - break; - - case AFMT_S16_LE: - fmt = AD1816_S16LE; - break; - - case AFMT_S16_BE: - fmt = AD1816_S16BE; - break; - - case AFMT_U8: - fmt = AD1816_U8; - break; - } - if (format & AFMT_STEREO) fmt |= AD1816_STEREO; - io_wr(ad1816, reg, fmt); - return format; -} - -static int -ad1816chan_setspeed(void *data, u_int32_t speed) -{ - struct ad1816_chinfo *ch = data; - struct ad1816_info *ad1816 = ch->parent; - - RANGE(speed, 4000, 55200); - ad1816_write(ad1816, (ch->dir == PCMDIR_PLAY)? 2 : 3, speed); - return speed; -} - -static int -ad1816chan_setblocksize(void *data, u_int32_t blocksize) -{ - return blocksize; -} - -static int -ad1816chan_trigger(void *data, int go) -{ - struct ad1816_chinfo *ch = data; - struct ad1816_info *ad1816 = ch->parent; - int wr, reg; - - buf_isadma(ch->buffer, go); - wr = (ch->dir == PCMDIR_PLAY); - reg = wr? AD1816_PLAY : AD1816_CAPT; - switch (go) { - case PCMTRIG_START: - /* start only if not already running */ - if (!(io_rd(ad1816, reg) & AD1816_ENABLE)) { - int cnt = ((ch->buffer->dl) >> 2) - 1; - ad1816_write(ad1816, wr? 8 : 10, cnt); /* count */ - ad1816_write(ad1816, 1, ad1816_read(ad1816, 1) | - (wr? 0x8000 : 0x4000)); /* enable int */ - /* enable playback */ - io_wr(ad1816, reg, io_rd(ad1816, reg) | AD1816_ENABLE); - if (!(io_rd(ad1816, reg) & AD1816_ENABLE)) - printf("ad1816: failed to start %s DMA!\n", - wr? "play" : "rec"); - } - break; - - case PCMTRIG_STOP: - case PCMTRIG_ABORT: /* XXX check this... */ - /* we don't test here if it is running... */ - if (wr) { - ad1816_write(ad1816, 1, ad1816_read(ad1816, 1) & - ~(wr? 0x8000 : 0x4000)); - /* disable int */ - io_wr(ad1816, reg, io_rd(ad1816, reg) & ~AD1816_ENABLE); - /* disable playback */ - if (io_rd(ad1816, reg) & AD1816_ENABLE) - printf("ad1816: failed to stop %s DMA!\n", - wr? "play" : "rec"); - ad1816_write(ad1816, wr? 8 : 10, 0); /* reset base cnt */ - ad1816_write(ad1816, wr? 9 : 11, 0); /* reset cur cnt */ - } - break; - } - return 0; -} - -static int -ad1816chan_getptr(void *data) -{ - struct ad1816_chinfo *ch = data; - return buf_isadmaptr(ch->buffer); -} - -static pcmchan_caps * -ad1816chan_getcaps(void *data) -{ - return &ad1816_caps; -} - -static void -ad1816_release_resources(struct ad1816_info *ad1816, device_t dev) -{ - if (ad1816->irq) { - bus_release_resource(dev, SYS_RES_IRQ, ad1816->irq_rid, - ad1816->irq); - ad1816->irq = 0; - } - if (ad1816->drq1) { - bus_release_resource(dev, SYS_RES_DRQ, ad1816->drq1_rid, - ad1816->drq1); - ad1816->drq1 = 0; - } - if (ad1816->drq2) { - bus_release_resource(dev, SYS_RES_DRQ, ad1816->drq2_rid, - ad1816->drq2); - ad1816->drq2 = 0; - } - if (ad1816->io_base) { - bus_release_resource(dev, SYS_RES_IOPORT, ad1816->io_rid, - ad1816->io_base); - ad1816->io_base = 0; - } - free(ad1816, M_DEVBUF); -} - -static int -ad1816_alloc_resources(struct ad1816_info *ad1816, device_t dev) -{ - int ok = 1, pdma, rdma; - if (!ad1816->io_base) - ad1816->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &ad1816->io_rid, - 0, ~0, 1, RF_ACTIVE); - if (!ad1816->irq) - ad1816->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &ad1816->irq_rid, - 0, ~0, 1, RF_ACTIVE); - if (!ad1816->drq1) - ad1816->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ, &ad1816->drq1_rid, - 0, ~0, 1, RF_ACTIVE); - if (ad1816->drq2_rid >= 0 && !ad1816->drq2) - ad1816->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, &ad1816->drq2_rid, - 0, ~0, 1, RF_ACTIVE); - - if (!ad1816->io_base || !ad1816->drq1 || !ad1816->irq) ok = 0; - if (ad1816->drq2_rid >= 0 && !ad1816->drq2) ok = 0; - - if (ok) { - pdma = rman_get_start(ad1816->drq1); - isa_dma_acquire(pdma); - isa_dmainit(pdma, DSP_BUFFSIZE); - if (ad1816->drq2) { - rdma = rman_get_start(ad1816->drq2); - isa_dma_acquire(rdma); - isa_dmainit(rdma, DSP_BUFFSIZE); - } else rdma = pdma; - if (pdma == rdma) - pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); - } - return ok; -} - -static int -ad1816_init(struct ad1816_info *ad1816, device_t dev) -{ - ad1816_write(ad1816, 1, 0x2); /* disable interrupts */ - ad1816_write(ad1816, 32, 0x90F0); /* SoundSys Mode, split fmt */ - - ad1816_write(ad1816, 5, 0x8080); /* FM volume mute */ - ad1816_write(ad1816, 6, 0x8080); /* I2S1 volume mute */ - ad1816_write(ad1816, 7, 0x8080); /* I2S0 volume mute */ - ad1816_write(ad1816, 17, 0x8888); /* VID Volume mute */ - ad1816_write(ad1816, 20, 0x5050); /* recsrc mic, agc off */ - /* adc gain is set to 0 */ - - return 0; -} - -static int -ad1816_probe(device_t dev) -{ - char *s = NULL; - u_int32_t logical_id = isa_get_logicalid(dev); - - switch (logical_id) { - case 0x80719304: /* ADS7180 */ - s = "Terratec Soundsystem BASE 1"; - break; - } - - if (s) { - device_set_desc(dev, s); - return 0; - } - return ENXIO; -} - -static int -ad1816_attach(device_t dev) -{ - struct ad1816_info *ad1816; - snddev_info *d = device_get_softc(dev); - void *ih; - char status[SND_STATUSLEN]; - - ad1816 = (struct ad1816_info *)malloc(sizeof *ad1816, M_DEVBUF, M_NOWAIT); - if (!ad1816) return ENXIO; - bzero(ad1816, sizeof *ad1816); - - ad1816->io_rid = 2; - ad1816->irq_rid = 0; - ad1816->drq1_rid = 0; - ad1816->drq2_rid = 1; - - if (!ad1816_alloc_resources(ad1816, dev)) goto no; - ad1816_init(ad1816, dev); - mixer_init(d, &ad1816_mixer, ad1816); - bus_setup_intr(dev, ad1816->irq, INTR_TYPE_TTY, ad1816_intr, ad1816, &ih); - 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*/DSP_BUFFSIZE, /*nsegments*/1, - /*maxsegz*/0x3ffff, - /*flags*/0, &ad1816->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(ad1816->io_base), - rman_get_start(ad1816->irq), - rman_get_start(ad1816->drq1)); - if (FULL_DUPLEX(dev)) snprintf(status + strlen(status), - SND_STATUSLEN - strlen(status), ":%ld", - rman_get_start(ad1816->drq1)); - - if (pcm_register(dev, ad1816, 1, 1)) goto no; - pcm_addchan(dev, PCMDIR_REC, &ad1816_chantemplate, ad1816); - pcm_addchan(dev, PCMDIR_PLAY, &ad1816_chantemplate, ad1816); - pcm_setstatus(dev, status); - - return 0; -no: - ad1816_release_resources(ad1816, dev); - return ENXIO; - -} - -static device_method_t ad1816_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ad1816_probe), - DEVMETHOD(device_attach, ad1816_attach), - - { 0, 0 } -}; - -static driver_t ad1816_driver = { - "pcm", - ad1816_methods, - sizeof(snddev_info), -}; - -DRIVER_MODULE(ad1816, isa, ad1816_driver, pcm_devclass, 0, 0); - -#endif Property changes on: head/sys/dev/pcm/isa/ad1816.c ___________________________________________________________________ Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/isa/ad1816.h =================================================================== --- head/sys/dev/pcm/isa/ad1816.h (revision 53505) +++ head/sys/dev/pcm/isa/ad1816.h (nonexistent) @@ -1,71 +0,0 @@ -/* - * (C) 1997 Luigi Rizzo (luigi@iet.unipi.it) - * - * This file contains information and macro definitions for - * the ad1816 chip - * - * $FreeBSD$ - */ - -/* AD1816 register macros */ - -#define AD1816_ALE 0 /* indirect reg access */ -#define AD1816_INT 1 /* interupt status */ -#define AD1816_LOW 2 /* indirect low byte */ -#define AD1816_HIGH 3 /* indirect high byte */ - -#if 0 -#define ad1816_pioD(d) ((d)->io_base+4) /* PIO debug */ -#define ad1816_pios(d) ((d)->io_base+5) /* PIO status */ -#define ad1816_piod(d) ((d)->io_base+6) /* PIO data */ -#endif - -/* values for playback/capture config: - bits: 0 enable/disable - 1 pio/dma - 2 stereo/mono - 3 companded/linearPCM - 4-5 format : 00 8bit linear (uncomp) - 00 8bit mulaw (comp) - 01 16bit le (uncomp) - 01 8bit alaw (comp) - 11 16bit be (uncomp) -*/ - -#define AD1816_PLAY 8 /* playback config */ -#define AD1816_CAPT 9 /* capture config */ - -#define AD1816_BUSY 0x80 /* chip is busy */ -#define AD1816_ALEMASK 0x3F /* mask for indirect adr. */ - -#if 0 -#define AD1816_INTRSI 0x01 /* sb intr */ -#define AD1816_INTRGI 0x02 /* game intr */ -#define AD1816_INTRRI 0x04 /* ring intr */ -#define AD1816_INTRDI 0x08 /* dsp intr */ -#define AD1816_INTRVI 0x10 /* vol intr */ -#define AD1816_INTRTI 0x20 /* timer intr */ -#endif - -#define AD1816_INTRCI 0x40 /* capture intr */ -#define AD1816_INTRPI 0x80 /* playback intr */ -/* PIO stuff is not supplied here */ -/* playback / capture config */ -#define AD1816_ENABLE 0x01 /* enable pl/cp */ -#define AD1816_PIO 0x02 /* use pio */ -#define AD1816_STEREO 0x04 -#define AD1816_COMP 0x08 /* data is companded */ -#define AD1816_U8 0x00 /* 8 bit linear pcm */ -#define AD1816_MULAW 0x08 /* 8 bit mulaw */ -#define AD1816_ALAW 0x18 /* 8 bit alaw */ -#define AD1816_S16LE 0x10 /* 16 bit linear little endian */ -#define AD1816_S16BE 0x30 /* 16 bit linear big endian */ -#define AD1816_FORMASK 0x38 /* format mask */ - -#define AD1816_REC_DEVICES \ - (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD) - -#define AD1816_MIXER_DEVICES \ - (SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_SYNTH | \ - SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IGAIN) - Property changes on: head/sys/dev/pcm/isa/ad1816.h ___________________________________________________________________ Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/isa/mss.c =================================================================== --- head/sys/dev/pcm/isa/mss.c (revision 53505) +++ head/sys/dev/pcm/isa/mss.c (nonexistent) @@ -1,1641 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * Copyright Luigi Rizzo, 1997,1998 - * Copyright by Hannu Savolainen 1994, 1995 - * 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 - -#if NPCM > 0 - -/* board-specific include files */ -#include - -struct mss_info; - -struct mss_chinfo { - struct mss_info *parent; - pcm_channel *channel; - snd_dbuf *buffer; - int dir; -}; - -struct mss_info { - struct resource *io_base; /* primary I/O address for the board */ - int io_rid; - struct resource *conf_base; /* and the opti931 also has a config space */ - int conf_rid; - struct resource *irq; - int irq_rid; - struct resource *drq1; /* play */ - int drq1_rid; - struct resource *drq2; /* rec */ - int drq2_rid; - bus_dma_tag_t parent_dmat; - - int pdma, rdma; - int bd_id; /* used to hold board-id info, eg. sb version, - * mss codec type, etc. etc. - */ - int opti_offset; /* offset from config_base for opti931 */ - u_long bd_flags; /* board-specific flags */ - struct mss_chinfo pch, rch; -}; - -static int mss_probe(device_t dev); -static int mss_attach(device_t dev); - -static driver_intr_t mss_intr; - -/* prototypes for local functions */ -static int mss_detect(device_t dev, struct mss_info *mss); -static char *ymf_test(device_t dev, struct mss_info *mss); -static void ad_unmute(struct mss_info *mss); - -/* mixer set funcs */ -static int mss_mixer_set(struct mss_info *mss, int dev, int left, int right); -static int mss_set_recsrc(struct mss_info *mss, int mask); - -/* io funcs */ -static int ad_wait_init(struct mss_info *mss, int x); -static int ad_read(struct mss_info *mss, int reg); -static void ad_write(struct mss_info *mss, int reg, u_char data); -static void ad_write_cnt(struct mss_info *mss, int reg, u_short data); - -/* io primitives */ -static void conf_wr(struct mss_info *mss, u_char reg, u_char data); -static u_char conf_rd(struct mss_info *mss, u_char reg); - -#if NPNP > 0 -static int pnpmss_probe(device_t dev); -static int pnpmss_attach(device_t dev); - -static driver_intr_t opti931_intr; -#endif - -static int mssmix_init(snd_mixer *m); -static int mssmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right); -static int mssmix_setrecsrc(snd_mixer *m, u_int32_t src); -static snd_mixer mss_mixer = { - "MSS mixer", - mssmix_init, - mssmix_set, - mssmix_setrecsrc, -}; - -static int ymmix_init(snd_mixer *m); -static int ymmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right); -static int ymmix_setrecsrc(snd_mixer *m, u_int32_t src); -static snd_mixer yamaha_mixer = { - "OPL3-SAx mixer", - ymmix_init, - ymmix_set, - ymmix_setrecsrc, -}; - -static devclass_t pcm_devclass; - -/* channel interface */ -static void *msschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -static int msschan_setdir(void *data, int dir); -static int msschan_setformat(void *data, u_int32_t format); -static int msschan_setspeed(void *data, u_int32_t speed); -static int msschan_setblocksize(void *data, u_int32_t blocksize); -static int msschan_trigger(void *data, int go); -static int msschan_getptr(void *data); -static pcmchan_caps *msschan_getcaps(void *data); - -static pcmchan_caps mss_caps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcmchan_caps guspnp_caps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE | AFMT_A_LAW, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcmchan_caps opti931_caps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcm_channel mss_chantemplate = { - msschan_init, - msschan_setdir, - msschan_setformat, - msschan_setspeed, - msschan_setblocksize, - msschan_trigger, - msschan_getptr, - msschan_getcaps, -}; - -#define MD_AD1848 0x91 -#define MD_AD1845 0x92 -#define MD_CS4248 0xA1 -#define MD_CS4231 0xA2 -#define MD_CS4231A 0xA3 -#define MD_CS4232 0xA4 -#define MD_CS4232A 0xA5 -#define MD_CS4236 0xA6 -#define MD_CS4237 0xA7 -#define MD_OPTI931 0xB1 -#define MD_OPTI925 0xB2 -#define MD_GUSPNP 0xB8 -#define MD_YM0020 0xC1 -#define MD_VIVO 0xD1 - -#define DV_F_TRUE_MSS 0x00010000 /* mss _with_ base regs */ - -#define FULL_DUPLEX(x) ((x)->bd_flags & BD_F_DUPLEX) - -static int -port_rd(struct resource *port, int off) -{ - if (port) - return bus_space_read_1(rman_get_bustag(port), - rman_get_bushandle(port), - off); - else - return -1; -} - -static void -port_wr(struct resource *port, int off, u_int8_t data) -{ - if (port) - return bus_space_write_1(rman_get_bustag(port), - rman_get_bushandle(port), - off, data); -} - -static int -io_rd(struct mss_info *mss, int reg) -{ - if (mss->bd_flags & BD_F_MSS_OFFSET) reg -= 4; - return port_rd(mss->io_base, reg); -} - -static void -io_wr(struct mss_info *mss, int reg, u_int8_t data) -{ - if (mss->bd_flags & BD_F_MSS_OFFSET) reg -= 4; - return port_wr(mss->io_base, reg, data); -} - -static void -conf_wr(struct mss_info *mss, u_char reg, u_char value) -{ - port_wr(mss->conf_base, 0, reg); - port_wr(mss->conf_base, 1, value); -} - -static u_char -conf_rd(struct mss_info *mss, u_char reg) -{ - port_wr(mss->conf_base, 0, reg); - return port_rd(mss->conf_base, 1); -} - -static void -opti_wr(struct mss_info *mss, u_char reg, u_char value) -{ - port_wr(mss->conf_base, mss->opti_offset + 0, reg); - port_wr(mss->conf_base, mss->opti_offset + 1, value); -} - -static u_char -opti_rd(struct mss_info *mss, u_char reg) -{ - port_wr(mss->conf_base, mss->opti_offset + 0, reg); - return port_rd(mss->conf_base, mss->opti_offset + 1); -} - -#if NPNP > 0 -static void -gus_wr(struct mss_info *mss, u_char reg, u_char value) -{ - port_wr(mss->conf_base, 3, reg); - port_wr(mss->conf_base, 5, value); -} - -static u_char -gus_rd(struct mss_info *mss, u_char reg) -{ - port_wr(mss->conf_base, 3, reg); - return port_rd(mss->conf_base, 5); -} -#endif - -static void -mss_release_resources(struct mss_info *mss, device_t dev) -{ - if (mss->irq) { - bus_release_resource(dev, SYS_RES_IRQ, mss->irq_rid, - mss->irq); - mss->irq = 0; - } - if (mss->drq1) { - bus_release_resource(dev, SYS_RES_DRQ, mss->drq1_rid, - mss->drq1); - mss->drq1 = 0; - mss->pdma = -1; - } - if (mss->drq2) { - bus_release_resource(dev, SYS_RES_DRQ, mss->drq2_rid, - mss->drq2); - mss->drq2 = 0; - mss->rdma = -1; - } - if (mss->io_base) { - bus_release_resource(dev, SYS_RES_IOPORT, mss->io_rid, - mss->io_base); - mss->io_base = 0; - } - if (mss->conf_base) { - bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid, - mss->conf_base); - mss->conf_base = 0; - } - free(mss, M_DEVBUF); -} - -static int -mss_alloc_resources(struct mss_info *mss, device_t dev) -{ - int ok = 1; - if (!mss->io_base) - mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid, - 0, ~0, 1, RF_ACTIVE); - if (!mss->irq) - mss->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &mss->irq_rid, - 0, ~0, 1, RF_ACTIVE); - if (!mss->drq1) - mss->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ, &mss->drq1_rid, - 0, ~0, 1, RF_ACTIVE); - if (mss->conf_rid >= 0 && !mss->conf_base) - mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->conf_rid, - 0, ~0, 1, RF_ACTIVE); - if (mss->drq2_rid >= 0 && !mss->drq2) - mss->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, &mss->drq2_rid, - 0, ~0, 1, RF_ACTIVE); - - if (!mss->io_base || !mss->drq1 || !mss->irq) ok = 0; - if (mss->conf_rid >= 0 && !mss->conf_base) ok = 0; - if (mss->drq2_rid >= 0 && !mss->drq2) ok = 0; - - if (ok) { - mss->pdma = rman_get_start(mss->drq1); - isa_dma_acquire(mss->pdma); - isa_dmainit(mss->pdma, DSP_BUFFSIZE); - mss->bd_flags &= ~BD_F_DUPLEX; - if (mss->drq2) { - mss->rdma = rman_get_start(mss->drq2); - isa_dma_acquire(mss->rdma); - isa_dmainit(mss->rdma, DSP_BUFFSIZE); - mss->bd_flags |= BD_F_DUPLEX; - } else mss->rdma = mss->pdma; - } - return ok; -} - -static int -mss_init(struct mss_info *mss, device_t dev) -{ - u_char r6, r9; - struct resource *alt; - int rid, tmp; - - mss->bd_flags |= BD_F_MCE_BIT; - switch(mss->bd_id) { -#if NPNP > 0 - case MD_OPTI931: - /* - * The MED3931 v.1.0 allocates 3 bytes for the config - * space, whereas v.2.0 allocates 4 bytes. What I know - * for sure is that the upper two ports must be used, - * and they should end on a boundary of 4 bytes. So I - * need the following trick. - */ - mss->opti_offset = - (rman_get_start(mss->conf_base) & ~3) + 2 - - rman_get_start(mss->conf_base); - printf("mss_init: opti_offset=%d\n", mss->opti_offset); - opti_wr(mss, 4, 0xd6); /* fifo empty, OPL3, audio enable, SB3.2 */ - ad_write(mss, 10, 2); /* enable interrupts */ - opti_wr(mss, 6, 2); /* MCIR6: mss enable, sb disable */ - opti_wr(mss, 5, 0x28); /* MCIR5: codec in exp. mode,fifo */ - break; - - case MD_GUSPNP: - gus_wr(mss, 0x4c /* _URSTI */, 0);/* Pull reset */ - DELAY(1000 * 30); - /* release reset and enable DAC */ - gus_wr(mss, 0x4c /* _URSTI */, 3); - DELAY(1000 * 30); - /* end of reset */ - - rid = 0; - alt = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - 0, ~0, 1, RF_ACTIVE); - port_wr(alt, 0, 0xC); /* enable int and dma */ - bus_release_resource(dev, SYS_RES_IOPORT, rid, alt); - - /* - * unmute left & right line. Need to go in mode3, unmute, - * and back to mode 2 - */ - tmp = ad_read(mss, 0x0c); - ad_write(mss, 0x0c, 0x6c); /* special value to enter mode 3 */ - ad_write(mss, 0x19, 0); /* unmute left */ - ad_write(mss, 0x1b, 0); /* unmute right */ - ad_write(mss, 0x0c, tmp); /* restore old mode */ - - /* send codec interrupts on irq1 and only use that one */ - gus_wr(mss, 0x5a, 0x4f); - - /* enable access to hidden regs */ - tmp = gus_rd(mss, 0x5b /* IVERI */); - gus_wr(mss, 0x5b, tmp | 1); - BVDDB(printf("GUS: silicon rev %c\n", 'A' + ((tmp & 0xf) >> 4))); - break; -#endif - case MD_YM0020: - conf_wr(mss, OPL3SAx_DMACONF, 0xa9); /* dma-b rec, dma-a play */ - r6 = conf_rd(mss, OPL3SAx_DMACONF); - r9 = conf_rd(mss, OPL3SAx_MISC); /* version */ - BVDDB(printf("Yamaha: ver 0x%x DMA config 0x%x\n", r6, r9);) - /* yamaha - set volume to max */ - conf_wr(mss, OPL3SAx_VOLUMEL, 0); - conf_wr(mss, OPL3SAx_VOLUMER, 0); - conf_wr(mss, OPL3SAx_DMACONF, FULL_DUPLEX(mss)? 0xa9 : 0x8b); - break; - } - if (FULL_DUPLEX(mss) && mss->bd_id != MD_OPTI931) - ad_write(mss, 12, ad_read(mss, 12) | 0x40); /* mode 2 */ - ad_write(mss, 9, FULL_DUPLEX(mss)? 0 : 4); - ad_write(mss, 10, 2); /* int enable */ - io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */ - /* the following seem required on the CS4232 */ - ad_unmute(mss); - return 0; -} - -/* - * mss_probe() is the probe routine. Note, it is not necessary to - * go through this for PnP devices, since they are already - * indentified precisely using their PnP id. - * - * The base address supplied in the device refers to the old MSS - * specs where the four 4 registers in io space contain configuration - * information. Some boards (as an example, early MSS boards) - * has such a block of registers, whereas others (generally CS42xx) - * do not. In order to distinguish between the two and do not have - * to supply two separate probe routines, the flags entry in isa_device - * has a bit to mark this. - * - */ - -static int -mss_probe(device_t dev) -{ - u_char tmp, tmpx; - int flags, irq, drq, result = ENXIO, setres = 0; - struct mss_info *mss; - - if (isa_get_vendorid(dev)) return ENXIO; /* not yet */ - - mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT); - if (!mss) return ENXIO; - bzero(mss, sizeof *mss); - - mss->io_rid = 0; - mss->conf_rid = -1; - mss->irq_rid = 0; - mss->drq1_rid = 0; - mss->drq2_rid = -1; - mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid, - 0, ~0, 8, RF_ACTIVE); - if (!mss->io_base) { - BVDDB(printf("mss_probe: no address given, try 0x%x\n", 0x530)); - mss->io_rid = 0; - /* XXX verify this */ - setres = 1; - bus_set_resource(dev, SYS_RES_IOPORT, mss->io_rid, - 0x530, 8); - mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid, - 0, ~0, 8, RF_ACTIVE); - } - if (!mss->io_base) goto no; - - /* got irq/dma regs? */ - flags = device_get_flags(dev); - irq = isa_get_irq(dev); - drq = isa_get_drq(dev); - - if (!(device_get_flags(dev) & DV_F_TRUE_MSS)) goto mss_probe_end; - - /* - * Check if the IO port returns valid signature. The original MS - * Sound system returns 0x04 while some cards - * (AudioTriX Pro for example) return 0x00 or 0x0f. - */ - - device_set_desc(dev, "MSS"); - tmpx = tmp = io_rd(mss, 3); - if (tmp == 0xff) { /* Bus float */ - BVDDB(printf("I/O addr inactive (%x), try pseudo_mss\n", tmp)); - device_set_flags(dev, flags & ~DV_F_TRUE_MSS); - goto mss_probe_end; - } - tmp &= 0x3f; - if (!(tmp == 0x04 || tmp == 0x0f || tmp == 0x00)) { - BVDDB(printf("No MSS signature detected on port 0x%lx (0x%x)\n", - rman_get_start(mss->io_base), tmpx)); - goto no; - } - if (irq > 11) { - printf("MSS: Bad IRQ %d\n", irq); - goto no; - } - if (!(drq == 0 || drq == 1 || drq == 3)) { - printf("MSS: Bad DMA %d\n", drq); - goto no; - } - if (tmpx & 0x80) { - /* 8-bit board: only drq1/3 and irq7/9 */ - if (drq == 0) { - printf("MSS: Can't use DMA0 with a 8 bit card/slot\n"); - goto no; - } - if (!(irq == 7 || irq == 9)) { - printf("MSS: Can't use IRQ%d with a 8 bit card/slot\n", - irq); - goto no; - } - } - mss_probe_end: - result = mss_detect(dev, mss); - no: - mss_release_resources(mss, dev); -#if 0 - if (setres) ISA_DELETE_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IOPORT, mss->io_rid); /* XXX ? */ -#endif - return result; -} - -static int -mss_detect(device_t dev, struct mss_info *mss) -{ - int i; - u_char tmp, tmp1, tmp2; - char *name, *yamaha; - - if (mss->bd_id != 0) { - device_printf(dev, "presel bd_id 0x%04x -- %s\n", mss->bd_id, - device_get_desc(dev)); - return 0; - } - - name = "AD1848"; - mss->bd_id = MD_AD1848; /* AD1848 or CS4248 */ - - /* - * Check that the I/O address is in use. - * - * bit 7 of the base I/O port is known to be 0 after the chip has - * performed its power on initialization. Just assume this has - * happened before the OS is starting. - * - * If the I/O address is unused, it typically returns 0xff. - */ - - for (i = 0; i < 10; i++) - if ((tmp = io_rd(mss, MSS_INDEX)) & MSS_IDXBUSY) DELAY(10000); - else break; - - if (i >= 10) { /* Not a AD1848 */ - BVDDB(printf("mss_detect, busy still set (0x%02x)\n", tmp)); - goto no; - } - /* - * Test if it's possible to change contents of the indirect - * registers. Registers 0 and 1 are ADC volume registers. The bit - * 0x10 is read only so try to avoid using it. - */ - - ad_write(mss, 0, 0xaa); - ad_write(mss, 1, 0x45);/* 0x55 with bit 0x10 clear */ - tmp1 = ad_read(mss, 0); - tmp2 = ad_read(mss, 1); - if (tmp1 != 0xaa || tmp2 != 0x45) { - BVDDB(printf("mss_detect error - IREG (%x/%x)\n", tmp1, tmp2)); - goto no; - } - - ad_write(mss, 0, 0x45); - ad_write(mss, 1, 0xaa); - tmp1 = ad_read(mss, 0); - tmp2 = ad_read(mss, 1); - if (tmp1 != 0x45 || tmp2 != 0xaa) { - BVDDB(printf("mss_detect error - IREG2 (%x/%x)\n", tmp1, tmp2)); - goto no; - } - - /* - * The indirect register I12 has some read only bits. Lets try to - * change them. - */ - - tmp = ad_read(mss, 12); - ad_write(mss, 12, (~tmp) & 0x0f); - tmp1 = ad_read(mss, 12); - - if ((tmp & 0x0f) != (tmp1 & 0x0f)) { - BVDDB(printf("mss_detect - I12 (0x%02x was 0x%02x)\n", tmp1, tmp)); - goto no; - } - - /* - * NOTE! Last 4 bits of the reg I12 tell the chip revision. - * 0x01=RevB - * 0x0A=RevC. also CS4231/CS4231A and OPTi931 - */ - - BVDDB(printf("mss_detect - chip revision 0x%02x\n", tmp & 0x0f);) - - /* - * The original AD1848/CS4248 has just 16 indirect registers. This - * means that I0 and I16 should return the same value (etc.). Ensure - * that the Mode2 enable bit of I12 is 0. Otherwise this test fails - * with new parts. - */ - - ad_write(mss, 12, 0); /* Mode2=disabled */ -#if 0 - for (i = 0; i < 16; i++) { - if ((tmp1 = ad_read(mss, i)) != (tmp2 = ad_read(mss, i + 16))) { - BVDDB(printf("mss_detect warning - I%d: 0x%02x/0x%02x\n", - i, tmp1, tmp2)); - /* - * note - this seems to fail on the 4232 on I11. So we just break - * rather than fail. (which makes this test pointless - cg) - */ - break; /* return 0; */ - } - } -#endif - /* - * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit - * (0x40). The bit 0x80 is always 1 in CS4248 and CS4231. - * - * On the OPTi931, however, I12 is readonly and only contains the - * chip revision ID (as in the CS4231A). The upper bits return 0. - */ - - ad_write(mss, 12, 0x40); /* Set mode2, clear 0x80 */ - - tmp1 = ad_read(mss, 12); - if (tmp1 & 0x80) name = "CS4248"; /* Our best knowledge just now */ - if ((tmp1 & 0xf0) == 0x00) { - BVDDB(printf("this should be an OPTi931\n");) - } else if ((tmp1 & 0xc0) != 0xC0) goto gotit; - /* - * The 4231 has bit7=1 always, and bit6 we just set to 1. - * We want to check that this is really a CS4231 - * Verify that setting I0 doesn't change I16. - */ - ad_write(mss, 16, 0); /* Set I16 to known value */ - ad_write(mss, 0, 0x45); - if ((tmp1 = ad_read(mss, 16)) == 0x45) goto gotit; - - ad_write(mss, 0, 0xaa); - if ((tmp1 = ad_read(mss, 16)) == 0xaa) { /* Rotten bits? */ - BVDDB(printf("mss_detect error - step H(%x)\n", tmp1)); - goto no; - } - /* Verify that some bits of I25 are read only. */ - tmp1 = ad_read(mss, 25); /* Original bits */ - ad_write(mss, 25, ~tmp1); /* Invert all bits */ - if ((ad_read(mss, 25) & 0xe7) == (tmp1 & 0xe7)) { - int id; - - /* It's at least CS4231 */ - name = "CS4231"; - mss->bd_id = MD_CS4231; - - /* - * It could be an AD1845 or CS4231A as well. - * CS4231 and AD1845 report the same revision info in I25 - * while the CS4231A reports different. - */ - - id = ad_read(mss, 25) & 0xe7; - /* - * b7-b5 = version number; - * 100 : all CS4231 - * 101 : CS4231A - * - * b2-b0 = chip id; - */ - switch (id) { - - case 0xa0: - name = "CS4231A"; - mss->bd_id = MD_CS4231A; - break; - - case 0xa2: - name = "CS4232"; - mss->bd_id = MD_CS4232; - break; - - case 0xb2: - /* strange: the 4231 data sheet says b4-b3 are XX - * so this should be the same as 0xa2 - */ - name = "CS4232A"; - mss->bd_id = MD_CS4232A; - break; - - case 0x80: - /* - * It must be a CS4231 or AD1845. The register I23 - * of CS4231 is undefined and it appears to be read - * only. AD1845 uses I23 for setting sample rate. - * Assume the chip is AD1845 if I23 is changeable. - */ - - tmp = ad_read(mss, 23); - - ad_write(mss, 23, ~tmp); - if (ad_read(mss, 23) != tmp) { /* AD1845 ? */ - name = "AD1845"; - mss->bd_id = MD_AD1845; - } - ad_write(mss, 23, tmp); /* Restore */ - - yamaha = ymf_test(dev, mss); - if (yamaha) { - mss->bd_id = MD_YM0020; - name = yamaha; - } - break; - - case 0x83: /* CS4236 */ - case 0x03: /* CS4236 on Intel PR440FX motherboard XXX */ - name = "CS4236"; - mss->bd_id = MD_CS4236; - break; - - default: /* Assume CS4231 */ - BVDDB(printf("unknown id 0x%02x, assuming CS4231\n", id);) - mss->bd_id = MD_CS4231; - } - } - ad_write(mss, 25, tmp1); /* Restore bits */ -gotit: - BVDDB(printf("mss_detect() - Detected %s\n", name)); - device_set_desc(dev, name); - device_set_flags(dev, - ((device_get_flags(dev) & ~DV_F_DEV_MASK) | - ((mss->bd_id << DV_F_DEV_SHIFT) & DV_F_DEV_MASK))); - return 0; -no: - return ENXIO; -} - -static char * -ymf_test(device_t dev, struct mss_info *mss) -{ - static int ports[] = {0x370, 0x310, 0x538}; - int p, i, j, version; - static char *chipset[] = { - NULL, /* 0 */ - "OPL3-SA2 (YMF711)", /* 1 */ - "OPL3-SA3 (YMF715)", /* 2 */ - "OPL3-SA3 (YMF715)", /* 3 */ - "OPL3-SAx (YMF719)", /* 4 */ - "OPL3-SAx (YMF719)", /* 5 */ - "OPL3-SAx (YMF719)", /* 6 */ - "OPL3-SAx (YMF719)", /* 7 */ - }; - - for (p = 0; p < 3; p++) { - mss->conf_rid = 1; - mss->conf_base = bus_alloc_resource(dev, - SYS_RES_IOPORT, - &mss->conf_rid, - ports[p], ports[p] + 1, 2, - RF_ACTIVE); - if (!mss->conf_base) return 0; - - /* Test the index port of the config registers */ - i = port_rd(mss->conf_base, 0); - port_wr(mss->conf_base, 0, OPL3SAx_DMACONF); - j = (port_rd(mss->conf_base, 0) == OPL3SAx_DMACONF)? 1 : 0; - port_wr(mss->conf_base, 0, i); - if (!j) { - bus_release_resource(dev, SYS_RES_IOPORT, - mss->conf_rid, mss->conf_base); - mss->conf_base = 0; - continue; - } - version = conf_rd(mss, OPL3SAx_MISC) & 0x07; - return chipset[version]; - } - return NULL; -} - -static int -mss_doattach(device_t dev, struct mss_info *mss) -{ - snddev_info *d = device_get_softc(dev); - void *ih; - int flags = device_get_flags(dev); - char status[SND_STATUSLEN]; - - if (!mss_alloc_resources(mss, dev)) goto no; - mss_init(mss, dev); - if (flags & DV_F_TRUE_MSS) { - /* has IRQ/DMA registers, set IRQ and DMA addr */ - static char interrupt_bits[12] = - {-1, -1, -1, -1, -1, 0x28, -1, 0x08, -1, 0x10, 0x18, 0x20}; - static char pdma_bits[4] = {1, 2, -1, 3}; - static char valid_rdma[4] = {1, 0, -1, 0}; - char bits; - - if (!mss->irq || (bits = interrupt_bits[rman_get_start(mss->irq)]) == -1) - goto no; - io_wr(mss, 0, bits | 0x40); /* config port */ - if ((io_rd(mss, 3) & 0x40) == 0) device_printf(dev, "IRQ Conflict?\n"); - /* Write IRQ+DMA setup */ - if (pdma_bits[mss->pdma] == -1) goto no; - bits |= pdma_bits[mss->pdma]; - if (mss->pdma != mss->rdma) { - if (mss->rdma == valid_rdma[mss->pdma]) bits |= 4; - else { - printf("invalid dual dma config %d:%d\n", - mss->pdma, mss->rdma); - goto no; - } - } - io_wr(mss, 0, bits); - printf("drq/irq conf %x\n", io_rd(mss, 0)); - } - mixer_init(d, (mss->bd_id == MD_YM0020)? &yamaha_mixer : &mss_mixer, mss); - switch (mss->bd_id) { - #if NPNP > 0 - case MD_OPTI931: - bus_setup_intr(dev, mss->irq, INTR_TYPE_TTY, opti931_intr, mss, &ih); - break; - #endif - default: - bus_setup_intr(dev, mss->irq, INTR_TYPE_TTY, mss_intr, mss, &ih); - } - if (mss->pdma == mss->rdma) - 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*/DSP_BUFFSIZE, /*nsegments*/1, - /*maxsegz*/0x3ffff, - /*flags*/0, &mss->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 %d", - rman_get_start(mss->io_base), rman_get_start(mss->irq), mss->pdma); - if (mss->pdma != mss->rdma) snprintf(status + strlen(status), - SND_STATUSLEN - strlen(status), ":%d", mss->rdma); - - if (pcm_register(dev, mss, 1, 1)) goto no; - pcm_addchan(dev, PCMDIR_REC, &mss_chantemplate, mss); - pcm_addchan(dev, PCMDIR_PLAY, &mss_chantemplate, mss); - pcm_setstatus(dev, status); - - return 0; -no: - mss_release_resources(mss, dev); - return ENXIO; -} - -static int -mss_attach(device_t dev) -{ - struct mss_info *mss; - int flags = device_get_flags(dev); - - mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT); - if (!mss) return ENXIO; - bzero(mss, sizeof *mss); - - mss->io_rid = 0; - mss->conf_rid = -1; - mss->irq_rid = 0; - mss->drq1_rid = 0; - mss->drq2_rid = -1; - if (flags & DV_F_DUAL_DMA) { - bus_set_resource(dev, SYS_RES_DRQ, 1, - flags & DV_F_DRQ_MASK, 1); - mss->drq2_rid = 1; - } - mss->bd_id = (device_get_flags(dev) & DV_F_DEV_MASK) >> DV_F_DEV_SHIFT; - if (mss->bd_id == MD_YM0020) ymf_test(dev, mss); - return mss_doattach(dev, mss); -} - -static device_method_t mss_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, mss_probe), - DEVMETHOD(device_attach, mss_attach), - - { 0, 0 } -}; - -static driver_t mss_driver = { - "pcm", - mss_methods, - sizeof(snddev_info), -}; - -DRIVER_MODULE(mss, isa, mss_driver, pcm_devclass, 0, 0); - -/* - * main irq handler for the CS423x. The OPTi931 code is - * a separate one. - * The correct way to operate for a device with multiple internal - * interrupt sources is to loop on the status register and ack - * interrupts until all interrupts are served and none are reported. At - * this point the IRQ line to the ISA IRQ controller should go low - * and be raised at the next interrupt. - * - * Since the ISA IRQ controller is sent EOI _before_ passing control - * to the isr, it might happen that we serve an interrupt early, in - * which case the status register at the next interrupt should just - * say that there are no more interrupts... - */ - -static void -mss_intr(void *arg) -{ - struct mss_info *mss = arg; - u_char c = 0, served = 0; - int i; - - DEB(printf("mss_intr\n")); - ad_read(mss, 11); /* fake read of status bits */ - - /* loop until there are interrupts, but no more than 10 times. */ - for (i = 10; i > 0 && io_rd(mss, MSS_STATUS) & 1; i--) { - /* get exact reason for full-duplex boards */ - c = FULL_DUPLEX(mss)? ad_read(mss, 24) : 0x30; - c &= ~served; - if (mss->pch.buffer->dl && (c & 0x10)) { - served |= 0x10; - chn_intr(mss->pch.channel); - } - if (mss->rch.buffer->dl && (c & 0x20)) { - served |= 0x20; - chn_intr(mss->rch.channel); - } - /* now ack the interrupt */ - if (FULL_DUPLEX(mss)) ad_write(mss, 24, ~c); /* ack selectively */ - else io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */ - } - if (i == 10) printf("mss_intr: irq, but not from mss\n"); - else if (served == 0) { - printf("mss_intr: unexpected irq with reason %x\n", c); - /* - * this should not happen... I have no idea what to do now. - * maybe should do a sanity check and restart dmas ? - */ - io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */ - } -} - -/* - * AD_WAIT_INIT waits if we are initializing the board and - * we cannot modify its settings - */ -static int -ad_wait_init(struct mss_info *mss, int x) -{ - int arg = x, n = 0; /* to shut up the compiler... */ - for (; x > 0; x--) - if ((n = io_rd(mss, MSS_INDEX)) & MSS_IDXBUSY) DELAY(10); - else return n; - printf("AD_WAIT_INIT FAILED %d 0x%02x\n", arg, n); - return n; -} - -static int -ad_read(struct mss_info *mss, int reg) -{ - u_long flags; - int x; - - flags = spltty(); - ad_wait_init(mss, 201); - x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK; - io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x); - x = io_rd(mss, MSS_IDATA); - splx(flags); - /* printf("ad_read %d, %x\n", reg, x); */ - return x; -} - -static void -ad_write(struct mss_info *mss, int reg, u_char data) -{ - u_long flags; - - int x; - /* printf("ad_write %d, %x\n", reg, data); */ - flags = spltty(); - ad_wait_init(mss, 1002); - x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK; - io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x); - io_wr(mss, MSS_IDATA, data); - splx(flags); -} - -static void -ad_write_cnt(struct mss_info *mss, int reg, u_short cnt) -{ - ad_write(mss, reg+1, cnt & 0xff); - ad_write(mss, reg, cnt >> 8); /* upper base must be last */ -} - -static void -wait_for_calibration(struct mss_info *mss) -{ - int n, t; - - /* - * Wait until the auto calibration process has finished. - * - * 1) Wait until the chip becomes ready (reads don't return 0x80). - * 2) Wait until the ACI bit of I11 gets on - * 3) Wait until the ACI bit of I11 gets off - */ - - n = ad_wait_init(mss, 1000); - if (n & MSS_IDXBUSY) printf("mss: Auto calibration timed out(1).\n"); - - for (t = 100; t > 0 && (ad_read(mss, 11) & 0x20) == 0; t--) DELAY(100); - for (t = 100; t > 0 && ad_read(mss, 11) & 0x20; t--) DELAY(100); -} - -static void -ad_unmute(struct mss_info *mss) -{ - ad_write(mss, 6, ad_read(mss, 6) & ~I6_MUTE); - ad_write(mss, 7, ad_read(mss, 7) & ~I6_MUTE); -} - -static void -ad_enter_MCE(struct mss_info *mss) -{ - int prev; - - mss->bd_flags |= BD_F_MCE_BIT; - ad_wait_init(mss, 203); - prev = io_rd(mss, MSS_INDEX); - prev &= ~MSS_TRD; - io_wr(mss, MSS_INDEX, prev | MSS_MCE); -} - -static void -ad_leave_MCE(struct mss_info *mss) -{ - u_long flags; - u_char prev; - - if ((mss->bd_flags & BD_F_MCE_BIT) == 0) { - printf("--- hey, leave_MCE: MCE bit was not set!\n"); - return; - } - - ad_wait_init(mss, 1000); - - flags = spltty(); - mss->bd_flags &= ~BD_F_MCE_BIT; - - prev = io_rd(mss, MSS_INDEX); - prev &= ~MSS_TRD; - io_wr(mss, MSS_INDEX, prev & ~MSS_MCE); /* Clear the MCE bit */ - wait_for_calibration(mss); - splx(flags); -} - -/* - * only one source can be set... - */ -static int -mss_set_recsrc(struct mss_info *mss, int mask) -{ - u_char recdev; - - switch (mask) { - case SOUND_MASK_LINE: - case SOUND_MASK_LINE3: - recdev = 0; - break; - - case SOUND_MASK_CD: - case SOUND_MASK_LINE1: - recdev = 0x40; - break; - - case SOUND_MASK_IMIX: - recdev = 0xc0; - break; - - case SOUND_MASK_MIC: - default: - mask = SOUND_MASK_MIC; - recdev = 0x80; - } - ad_write(mss, 0, (ad_read(mss, 0) & 0x3f) | recdev); - ad_write(mss, 1, (ad_read(mss, 1) & 0x3f) | recdev); - return mask; -} - -/* there are differences in the mixer depending on the actual sound card. */ -static int -mss_mixer_set(struct mss_info *mss, int dev, int left, int right) -{ - int regoffs; - mixer_tab *mix_d = (mss->bd_id == MD_OPTI931)? &opti931_devices : &mix_devices; - u_char old, val; - - if ((*mix_d)[dev][LEFT_CHN].nbits == 0) { - DEB(printf("nbits = 0 for dev %d\n", dev)); - return -1; - } - - if ((*mix_d)[dev][RIGHT_CHN].nbits == 0) right = left; /* mono */ - - /* Set the left channel */ - - regoffs = (*mix_d)[dev][LEFT_CHN].regno; - old = val = ad_read(mss, regoffs); - /* if volume is 0, mute chan. Otherwise, unmute. */ - if (regoffs != 0) val = (left == 0)? old | 0x80 : old & 0x7f; - change_bits(mix_d, &val, dev, LEFT_CHN, left); - ad_write(mss, regoffs, val); - - DEB(printf("LEFT: dev %d reg %d old 0x%02x new 0x%02x\n", - dev, regoffs, old, val)); - - if ((*mix_d)[dev][RIGHT_CHN].nbits != 0) { /* have stereo */ - /* Set the right channel */ - regoffs = (*mix_d)[dev][RIGHT_CHN].regno; - old = val = ad_read(mss, regoffs); - if (regoffs != 1) val = (right == 0)? old | 0x80 : old & 0x7f; - change_bits(mix_d, &val, dev, RIGHT_CHN, right); - ad_write(mss, regoffs, val); - - DEB(printf("RIGHT: dev %d reg %d old 0x%02x new 0x%02x\n", - dev, regoffs, old, val)); - } - return 0; /* success */ -} - -static int -mss_speed(struct mss_chinfo *ch, int speed) -{ - struct mss_info *mss = ch->parent; - /* - * In the CS4231, the low 4 bits of I8 are used to hold the - * sample rate. Only a fixed number of values is allowed. This - * table lists them. The speed-setting routines scans the table - * looking for the closest match. This is the only supported method. - * - * In the CS4236, there is an alternate metod (which we do not - * support yet) which provides almost arbitrary frequency setting. - * In the AD1845, it looks like the sample rate can be - * almost arbitrary, and written directly to a register. - * In the OPTi931, there is a SB command which provides for - * almost arbitrary frequency setting. - * - */ - ad_enter_MCE(mss); - if (mss->bd_id == MD_AD1845) { /* Use alternate speed select regs */ - ad_write(mss, 22, (speed >> 8) & 0xff); /* Speed MSB */ - ad_write(mss, 23, speed & 0xff); /* Speed LSB */ - /* XXX must also do something in I27 for the ad1845 */ - } else { - int i, sel = 0; /* assume entry 0 does not contain -1 */ - static int speeds[] = - {8000, 5512, 16000, 11025, 27429, 18900, 32000, 22050, - -1, 37800, -1, 44100, 48000, 33075, 9600, 6615}; - - for (i = 1; i < 16; i++) - if (speeds[i] > 0 && - abs(speed-speeds[i]) < abs(speed-speeds[sel])) sel = i; - speed = speeds[sel]; - ad_write(mss, 8, (ad_read(mss, 8) & 0xf0) | sel); - } - ad_leave_MCE(mss); - - return speed; -} - -/* - * mss_format checks that the format is supported (or defaults to AFMT_U8) - * and returns the bit setting for the 1848 register corresponding to - * the desired format. - * - * fixed lr970724 - */ - -static int -mss_format(struct mss_chinfo *ch, u_int32_t format) -{ - struct mss_info *mss = ch->parent; - int i, arg = format & ~AFMT_STEREO; - - /* - * The data format uses 3 bits (just 2 on the 1848). For each - * bit setting, the following array returns the corresponding format. - * The code scans the array looking for a suitable format. In - * case it is not found, default to AFMT_U8 (not such a good - * choice, but let's do it for compatibility...). - */ - - static int fmts[] = - {AFMT_U8, AFMT_MU_LAW, AFMT_S16_LE, AFMT_A_LAW, - -1, AFMT_IMA_ADPCM, AFMT_U16_BE, -1}; - - for (i = 0; i < 8; i++) if (arg == fmts[i]) break; - arg = i << 1; - if (format & AFMT_STEREO) arg |= 1; - arg <<= 4; - ad_enter_MCE(mss); - ad_write(mss, 8, (ad_read(mss, 8) & 0x0f) | arg); - if (FULL_DUPLEX(mss)) ad_write(mss, 28, arg); /* capture mode */ - ad_leave_MCE(mss); - return format; -} - -static int -mss_trigger(struct mss_chinfo *ch, int go) -{ - struct mss_info *mss = ch->parent; - u_char m; - int retry, wr, cnt; - - wr = (ch->dir == PCMDIR_PLAY)? 1 : 0; - m = ad_read(mss, 9); - switch (go) { - case PCMTRIG_START: - cnt = (ch->buffer->dl / ch->buffer->sample_size) - 1; - - DEB(if (m & 4) printf("OUCH! reg 9 0x%02x\n", m);); - m |= wr? I9_PEN : I9_CEN; /* enable DMA */ - ad_write_cnt(mss, (wr || !FULL_DUPLEX(mss))? 14 : 30, cnt); - break; - - case PCMTRIG_STOP: - case PCMTRIG_ABORT: /* XXX check this... */ - m &= ~(wr? I9_PEN : I9_CEN); /* Stop DMA */ -#if 0 - /* - * try to disable DMA by clearing count registers. Not sure it - * is needed, and it might cause false interrupts when the - * DMA is re-enabled later. - */ - ad_write_cnt(mss, (wr || !FULL_DUPLEX(mss))? 14 : 30, 0); -#endif - } - /* on the OPTi931 the enable bit seems hard to set... */ - for (retry = 10; retry > 0; retry--) { - ad_write(mss, 9, m); - if (ad_read(mss, 9) == m) break; - } - if (retry == 0) printf("start dma, failed to set bit 0x%02x 0x%02x\n", - m, ad_read(mss, 9)); - return 0; -} - -#if NPNP > 0 -static int -pnpmss_probe(device_t dev) -{ - char *s = NULL; - u_int32_t logical_id = isa_get_logicalid(dev); - u_int32_t vend_id = isa_get_vendorid(dev); - u_int32_t id = vend_id & 0xff00ffff; - - switch (logical_id) { - case 0x0000630e: /* CSC0000 */ - if (id == 0x3700630e) s = "CS4237"; - else if (id == 0x2500630e) s = "CS4235"; - else if (id == 0x3600630e) s = "CS4236"; - else if (id == 0x3500630e) s = "CS4236B"; - else if (id == 0x3200630e) s = "CS4232"; - else s = "Unknown CS"; - break; - - case 0x2100a865: /* YMH0021 */ - if (id == 0x2000a865) s = "Yamaha SA2"; - else if (id == 0x3000a865) s = "Yamaha SA3"; - else if (id == 0x0000a865) s = "Yamaha YMF719 OPL-SA3"; - else s = "Yamaha OPL-SAx"; - break; - - case 0x1110d315: /* ENS1011 */ - s = "ENSONIQ SoundscapeVIVO"; - break; - - case 0x1093143e: /* OPT9310 */ - s = "OPTi931"; - break; - - case 0x5092143e: /* OPT9250 XXX guessing */ - s = "OPTi925"; - break; - - case 0x0000561e: - s = "GusPnP"; - break; - - case 0x01000000: - if (vend_id == 0x0100a90d) s = "CMI8330"; - break; - } - - if (s) { - device_set_desc(dev, s); - return 0; - } - return ENXIO; -} - -static int -pnpmss_attach(device_t dev) -{ - struct mss_info *mss; - u_int32_t vend_id = isa_get_vendorid(dev); - - mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT); - if (!mss) return ENXIO; - bzero(mss, sizeof *mss); - - mss->io_rid = 0; - mss->conf_rid = -1; - mss->irq_rid = 0; - mss->drq1_rid = 0; - mss->drq2_rid = 1; - - switch (vend_id & 0xff00ffff) { - case 0x2000a865: /* Yamaha SA2 */ - case 0x3000a865: /* Yamaha SA3 */ - case 0x0000a865: /* Yamaha YMF719 SA3 */ - case 0x2100a865: /* pnpbios sets vendor=logical */ - mss->io_rid = 1; - mss->conf_rid = 4; - mss->bd_id = MD_YM0020; - break; - - case 0x8100d315: /* ENSONIQ SoundscapeVIVO */ - mss->io_rid = 1; - mss->bd_id = MD_VIVO; - break; - - case 0x3700630e: /* CS4237 */ - case 0x2500630e: /* AOpen AW37, CS4235 */ - mss->bd_flags |= BD_F_MSS_OFFSET; - mss->bd_id = MD_CS4237; - break; - - case 0x3500630e: /* CS4236B */ - case 0x3600630e: /* CS4236 */ - mss->bd_flags |= BD_F_MSS_OFFSET; - mss->bd_id = MD_CS4236; - break; - - case 0x3100143e: /* opti931 */ - mss->bd_flags |= BD_F_MSS_OFFSET; - mss->conf_rid = 3; - mss->bd_id = MD_OPTI931; - break; - - case 0x2500143e: /* opti925 */ - mss->io_rid = 1; - mss->conf_rid = 3; - mss->bd_id = MD_OPTI925; - break; - - case 0x0100561e: /* guspnp */ - mss->bd_flags |= BD_F_MSS_OFFSET; - mss->io_rid = 2; - mss->conf_rid = 1; - mss->drq1_rid = 1; - mss->drq2_rid = 0; - mss->bd_id = MD_GUSPNP; - break; - - default: - mss->bd_flags |= BD_F_MSS_OFFSET; - mss->bd_id = MD_CS4232; - break; - } - return mss_doattach(dev, mss); -} - -static device_method_t pnpmss_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, pnpmss_probe), - DEVMETHOD(device_attach, pnpmss_attach), - - { 0, 0 } -}; - -static driver_t pnpmss_driver = { - "pcm", - pnpmss_methods, - sizeof(snddev_info), -}; - -DRIVER_MODULE(pnpmss, isa, pnpmss_driver, pcm_devclass, 0, 0); - -/* - * the opti931 seems to miss interrupts when working in full - * duplex, so we try some heuristics to catch them. - */ -static void -opti931_intr(void *arg) -{ - struct mss_info *mss = (struct mss_info *)arg; - u_char masked = 0, i11, mc11, c = 0; - u_char reason; /* b0 = playback, b1 = capture, b2 = timer */ - int loops = 10; - -#if 0 - reason = io_rd(mss, MSS_STATUS); - if (!(reason & 1)) {/* no int, maybe a shared line ? */ - printf("intr: flag 0, mcir11 0x%02x\n", ad_read(mss, 11)); - return; - } -#endif - i11 = ad_read(mss, 11); /* XXX what's for ? */ - again: - - c = mc11 = FULL_DUPLEX(mss)? opti_rd(mss, 11) : 0xc; - mc11 &= 0x0c; - if (c & 0x10) { - DEB(printf("Warning: CD interrupt\n");) - mc11 |= 0x10; - } - if (c & 0x20) { - DEB(printf("Warning: MPU interrupt\n");) - mc11 |= 0x20; - } - if (mc11 & masked) printf("irq reset failed, mc11 0x%02x, 0x%02x\n", - mc11, masked); - masked |= mc11; - /* - * the nice OPTi931 sets the IRQ line before setting the bits in - * mc11. So, on some occasions I have to retry (max 10 times). - */ - if (mc11 == 0) { /* perhaps can return ... */ - reason = io_rd(mss, MSS_STATUS); - if (reason & 1) { - DEB(printf("one more try...\n");) - if (--loops) goto again; - else DDB(printf("intr, but mc11 not set\n");) - } - if (loops == 0) printf("intr, nothing in mcir11 0x%02x\n", mc11); - return; - } - - if (mss->rch.buffer->dl && (mc11 & 8)) chn_intr(mss->rch.channel); - if (mss->pch.buffer->dl && (mc11 & 4)) chn_intr(mss->pch.channel); - opti_wr(mss, 11, ~mc11); /* ack */ - if (--loops) goto again; - DEB(printf("xxx too many loops\n");) -} - -#endif /* NPNP > 0 */ - -static int -mssmix_init(snd_mixer *m) -{ - struct mss_info *mss = mix_getdevinfo(m); - - mix_setdevs(m, MODE2_MIXER_DEVICES); - mix_setrecdevs(m, MSS_REC_DEVICES); - switch(mss->bd_id) { - case MD_OPTI931: - mix_setdevs(m, OPTI931_MIXER_DEVICES); - ad_write(mss, 20, 0x88); - ad_write(mss, 21, 0x88); - break; - - case MD_AD1848: - mix_setdevs(m, MODE1_MIXER_DEVICES); - break; - - case MD_GUSPNP: - /* this is only necessary in mode 3 ... */ - ad_write(mss, 22, 0x88); - ad_write(mss, 23, 0x88); - break; - } - return 0; -} - -static int -mssmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - struct mss_info *mss = mix_getdevinfo(m); - - mss_mixer_set(mss, dev, left, right); - - return left | (right << 8); -} - -static int -mssmix_setrecsrc(snd_mixer *m, u_int32_t src) -{ - struct mss_info *mss = mix_getdevinfo(m); - - src = mss_set_recsrc(mss, src); - return src; -} - -static int -ymmix_init(snd_mixer *m) -{ - struct mss_info *mss = mix_getdevinfo(m); - - mssmix_init(m); - mix_setdevs(m, mix_getdevs(m) | SOUND_MASK_VOLUME | SOUND_MASK_MIC); - /* Set master volume */ - conf_wr(mss, OPL3SAx_VOLUMEL, 7); - conf_wr(mss, OPL3SAx_VOLUMER, 7); - - return 0; -} - -static int -ymmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - struct mss_info *mss = mix_getdevinfo(m); - int t; - - switch (dev) { - case SOUND_MIXER_VOLUME: - if (left) t = 15 - (left * 15) / 100; - else t = 0x80; /* mute */ - conf_wr(mss, OPL3SAx_VOLUMEL, t); - if (right) t = 15 - (right * 15) / 100; - else t = 0x80; /* mute */ - conf_wr(mss, OPL3SAx_VOLUMER, t); - break; - - case SOUND_MIXER_MIC: - t = left; - if (left) t = 31 - (left * 31) / 100; - else t = 0x80; /* mute */ - conf_wr(mss, OPL3SAx_MIC, t); - break; - - case SOUND_MIXER_BASS: - case SOUND_MIXER_TREBLE: - /* Later maybe */ - - default: - mss_mixer_set(mss, dev, left, right); - } - - return left | (right << 8); -} - -static int -ymmix_setrecsrc(snd_mixer *m, u_int32_t src) -{ - struct mss_info *mss = mix_getdevinfo(m); - src = mss_set_recsrc(mss, src); - return src; -} - -/* channel interface */ -static void * -msschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) -{ - struct mss_info *mss = devinfo; - struct mss_chinfo *ch = (dir == PCMDIR_PLAY)? &mss->pch : &mss->rch; - - ch->parent = mss; - ch->channel = c; - ch->buffer = b; - ch->buffer->bufsize = DSP_BUFFSIZE; - if (chn_allocbuf(ch->buffer, mss->parent_dmat) == -1) return NULL; - return ch; -} - -static int -msschan_setdir(void *data, int dir) -{ - struct mss_chinfo *ch = data; - - ch->buffer->chan = (dir == PCMDIR_PLAY)? ch->parent->pdma : ch->parent->rdma; - ch->dir = dir; - return 0; -} - -static int -msschan_setformat(void *data, u_int32_t format) -{ - struct mss_chinfo *ch = data; - - mss_format(ch, format); - return 0; -} - -static int -msschan_setspeed(void *data, u_int32_t speed) -{ - struct mss_chinfo *ch = data; - - return mss_speed(ch, speed); -} - -static int -msschan_setblocksize(void *data, u_int32_t blocksize) -{ - return blocksize; -} - -static int -msschan_trigger(void *data, int go) -{ - struct mss_chinfo *ch = data; - - buf_isadma(ch->buffer, go); - mss_trigger(ch, go); - return 0; -} - -static int -msschan_getptr(void *data) -{ - struct mss_chinfo *ch = data; - return buf_isadmaptr(ch->buffer); -} - -static pcmchan_caps * -msschan_getcaps(void *data) -{ - struct mss_chinfo *ch = data; - - switch(ch->parent->bd_id) { - case MD_OPTI931: - return &opti931_caps; - break; - - case MD_GUSPNP: - return &guspnp_caps; - break; - - default: - return &mss_caps; - break; - } -} - -#endif /* NPCM > 0 */ Property changes on: head/sys/dev/pcm/isa/mss.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/isa/sb.c =================================================================== --- head/sys/dev/pcm/isa/sb.c (revision 53505) +++ head/sys/dev/pcm/isa/sb.c (nonexistent) @@ -1,1347 +0,0 @@ -/* - * 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 -#if NPCM > 0 - -#define __SB_MIXER_C__ /* XXX warning... */ -#include - -/* channel interface */ -static void *sbchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -static int sbchan_setdir(void *data, int dir); -static int sbchan_setformat(void *data, u_int32_t format); -static int sbchan_setspeed(void *data, u_int32_t speed); -static int sbchan_setblocksize(void *data, u_int32_t blocksize); -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 */ -#ifdef notyet -static void *esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -#endif -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, - AFMT_U8 -}; - -static pcmchan_caps sb_reccaps = { - 4000, 13000, - AFMT_U8, - AFMT_U8 -}; - -static pcmchan_caps sbpro_playcaps = { - 4000, 45000, - AFMT_STEREO | AFMT_U8, - AFMT_STEREO | AFMT_U8 -}; - -static pcmchan_caps sbpro_reccaps = { - 4000, 15000, - AFMT_STEREO | AFMT_U8, - AFMT_STEREO | AFMT_U8 -}; - -static pcmchan_caps sb16_playcaps = { - 5000, 45000, - AFMT_STEREO | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE -}; - -static pcmchan_caps sb16_reccaps = { - 5000, 45000, - AFMT_STEREO | AFMT_U8, - AFMT_STEREO | AFMT_U8 -}; - -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, - sbchan_setformat, - sbchan_setspeed, - sbchan_setblocksize, - sbchan_trigger, - sbchan_getptr, - sbchan_getcaps, -}; - -static pcm_channel ess_chantemplate = { - sbchan_init, - esschan_setdir, - esschan_setformat, - esschan_setspeed, - esschan_setblocksize, - esschan_trigger, - esschan_getptr, - esschan_getcaps, -}; -#define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16) - -struct sb_info; - -struct sb_chinfo { - struct sb_info *parent; - pcm_channel *channel; - snd_dbuf *buffer; - int dir; - u_int32_t fmt; - int ess_dma_started; -}; - -struct sb_info { - struct resource *io_base; /* I/O address for the board */ - int io_rid; - struct resource *irq; - int irq_rid; - struct resource *drq1; /* play */ - int drq1_rid; - struct resource *drq2; /* rec */ - int drq2_rid; - bus_dma_tag_t parent_dmat; - - int dma16, dma8; - int bd_id; - u_long bd_flags; /* board-specific flags */ - struct sb_chinfo pch, rch; -}; - -static int sb_rd(struct sb_info *sb, int reg); -static void sb_wr(struct sb_info *sb, int reg, u_int8_t val); -static int sb_dspready(struct sb_info *sb); -static int sb_cmd(struct sb_info *sb, u_char val); -static int sb_cmd1(struct sb_info *sb, u_char cmd, int val); -static int sb_cmd2(struct sb_info *sb, u_char cmd, int val); -static u_int sb_get_byte(struct sb_info *sb); -static int ess_write(struct sb_info *sb, u_char reg, int val); -static int ess_read(struct sb_info *sb, u_char reg); - -/* - * in the SB, there is a set of indirect "mixer" registers with - * address at offset 4, data at offset 5 - */ -static void sb_setmixer(struct sb_info *sb, u_int port, u_int value); -static int sb_getmixer(struct sb_info *sb, u_int port); - -static void sb_intr(void *arg); -static void ess_intr(void *arg); -static int sb_init(device_t dev, struct sb_info *sb); -static int sb_reset_dsp(struct sb_info *sb); - -static int sb_format(struct sb_chinfo *ch, u_int32_t format); -static int sb_speed(struct sb_chinfo *ch, int speed); -static int sb_start(struct sb_chinfo *ch); -static int sb_stop(struct sb_chinfo *ch); - -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); - -static snd_mixer sb_mixer = { - "SoundBlaster mixer", - sbmix_init, - sbmix_set, - sbmix_setrecsrc, -}; - -static devclass_t pcm_devclass; - -/* - * Common code for the midi and pcm functions - * - * sb_cmd write a single byte to the CMD port. - * sb_cmd1 write a CMD + 1 byte arg - * sb_cmd2 write a CMD + 2 byte arg - * sb_get_byte returns a single byte from the DSP data port - * - * ess_write is actually sb_cmd1 - * ess_read access ext. regs via sb_cmd(0xc0, reg) followed by sb_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 -sb_rd(struct sb_info *sb, int reg) -{ - return port_rd(sb->io_base, reg); -} - -static void -sb_wr(struct sb_info *sb, int reg, u_int8_t val) -{ - port_wr(sb->io_base, reg, val); -} - -static int -sb_dspready(struct sb_info *sb) -{ - return ((sb_rd(sb, SBDSP_STATUS) & 0x80) == 0); -} - -static int -sb_dspwr(struct sb_info *sb, u_char val) -{ - int i; - - for (i = 0; i < 1000; i++) { - if (sb_dspready(sb)) { - sb_wr(sb, SBDSP_CMD, val); - return 1; - } - if (i > 10) DELAY((i > 100)? 1000 : 10); - } - printf("sb_dspwr(0x%02x) timed out.\n", val); - return 0; -} - -static int -sb_cmd(struct sb_info *sb, u_char val) -{ -#if 0 - printf("sb_cmd: %x\n", val); -#endif - return sb_dspwr(sb, val); -} - -static int -sb_cmd1(struct sb_info *sb, u_char cmd, int val) -{ -#if 0 - printf("sb_cmd1: %x, %x\n", cmd, val); -#endif - if (sb_dspwr(sb, cmd)) { - return sb_dspwr(sb, val & 0xff); - } else return 0; -} - -static int -sb_cmd2(struct sb_info *sb, u_char cmd, int val) -{ -#if 0 - printf("sb_cmd2: %x, %x\n", cmd, val); -#endif - if (sb_dspwr(sb, cmd)) { - return sb_dspwr(sb, val & 0xff) && - sb_dspwr(sb, (val >> 8) & 0xff); - } else return 0; -} - -/* - * in the SB, there is a set of indirect "mixer" registers with - * address at offset 4, data at offset 5 - */ -static void -sb_setmixer(struct sb_info *sb, u_int port, u_int value) -{ - u_long flags; - - flags = spltty(); - sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ - DELAY(10); - sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff)); - DELAY(10); - splx(flags); -} - -static int -sb_getmixer(struct sb_info *sb, u_int port) -{ - int val; - u_long flags; - - flags = spltty(); - sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ - DELAY(10); - val = sb_rd(sb, SB_MIX_DATA); - DELAY(10); - splx(flags); - - return val; -} - -static u_int -sb_get_byte(struct sb_info *sb) -{ - int i; - - for (i = 1000; i > 0; i--) { - if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80) - return sb_rd(sb, DSP_READ); - else - DELAY(20); - } - 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) -{ - sb_wr(sb, SBDSP_RST, 3); - DELAY(100); - sb_wr(sb, SBDSP_RST, 0); - if (sb_get_byte(sb) != 0xAA) { - DEB(printf("sb_reset_dsp 0x%lx failed\n", - rman_get_start(d->io_base))); - return ENXIO; /* Sorry */ - } - if (sb->bd_flags & BD_F_ESS) sb_cmd(sb, 0xc6); - return 0; -} - -static void -sb_release_resources(struct sb_info *sb, device_t dev) -{ - /* should we bus_teardown_intr here? */ - if (sb->irq) { - bus_release_resource(dev, SYS_RES_IRQ, sb->irq_rid, sb->irq); - sb->irq = 0; - } - if (sb->drq1) { - bus_release_resource(dev, SYS_RES_DRQ, sb->drq1_rid, sb->drq1); - sb->drq1 = 0; - } - if (sb->drq2) { - bus_release_resource(dev, SYS_RES_DRQ, sb->drq2_rid, sb->drq2); - sb->drq2 = 0; - } - if (sb->io_base) { - bus_release_resource(dev, SYS_RES_IOPORT, sb->io_rid, - sb->io_base); - sb->io_base = 0; - } - free(sb, M_DEVBUF); -} - -static int -sb_alloc_resources(struct sb_info *sb, device_t dev) -{ - if (!sb->io_base) - sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, - &sb->io_rid, 0, ~0, 1, - RF_ACTIVE); - if (!sb->irq) - sb->irq = bus_alloc_resource(dev, SYS_RES_IRQ, - &sb->irq_rid, 0, ~0, 1, - RF_ACTIVE); - if (!sb->drq1) - sb->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ, - &sb->drq1_rid, 0, ~0, 1, - RF_ACTIVE); - if (!sb->drq2 && sb->drq2_rid > 0) - sb->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, - &sb->drq2_rid, 0, ~0, 1, - RF_ACTIVE); - - if (sb->io_base && sb->drq1 && sb->irq) { - sb->dma8 = rman_get_start(sb->drq1); - isa_dma_acquire(sb->dma8); - isa_dmainit(sb->dma8, DSP_BUFFSIZE); - - if (sb->drq2) { - sb->dma16 = rman_get_start(sb->drq2); - isa_dma_acquire(sb->dma16); - isa_dmainit(sb->dma16, DSP_BUFFSIZE); - } else sb->dma16 = sb->dma8; - - if (sb->dma8 > sb->dma16) { - int tmp = sb->dma16; - sb->dma16 = sb->dma8; - sb->dma8 = tmp; - } - return 0; - } else return ENXIO; -} - -static int -sb_identify_board(device_t dev, struct sb_info *sb) -{ - char *fmt = NULL; - static char buf[64]; - int essver = 0; - - sb_cmd(sb, DSP_CMD_GETVER); /* Get version */ - sb->bd_id = (sb_get_byte(sb) << 8) | sb_get_byte(sb); - - switch (sb->bd_id >> 8) { - case 1: /* old sound blaster has nothing... */ - case 2: - fmt = "SoundBlaster %d.%d" ; /* default */ - break; - - case 3: - fmt = "SoundBlaster Pro %d.%d"; - if (sb->bd_id == 0x301) { - int rev; - - /* Try to detect ESS chips. */ - sb_cmd(sb, DSP_CMD_GETID); /* Return ident. bytes. */ - essver = (sb_get_byte(sb) << 8) | sb_get_byte(sb); - rev = essver & 0x000f; - essver &= 0xfff0; - if (essver == 0x4880) { - /* the ESS488 can be treated as an SBPRO */ - fmt = "SoundBlaster Pro (ESS488 rev %d)"; - } else if (essver == 0x6880) { - if (rev < 8) fmt = "ESS688 rev %d"; - else fmt = "ESS1868 rev %d"; - sb->bd_flags |= BD_F_ESS; - } else return ENXIO; - sb->bd_id &= 0xff00; - sb->bd_id |= ((essver & 0xf000) >> 8) | rev; - } - break; - - case 4: - sb->bd_flags |= BD_F_SB16; - if (sb->bd_flags & BD_F_SB16X) fmt = "SB16 ViBRA16X %d.%d"; - else fmt = "SoundBlaster 16 %d.%d"; - break; - - default: - device_printf(dev, "failed to get SB version (%x)\n", - sb->bd_id); - return ENXIO; - } - if (essver) snprintf(buf, sizeof buf, fmt, sb->bd_id & 0x000f); - else snprintf(buf, sizeof buf, fmt, sb->bd_id >> 8, sb->bd_id & 0xff); - device_set_desc_copy(dev, buf); - return sb_reset_dsp(sb); -} - -static int -sb_init(device_t dev, struct sb_info *sb) -{ - int x, irq; - - sb->bd_flags &= ~BD_F_MIX_MASK; - /* do various initializations depending on board id. */ - switch (sb->bd_id >> 8) { - case 1: /* old sound blaster has nothing... */ - break; - - case 2: - sb->bd_flags |= BD_F_DUP_MIDI; - if (sb->bd_id > 0x200) sb->bd_flags |= BD_F_MIX_CT1335; - break; - - case 3: - sb->bd_flags |= BD_F_DUP_MIDI | BD_F_MIX_CT1345; - break; - - case 4: - sb->bd_flags |= BD_F_SB16 | BD_F_MIX_CT1745; - if (sb->dma16 != sb->dma8) sb->bd_flags |= BD_F_DUPLEX; - - /* soft irq/dma configuration */ - x = -1; - irq = rman_get_start(sb->irq); - if (irq == 5) x = 2; - else if (irq == 7) x = 4; - else if (irq == 9) x = 1; - else if (irq == 10) x = 8; - if (x == -1) device_printf(dev, - "bad irq %d (5/7/9/10 valid)\n", - irq); - else sb_setmixer(sb, IRQ_NR, x); - sb_setmixer(sb, DMA_NR, (1 << sb->dma16) | (1 << sb->dma8)); - break; - } - return 0; -} - -static int -sb_probe(device_t dev) -{ - snddev_info *d = device_get_softc(dev); - struct sb_info *sb; - int allocated, i; - int error; - - if (isa_get_vendorid(dev)) return ENXIO; /* not yet */ - - device_set_desc(dev, "SoundBlaster"); - bzero(d, sizeof *d); - sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT); - if (!sb) return ENXIO; - bzero(sb, sizeof *sb); - - allocated = 0; - sb->io_rid = 0; - sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &sb->io_rid, - 0, ~0, 16, RF_ACTIVE); - if (!sb->io_base) { - BVDDB(printf("sb_probe: no addr, trying (0x220, 0x240)\n")); - allocated = 1; - sb->io_rid = 0; - sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, - &sb->io_rid, 0x220, 0x22f, - 16, RF_ACTIVE); - if (!sb->io_base) { - sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, - &sb->io_rid, 0x240, - 0x24f, 16, RF_ACTIVE); - } - } - if (!sb->io_base) return ENXIO; - - error = sb_reset_dsp(sb); - if (error) goto no; - error = sb_identify_board(dev, sb); - if (error) goto no; -no: - i = sb->io_rid; - sb_release_resources(sb, dev); - if (allocated) bus_delete_resource(dev, SYS_RES_IOPORT, i); - return error; -} - -static int -sb_doattach(device_t dev, struct sb_info *sb) -{ - snddev_info *d = device_get_softc(dev); - void *ih; - int error; - char status[SND_STATUSLEN]; - - sb->irq_rid = 0; - sb->drq1_rid = 0; - sb->drq2_rid = 1; - if (sb_alloc_resources(sb, dev)) goto no; - error = sb_reset_dsp(sb); - if (error) goto no; - error = sb_identify_board(dev, sb); - if (error) goto no; - - sb_init(dev, sb); - 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); - - if (sb->bd_flags & BD_F_SB16) - pcm_setflags(dev, pcm_getflags(dev) | SD_F_EVILSB16); - if (sb->dma16 == sb->dma8) - 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*/DSP_BUFFSIZE, /*nsegments*/1, - /*maxsegz*/0x3ffff, - /*flags*/0, &sb->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 %d", - rman_get_start(sb->io_base), rman_get_start(sb->irq), - sb->dma8); - if (sb->dma16 != sb->dma8) snprintf(status + strlen(status), - SND_STATUSLEN - strlen(status), ":%d", sb->dma16); - - 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_setstatus(dev, status); - - return 0; - -no: - sb_release_resources(sb, dev); - return ENXIO; -} - -static int -sb_attach(device_t dev) -{ - struct sb_info *sb; - int flags = device_get_flags(dev); - - if (flags & DV_F_DUAL_DMA) { - bus_set_resource(dev, SYS_RES_DRQ, 1, - flags & DV_F_DRQ_MASK, 1); - } - sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT); - if (!sb) return ENXIO; - bzero(sb, sizeof *sb); - - /* XXX in probe should set io resource to right val instead of this */ - sb->io_rid = 0; - sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &sb->io_rid, - 0, ~0, 16, RF_ACTIVE); - if (!sb->io_base) { - BVDDB(printf("sb_probe: no addr, trying (0x220, 0x240)\n")); - sb->io_rid = 0; - sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, - &sb->io_rid, 0x220, 0x22f, - 16, RF_ACTIVE); - if (!sb->io_base) { - sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, - &sb->io_rid, 0x240, - 0x24f, 16, RF_ACTIVE); - } - } - if (!sb->io_base) return ENXIO; - - return sb_doattach(dev, sb); -} - -static device_method_t sb_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, sb_probe), - DEVMETHOD(device_attach, sb_attach), - - { 0, 0 } -}; - -static driver_t sb_driver = { - "pcm", - sb_methods, - sizeof(snddev_info), -}; - -DRIVER_MODULE(sb, isa, sb_driver, pcm_devclass, 0, 0); - -static void -sb_intr(void *arg) -{ - struct sb_info *sb = (struct sb_info *)arg; - int reason = 3, c; - - /* - * SB < 4.0 is half duplex and has only 1 bit for int source, - * so we fake it. SB 4.x (SB16) has the int source in a separate - * register. - * The Vibra16X has separate flags for 8 and 16 bit transfers, but - * I have no idea how to tell capture from playback interrupts... - */ - if (sb->bd_flags & BD_F_SB16) { - c = sb_getmixer(sb, IRQ_STAT); - /* this tells us if the source is 8-bit or 16-bit dma. We - * have to check the io channel to map it to read or write... - */ - reason = 0; - if (c & 1) { /* 8-bit dma */ - if (sb->pch.fmt & AFMT_U8) reason |= 1; - if (sb->rch.fmt & AFMT_U8) reason |= 2; - } - if (c & 2) { /* 16-bit dma */ - if (sb->pch.fmt & AFMT_S16_LE) reason |= 1; - if (sb->rch.fmt & AFMT_S16_LE) reason |= 2; - } - } else c = 1; -#if 0 - printf("sb_intr: reason=%d c=0x%x\n", reason, c); -#endif - if ((reason & 1) && (sb->pch.buffer->dl > 0)) - chn_intr(sb->pch.channel); - if ((reason & 2) && (sb->rch.buffer->dl > 0)) - chn_intr(sb->rch.channel); - if (c & 1) sb_rd(sb, DSP_DATA_AVAIL); /* 8-bit int ack */ - if (c & 2) 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) { - sb->pch.buffer->dl = -1; - chn_intr(sb->pch.channel); - } - if (sb->rch.buffer->dl > 0) { - sb->rch.buffer->dl = -1; - chn_intr(sb->rch.channel); - } -} - -static int -sb_format(struct sb_chinfo *ch, u_int32_t format) -{ - ch->fmt = format; - return 0; -} - -static int -sb_speed(struct sb_chinfo *ch, int speed) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0; - - if (sb->bd_flags & BD_F_SB16) { - RANGE(speed, 5000, 45000); - sb_cmd(sb, 0x42 - play); - sb_cmd(sb, speed >> 8); - sb_cmd(sb, speed & 0xff); - } else { - u_char tconst; - int max_speed = 45000, tmp; - u_long flags; - - /* here enforce speed limitations - max 22050 on sb 1.x*/ - if (sb->bd_id <= 0x200) max_speed = 22050; - - /* - * SB models earlier than SB Pro have low limit for the - * input rate. Note that this is only for input, but since - * we do not support separate values for rec & play.... - */ - if (!play) { - if (sb->bd_id <= 0x200) max_speed = 13000; - else if (sb->bd_id < 0x300) max_speed = 15000; - } - RANGE(speed, 4000, max_speed); - if (stereo) speed <<= 1; - - /* - * Now the speed should be valid. Compute the value to be - * programmed into the board. - */ - if (speed > 22050) { /* High speed mode on 2.01/3.xx */ - tconst = (u_char) - ((65536 - ((256000000 + speed / 2) / speed)) - >> 8); - sb->bd_flags |= BD_F_HISPEED; - tmp = 65536 - (tconst << 8); - speed = (256000000 + tmp / 2) / tmp; - } else { - sb->bd_flags &= ~BD_F_HISPEED; - tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff; - tmp = 256 - tconst; - speed = (1000000 + tmp / 2) / tmp; - } - flags = spltty(); - sb_cmd1(sb, 0x40, tconst); /* set time constant */ - splx(flags); - if (stereo) speed >>= 1; - } - return speed; -} - -static int -sb_start(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0; - int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0; - int l = ch->buffer->dl; - u_char i1, i2 = 0; - - if (b16) l >>= 1; - l--; - if (play) sb_cmd(sb, DSP_CMD_SPKON); - if (sb->bd_flags & BD_F_SB16) { - i1 = DSP_F16_AUTO | DSP_F16_FIFO_ON | - (play? DSP_F16_DAC : DSP_F16_ADC); - i1 |= (b16 && (sb->bd_flags & BD_F_DUPLEX))? DSP_DMA16 : DSP_DMA8; - i2 = (stereo? DSP_F16_STEREO : 0) | (b16? DSP_F16_SIGNED : 0); - sb_cmd(sb, i1); - sb_cmd2(sb, i2, l); - } else { - if (sb->bd_flags & BD_F_HISPEED) i1 = play? 0x90 : 0x98; - else i1 = play? 0x1c : 0x2c; - sb_setmixer(sb, 0x0e, stereo? 2 : 0); - /* an ESS extension -- they can do 16 bits */ - if (b16) i1 |= 1; - sb_cmd2(sb, 0x48, l); - sb_cmd(sb, i1); - } - sb->bd_flags |= BD_F_DMARUN << b16; - return 0; -} - -static int -sb_stop(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0; - - if (sb->bd_flags & BD_F_HISPEED) sb_reset_dsp(sb); - else { - sb_cmd(sb, b16? DSP_CMD_DMAPAUSE_16 : DSP_CMD_DMAPAUSE_8); - /* - * The above seems to have the undocumented side effect of - * blocking the other side as well. If the other - * channel was active (SB16) I have to re-enable it :( - */ - if (sb->bd_flags & (BD_F_DMARUN << (1 - b16))) - sb_cmd(sb, b16? 0xd4 : 0xd6 ); - } - if (play) sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */ - sb->bd_flags &= ~(BD_F_DMARUN << b16); - return 0; -} - -/* 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); - /* normal DMA mode */ - ess_write(sb, 0xb8, play ? 0x00 : 0x0a); - /* 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 ? 0x00 : 0x0a; - 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 */ -static void * -sbchan_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 = DSP_BUFFSIZE; - if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1) return NULL; - ch->buffer->chan = (dir == PCMDIR_PLAY)? sb->dma16 : sb->dma8; - return ch; -} - -static int -sbchan_setdir(void *data, int dir) -{ - struct sb_chinfo *ch = data; - ch->dir = dir; - return 0; -} - -static int -sbchan_setformat(void *data, u_int32_t format) -{ - struct sb_chinfo *ch = data; - sb_format(ch, format); - return 0; -} - -static int -sbchan_setspeed(void *data, u_int32_t speed) -{ - struct sb_chinfo *ch = data; - return sb_speed(ch, speed); -} - -static int -sbchan_setblocksize(void *data, u_int32_t blocksize) -{ - return blocksize; -} - -static int -sbchan_trigger(void *data, int go) -{ - struct sb_chinfo *ch = data; - buf_isadma(ch->buffer, go); - if (go == PCMTRIG_START) sb_start(ch); else sb_stop(ch); - return 0; -} - -static int -sbchan_getptr(void *data) -{ - struct sb_chinfo *ch = data; - return buf_isadmaptr(ch->buffer); -} - -static pcmchan_caps * -sbchan_getcaps(void *data) -{ - struct sb_chinfo *ch = data; - int p = (ch->dir == PCMDIR_PLAY)? 1 : 0; - if (ch->parent->bd_id <= 0x200) - return p? &sb_playcaps : &sb_reccaps; - else if (ch->parent->bd_id >= 0x400) - return p? &sb16_playcaps : &sb16_reccaps; - else - return p? &sbpro_playcaps : &sbpro_reccaps; -} -/* channel interface for ESS18xx */ -#ifdef notyet -static void * -esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) -{ - /* the same as sbchan_init()? */ -} -#endif - -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; - 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 -sbmix_init(snd_mixer *m) -{ - struct sb_info *sb = mix_getdevinfo(m); - - switch (sb->bd_flags & BD_F_MIX_MASK) { - case BD_F_MIX_CT1345: /* SB 3.0 has 1345 mixer */ - mix_setdevs(m, SBPRO_MIXER_DEVICES); - mix_setrecdevs(m, SBPRO_RECORDING_DEVICES); - sb_setmixer(sb, 0, 1); /* reset mixer */ - 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; - - case BD_F_MIX_CT1745: /* SB16 mixer ... */ - mix_setdevs(m, SB16_MIXER_DEVICES); - mix_setrecdevs(m, SB16_RECORDING_DEVICES); - sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */ - sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */ - sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */ - } - return 0; -} - -static int -sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - struct sb_info *sb = mix_getdevinfo(m); - int regoffs; - u_char val; - mixer_tab *iomap; - - 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; - break; - - case BD_F_MIX_CT1745: - iomap = &sb16_mix; - break; - - default: - return -1; - /* XXX how about the SG NX Pro, iomap = sgnxpro_mix */ - } - - /* Change left channel */ - regoffs = (*iomap)[dev][LEFT_CHN].regno; - if (regoffs != 0) { - val = sb_getmixer(sb, regoffs); - change_bits(iomap, &val, dev, LEFT_CHN, left); - sb_setmixer(sb, regoffs, val); - } - - /* Change right channel */ - regoffs = (*iomap)[dev][RIGHT_CHN].regno; - if (regoffs != 0) { - val = sb_getmixer(sb, regoffs); /* Read the new one */ - change_bits(iomap, &val, dev, RIGHT_CHN, right); - sb_setmixer(sb, regoffs, val); - } else - right = left; - - return left | (right << 8); -} - -static int -sbmix_setrecsrc(snd_mixer *m, u_int32_t src) -{ - struct sb_info *sb = mix_getdevinfo(m); - u_char recdev; - - switch (sb->bd_flags & BD_F_MIX_MASK) { - case BD_F_MIX_CT1345: - if (src == SOUND_MASK_LINE) recdev = 0x06; - else if (src == SOUND_MASK_CD) recdev = 0x02; - else { /* default: mic */ - src = SOUND_MASK_MIC; - recdev = 0; - } - sb_setmixer(sb, RECORD_SRC, recdev | - (sb_getmixer(sb, RECORD_SRC) & ~0x07)); - break; - - case BD_F_MIX_CT1745: /* sb16 */ - recdev = 0; - if (src & SOUND_MASK_MIC) recdev |= 0x01; /* mono mic */ - if (src & SOUND_MASK_CD) recdev |= 0x06; /* l+r cd */ - if (src & SOUND_MASK_LINE) recdev |= 0x18; /* l+r line */ - if (src & SOUND_MASK_SYNTH) recdev |= 0x60; /* l+r midi */ - sb_setmixer(sb, SB16_IMASK_L, recdev); - sb_setmixer(sb, SB16_IMASK_R, recdev); - /* - * since the same volume controls apply to the input and - * output sections, the best approach to have a consistent - * behaviour among cards would be to disable the output path - * on devices which are used to record. - * However, since users like to have feedback, we only disable - * the mic -- permanently. - */ - sb_setmixer(sb, SB16_OMASK, 0x1f & ~1); - break; - } - return src; -} - -#if NPNP > 0 -static int -sbpnp_probe(device_t dev) -{ - char *s = NULL; - u_int32_t logical_id = isa_get_logicalid(dev); - - switch(logical_id) { - case 0x43008c0e: /* CTL0043 */ - case 0x01008c0e: /* CTL0001 */ - s = "Vibra16X"; - break; - - case 0x31008c0e: /* CTL0031 */ - case 0x41008c0e: /* CTL0041 */ - case 0x42008c0e: /* CTL0042 */ - s = "SB16 PnP"; - break; - - case 0x44008c0e: /* CTL0044 */ - s = "Creative SB AWE64 Gold"; - break; - - case 0x45008c0e: /* CTL0045 */ - s = "Creative AWE64 PnP"; - break; - - case 0x01100000: /* @@@1001 */ - s = "Avance Asound 110"; - break; - - case 0x01200000: /* @@@2001 */ - s = "Avance Logic ALS120"; - break; - - case 0x68187316: /* ESS1868 */ - s = "ESS1868"; - break; - - case 0x69187316: /* ESS1869 */ - s = "ESS1869"; - break; - - case 0x88187316: /* ESS1888 */ - s = "ESS1888"; - break; - } - if (s) { - device_set_desc(dev, s); - return 0; - } - return ENXIO; -} - -static int -sbpnp_attach(device_t dev) -{ - struct sb_info *sb; - u_int32_t vend_id = isa_get_vendorid(dev); - - sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT); - if (!sb) return ENXIO; - bzero(sb, sizeof *sb); - - switch(vend_id) { - case 0xf0008c0e: - case 0x10019305: - case 0x20019305: - /* XXX add here the vend_id for other vibra16X cards... */ - sb->bd_flags = BD_F_SB16X; - } - return sb_doattach(dev, sb); -} - -static device_method_t sbpnp_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, sbpnp_probe), - DEVMETHOD(device_attach, sbpnp_attach), - - { 0, 0 } -}; - -static driver_t sbpnp_driver = { - "pcm", - sbpnp_methods, - sizeof(snddev_info), -}; - -DRIVER_MODULE(sbpnp, isa, sbpnp_driver, pcm_devclass, 0, 0); - -#endif /* NPNP > 0 */ - -#endif /* NPCM > 0 */ - - Property changes on: head/sys/dev/pcm/isa/sb.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/isa/sb.h =================================================================== --- head/sys/dev/pcm/isa/sb.h (revision 53505) +++ head/sys/dev/pcm/isa/sb.h (nonexistent) @@ -1,382 +0,0 @@ -/* - * file: sbcard.h - * $FreeBSD$ - */ - -typedef struct _sbdev_info { - -} sbdev_info ; - -extern int sbc_major, sbc_minor ; -/* - * sound blaster registers - */ - -#define SBDSP_RST 0x6 -#define DSP_READ 0xA -#define DSP_WRITE 0xC -#define SBDSP_CMD 0xC -#define SBDSP_STATUS 0xC -#define DSP_DATA_AVAIL 0xE -#define DSP_DATA_AVL16 0xF - -#define SB_MIX_ADDR 0x4 -#define SB_MIX_DATA 0x5 -#if 0 -#define OPL3_LEFT (io_base + 0x0) -#define OPL3_RIGHT (io_base + 0x2) -#define OPL3_BOTH (io_base + 0x8) -#endif - -/* - * DSP Commands. There are many, and in many cases they are used explicitly - */ - -/* these are not used except for programmed I/O (not in this driver) */ -#define DSP_DAC8 0x10 /* direct DAC output */ -#define DSP_ADC8 0x20 /* direct ADC input */ - -/* these should be used in the SB 1.0 */ -#define DSP_CMD_DAC8 0x14 /* single cycle 8-bit dma out */ -#define DSP_CMD_ADC8 0x24 /* single cycle 8-bit dma in */ - -/* these should be used in the SB 2.0 and 2.01 */ -#define DSP_CMD_DAC8_AUTO 0x1c /* auto 8-bit dma out */ -#define DSP_CMD_ADC8_AUTO 0x2c /* auto 8-bit dma out */ - -#define DSP_CMD_HSSIZE 0x48 /* high speed dma count */ -#define DSP_CMD_HSDAC_AUTO 0x90 /* high speed dac, auto */ -#define DSP_CMD_HSADC_AUTO 0x98 /* high speed adc, auto */ - -/* SBPro commands. Some cards (JAZZ, SMW) also support 16 bits */ - - /* prepare for dma input */ -#define DSP_CMD_DMAMODE(stereo, bit16) (0xA0 | (stereo ? 8:0) | (bit16 ? 4:0)) - -#define DSP_CMD_DAC2 0x16 /* 2-bit adpcm dma out (cont) */ -#define DSP_CMD_DAC2S 0x17 /* 2-bit adpcm dma out (start) */ - -#define DSP_CMD_DAC2S_AUTO 0x1f /* auto 2-bit adpcm dma out (start) */ - - -/* SB16 commands */ -#define DSP_CMD_O16 0xb0 -#define DSP_CMD_I16 0xb8 -#define DSP_CMD_O8 0xc0 -#define DSP_CMD_I8 0xc8 - -#define DSP_MODE_U8MONO 0x00 -#define DSP_MODE_U8STEREO 0x20 -#define DSP_MODE_S16MONO 0x10 -#define DSP_MODE_S16STEREO 0x30 - -#define DSP_CMD_SPKON 0xD1 -#define DSP_CMD_SPKOFF 0xD3 -#define DSP_CMD_SPKR(on) (0xD1 | (on ? 0:2)) - -#define DSP_CMD_DMAPAUSE_8 0xD0 -#define DSP_CMD_DMAPAUSE_16 0xD5 -#define DSP_CMD_DMAEXIT_8 0xDA -#define DSP_CMD_DMAEXIT_16 0xD9 -#define DSP_CMD_TCONST 0x40 /* set time constant */ -#define DSP_CMD_HSDAC 0x91 /* high speed dac */ -#define DSP_CMD_HSADC 0x99 /* high speed adc */ - -#define DSP_CMD_GETVER 0xE1 -#define DSP_CMD_GETID 0xE7 /* return id bytes */ - - -#define DSP_CMD_OUT16 0x41 /* send parms for dma out on sb16 */ -#define DSP_CMD_IN16 0x42 /* send parms for dma in on sb16 */ -#if 0 /*** unknown ***/ -#define DSP_CMD_FA 0xFA /* get version from prosonic*/ -#define DSP_CMD_FB 0xFB /* set irq/dma for prosonic*/ -#endif - -/* - * in fact, for the SB16, dma commands are as follows: - * - * cmd, mode, len_low, len_high. - * - * cmd is a combination of DSP_DMA16 or DSP_DMA8 and - */ - -#define DSP_DMA16 0xb0 -#define DSP_DMA8 0xc0 -# define DSP_F16_DAC 0x00 -# define DSP_F16_ADC 0x08 -# define DSP_F16_AUTO 0x04 -# define DSP_F16_FIFO_ON 0x02 - -/* - * mode is a combination of the following: - */ -#define DSP_F16_STEREO 0x20 -#define DSP_F16_SIGNED 0x10 - -#define IMODE_NONE 0 -#define IMODE_OUTPUT PCM_ENABLE_OUTPUT -#define IMODE_INPUT PCM_ENABLE_INPUT -#define IMODE_INIT 3 -#define IMODE_MIDI 4 - -#define NORMAL_MIDI 0 -#define UART_MIDI 1 - -/* - * values used for bd_flags in SoundBlaster driver - */ -#define BD_F_HISPEED 0x0001 /* doing high speed ... */ - -#define BD_F_JAZZ16 0x0002 /* jazz16 detected */ -#define BD_F_JAZZ16_2 0x0004 /* jazz16 type 2 */ - -#define BD_F_DUP_MIDI 0x0008 /* duplex midi */ - -#define BD_F_MIX_MASK 0x0070 /* up to 8 mixers (I know of 3) */ -#define BD_F_MIX_CT1335 0x0010 /* CT1335 */ -#define BD_F_MIX_CT1345 0x0020 /* CT1345 */ -#define BD_F_MIX_CT1745 0x0030 /* CT1745 */ - -#define BD_F_SB16 0x0100 /* this is a SB16 */ -#define BD_F_SB16X 0x0200 /* this is a vibra16X or clone */ -#define BD_F_MIDIBUSY 0x0400 /* midi busy */ -#define BD_F_ESS 0x0800 /* this is an ESS chip */ -/* - * on some SB16 cards, at times I swap DMA channels. Remember this - * so that they can be restored later. - */ -#define BD_F_SWAPPED 0x1000 /* have swapped DMA channels */ -#define BD_F_DMARUN 0x2000 -#define BD_F_DMARUN2 0x4000 -#define BD_F_DUPLEX 0x8000 -/* - * sound/sb_mixer.h - * - * Definitions for the SB Pro and SB16 mixers - * - * Copyright by Hannu Savolainen 1993 - * - * 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. - * - * Modified: Hunyue Yau Jan 6 1994 Added defines for the Sound Galaxy NX Pro - * mixer. - * - */ - -#define SBPRO_RECORDING_DEVICES \ - (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD) - -/* Same as SB Pro, unless I find otherwise */ -#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES - -#define SBPRO_MIXER_DEVICES \ - (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \ - SOUND_MASK_CD | SOUND_MASK_VOLUME) - -/* - * SG NX Pro has treble and bass settings on the mixer. The 'speaker' channel - * is the COVOX/DisneySoundSource emulation volume control on the mixer. It - * does NOT control speaker volume. Should have own mask eventually? - */ -#define SGNXPRO_MIXER_DEVICES \ - (SBPRO_MIXER_DEVICES | SOUND_MASK_BASS | \ - SOUND_MASK_TREBLE | SOUND_MASK_SPEAKER ) - -#define SB16_RECORDING_DEVICES \ - (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD) - -#define SB16_MIXER_DEVICES \ - (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | \ - SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | \ - SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \ - SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE) - -/* - * Mixer registers - * - * NOTE! RECORD_SRC == IN_FILTER - */ - -/* - * Mixer registers of SB Pro - */ -#define VOC_VOL 0x04 -#define MIC_VOL 0x0A -#define MIC_MIX 0x0A -#define RECORD_SRC 0x0C -#define IN_FILTER 0x0C -#define OUT_FILTER 0x0E -#define MASTER_VOL 0x22 -#define FM_VOL 0x26 -#define CD_VOL 0x28 -#define LINE_VOL 0x2E -#define IRQ_NR 0x80 -#define DMA_NR 0x81 -#define IRQ_STAT 0x82 - -/* - * Additional registers on the SG NX Pro - */ -#define COVOX_VOL 0x42 -#define TREBLE_LVL 0x44 -#define BASS_LVL 0x46 - -#define FREQ_HI (1 << 3)/* Use High-frequency ANFI filters */ -#define FREQ_LOW 0 /* Use Low-frequency ANFI filters */ -#define FILT_ON 0 /* Yes, 0 to turn it on, 1 for off */ -#define FILT_OFF (1 << 5) - -#define MONO_DAC 0x00 -#define STEREO_DAC 0x02 - -/* - * Mixer registers of SB16 - */ -#define SB16_IMASK_L 0x3d -#define SB16_IMASK_R 0x3e -#define SB16_OMASK 0x3c - - -#ifndef __SB_MIXER_C__ -mixer_tab sbpro_mix; -mixer_tab ess_mix; -mixer_tab sb16_mix; -#ifdef __SGNXPRO__ -mixer_tab sgnxpro_mix; -#endif -static u_char sb16_recmasks_L[SOUND_MIXER_NRDEVICES]; -static u_char sb16_recmasks_R[SOUND_MIXER_NRDEVICES]; -#else /* __SB_MIXER_C__ defined */ -mixer_tab sbpro_mix = { - PMIX_ENT(SOUND_MIXER_VOLUME, 0x22, 4, 4, 0x22, 0, 4), - PMIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_SYNTH, 0x26, 4, 4, 0x26, 0, 4), - PMIX_ENT(SOUND_MIXER_PCM, 0x04, 4, 4, 0x04, 0, 4), - PMIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_LINE, 0x2e, 4, 4, 0x2e, 0, 4), - PMIX_ENT(SOUND_MIXER_MIC, 0x0a, 0, 3, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_CD, 0x28, 4, 4, 0x28, 0, 4), - PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0) -}; - -mixer_tab ess_mix = { - PMIX_ENT(SOUND_MIXER_VOLUME, 0x32, 4, 4, 0x32, 0, 4), - PMIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_SYNTH, 0x36, 4, 4, 0x26, 0, 4), - PMIX_ENT(SOUND_MIXER_PCM, 0x14, 4, 4, 0x04, 0, 4), - PMIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 0, 3, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_LINE, 0x3e, 4, 4, 0x2e, 0, 4), - PMIX_ENT(SOUND_MIXER_MIC, 0x1a, 4, 4, 0x1a, 0, 4), - PMIX_ENT(SOUND_MIXER_CD, 0x38, 4, 4, 0x28, 0, 4), - PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0) -}; - -#ifdef __SGNXPRO__ -mixer_tab sgnxpro_mix = { - PMIX_ENT(SOUND_MIXER_VOLUME, 0x22, 4, 4, 0x22, 0, 4), - PMIX_ENT(SOUND_MIXER_BASS, 0x46, 0, 3, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_TREBLE, 0x44, 0, 3, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_SYNTH, 0x26, 4, 4, 0x26, 0, 4), - PMIX_ENT(SOUND_MIXER_PCM, 0x04, 4, 4, 0x04, 0, 4), - PMIX_ENT(SOUND_MIXER_SPEAKER, 0x42, 0, 3, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_LINE, 0x2e, 4, 4, 0x2e, 0, 4), - PMIX_ENT(SOUND_MIXER_MIC, 0x0a, 0, 3, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_CD, 0x28, 4, 4, 0x28, 0, 4), - PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0) -}; -#endif - -mixer_tab sb16_mix = { - PMIX_ENT(SOUND_MIXER_VOLUME, 0x30, 3, 5, 0x31, 3, 5), - PMIX_ENT(SOUND_MIXER_BASS, 0x46, 4, 4, 0x47, 4, 4), - PMIX_ENT(SOUND_MIXER_TREBLE, 0x44, 4, 4, 0x45, 4, 4), - PMIX_ENT(SOUND_MIXER_SYNTH, 0x34, 3, 5, 0x35, 3, 5), - PMIX_ENT(SOUND_MIXER_PCM, 0x32, 3, 5, 0x33, 3, 5), - PMIX_ENT(SOUND_MIXER_SPEAKER, 0x3b, 6, 2, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_LINE, 0x38, 3, 5, 0x39, 3, 5), - PMIX_ENT(SOUND_MIXER_MIC, 0x3a, 3, 5, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_CD, 0x36, 3, 5, 0x37, 3, 5), - PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_RECLEV, 0x3f, 6, 2, 0x40, 6, 2), /* Obsol,Use IGAIN*/ - PMIX_ENT(SOUND_MIXER_IGAIN, 0x3f, 6, 2, 0x40, 6, 2), - PMIX_ENT(SOUND_MIXER_OGAIN, 0x41, 6, 2, 0x42, 6, 2) -}; - -#if 0 -static u_char sb16_recmasks_L[SOUND_MIXER_NRDEVICES] = -{ - 0x00, /* SOUND_MIXER_VOLUME */ - 0x00, /* SOUND_MIXER_BASS */ - 0x00, /* SOUND_MIXER_TREBLE */ - 0x40, /* SOUND_MIXER_SYNTH */ - 0x00, /* SOUND_MIXER_PCM */ - 0x00, /* SOUND_MIXER_SPEAKER */ - 0x10, /* SOUND_MIXER_LINE */ - 0x01, /* SOUND_MIXER_MIC */ - 0x04, /* SOUND_MIXER_CD */ - 0x00, /* SOUND_MIXER_IMIX */ - 0x00, /* SOUND_MIXER_ALTPCM */ - 0x00, /* SOUND_MIXER_RECLEV */ - 0x00, /* SOUND_MIXER_IGAIN */ - 0x00 /* SOUND_MIXER_OGAIN */ -}; - -static u_char sb16_recmasks_R[SOUND_MIXER_NRDEVICES] = -{ - 0x00, /* SOUND_MIXER_VOLUME */ - 0x00, /* SOUND_MIXER_BASS */ - 0x00, /* SOUND_MIXER_TREBLE */ - 0x20, /* SOUND_MIXER_SYNTH */ - 0x00, /* SOUND_MIXER_PCM */ - 0x00, /* SOUND_MIXER_SPEAKER */ - 0x08, /* SOUND_MIXER_LINE */ - 0x01, /* SOUND_MIXER_MIC */ - 0x02, /* SOUND_MIXER_CD */ - 0x00, /* SOUND_MIXER_IMIX */ - 0x00, /* SOUND_MIXER_ALTPCM */ - 0x00, /* SOUND_MIXER_RECLEV */ - 0x00, /* SOUND_MIXER_IGAIN */ - 0x00 /* SOUND_MIXER_OGAIN */ -}; -#endif - -/* - * Recording sources (SB Pro) - */ -#endif /* __SB_MIXER_C__ */ - -#define SRC_MIC 1 /* Select Microphone recording source */ -#define SRC_CD 3 /* Select CD recording source */ -#define SRC_LINE 7 /* Use Line-in for recording source */ - - Property changes on: head/sys/dev/pcm/isa/sb.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/isa/es1888.c =================================================================== --- head/sys/dev/pcm/isa/es1888.c (revision 53505) +++ head/sys/dev/pcm/isa/es1888.c (nonexistent) @@ -1,170 +0,0 @@ -/*- - * Copyright (c) 1999 Doug Rabson - * 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 - -#if NPCM > 0 - -static int -es1888_dspready(u_int32_t port) -{ - return ((inb(port + SBDSP_STATUS) & 0x80) == 0); -} - -static int -es1888_dspwr(u_int32_t port, u_char val) -{ - int i; - - for (i = 0; i < 1000; i++) { - if (es1888_dspready(port)) { - outb(port + SBDSP_CMD, val); - return 0; - } - if (i > 10) DELAY((i > 100)? 1000 : 10); - } - return ENXIO; -} - -static u_int -es1888_get_byte(u_int32_t port) -{ - int i; - - for (i = 1000; i > 0; i--) { - if (inb(port + DSP_DATA_AVAIL) & 0x80) - return inb(port + DSP_READ); - else - DELAY(20); - } - return 0xffff; -} - -static int -es1888_reset(u_int32_t port) -{ - outb(port + SBDSP_RST, 3); - DELAY(100); - outb(port + SBDSP_RST, 0); - if (es1888_get_byte(port) != 0xAA) { - return ENXIO; /* Sorry */ - } - return 0; -} - -static void -es1888_configuration_mode(void) -{ - /* - * Emit the Read-Sequence-Key to enter configuration - * mode. Note this only works after a reset (or after bit 2 of - * mixer register 0x40 is set). - * - * 3 reads from 0x229 in a row guarantees reset of key - * sequence to beginning. - */ - inb(0x229); - inb(0x229); - inb(0x229); - - inb(0x22b); /* state 1 */ - inb(0x229); /* state 2 */ - inb(0x22b); /* state 3 */ - inb(0x229); /* state 4 */ - inb(0x229); /* state 5 */ - inb(0x22b); /* state 6 */ - inb(0x229); /* state 7 */ -} - -static void -es1888_set_port(u_int32_t port) -{ - es1888_configuration_mode(); - inb(port); -} - -static void -es1888_identify(driver_t *driver, device_t parent) -{ - u_int32_t lo, hi; - device_t dev; - - es1888_set_port(0x220); - if (es1888_reset(0x220)) - return; - - /* - * Check identification bytes for es1888. - */ - if (es1888_dspwr(0x220, 0xe7)) - return; - hi = es1888_get_byte(0x220); - lo = es1888_get_byte(0x220); - if (hi != 0x68 || (lo & 0xf0) != 0x80) - return; - - /* - * Program irq and drq. - */ - if (es1888_dspwr(0x220, 0xc6) /* enter extended mode */ - || es1888_dspwr(0x220, 0xb1) /* write register b1 */ - || es1888_dspwr(0x220, 0x14) /* enable irq 5 */ - || es1888_dspwr(0x220, 0xb2) /* write register b1 */ - || es1888_dspwr(0x220, 0x18)) /* enable drq 1 */ - return; - - /* - * Create the device and program its resources. - */ - dev = BUS_ADD_CHILD(parent, ISA_ORDER_PNP, NULL, -1); - bus_set_resource(dev, SYS_RES_IOPORT, 0, 0x220, 0x10); - bus_set_resource(dev, SYS_RES_IRQ, 0, 5, 1); - bus_set_resource(dev, SYS_RES_DRQ, 0, 1, 1); - isa_set_vendorid(dev, PNP_EISAID("ESS1888")); - isa_set_logicalid(dev, PNP_EISAID("ESS1888")); -} - -static device_method_t es1888_methods[] = { - /* Device interface */ - DEVMETHOD(device_identify, es1888_identify), - - { 0, 0 } -}; - -static driver_t es1888_driver = { - "pcm", - es1888_methods, - 1, /* no softc */ -}; - -static devclass_t pcm_devclass; - -DRIVER_MODULE(es1888, isa, es1888_driver, pcm_devclass, 0, 0); - -#endif /* NPCM > 0 */ Property changes on: head/sys/dev/pcm/isa/es1888.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/isa/mss.h =================================================================== --- head/sys/dev/pcm/isa/mss.h (revision 53505) +++ head/sys/dev/pcm/isa/mss.h (nonexistent) @@ -1,374 +0,0 @@ -/* - * file: mss.h - * - * (C) 1997 Luigi Rizzo (luigi@iet.unipi.it) - * - * This file contains information and macro definitions for - * AD1848-compatible devices, used in the MSS/WSS compatible boards. - * - */ - -/* - * - -The codec part of the board is seen as a set of 4 registers mapped -at the base address for the board (default 0x534). Note that some -(early) boards implemented 4 additional registers 4 location before -(usually 0x530) to store configuration information. This is a source -of confusion in that one never knows what address to specify. The -(current) convention is to use the old address (0x530) in the kernel -configuration file and consider MSS registers start four location -ahead. - - * - */ - -/* - * The four visible registers of the MSS : - * - */ - -#define MSS_INDEX (0 + 4) -#define MSS_IDXBUSY 0x80 /* readonly, set when busy */ -#define MSS_MCE 0x40 /* the MCE bit. */ - /* - * the MCE bit must be set whenever the current mode of the - * codec is changed; this in particular is true for the - * Data Format (I8, I28) and Interface Config(I9) registers. - * Only exception are CEN and PEN which can be changed on the fly. - * The DAC output is muted when MCE is set. - */ -#define MSS_TRD 0x20 /* Transfer request disable */ - /* - * When TRD is set, DMA transfers cease when the INT bit in - * the MSS status reg is set. Must be cleared for automode - * DMA, set otherwise. - */ -#define MSS_IDXMASK 0x1f /* mask for indirect address */ - -#define MSS_IDATA (1 + 4) - /* - * data to be transferred to the indirect register addressed - * by index addr. During init and sw. powerdown, cannot be - * written to, and is always read as 0x80 (consistent with the - * busy flag). - */ - -#define MSS_STATUS (2 + 4) - -#define IS_CUL 0x80 /* capture upper/lower */ -#define IS_CLR 0x40 /* capture left/right */ -#define IS_CRDY 0x20 /* capture ready for programmed i/o */ -#define IS_SER 0x10 /* sample error (overrun/underrun) */ -#define IS_PUL 0x08 /* playback upper/lower */ -#define IS_PLR 0x04 /* playback left/right */ -#define IS_PRDY 0x02 /* playback ready for programmed i/o */ -#define IS_INT 0x01 /* int status (1 = active) */ - /* - * IS_INT is clreared by any write to the status register. - */ -#if 0 -#define io_Polled_IO(d) ((d)->io_base+3+4) - /* - * this register is used in case of polled i/o - */ -#endif - -/* - * The MSS has a set of 16 (or 32 depending on the model) indirect - * registers accessible through the data port by specifying the - * appropriate address in the address register. - * - * The 16 low registers are uniformly handled in AD1848/CS4248 compatible - * mode (often called MODE1). For the upper 16 registers there are - * some differences among different products, mainly Crystal uses them - * differently from OPTi. - * - */ - -/* - * volume registers - */ - -#define I6_MUTE 0x80 - -/* - * register I9 -- interface configuration. - */ - -#define I9_PEN 0x01 /* playback enable */ -#define I9_CEN 0x02 /* capture enable */ - -/* - * values used in bd_flags - */ -#define BD_F_MCE_BIT 0x0001 -#define BD_F_IRQ_OK 0x0002 -#define BD_F_TMR_RUN 0x0004 -#define BD_F_MSS_OFFSET 0x0008 /* offset mss writes by -4 */ -#define BD_F_DUPLEX 0x0010 - -/* - * sound/ad1848_mixer.h - * - * Definitions for the mixer of AD1848 and compatible codecs. - * - * Copyright by Hannu Savolainen 1994 - * - * 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. - */ -/* - * The AD1848 codec has generic input lines called Line, Aux1 and Aux2. - * Soundcard manufacturers have connected actual inputs (CD, synth, line, - * etc) to these inputs in different order. Therefore it's difficult - * to assign mixer channels to to these inputs correctly. The following - * contains two alternative mappings. The first one is for GUS MAX and - * the second is just a generic one (line1, line2 and line3). - * (Actually this is not a mapping but rather some kind of interleaving - * solution). - */ - -#define MSS_REC_DEVICES \ - (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD|SOUND_MASK_IMIX) - - -/* - * Table of mixer registers. There is a default table for the - * AD1848/CS423x clones, and one for the OPTI931. As more MSS - * clones come out, there ought to be more tables. - * - * Fields in the table are : polarity, register, offset, bits - * - * The channel numbering used by individual soundcards is not fixed. - * Some cards have assigned different meanings for the AUX1, AUX2 - * and LINE inputs. Some have different features... - * - * Following there is a macro ...MIXER_DEVICES which is a bitmap - * of all non-zero fields in the table. - * MODE1_MIXER_DEVICES is the basic mixer of the 1848 in mode 1 - * registers I0..I15) - * - */ - -mixer_ent mix_devices[32][2] = { -MIX_NONE(SOUND_MIXER_VOLUME), -MIX_NONE(SOUND_MIXER_BASS), -MIX_NONE(SOUND_MIXER_TREBLE), -MIX_ENT(SOUND_MIXER_SYNTH, 2, 1, 0, 5, 3, 1, 0, 5), -MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6), -MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0), -MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5), -MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1), -MIX_ENT(SOUND_MIXER_CD, 4, 1, 0, 5, 5, 1, 0, 5), -MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0), -MIX_NONE(SOUND_MIXER_ALTPCM), -MIX_NONE(SOUND_MIXER_RECLEV), -MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4), -MIX_NONE(SOUND_MIXER_OGAIN), -MIX_NONE(SOUND_MIXER_LINE1), -MIX_NONE(SOUND_MIXER_LINE2), -MIX_NONE(SOUND_MIXER_LINE3), -}; - -#define MODE2_MIXER_DEVICES \ - (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | \ - SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | \ - SOUND_MASK_IMIX | SOUND_MASK_IGAIN ) - -#define MODE1_MIXER_DEVICES \ - (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_MIC | \ - SOUND_MASK_CD | SOUND_MASK_IMIX | SOUND_MASK_IGAIN ) - - -/* - * entries for the opti931... - */ - -mixer_ent opti931_devices[32][2] = { /* for the opti931 */ -MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 1, 5, 23, 1, 1, 5), -MIX_NONE(SOUND_MIXER_BASS), -MIX_NONE(SOUND_MIXER_TREBLE), -MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 5, 1, 1, 4), -MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 5, 7, 1, 0, 5), -MIX_NONE(SOUND_MIXER_SPEAKER), -MIX_ENT(SOUND_MIXER_LINE, 18, 1, 1, 4, 19, 1, 1, 4), -MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1), -MIX_ENT(SOUND_MIXER_CD, 2, 1, 1, 4, 3, 1, 1, 4), -MIX_NONE(SOUND_MIXER_IMIX), -MIX_NONE(SOUND_MIXER_ALTPCM), -MIX_NONE(SOUND_MIXER_RECLEV), -MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4), -MIX_NONE(SOUND_MIXER_OGAIN), -MIX_ENT(SOUND_MIXER_LINE1, 16, 1, 1, 4, 17, 1, 1, 4), -MIX_NONE(SOUND_MIXER_LINE2), -MIX_NONE(SOUND_MIXER_LINE3), -}; - -#define OPTI931_MIXER_DEVICES \ - (SOUND_MASK_VOLUME | SOUND_MASK_SYNTH | SOUND_MASK_PCM | \ - SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | \ - SOUND_MASK_IGAIN | SOUND_MASK_LINE1 ) - -/*- - * Copyright (c) 1999 Doug Rabson - * 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$ - */ - -/* - * Register definitions for the Yamaha OPL3-SA[23x]. - */ -#define OPL3SAx_POWER 0x01 /* Power Management (R/W) */ -#define OPL3SAx_POWER_PDX 0x01 /* Set to 1 to halt oscillator */ -#define OPL3SAx_POWER_PDN 0x02 /* Set to 1 to power down */ -#define OPL3SAx_POWER_PSV 0x04 /* Set to 1 to power save */ -#define OPL3SAx_POWER_ADOWN 0x20 /* Analog power (?) */ - -#define OPL3SAx_SYSTEM 0x02 /* System control (R/W) */ -#define OPL3SAx_SYSTEM_VZE 0x01 /* I2S audio routing */ -#define OPL3SAx_SYSTEM_IDSEL 0x03 /* SB compat version select */ -#define OPL3SAx_SYSTEM_SBHE 0x80 /* 0 for AT bus, 1 for XT bus */ - -#define OPL3SAx_IRQCONF 0x03 /* Interrupt configuration (R/W */ -#define OPL3SAx_IRQCONF_WSSA 0x01 /* WSS interrupts through IRQA */ -#define OPL3SAx_IRQCONF_SBA 0x02 /* WSS interrupts through IRQA */ -#define OPL3SAx_IRQCONF_MPUA 0x04 /* WSS interrupts through IRQA */ -#define OPL3SAx_IRQCONF_OPL3A 0x08 /* WSS interrupts through IRQA */ -#define OPL3SAx_IRQCONF_WSSB 0x10 /* WSS interrupts through IRQB */ -#define OPL3SAx_IRQCONF_SBB 0x20 /* WSS interrupts through IRQB */ -#define OPL3SAx_IRQCONF_MPUB 0x40 /* WSS interrupts through IRQB */ -#define OPL3SAx_IRQCONF_OPL3B 0x80 /* WSS interrupts through IRQB */ - -#define OPL3SAx_IRQSTATUSA 0x04 /* Interrupt (IRQ-A) Status (RO) */ -#define OPL3SAx_IRQSTATUSB 0x05 /* Interrupt (IRQ-B) Status (RO) */ -#define OPL3SAx_IRQSTATUS_PI 0x01 /* Playback Flag of CODEC */ -#define OPL3SAx_IRQSTATUS_CI 0x02 /* Recording Flag of CODEC */ -#define OPL3SAx_IRQSTATUS_TI 0x04 /* Timer Flag of CODEC */ -#define OPL3SAx_IRQSTATUS_SB 0x08 /* SB compat Playback Interrupt Flag */ -#define OPL3SAx_IRQSTATUS_MPU 0x10 /* MPU401 Interrupt Flag */ -#define OPL3SAx_IRQSTATUS_OPL3 0x20 /* Internal FM Timer Flag */ -#define OPL3SAx_IRQSTATUS_MV 0x40 /* HW Volume Interrupt Flag */ -#define OPL3SAx_IRQSTATUS_PI 0x01 /* Playback Flag of CODEC */ -#define OPL3SAx_IRQSTATUS_CI 0x02 /* Recording Flag of CODEC */ -#define OPL3SAx_IRQSTATUS_TI 0x04 /* Timer Flag of CODEC */ -#define OPL3SAx_IRQSTATUS_SB 0x08 /* SB compat Playback Interrupt Flag */ -#define OPL3SAx_IRQSTATUS_MPU 0x10 /* MPU401 Interrupt Flag */ -#define OPL3SAx_IRQSTATUS_OPL3 0x20 /* Internal FM Timer Flag */ -#define OPL3SAx_IRQSTATUS_MV 0x40 /* HW Volume Interrupt Flag */ - -#define OPL3SAx_DMACONF 0x06 /* DMA configuration (R/W) */ -#define OPL3SAx_DMACONF_WSSPA 0x01 /* WSS Playback on DMA-A */ -#define OPL3SAx_DMACONF_WSSRA 0x02 /* WSS Recording on DMA-A */ -#define OPL3SAx_DMACONF_SBA 0x02 /* SB Playback on DMA-A */ -#define OPL3SAx_DMACONF_WSSPB 0x10 /* WSS Playback on DMA-A */ -#define OPL3SAx_DMACONF_WSSRB 0x20 /* WSS Recording on DMA-A */ -#define OPL3SAx_DMACONF_SBB 0x20 /* SB Playback on DMA-A */ - -#define OPL3SAx_VOLUMEL 0x07 /* Master Volume Left (R/W) */ -#define OPL3SAx_VOLUMEL_MVL 0x0f /* Attenuation level */ -#define OPL3SAx_VOLUMEL_MVLM 0x80 /* Mute */ - -#define OPL3SAx_VOLUMER 0x08 /* Master Volume Right (R/W) */ -#define OPL3SAx_VOLUMER_MVR 0x0f /* Attenuation level */ -#define OPL3SAx_VOLUMER_MVRM 0x80 /* Mute */ - -#define OPL3SAx_MIC 0x09 /* MIC Volume (R/W) */ -#define OPL3SAx_VOLUMER_MCV 0x1f /* Attenuation level */ -#define OPL3SAx_VOLUMER_MICM 0x80 /* Mute */ - -#define OPL3SAx_MISC 0x0a /* Miscellaneous */ -#define OPL3SAx_MISC_VER 0x07 /* Version */ -#define OPL3SAx_MISC_MODE 0x08 /* SB or WSS mode */ -#define OPL3SAx_MISC_MCSW 0x10 /* */ -#define OPL3SAx_MISC_VEN 0x80 /* Enable hardware volume control */ - -#define OPL3SAx_WSSDMA 0x0b /* WSS DMA Counter (RW) (4 regs) */ - -#define OPL3SAx_WSSIRQSCAN 0x0f /* WSS Interrupt Scan out/in (R/W) */ -#define OPL3SAx_WSSIRQSCAN_SPI 0x01 -#define OPL3SAx_WSSIRQSCAN_SCI 0x02 -#define OPL3SAx_WSSIRQSCAN_STI 0x04 - -#define OPL3SAx_SBSTATE 0x10 /* SB compat Internal State (R/W) */ -#define OPL3SAx_SBSTATE_SBPDR 0x01 /* SB Power Down Request */ -#define OPL3SAx_SBSTATE_SE 0x02 /* Scan Enable */ -#define OPL3SAx_SBSTATE_SM 0x04 /* Scan Mode */ -#define OPL3SAx_SBSTATE_SS 0x08 /* Scan Select */ -#define OPL3SAx_SBSTATE_SBPDA 0x80 /* SB Power Down Acknowledge */ - -#define OPL3SAx_SBDATA 0x11 /* SB compat State Scan Data (R/W) */ - -#define OPL3SAx_DIGITALPOWER 0x12 /* Digital Partial Power Down (R/W) */ -#define OPL3SAx_DIGITALPOWER_PnP 0x01 -#define OPL3SAx_DIGITALPOWER_SB 0x02 -#define OPL3SAx_DIGITALPOWER_WSSP 0x04 -#define OPL3SAx_DIGITALPOWER_WSSR 0x08 -#define OPL3SAx_DIGITALPOWER_FM 0x10 -#define OPL3SAx_DIGITALPOWER_MCLK0 0x20 -#define OPL3SAx_DIGITALPOWER_MPU 0x40 -#define OPL3SAx_DIGITALPOWER_JOY 0x80 - -#define OPL3SAx_ANALOGPOWER 0x13 /* Analog Partial Power Down (R/W) */ -#define OPL3SAx_ANALOGPOWER_WIDE 0x01 -#define OPL3SAx_ANALOGPOWER_SBDAC 0x02 -#define OPL3SAx_ANALOGPOWER_DA 0x04 -#define OPL3SAx_ANALOGPOWER_AD 0x08 -#define OPL3SAx_ANALOGPOWER_FMDAC 0x10 - -#define OPL3SAx_WIDE 0x14 /* Enhanced control(WIDE) (R/W) */ -#define OPL3SAx_WIDE_WIDEL 0x07 /* Wide level on Left Channel */ -#define OPL3SAx_WIDE_WIDER 0x70 /* Wide level on Right Channel */ - -#define OPL3SAx_BASS 0x15 /* Enhanced control(BASS) (R/W) */ -#define OPL3SAx_BASS_BASSL 0x07 /* Bass level on Left Channel */ -#define OPL3SAx_BASS_BASSR 0x70 /* Bass level on Right Channel */ - -#define OPL3SAx_TREBLE 0x16 /* Enhanced control(TREBLE) (R/W) */ -#define OPL3SAx_TREBLE_TREBLEL 0x07 /* Treble level on Left Channel */ -#define OPL3SAx_TREBLE_TREBLER 0x70 /* Treble level on Right Channel */ - -#define OPL3SAx_HWVOL 0x17 /* HW Volume IRQ Configuration (R/W) */ -#define OPL3SAx_HWVOL_IRQA 0x10 /* HW Volume IRQ on IRQ-A */ -#define OPL3SAx_HWVOL_IRQB 0x20 /* HW Volume IRQ on IRQ-B */ - - Property changes on: head/sys/dev/pcm/isa/mss.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/ac97.c =================================================================== --- head/sys/dev/pcm/ac97.c (revision 53505) +++ head/sys/dev/pcm/ac97.c (nonexistent) @@ -1,335 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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 - -#define AC97_MUTE 0x8000 - -#define AC97_REG_RESET 0x00 -#define AC97_MIX_MASTER 0x02 -#define AC97_MIX_PHONES 0x04 -#define AC97_MIX_MONO 0x06 -#define AC97_MIX_TONE 0x08 -#define AC97_MIX_BEEP 0x0a -#define AC97_MIX_PHONE 0x0c -#define AC97_MIX_MIC 0x0e -#define AC97_MIX_LINE 0x10 -#define AC97_MIX_CD 0x12 -#define AC97_MIX_VIDEO 0x14 -#define AC97_MIX_AUX 0x16 -#define AC97_MIX_PCM 0x18 -#define AC97_REG_RECSEL 0x1a -#define AC97_MIX_RGAIN 0x1c -#define AC97_MIX_MGAIN 0x1e -#define AC97_REG_GEN 0x20 -#define AC97_REG_3D 0x22 -#define AC97_REG_POWER 0x26 -#define AC97_REG_ID1 0x7c -#define AC97_REG_ID2 0x7e - -struct ac97mixtable_entry { - int reg:8; - unsigned bits:4; - unsigned ofs:4; - unsigned stereo:1; - unsigned mute:1; - unsigned recidx:4; - unsigned mask:1; -}; - -struct ac97_info { - ac97_read *read; - ac97_write *write; - void *devinfo; - char id[4]; - char rev; - unsigned caps, se; - struct ac97mixtable_entry mix[32]; -}; - -struct ac97_codecid { - u_int32_t id; - char *name; -}; - -static const struct ac97mixtable_entry ac97mixtable_default[32] = { - [SOUND_MIXER_VOLUME] = { AC97_MIX_MASTER, 5, 0, 1, 1, 6, 0 }, - [SOUND_MIXER_BASS] = { AC97_MIX_TONE, 4, 8, 0, 0, 0, 1 }, - [SOUND_MIXER_TREBLE] = { AC97_MIX_TONE, 4, 0, 0, 0, 0, 1 }, - [SOUND_MIXER_PCM] = { AC97_MIX_PCM, 5, 0, 1, 1, 0, 0 }, - [SOUND_MIXER_SPEAKER] = { AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0 }, - [SOUND_MIXER_LINE] = { AC97_MIX_LINE, 5, 0, 1, 1, 5, 0 }, - [SOUND_MIXER_MIC] = { AC97_MIX_MIC, 5, 0, 0, 1, 1, 0 }, - [SOUND_MIXER_CD] = { AC97_MIX_CD, 5, 0, 1, 1, 2, 0 }, - [SOUND_MIXER_LINE1] = { AC97_MIX_AUX, 5, 0, 1, 1, 4, 0 }, - [SOUND_MIXER_VIDEO] = { AC97_MIX_VIDEO, 5, 0, 1, 1, 3, 0 }, - [SOUND_MIXER_RECLEV] = { -AC97_MIX_RGAIN, 4, 0, 1, 1, 0, 0 } -}; - -static const unsigned ac97mixdevs = - SOUND_MASK_VOLUME | - SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | - SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_LINE1 | - SOUND_MASK_VIDEO | SOUND_MASK_RECLEV; - -static const unsigned ac97recdevs = - SOUND_MASK_VOLUME | SOUND_MASK_LINE | SOUND_MASK_MIC | - SOUND_MASK_CD | SOUND_MASK_LINE1 | SOUND_MASK_VIDEO; - -static struct ac97_codecid ac97codecid[] = { - { 0x414B4D00, "Asahi Kasei AK4540" }, - { 0x43525900, "Cirrus Logic CS4297" }, - { 0x83847600, "SigmaTel STAC????" }, - { 0x83847604, "SigmaTel STAC9701/3/4/5" }, - { 0x83847605, "SigmaTel STAC9704" }, - { 0x83847608, "SigmaTel STAC9708" }, - { 0x83847609, "SigmaTel STAC9721" }, - { 0, NULL } -}; - -static char *ac97enhancement[] = { - "", - "Analog Devices Phat Stereo", - "Creative Stereo Enhancement", - "National Semi 3D Stereo Enhancement", - "Yamaha Ymersion", - "BBE 3D Stereo Enhancement", - "Crystal Semi 3D Stereo Enhancement", - "Qsound QXpander", - "Spatializer 3D Stereo Enhancement", - "SRS 3D Stereo Enhancement", - "Platform Tech 3D Stereo Enhancement", - "AKM 3D Audio", - "Aureal Stereo Enhancement", - "Aztech 3D Enhancement", - "Binaura 3D Audio Enhancement", - "ESS Technology Stereo Enhancement", - "Harman International VMAx", - "Nvidea 3D Stereo Enhancement", - "Philips Incredible Sound", - "Texas Instruments 3D Stereo Enhancement", - "VLSI Technology 3D Stereo Enhancement", - "TriTech 3D Stereo Enhancement", - "Realtek 3D Stereo Enhancement", - "Samsung 3D Stereo Enhancement", - "Wolfson Microelectronics 3D Enhancement", - "Delta Integration 3D Enhancement", - "SigmaTel 3D Enhancement", - "Reserved 27", - "Rockwell 3D Stereo Enhancement", - "Reserved 29", - "Reserved 30", - "Reserved 31" -}; - -static char *ac97feature[] = { - "mic channel", - "reserved", - "tone", - "simulated stereo", - "headphone", - "bass boost", - "18 bit DAC", - "20 bit DAC", - "18 bit ADC", - "20 bit ADC" -}; - -static int -ac97_setrecsrc(struct ac97_info *codec, int channel) -{ - struct ac97mixtable_entry *e = &codec->mix[channel]; - if (e->recidx > 0) { - int val = e->recidx - 1; - val |= val << 8; - codec->write(codec->devinfo, AC97_REG_RECSEL, val); - return 0; - } else return -1; -} - -static int -ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned right) -{ - struct ac97mixtable_entry *e = &codec->mix[channel]; - if (e->reg != 0) { - int max, val; - - if (!e->stereo) right = left; - if (e->reg > 0) { - left = 100 - left; - right = 100 - right; - } - - max = (1 << e->bits) - 1; - left = (left * max) / 100; - right = (right * max) / 100; - - val = (left << 8) | right; - - left = (left * 100) / max; - right = (right * 100) / max; - - if (e->reg > 0) { - left = 100 - left; - right = 100 - right; - } - - if (!e->stereo) { - val &= max; - val <<= e->ofs; - if (e->mask) { - int cur = codec->read(codec->devinfo, e->reg); - val |= cur & ~(max << e->ofs); - } - } - if (left == 0 && right == 0 && e->mute == 1) val = AC97_MUTE; - codec->write(codec->devinfo, abs(e->reg), val); - return left | (right << 8); - } else return -1; -} - -#if 0 -static int -ac97_getmixer(struct ac97_info *codec, int channel) -{ - struct ac97mixtable_entry *e = &codec->mix[channel]; - if (channel < SOUND_MIXER_NRDEVICES && e->reg != 0) { - int max, val, volume; - - max = (1 << e->bits) - 1; - val = codec->read(codec->devinfo, e->reg); - if (val == AC97_MUTE && e->mute == 1) volume = 0; - else { - if (e->stereo == 0) val >>= e->ofs; - val &= max; - volume = (val * 100) / max; - if (e->reg > 0) volume = 100 - volume; - } - return volume; - } else return -1; -} -#endif - -static unsigned -ac97_init(struct ac97_info *codec) -{ - unsigned i, j; - u_int32_t id; - - for (i = 0; i < 32; i++) codec->mix[i] = ac97mixtable_default[i]; - - codec->write(codec->devinfo, AC97_REG_POWER, 0); - codec->write(codec->devinfo, AC97_REG_RESET, 0); - DELAY(10000); - - i = codec->read(codec->devinfo, AC97_REG_RESET); - codec->caps = i & 0x03ff; - codec->se = (i & 0x7c00) >> 10; - - id = (codec->read(codec->devinfo, AC97_REG_ID1) << 16) | - codec->read(codec->devinfo, AC97_REG_ID2); - codec->rev = id & 0x000000ff; - - codec->write(codec->devinfo, AC97_MIX_MASTER, 0x20); - if ((codec->read(codec->devinfo, AC97_MIX_MASTER) & 0x20) == 0x20) - codec->mix[SOUND_MIXER_VOLUME].bits++; - codec->write(codec->devinfo, AC97_MIX_MASTER, 0x00); - - if (bootverbose) { - printf("ac97: codec id 0x%8x", id); - for (i = 0; ac97codecid[i].id; i++) { - if (ac97codecid[i].id == id) printf(" (%s)", ac97codecid[i].name); - } - printf("\nac97: codec features "); - for (i = j = 0; i < 10; i++) { - if (codec->caps & (1 << i)) { - printf("%s%s", j? ", " : "", ac97feature[i]); - j++; - } - } - printf("%s%d bit master volume", j? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits); - printf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]); - } - - if ((codec->read(codec->devinfo, AC97_REG_POWER) & 2) == 0) - printf("ac97: dac not ready\n"); - return 0; -} - -struct ac97_info * -ac97_create(void *devinfo, ac97_read *rd, ac97_write *wr) -{ - struct ac97_info *codec; - - codec = (struct ac97_info *)malloc(sizeof *codec, M_DEVBUF, M_NOWAIT); - if (codec != NULL) { - codec->read = rd; - codec->write = wr; - codec->devinfo = devinfo; - } - return codec; -} - -static int -ac97mix_init(snd_mixer *m) -{ - struct ac97_info *codec = mix_getdevinfo(m); - if (codec == NULL) return -1; - ac97_init(codec); - mix_setdevs(m, ac97mixdevs | ((codec->caps & 4)? SOUND_MASK_BASS | SOUND_MASK_TREBLE : 0)); - mix_setrecdevs(m, ac97recdevs); - return 0; -} - -static int -ac97mix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - struct ac97_info *codec = mix_getdevinfo(m); - if (codec == NULL) return -1; - return ac97_setmixer(codec, dev, left, right); -} - -static int -ac97mix_setrecsrc(snd_mixer *m, u_int32_t src) -{ - int i; - struct ac97_info *codec = mix_getdevinfo(m); - if (codec == NULL) return -1; - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - if ((src & (1 << i)) != 0) break; - return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1; -} - -snd_mixer ac97_mixer = { - "AC97 mixer", - ac97mix_init, - ac97mix_set, - ac97mix_setrecsrc, -}; - Property changes on: head/sys/dev/pcm/ac97.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/channel.h =================================================================== --- head/sys/dev/pcm/channel.h (revision 53505) +++ head/sys/dev/pcm/channel.h (nonexistent) @@ -1,81 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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$ - */ - -int chn_reinit(pcm_channel *c); -int chn_write(pcm_channel *c, struct uio *buf); -int chn_read(pcm_channel *c, struct uio *buf); -int chn_sync(pcm_channel *c, int threshold); -int chn_flush(pcm_channel *c); -int chn_poll(pcm_channel *c, int ev, struct proc *p); - -int chn_init(pcm_channel *c, void *devinfo, int dir); -int chn_setdir(pcm_channel *c, int dir); -int chn_reset(pcm_channel *c); -int chn_setvolume(pcm_channel *c, int left, int right); -int chn_setspeed(pcm_channel *c, int speed); -int chn_setformat(pcm_channel *c, u_int32_t fmt); -int chn_setblocksize(pcm_channel *c, int blksz); -int chn_trigger(pcm_channel *c, int go); -int chn_getptr(pcm_channel *c); -pcmchan_caps *chn_getcaps(pcm_channel *c); - -int chn_allocbuf(snd_dbuf *b, bus_dma_tag_t parent_dmat); -void chn_resetbuf(pcm_channel *c); -void chn_intr(pcm_channel *c); -void chn_dmaupdate(pcm_channel *c); -int chn_abort(pcm_channel *c); - -void buf_isadma(snd_dbuf *b, int go); -int buf_isadmaptr(snd_dbuf *b); -int chn_feedchain(pcm_channel *c); - -extern pcm_feeder feeder_root; - -#define PCMDIR_PLAY 1 -#define PCMDIR_REC -1 - -#define PCMTRIG_START 1 -#define PCMTRIG_STOP 0 -#define PCMTRIG_ABORT -1 - -#define CHN_F_READING 0x00000001 /* have a pending read */ -#define CHN_F_WRITING 0x00000002 /* have a pending write */ -#define CHN_F_CLOSING 0x00000004 /* a pending close */ -#define CHN_F_ABORTING 0x00000008 /* a pending abort */ -#define CHN_F_PENDING_IO (CHN_F_READING | CHN_F_WRITING) -#define CHN_F_RUNNING 0x00000010 /* dma is running */ -#define CHN_F_TRIGGERED 0x00000020 - -#define CHN_F_BUSY 0x00001000 /* has been opened */ -#define CHN_F_HAS_SIZE 0x00002000 /* user set block size */ -#define CHN_F_NBIO 0x00004000 /* do non-blocking i/o */ -#define CHN_F_INIT 0x00008000 /* changed parameters. need init */ -#define CHN_F_MAPPED 0x00010000 /* has been mmap()ed */ - - -#define CHN_F_RESET (CHN_F_BUSY) Property changes on: head/sys/dev/pcm/channel.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/dev/pcm/dsp.c =================================================================== --- head/sys/dev/pcm/dsp.c (revision 53505) +++ head/sys/dev/pcm/dsp.c (nonexistent) @@ -1,559 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * 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 -#include - -#include - -static int getchns(snddev_info *d, int chan, pcm_channel **rdch, pcm_channel **wrch); - -static pcm_channel * -allocchn(snddev_info *d, int direction) -{ - pcm_channel *chns = (direction == PCMDIR_PLAY)? d->play : d->rec; - int i, cnt = (direction == PCMDIR_PLAY)? d->playcount : d->reccount; - for (i = 0; i < cnt; i++) { - if (!(chns[i].flags & CHN_F_BUSY)) { - chns[i].flags |= CHN_F_BUSY; - return &chns[i]; - } - } - return NULL; -} - -static int -getchns(snddev_info *d, int chan, pcm_channel **rdch, pcm_channel **wrch) -{ - if ((d->flags & SD_F_PRIO_SET) == SD_F_PRIO_SET) - panic("read and write both prioritised"); - if (d->flags & SD_F_SIMPLEX) { - *rdch = (d->flags & SD_F_PRIO_RD)? d->arec[chan] : &d->fakechan; - *wrch = (d->flags & SD_F_PRIO_WR)? d->aplay[chan] : &d->fakechan; - } else { - *rdch = d->arec[chan]; - *wrch = d->aplay[chan]; - } - return 0; -} - -static void -setchns(snddev_info *d, int chan) -{ - if ((d->flags & SD_F_PRIO_SET) == SD_F_PRIO_SET) - panic("read and write both prioritised"); - d->flags |= SD_F_DIR_SET; - if (d->flags & SD_F_EVILSB16) { - if ((d->flags & SD_F_PRIO_RD) && (d->aplay[chan])) { - pcm_channel *tmp; - tmp = d->arec[chan]; - d->arec[chan] = d->aplay[chan]; - d->aplay[chan] = tmp; - } - if (d->aplay[chan]) chn_setdir(d->aplay[chan], PCMDIR_PLAY); - if (d->arec[chan]) chn_setdir(d->arec[chan], PCMDIR_REC); - } -} - -int -dsp_open(snddev_info *d, int chan, int oflags, int devtype) -{ - pcm_channel *rdch = NULL, *wrch = NULL; - u_int32_t fmt; - - if (chan >= d->chancount) return ENODEV; - if (d->aplay[chan] || d->arec[chan]) return EBUSY; - if (oflags & FREAD) { - rdch = allocchn(d, PCMDIR_REC); - if (!rdch) return EBUSY; - } - if (oflags & FWRITE) { - wrch = allocchn(d, PCMDIR_PLAY); - if (!wrch) { - if (rdch) rdch->flags &= ~CHN_F_BUSY; - return EBUSY; - } - } - d->aplay[chan] = wrch; - d->arec[chan] = rdch; - switch (devtype) { - case SND_DEV_DSP16: - fmt = AFMT_S16_LE; - break; - - case SND_DEV_DSP: - fmt = AFMT_U8; - break; - - case SND_DEV_AUDIO: - fmt = AFMT_MU_LAW; - break; - - case SND_DEV_NORESET: - fmt = 0; - break; - - default: - return ENXIO; - } - - if (rdch) { - chn_reset(rdch); - if (oflags & O_NONBLOCK) rdch->flags |= CHN_F_NBIO; - if (fmt) { - rdch->volume = (100 << 8) | 100; - rdch->format = fmt; - rdch->speed = DSP_DEFAULT_SPEED; - rdch->blocksize = 2048; - } - } - if (wrch) { - chn_reset(wrch); - if (oflags & O_NONBLOCK) wrch->flags |= CHN_F_NBIO; - if (fmt) { - wrch->volume = (100 << 8) | 100; - wrch->format = fmt; - wrch->speed = DSP_DEFAULT_SPEED; - wrch->blocksize = 2048; - } - } - return 0; -} - -int -dsp_close(snddev_info *d, int chan, int devtype) -{ - pcm_channel *rdch, *wrch; - - d->flags &= ~SD_F_TRANSIENT; - rdch = d->arec[chan]; - wrch = d->aplay[chan]; - - if (rdch) { - chn_abort(rdch); - rdch->flags &= ~(CHN_F_BUSY | CHN_F_RUNNING | CHN_F_MAPPED); - } - if (wrch) wrch->flags &= ~(CHN_F_BUSY | CHN_F_RUNNING | CHN_F_MAPPED); - d->aplay[chan] = NULL; - d->arec[chan] = NULL; - return 0; -} - -int -dsp_read(snddev_info *d, int chan, struct uio *buf, int flag) -{ - pcm_channel *rdch, *wrch; - - if (!(d->flags & SD_F_PRIO_SET)) d->flags |= SD_F_PRIO_RD; - if (!(d->flags & SD_F_DIR_SET)) setchns(d, chan); - getchns(d, chan, &rdch, &wrch); - if (!rdch || !(rdch->flags & CHN_F_BUSY)) - panic("dsp_read: non%s channel", rdch? "busy" : "existant"); - if (rdch->flags & CHN_F_MAPPED) return EINVAL; - if (!(rdch->flags & CHN_F_RUNNING)) { - rdch->flags |= CHN_F_RUNNING; - chn_reinit(rdch); - } - return chn_read(rdch, buf); -} - -int -dsp_write(snddev_info *d, int chan, struct uio *buf, int flag) -{ - pcm_channel *rdch, *wrch; - - if (!(d->flags & SD_F_PRIO_SET)) d->flags |= SD_F_PRIO_WR; - if (!(d->flags & SD_F_DIR_SET)) setchns(d, chan); - getchns(d, chan, &rdch, &wrch); - if (!wrch || !(wrch->flags & CHN_F_BUSY)) - panic("dsp_write: non%s channel", wrch? "busy" : "existant"); - if (wrch->flags & CHN_F_MAPPED) return EINVAL; - if (!(wrch->flags & CHN_F_RUNNING)) { - wrch->flags |= CHN_F_RUNNING; - chn_reinit(wrch); - } - return chn_write(wrch, buf); -} - -int -dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) -{ - int ret = 0, *arg_i = (int *)arg; - u_long s; - pcm_channel *wrch = NULL, *rdch = NULL; - - rdch = d->arec[chan]; - wrch = d->aplay[chan]; - - /* - * all routines are called with int. blocked. Make sure that - * ints are re-enabled when calling slow or blocking functions! - */ - s = spltty(); - switch(cmd) { - - /* - * we start with the new ioctl interface. - */ - case AIONWRITE: /* how many bytes can write ? */ - if (wrch && wrch->buffer.dl) chn_dmaupdate(wrch); - *arg_i = wrch? wrch->buffer.fl : 0; - break; - - case AIOSSIZE: /* set the current blocksize */ - { - struct snd_size *p = (struct snd_size *)arg; - splx(s); - if (wrch) chn_setblocksize(wrch, p->play_size); - if (rdch) chn_setblocksize(rdch, p->rec_size); - } - /* FALLTHROUGH */ - case AIOGSIZE: /* get the current blocksize */ - { - struct snd_size *p = (struct snd_size *)arg; - if (wrch) p->play_size = wrch->blocksize; - if (rdch) p->rec_size = rdch->blocksize; - } - break; - - case AIOSFMT: - { - snd_chan_param *p = (snd_chan_param *)arg; - splx(s); - if (wrch) { - chn_setformat(wrch, p->play_format); - chn_setspeed(wrch, p->play_rate); - } - if (rdch) { - chn_setformat(rdch, p->rec_format); - chn_setspeed(rdch, p->rec_rate); - } - } - /* FALLTHROUGH */ - - case AIOGFMT: - { - snd_chan_param *p = (snd_chan_param *)arg; - p->play_rate = wrch? wrch->speed : 0; - p->rec_rate = rdch? rdch->speed : 0; - p->play_format = wrch? wrch->format : 0; - p->rec_format = rdch? rdch->format : 0; - } - break; - - case AIOGCAP: /* get capabilities */ - { - snd_capabilities *p = (snd_capabilities *)arg; - pcmchan_caps *pcaps = NULL, *rcaps = NULL; - if (rdch) rcaps = chn_getcaps(rdch); - if (wrch) pcaps = chn_getcaps(wrch); - p->rate_min = max(rcaps? rcaps->minspeed : 0, - pcaps? pcaps->minspeed : 0); - p->rate_max = min(rcaps? rcaps->maxspeed : 1000000, - pcaps? pcaps->maxspeed : 1000000); - p->bufsize = min(rdch? rdch->buffer.bufsize : 1000000, - wrch? wrch->buffer.bufsize : 1000000); - /* XXX bad on sb16 */ - p->formats = (rcaps? rcaps->formats : 0xffffffff) & - (pcaps? pcaps->formats : 0xffffffff); - p->mixers = 1; /* default: one mixer */ - p->inputs = d->mixer.devs; - p->left = p->right = 100; - } - break; - - case AIOSTOP: - if (*arg_i == AIOSYNC_PLAY && wrch) *arg_i = chn_abort(wrch); - else if (*arg_i == AIOSYNC_CAPTURE && rdch) *arg_i = chn_abort(rdch); - else { - splx(s); - printf("AIOSTOP: bad channel 0x%x\n", *arg_i); - *arg_i = 0; - } - break; - - case AIOSYNC: - printf("AIOSYNC chan 0x%03lx pos %lu unimplemented\n", - ((snd_sync_parm *)arg)->chan, ((snd_sync_parm *)arg)->pos); - break; - /* - * here follow the standard ioctls (filio.h etc.) - */ - case FIONREAD: /* get # bytes to read */ - if (rdch && rdch->buffer.dl) chn_dmaupdate(rdch); - *arg_i = rdch? rdch->buffer.rl : 0; - break; - - case FIOASYNC: /*set/clear async i/o */ - DEB( printf("FIOASYNC\n") ; ) - break; - - case SNDCTL_DSP_NONBLOCK: - case FIONBIO: /* set/clear non-blocking i/o */ - if (rdch) rdch->flags &= ~CHN_F_NBIO; - if (wrch) wrch->flags &= ~CHN_F_NBIO; - if (*arg_i) { - if (rdch) rdch->flags |= CHN_F_NBIO; - if (wrch) wrch->flags |= CHN_F_NBIO; - } - break; - - /* - * Finally, here is the linux-compatible ioctl interface - */ -#define THE_REAL_SNDCTL_DSP_GETBLKSIZE _IOWR('P', 4, int) - case THE_REAL_SNDCTL_DSP_GETBLKSIZE: - case SNDCTL_DSP_GETBLKSIZE: - *arg_i = wrch? wrch->blocksize : 0; /* XXX rdch? */ - break ; - - case SNDCTL_DSP_SETBLKSIZE: - splx(s); - if (wrch) chn_setblocksize(wrch, *arg_i); - if (rdch) chn_setblocksize(rdch, *arg_i); - break; - - case SNDCTL_DSP_RESET: - DEB(printf("dsp reset\n")); - if (wrch) chn_abort(wrch); - if (rdch) chn_abort(rdch); - break; - - case SNDCTL_DSP_SYNC: - DEB(printf("dsp sync\n")); - splx(s); - if (wrch) chn_sync(wrch, wrch->buffer.bufsize - 4); - break; - - case SNDCTL_DSP_SPEED: - splx(s); - if (wrch) chn_setspeed(wrch, *arg_i); - if (rdch) chn_setspeed(rdch, *arg_i); - /* fallthru */ - - case SOUND_PCM_READ_RATE: - *arg_i = wrch? wrch->speed : rdch->speed; - break; - - case SNDCTL_DSP_STEREO: - splx(s); - if (wrch) chn_setformat(wrch, (wrch->format & ~AFMT_STEREO) | - ((*arg_i)? AFMT_STEREO : 0)); - if (rdch) chn_setformat(rdch, (rdch->format & ~AFMT_STEREO) | - ((*arg_i)? AFMT_STEREO : 0)); - *arg_i = ((wrch? wrch->format : rdch->format) & AFMT_STEREO)? 1 : 0; - break; - - case SOUND_PCM_WRITE_CHANNELS: - splx(s); - if (wrch) chn_setformat(wrch, (wrch->format & ~AFMT_STEREO) | - ((*arg_i == 2)? AFMT_STEREO : 0)); - if (rdch) chn_setformat(rdch, (rdch->format & ~AFMT_STEREO) | - ((*arg_i == 2)? AFMT_STEREO : 0)); - /* fallthru */ - - case SOUND_PCM_READ_CHANNELS: - *arg_i = ((wrch? wrch->format : rdch->format) & AFMT_STEREO)? 2 : 1; - break; - - case SNDCTL_DSP_GETFMTS: /* returns a mask of supported fmts */ - *arg_i = wrch? chn_getcaps(wrch)->formats : chn_getcaps(rdch)->formats; - break ; - - case SNDCTL_DSP_SETFMT: /* sets _one_ format */ - splx(s); - if (wrch) chn_setformat(wrch, (*arg_i) | (wrch->format & AFMT_STEREO)); - if (rdch) chn_setformat(rdch, (*arg_i) | (rdch->format & AFMT_STEREO)); - *arg_i = (wrch? wrch->format: rdch->format) & ~AFMT_STEREO; - break; - - case SNDCTL_DSP_SUBDIVIDE: - /* XXX watch out, this is RW! */ - DEB(printf("SNDCTL_DSP_SUBDIVIDE unimplemented\n");) - break; - - case SNDCTL_DSP_SETFRAGMENT: - /* XXX watch out, this is RW! */ - DEB(printf("SNDCTL_DSP_SETFRAGMENT 0x%08x\n", *(int *)arg)); - { - int bytes = 1 << min(*arg_i & 0xffff, 16); - int count = (*arg_i >> 16) & 0xffff; - pcm_channel *c = wrch? wrch : rdch; - splx(s); - if (rdch) chn_setblocksize(rdch, bytes); - if (wrch) chn_setblocksize(wrch, bytes); - - /* eg: 4dwave can only interrupt at buffer midpoint, so - * it will force blocksize == bufsize/2 - */ - count = c->buffer.bufsize / c->blocksize; - bytes = ffs(c->blocksize) - 1; - *arg_i = (count << 16) | bytes; - } - break; - - case SNDCTL_DSP_GETISPACE: - /* return space available in the input queue */ - { - audio_buf_info *a = (audio_buf_info *)arg; - if (rdch) { - snd_dbuf *b = &rdch->buffer; - if (b->dl) chn_dmaupdate(rdch); - a->bytes = b->fl; - a->fragments = 1; - a->fragstotal = b->bufsize / rdch->blocksize; - a->fragsize = rdch->blocksize; - } - } - break; - - case SNDCTL_DSP_GETOSPACE: - /* return space available in the output queue */ - { - audio_buf_info *a = (audio_buf_info *)arg; - if (wrch) { - snd_dbuf *b = &wrch->buffer; - if (b->dl) chn_dmaupdate(wrch); - a->bytes = b->fl; - a->fragments = 1; - a->fragstotal = b->bufsize / wrch->blocksize; - a->fragsize = wrch->blocksize; - } - } - break; - - case SNDCTL_DSP_GETIPTR: - { - count_info *a = (count_info *)arg; - if (rdch) { - snd_dbuf *b = &rdch->buffer; - if (b->dl) chn_dmaupdate(rdch); - a->bytes = b->total; - a->blocks = (b->total - b->prev_total) / rdch->blocksize; - a->ptr = b->fp; - b->prev_total += a->blocks * rdch->blocksize; - } else ret = EINVAL; - } - break; - - case SNDCTL_DSP_GETOPTR: - { - count_info *a = (count_info *)arg; - if (wrch) { - snd_dbuf *b = &wrch->buffer; - if (b->dl) chn_dmaupdate(wrch); - a->bytes = b->total; - a->blocks = (b->total - b->prev_total) / wrch->blocksize; - a->ptr = b->rp; - b->prev_total += a->blocks * wrch->blocksize; - } else ret = EINVAL; - } - break; - - case SNDCTL_DSP_GETCAPS: - *arg_i = DSP_CAP_REALTIME | DSP_CAP_MMAP | DSP_CAP_TRIGGER; - if (rdch && wrch && !(d->flags & SD_F_SIMPLEX)) - *arg_i |= DSP_CAP_DUPLEX; - break; - - case SOUND_PCM_READ_BITS: - *arg_i = ((wrch? wrch->format : rdch->format) & AFMT_16BIT)? 16 : 8; - break; - - case SNDCTL_DSP_SETTRIGGER: - if (rdch) { - rdch->flags &= ~CHN_F_TRIGGERED; - if (*arg_i & PCM_ENABLE_INPUT) - rdch->flags |= CHN_F_TRIGGERED; - chn_intr(rdch); - } - if (wrch) { - wrch->flags &= ~CHN_F_TRIGGERED; - if (*arg_i & PCM_ENABLE_OUTPUT) - wrch->flags |= CHN_F_TRIGGERED; - chn_intr(wrch); - } - break; - - case SNDCTL_DSP_GETTRIGGER: - *arg_i = 0; - if (wrch && wrch->flags & CHN_F_TRIGGERED) - *arg_i |= PCM_ENABLE_OUTPUT; - if (rdch && rdch->flags & CHN_F_TRIGGERED) - *arg_i |= PCM_ENABLE_INPUT; - break; - - case SNDCTL_DSP_MAPINBUF: - case SNDCTL_DSP_MAPOUTBUF: - case SNDCTL_DSP_SETSYNCRO: - /* undocumented */ - - case SNDCTL_DSP_POST: - case SOUND_PCM_WRITE_FILTER: - case SOUND_PCM_READ_FILTER: - /* dunno what these do, don't sound important */ - default: - DEB(printf("default ioctl snd%d fn 0x%08x fail\n", unit, cmd)); - ret = EINVAL; - break; - } - splx(s); - return ret; -} - -int -dsp_poll(snddev_info *d, int chan, int events, struct proc *p) -{ - int ret = 0, e; - pcm_channel *wrch = NULL, *rdch = NULL; - - getchns(d, chan, &rdch, &wrch); - e = events & (POLLOUT | POLLWRNORM); - if (wrch && e) ret |= chn_poll(wrch, e, p); - e = events & (POLLIN | POLLRDNORM); - if (rdch && e) ret |= chn_poll(rdch, e, p); - return ret; -} - -int -dsp_mmap(snddev_info *d, int chan, vm_offset_t offset, int nprot) -{ - pcm_channel *wrch = NULL, *rdch = NULL, *c = NULL; - - getchns(d, chan, &rdch, &wrch); - /* XXX this is broken by line 204 of vm/device_pager.c, so force write buffer */ - if (1 || (wrch && (nprot & PROT_WRITE))) c = wrch; - else if (rdch && (nprot & PROT_READ)) c = rdch; - if (c) { - c->flags |= CHN_F_MAPPED; - return atop(vtophys(c->buffer.buf + offset)); - } - return -1; -} - Property changes on: head/sys/dev/pcm/dsp.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property