* change buffering method a bit

* swap record/mic channels
* initialise all channels
* align dma buffers to 8 bytes

Submitted by:	Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
(mostly)
This commit is contained in:
Cameron Grant 2001-08-29 02:31:03 +00:00
parent 546a92c4d4
commit 9924faf6e7

View File

@ -53,6 +53,7 @@ struct sc_chinfo {
u_int32_t num, run;
u_int32_t blksz, blkcnt;
u_int32_t regbase, spdreg;
u_int32_t civ;
struct snd_dbuf *buffer;
struct pcm_channel *channel;
@ -176,7 +177,7 @@ static void
ich_filldtbl(struct sc_chinfo *ch)
{
u_int32_t base;
int i, bs, gap;
int i;
base = vtophys(sndbuf_getbuf(ch->buffer));
ch->blkcnt = sndbuf_getsize(ch->buffer) / ch->blksz;
@ -185,22 +186,10 @@ ich_filldtbl(struct sc_chinfo *ch)
ch->blksz = sndbuf_getsize(ch->buffer) / ch->blkcnt;
}
bs = sndbuf_getsize(ch->buffer) / ICH_DTBL_LENGTH;
gap = ICH_DTBL_LENGTH / ch->blkcnt;
for (i = 0; i < ICH_DTBL_LENGTH; i++) {
ch->dtbl[i].buffer = base + (i * bs);
ch->dtbl[i].length = bs / 2;
if (i % gap == gap - 1)
ch->dtbl[i].length |= ICH_BDC_IOC;
ch->dtbl[i].buffer = base + (ch->blksz * (i % ch->blkcnt));
ch->dtbl[i].length = ICH_BDC_IOC | (ch->blksz / 2);
}
#ifdef DALEK
for (i = 0; i < ICH_DTBL_LENGTH; i++) {
ch->dtbl[i].buffer = base;
ch->dtbl[i].length = ch->blksz / 2;
if (pos % ch->blksz == 0)
ch->dtbl[i].length |= ICH_BDC_IOC;
}
#endif
}
static int
@ -258,18 +247,18 @@ ichchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *
ch->spdreg = sc->hasvra? AC97_REGEXT_FDACRATE : 0;
break;
case 1: /* mic */
KASSERT(dir == PCMDIR_REC, ("wrong direction"));
ch->regbase = ICH_REG_MC_BASE;
ch->spdreg = sc->hasvrm? AC97_REGEXT_MADCRATE : 0;
break;
case 2: /* record */
case 1: /* record */
KASSERT(dir == PCMDIR_REC, ("wrong direction"));
ch->regbase = ICH_REG_PI_BASE;
ch->spdreg = sc->hasvra? AC97_REGEXT_LADCRATE : 0;
break;
case 2: /* mic */
KASSERT(dir == PCMDIR_REC, ("wrong direction"));
ch->regbase = ICH_REG_MC_BASE;
ch->spdreg = sc->hasvrm? AC97_REGEXT_MADCRATE : 0;
break;
default:
return NULL;
}
@ -308,7 +297,7 @@ ichchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
ch->blksz = blocksize;
ich_filldtbl(ch);
ich_wr(sc, ch->regbase + ICH_REG_X_LVI, ICH_DTBL_LENGTH - 1, 1);
ich_wr(sc, ch->regbase + ICH_REG_X_LVI, ch->blkcnt - 1, 1);
return ch->blksz;
}
@ -339,19 +328,11 @@ ichchan_getptr(kobj_t obj, void *data)
{
struct sc_chinfo *ch = data;
struct sc_info *sc = ch->parent;
u_int32_t bs, ci, ofs, pos;
u_int32_t pos;
ofs = 0;
ci = 1234;
while (ci != ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1)) {
ci = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1);
ofs = ich_rd(sc, ch->regbase + ICH_REG_X_PICB, 2) * 2;
}
ch->civ = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1) % ch->blkcnt;
bs = sndbuf_getsize(ch->buffer) / ICH_DTBL_LENGTH;
ofs = bs - ofs;
pos = ci * bs;
pos += ofs;
pos = ch->civ * ch->blksz;
return pos;
}
@ -384,7 +365,7 @@ ich_intr(void *p)
{
struct sc_info *sc = (struct sc_info *)p;
struct sc_chinfo *ch;
u_int32_t st, lvi;
u_int32_t cbi, lbi, lvi, st;
int i;
for (i = 0; i < 3; i++) {
@ -393,17 +374,26 @@ ich_intr(void *p)
st = ich_rd(sc, ch->regbase + ICH_REG_X_SR, 2);
st &= ICH_X_SR_FIFOE | ICH_X_SR_BCIS | ICH_X_SR_LVBCI;
if (st != 0) {
/* clear status bit */
ich_wr(sc, ch->regbase + ICH_REG_X_SR, st, 2);
if (st & (ICH_X_SR_BCIS/* | ICH_X_SR_LVBCI*/)) {
if (st & (ICH_X_SR_BCIS | ICH_X_SR_LVBCI)) {
/* block complete - update buffer */
if (ch->run)
chn_intr(ch->channel);
lvi = ich_rd(sc, ch->regbase + ICH_REG_X_LVI, 1);
lvi += ICH_DTBL_LENGTH / ch->blkcnt;
cbi = ch->civ % ch->blkcnt;
if (cbi == 0)
cbi = ch->blkcnt - 1;
else
cbi--;
lbi = lvi % ch->blkcnt;
if (cbi >= lbi)
lvi += cbi - lbi;
else
lvi += cbi + ch->blkcnt - lbi;
lvi %= ICH_DTBL_LENGTH;
ich_wr(sc, ch->regbase + ICH_REG_X_LVI, lvi, 1);
}
/* clear status bit */
ich_wr(sc, ch->regbase + ICH_REG_X_SR, st, 2);
}
}
}
@ -432,7 +422,7 @@ ich_init(struct sc_info *sc)
ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD | ICH_GLOB_CTL_PRES, 4);
if (ich_resetchan(sc, 0) || ich_resetchan(sc, 0))
if (ich_resetchan(sc, 0) || ich_resetchan(sc, 1) || ich_resetchan(sc, 2))
return ENXIO;
if (bus_dmamem_alloc(sc->dmat, (void **)&sc->dtbl, BUS_DMA_NOWAIT, &sc->dtmap))
@ -507,7 +497,7 @@ ich_pci_attach(device_t dev)
sc->nabmbart = rman_get_bustag(sc->nabmbar);
sc->nabmbarh = rman_get_bushandle(sc->nabmbar);
if (bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
if (bus_dma_tag_create(NULL, 8, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
NULL, NULL, ICH_DEFAULT_BUFSZ, 1, 0x3ffff, 0, &sc->dmat) != 0) {
device_printf(dev, "unable to create dma tag\n");
goto bad;