summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2001-10-08 06:10:39 +0000
committercg <cg@FreeBSD.org>2001-10-08 06:10:39 +0000
commit046dce9528aabc36378f72b9f18b64af46feda8d (patch)
tree4353ac98a09048841d28ca6f1d001bb601ac6920
parent52fbddb20aba8a6a7e39a4dd5be1afe05d01d696 (diff)
downloadFreeBSD-src-046dce9528aabc36378f72b9f18b64af46feda8d.zip
FreeBSD-src-046dce9528aabc36378f72b9f18b64af46feda8d.tar.gz
use pcm_getbuffersize()
only creat a mic recording channel if the codec supports it
-rw-r--r--sys/dev/sound/pci/emu10k1.c192
1 files changed, 110 insertions, 82 deletions
diff --git a/sys/dev/sound/pci/emu10k1.c b/sys/dev/sound/pci/emu10k1.c
index 583deac..e79316c 100644
--- a/sys/dev/sound/pci/emu10k1.c
+++ b/sys/dev/sound/pci/emu10k1.c
@@ -37,7 +37,8 @@ SND_DECLARE_FILE("$FreeBSD$");
/* -------------------------------------------------------------------- */
#define EMU10K1_PCI_ID 0x00021102
-#define EMU_BUFFSIZE 4096
+#define EMU10K2_PCI_ID 0x00041102
+#define EMU_DEFAULT_BUFSZ 4096
#define EMU_CHANS 4
#undef EMUDEBUG
@@ -94,10 +95,10 @@ struct sc_info {
bus_dma_tag_t parent_dmat;
struct resource *reg, *irq;
- int regtype, regid, irqid;
void *ih;
void *lock;
+ unsigned int bufsz;
int timer, timerinterval;
int pnum, rnum;
struct emu_mem mem;
@@ -280,16 +281,20 @@ emu_settimer(struct sc_info *sc)
rate = 0;
for (i = 0; i < EMU_CHANS; i++) {
pch = &sc->pch[i];
- tmp = (pch->spd * sndbuf_getbps(pch->buffer)) / pch->blksz;
- if (tmp > rate)
- rate = tmp;
+ if (pch->buffer) {
+ tmp = (pch->spd * sndbuf_getbps(pch->buffer)) / pch->blksz;
+ if (tmp > rate)
+ rate = tmp;
+ }
}
for (i = 0; i < 3; i++) {
rch = &sc->rch[i];
- tmp = (rch->spd * sndbuf_getbps(rch->buffer)) / rch->blksz;
- if (tmp > rate)
- rate = tmp;
+ if (rch->buffer) {
+ tmp = (rch->spd * sndbuf_getbps(rch->buffer)) / rch->blksz;
+ if (tmp > rate)
+ rate = tmp;
+ }
}
RANGE(rate, 48, 9600);
sc->timerinterval = 48000 / rate;
@@ -625,13 +630,13 @@ emupchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel
ch->buffer = b;
ch->parent = sc;
ch->channel = c;
- ch->blksz = EMU_BUFFSIZE / 2;
+ ch->blksz = sc->bufsz / 2;
ch->fmt = AFMT_U8;
ch->spd = 8000;
snd_mtxlock(sc->lock);
ch->master = emu_valloc(sc);
ch->slave = emu_valloc(sc);
- r = (emu_vinit(sc, ch->master, ch->slave, EMU_BUFFSIZE, ch->buffer))? NULL : ch;
+ r = (emu_vinit(sc, ch->master, ch->slave, sc->bufsz, ch->buffer))? NULL : ch;
snd_mtxunlock(sc->lock);
return r;
@@ -760,7 +765,7 @@ emurchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel
ch->buffer = b;
ch->parent = sc;
ch->channel = c;
- ch->blksz = EMU_BUFFSIZE / 2;
+ ch->blksz = sc->bufsz / 2;
ch->fmt = AFMT_U8;
ch->spd = 8000;
ch->num = sc->rnum;
@@ -774,23 +779,23 @@ emurchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel
break;
case 1:
- ch->idxreg = MICIDX;
- ch->basereg = MICBA;
- ch->sizereg = MICBS;
- ch->setupreg = 0;
- ch->irqmask = INTE_MICBUFENABLE;
- break;
-
- case 2:
ch->idxreg = FXIDX;
ch->basereg = FXBA;
ch->sizereg = FXBS;
ch->setupreg = FXWC;
ch->irqmask = INTE_EFXBUFENABLE;
break;
+
+ case 2:
+ ch->idxreg = MICIDX;
+ ch->basereg = MICBA;
+ ch->sizereg = MICBS;
+ ch->setupreg = 0;
+ ch->irqmask = INTE_MICBUFENABLE;
+ break;
}
sc->rnum++;
- if (sndbuf_alloc(ch->buffer, sc->parent_dmat, EMU_BUFFSIZE) == -1)
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) == -1)
return NULL;
else {
snd_mtxlock(sc->lock);
@@ -818,9 +823,9 @@ emurchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
if (ch->num == 0)
speed = adcspeed[emu_recval(speed)];
if (ch->num == 1)
- speed = 8000;
- if (ch->num == 2)
speed = 48000;
+ if (ch->num == 2)
+ speed = 8000;
ch->spd = speed;
return ch->spd;
}
@@ -847,18 +852,44 @@ emurchan_trigger(kobj_t obj, void *data, int go)
{
struct sc_rchinfo *ch = data;
struct sc_info *sc = ch->parent;
- u_int32_t val;
+ u_int32_t val, sz;
+
+ switch(sc->bufsz) {
+ case 4096:
+ sz = ADCBS_BUFSIZE_4096;
+ break;
+
+ case 8192:
+ sz = ADCBS_BUFSIZE_8192;
+ break;
+
+ case 16384:
+ sz = ADCBS_BUFSIZE_16384;
+ break;
+
+ case 32768:
+ sz = ADCBS_BUFSIZE_32768;
+ break;
+
+ case 65536:
+ sz = ADCBS_BUFSIZE_65536;
+ break;
+
+ default:
+ sz = ADCBS_BUFSIZE_4096;
+ }
snd_mtxlock(sc->lock);
switch(go) {
case PCMTRIG_START:
ch->run = 1;
- emu_wrptr(sc, 0, ch->sizereg, ADCBS_BUFSIZE_4096);
+ emu_wrptr(sc, 0, ch->sizereg, sz);
if (ch->num == 0) {
val = ADCCR_LCHANENABLE;
if (ch->fmt & AFMT_STEREO)
val |= ADCCR_RCHANENABLE;
val |= emu_recval(ch->spd);
+ emu_wrptr(sc, 0, ch->setupreg, 0);
emu_wrptr(sc, 0, ch->setupreg, val);
}
val = emu_rd(sc, INTE, 4);
@@ -909,6 +940,19 @@ emurchan_getcaps(kobj_t obj, void *data)
return &emu_reccaps[ch->num];
}
+static kobj_method_t emurchan_methods[] = {
+ KOBJMETHOD(channel_init, emurchan_init),
+ KOBJMETHOD(channel_setformat, emurchan_setformat),
+ KOBJMETHOD(channel_setspeed, emurchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, emurchan_setblocksize),
+ KOBJMETHOD(channel_trigger, emurchan_trigger),
+ KOBJMETHOD(channel_getptr, emurchan_getptr),
+ KOBJMETHOD(channel_getcaps, emurchan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(emurchan);
+
+/* -------------------------------------------------------------------- */
/* The interrupt handler */
static void
emu_intr(void *p)
@@ -942,13 +986,13 @@ emu_intr(void *p)
if (sc->rch[0].channel)
chn_intr(sc->rch[0].channel);
}
- if (stat & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL)) {
- ack |= stat & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL);
+ if (stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL)) {
+ ack |= stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL);
if (sc->rch[1].channel)
chn_intr(sc->rch[1].channel);
}
- if (stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL)) {
- ack |= stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL);
+ if (stat & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL)) {
+ ack |= stat & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL);
if (sc->rch[2].channel)
chn_intr(sc->rch[2].channel);
}
@@ -959,7 +1003,7 @@ emu_intr(void *p)
}
if (stat & IPR_SAMPLERATETRACKER) {
ack |= IPR_SAMPLERATETRACKER;
- device_printf(sc->dev, "sample rate tracker lock status change\n");
+ /* device_printf(sc->dev, "sample rate tracker lock status change\n"); */
}
if (stat & ~ack)
@@ -969,18 +1013,6 @@ emu_intr(void *p)
}
}
-static kobj_method_t emurchan_methods[] = {
- KOBJMETHOD(channel_init, emurchan_init),
- KOBJMETHOD(channel_setformat, emurchan_setformat),
- KOBJMETHOD(channel_setspeed, emurchan_setspeed),
- KOBJMETHOD(channel_setblocksize, emurchan_setblocksize),
- KOBJMETHOD(channel_trigger, emurchan_trigger),
- KOBJMETHOD(channel_getptr, emurchan_getptr),
- KOBJMETHOD(channel_getcaps, emurchan_getcaps),
- { 0, 0 }
-};
-CHANNEL_DECLARE(emurchan);
-
/* -------------------------------------------------------------------- */
static void
@@ -1401,20 +1433,27 @@ emu_pci_probe(device_t dev)
case EMU10K1_PCI_ID:
s = "Creative EMU10K1";
break;
+/*
+ case EMU10K2_PCI_ID:
+ s = "Creative EMU10K2";
+ break;
+*/
+ default:
+ return ENXIO;
}
- if (s) device_set_desc(dev, s);
- return s? 0 : ENXIO;
+ device_set_desc(dev, s);
+ return 0;
}
static int
emu_pci_attach(device_t dev)
{
- u_int32_t data;
- struct sc_info *sc;
struct ac97_info *codec = NULL;
- int i, mapped;
- char status[SND_STATUSLEN];
+ struct sc_info *sc;
+ u_int32_t data;
+ int i, gotmic;
+ char status[SND_STATUSLEN];
if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) {
device_printf(dev, "cannot allocate softc\n");
@@ -1427,39 +1466,26 @@ emu_pci_attach(device_t dev)
sc->rev = pci_get_revid(dev);
data = pci_read_config(dev, PCIR_COMMAND, 2);
- data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
+ data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
pci_write_config(dev, PCIR_COMMAND, data, 2);
data = pci_read_config(dev, PCIR_COMMAND, 2);
- mapped = 0;
- for (i = 0; (mapped == 0) && (i < PCI_MAXMAPS_0); i++) {
- sc->regid = PCIR_MAPS + i*4;
- sc->regtype = SYS_RES_MEMORY;
- sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid,
- 0, ~0, 1, RF_ACTIVE);
- if (!sc->reg) {
- sc->regtype = SYS_RES_IOPORT;
- sc->reg = bus_alloc_resource(dev, sc->regtype,
- &sc->regid, 0, ~0, 1,
- RF_ACTIVE);
- }
- if (sc->reg) {
- sc->st = rman_get_bustag(sc->reg);
- sc->sh = rman_get_bushandle(sc->reg);
- mapped++;
- }
- }
-
- if (mapped == 0) {
+ i = PCIR_MAPS;
+ sc->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &i, 0, ~0, 1, RF_ACTIVE);
+ if (sc->reg == NULL) {
device_printf(dev, "unable to map register space\n");
goto bad;
}
+ sc->st = rman_get_bustag(sc->reg);
+ sc->sh = rman_get_bushandle(sc->reg);
+
+ sc->bufsz = pcm_getbuffersize(dev, 4096, EMU_DEFAULT_BUFSZ, 65536);
if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
/*lowaddr*/1 << 31, /* can only access 0-2gb */
/*highaddr*/BUS_SPACE_MAXADDR,
/*filter*/NULL, /*filterarg*/NULL,
- /*maxsize*/262144, /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
/*flags*/0, &sc->parent_dmat) != 0) {
device_printf(dev, "unable to create dma tag\n");
goto bad;
@@ -1472,24 +1498,22 @@ emu_pci_attach(device_t dev)
codec = AC97_CREATE(dev, sc, emu_ac97);
if (codec == NULL) goto bad;
+ gotmic = (ac97_getcaps(codec) & AC97_CAP_MICCHANNEL)? 1 : 0;
if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
- sc->irqid = 0;
- sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid,
- 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
+ i = 0;
+ sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &i, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, emu_intr, sc, &sc->ih)) {
device_printf(dev, "unable to map interrupt\n");
goto bad;
}
- snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld",
- (sc->regtype == SYS_RES_IOPORT)? "io" : "memory",
- rman_get_start(sc->reg), rman_get_start(sc->irq));
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld", rman_get_start(sc->reg), rman_get_start(sc->irq));
- if (pcm_register(dev, sc, EMU_CHANS, 3)) goto bad;
+ if (pcm_register(dev, sc, EMU_CHANS, gotmic? 3 : 2)) goto bad;
for (i = 0; i < EMU_CHANS; i++)
pcm_addchan(dev, PCMDIR_PLAY, &emupchan_class, sc);
- for (i = 0; i < 3; i++)
+ for (i = 0; i < (gotmic? 3 : 2); i++)
pcm_addchan(dev, PCMDIR_REC, &emurchan_class, sc);
pcm_setstatus(dev, status);
@@ -1498,9 +1522,9 @@ emu_pci_attach(device_t dev)
bad:
if (codec) ac97_destroy(codec);
- if (sc->reg) bus_release_resource(dev, sc->regtype, sc->regid, sc->reg);
+ if (sc->reg) bus_release_resource(dev, SYS_RES_IOPORT, PCIR_MAPS, sc->reg);
if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih);
- if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
if (sc->parent_dmat) bus_dma_tag_destroy(sc->parent_dmat);
if (sc->lock) snd_mtxfree(sc->lock);
free(sc, M_DEVBUF);
@@ -1521,9 +1545,9 @@ emu_pci_detach(device_t dev)
/* shutdown chip */
emu_uninit(sc);
- bus_release_resource(dev, sc->regtype, sc->regid, sc->reg);
+ bus_release_resource(dev, SYS_RES_IOPORT, PCIR_MAPS, sc->reg);
bus_teardown_intr(dev, sc->irq, sc->ih);
- bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
bus_dma_tag_destroy(sc->parent_dmat);
snd_mtxfree(sc->lock);
free(sc, M_DEVBUF);
@@ -1562,10 +1586,14 @@ emujoy_pci_probe(device_t dev)
s = "Creative EMU10K1 Joystick";
device_quiet(dev);
break;
+ case 0x70031102:
+ s = "Creative EMU10K2 Joystick";
+ device_quiet(dev);
+ break;
}
if (s) device_set_desc(dev, s);
- return s? 0 : ENXIO;
+ return s? -1000 : ENXIO;
}
static int
OpenPOWER on IntegriCloud