28#ifdef HAVE_KERNEL_OPTION_HEADERS
44#define SOLO_DEFAULT_BUFSZ 16384
45#define ABS(x) (((x) < 0)? -(x) : (x))
48#define ESS18XX_DUPLEX 1
51#define ESS18XX_NEWSPEED
106#define ess_lock(_ess) snd_mtxlock((_ess)->lock)
107#define ess_unlock(_ess) snd_mtxunlock((_ess)->lock)
108#define ess_lock_assert(_ess) snd_mtxassert((_ess)->lock)
147 bus_space_tag_t st = rman_get_bustag(port);
148 bus_space_handle_t sh = rman_get_bushandle(port);
152 return bus_space_read_1(st, sh,
regno);
154 return bus_space_read_2(st, sh,
regno);
156 return bus_space_read_4(st, sh,
regno);
165 bus_space_tag_t st = rman_get_bustag(port);
166 bus_space_handle_t sh = rman_get_bushandle(port);
204 for (i = 0; i < 1000; i++) {
209 if (i > 10) DELAY((i > 100)? 1000 : 10);
211 printf(
"ess_dspwr(0x%02x) timed out.\n",
val);
218 DEB(printf(
"ess_cmd: %x\n",
val));
225 DEB(printf(
"ess_cmd1: %x, %x\n", cmd,
val));
234 DEB(printf(
"ess_setmixer: reg=%x, val=%x\n", port,
value);)
259 for (i = 1000; i > 0; i--) {
260 if (
ess_rd(sc, 0xc) & 0x40)
283 DEB(printf(
"ess_reset_dsp\n"));
288 DEB(printf(
"ess_reset_dsp failed\n"));
302 int src, pirq = 0, rirq = 0;
308 if (
ess_rd(sc, 0x0c) & 0x01)
317 pirq = (
src & sc->pch.hwch)? 1 : 0;
325 printf(
"solo: IRQ neither playback nor rec!\n");
328 DEB(printf(
"ess_intr: pirq:%d rirq:%d\n",pirq,rirq));
331 if (sc->pch.stopping) {
333 sc->pch.stopping = 0;
334 if (sc->pch.hwch == 1)
373 speed = (795500 + t / 2) / t;
374 t = (256 - t) | 0x80;
377 speed = (397700 + t / 2) / t;
381 return t & 0x000000ff;
387 int speed, s0, s1, use0;
393 t0 = 128 - (793800 /
speed);
394 s0 = 793800 / (128 - t0);
396 t1 = 128 - (768000 /
speed);
397 s1 = 768000 / (128 - t1);
402 *
spd = use0? s0 : s1;
403 return use0? t0 : t1;
413 cutoff = (
spd * 9 * 82) / 20;
414 return (256 - (7160000 / cutoff));
424 u_int8_t spdval, fmtval;
426 DEB(printf(
"ess_setupch\n"));
439 ess_write(sc, 0xb8, 0x04 | (play? 0x00 : 0x0a));
458 ess_write(sc, 0xb7, 0x91 | (unsign? 0x00 : 0x20) |
465 }
else if (ch == 2) {
475 fmtval = b16 | (
stereo << 1) | ((!unsign) << 2);
492 DEB(printf(
"ess_start\n"););
513 DEB(printf(
"ess_stop\n"));
519 DEB(printf(
"done with stop\n"));
531 DEB(printf(
"esschan_init\n"));
585 DEB(printf(
"esschan_trigger: %d\n",
go));
648 mix_setdevs(
m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE |
649 SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME |
661 int preg = 0, rreg = 0, l,
r;
663 l = (
left * 15) / 100;
666 case SOUND_MIXER_SYNTH:
671 case SOUND_MIXER_PCM:
676 case SOUND_MIXER_LINE:
681 case SOUND_MIXER_MIC:
686 case SOUND_MIXER_LINE1:
696 case SOUND_MIXER_VOLUME:
701 left = (l == 64)? 0 : (l * 100) / 63;
702 right = (
r == 64)? 0 : (
r * 100) / 63;
711 left = (l * 100) / 15;
728 case SOUND_MASK_LINE:
732 case SOUND_MASK_IMIX:
739 src = SOUND_MASK_MIC;
761 KASSERT(ch == 1 || ch == 2, (
"bad ch"));
762 sc->
dmasz[ch - 1] = cnt;
771 }
else if (ch == 2) {
782 int p = 0, i = 0, j = 0;
784 KASSERT(ch == 1 || ch == 2, (
"bad ch"));
798 printf(
"DMA count reg bogus: %04x & %04x\n",
802 }
while ((p > sc->
dmasz[ch - 1] || i < p || (p - i) > 0x8) && j++ < 1000);
807 return sc->
dmasz[ch - 1] - p;
813 KASSERT(ch == 1 || ch == 2, (
"bad ch"));
826 bus_teardown_intr(
dev, sc->
irq, sc->
ih);
827 bus_release_resource(
dev, SYS_RES_IRQ, 0, sc->
irq);
831 bus_release_resource(
dev, SYS_RES_IOPORT,
PCIR_BAR(0), sc->
io);
836 bus_release_resource(
dev, SYS_RES_IOPORT,
PCIR_BAR(1), sc->
sb);
841 bus_release_resource(
dev, SYS_RES_IOPORT,
PCIR_BAR(2), sc->
vc);
851 bus_release_resource(
dev, SYS_RES_IOPORT,
PCIR_BAR(4), sc->
gp);
874 sc->
io = bus_alloc_resource_any(
dev, SYS_RES_IOPORT, &
rid, RF_ACTIVE);
877 sc->
sb = bus_alloc_resource_any(
dev, SYS_RES_IOPORT, &
rid, RF_ACTIVE);
880 sc->
vc = bus_alloc_resource_any(
dev, SYS_RES_IOPORT, &
rid, RF_ACTIVE);
883 sc->
mpu = bus_alloc_resource_any(
dev, SYS_RES_IOPORT, &
rid, RF_ACTIVE);
886 sc->
gp = bus_alloc_resource_any(
dev, SYS_RES_IOPORT, &
rid, RF_ACTIVE);
889 sc->
irq = bus_alloc_resource_any(
dev, SYS_RES_IRQ, &
rid,
890 RF_ACTIVE | RF_SHAREABLE);
894 return (sc->
irq && sc->
io && sc->
sb && sc->
vc &&
895 sc->
mpu && sc->
gp && sc->
lock)? 0 : ENXIO;
904 subdev = (pci_get_subdevice(
dev) << 16) | pci_get_subvendor(
dev);
905 switch (pci_get_devid(
dev)) {
907 if (subdev == 0x8888125d)
909 else if (subdev == 0x1818125d)
912 s =
"ESS Solo-1 (unknown vendor)";
917 device_set_desc(
dev, s);
918 return s ? BUS_PROBE_DEFAULT : ENXIO;
921#define ESS_PCI_LEGACYCONTROL 0x40
922#define ESS_PCI_CONFIG 0x50
923#define ESS_PCI_DDMACONTROL 0x60
938 ddma = rman_get_start(sc->
vc) | 1;
969 sc = malloc(
sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
970 pci_enable_busmaster(
dev);
977 ddma = rman_get_start(sc->
vc) | 1;
989#ifdef ESS18XX_NEWSPEED
995 device_printf(
dev,
"unable to map interrupt\n");
1003 if (bus_dma_tag_create(bus_get_dma_tag(
dev), 65536, 0,
1005 if (bus_dma_tag_create(bus_get_dma_tag(
dev), 2, 0,
1006 BUS_SPACE_MAXADDR_24BIT,
1014 device_printf(dev,
"unable to create dma tag\n");
1028 rman_get_start(sc->
io), rman_get_start(sc->
sb), rman_get_start(sc->
vc),
int sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, int dmaflags, unsigned int size)
bus_addr_t sndbuf_getbufaddr(struct snd_dbuf *buf)
unsigned int sndbuf_getsize(struct snd_dbuf *b)
void chn_intr(struct pcm_channel *c)
#define PCMTRIG_COMMON(x)
struct pcmchan_matrix * m
static int mixer_setrecsrc(struct snd_mixer *mixer, u_int32_t src)
int mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
static int mixer_set(struct snd_mixer *m, u_int dev, u_int32_t muted, u_int lev)
void mix_setdevs(struct snd_mixer *m, u_int32_t v)
int mixer_reinit(device_t dev)
void * mix_getdevinfo(struct snd_mixer *m)
void mix_setrecdevs(struct snd_mixer *m, u_int32_t v)
Record mask of available recording devices.
static int ess_resume(device_t dev)
static int ess_suspend(device_t dev)
static kobj_method_t esschan_methods[]
static int ess_attach(device_t dev)
static void * esschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
static int essmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
static int ess_reset_dsp(struct ess_info *sc)
static int ess_start(struct ess_chinfo *ch)
static int ess_probe(device_t dev)
static struct pcmchan_caps * esschan_getcaps(kobj_t obj, void *data)
static u_int8_t ess_calcspeed9(int *spd)
static int ess_dmasetup(struct ess_info *sc, int ch, u_int32_t base, u_int16_t cnt, int dir)
static int ess_detach(device_t dev)
static int ess_getmixer(struct ess_info *sc, u_int port)
static int ess_stop(struct ess_chinfo *ch)
static void ess_intr(void *arg)
static int esschan_setformat(kobj_t obj, void *data, u_int32_t format)
MODULE_DEPEND(snd_solo, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER)
static int ess_write(struct ess_info *sc, u_char reg, int val)
static u_int32_t essmix_setrecsrc(struct snd_mixer *m, u_int32_t src)
static void ess_release_resources(struct ess_info *sc, device_t dev)
static u_int32_t esschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
static int ess_dspwr(struct ess_info *sc, u_char val)
static u_int8_t ess_calcfilter(int spd)
static device_method_t ess_methods[]
static int ess_read(struct ess_info *sc, u_char reg)
static int ess_dmapos(struct ess_info *sc, int ch)
static int esschan_trigger(kobj_t obj, void *data, int go)
SND_DECLARE_FILE("$FreeBSD$")
MODULE_VERSION(snd_solo, 1)
static int ess_cmd(struct ess_info *sc, u_char val)
static kobj_method_t solomixer_methods[]
static int ess_get_byte(struct ess_info *sc)
static u_int32_t esschan_setspeed(kobj_t obj, void *data, u_int32_t speed)
static u_int32_t esschan_getptr(kobj_t obj, void *data)
static int ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len)
static void port_wr(struct resource *port, int regno, u_int32_t data, int size)
#define ESS_PCI_LEGACYCONTROL
static struct pcmchan_caps ess_reccaps
static int ess_cmd1(struct ess_info *sc, u_char cmd, int val)
static int ess_rd(struct ess_info *sc, int reg)
static driver_t ess_driver
static int ess_dmatrigger(struct ess_info *sc, int ch, int go)
static int ess_dspready(struct ess_info *sc)
static u_int32_t ess_playfmt[]
static int essmix_init(struct snd_mixer *m)
static u_int8_t ess_calcspeed8(int *spd)
static u_int32_t ess_recfmt[]
#define SOLO_DEFAULT_BUFSZ
static struct pcmchan_caps ess_playcaps
static int ess_alloc_resources(struct ess_info *sc, device_t dev)
static void ess_wr(struct ess_info *sc, int reg, u_int8_t val)
DRIVER_MODULE(snd_solo, pci, ess_driver, pcm_devclass, 0, 0)
static int port_rd(struct resource *port, int regno, int size)
static void ess_setmixer(struct ess_info *sc, u_int port, u_int value)
#define ESS_PCI_DDMACONTROL
void * snd_mtxcreate(const char *desc, const char *type)
void pcm_setflags(device_t dev, uint32_t val)
void * pcm_getdevinfo(device_t dev)
uint32_t pcm_getflags(device_t dev)
int pcm_setstatus(device_t dev, char *str)
void snd_mtxfree(void *m)
int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo)
int pcm_unregister(device_t dev)
int pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
int snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand, void *param, void **cookiep)
unsigned int pcm_getbuffersize(device_t dev, unsigned int minbufsz, unsigned int deflt, unsigned int maxbufsz)
#define SND_FORMAT(f, c, e)
struct pcm_channel * channel
bus_dma_tag_t parent_dmat
struct ess_chinfo pch rch