summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2001-08-29 02:31:03 +0000
committercg <cg@FreeBSD.org>2001-08-29 02:31:03 +0000
commitbe67da33283716a7b1e17c3e7adfee3da9ea77d4 (patch)
treed9158bd335dbba02a8eba0a6cc4b65af87cc984d /sys
parent5b037844c5bdc9bdbe2186cd9bfaf9bb71392f54 (diff)
downloadFreeBSD-src-be67da33283716a7b1e17c3e7adfee3da9ea77d4.zip
FreeBSD-src-be67da33283716a7b1e17c3e7adfee3da9ea77d4.tar.gz
* 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)
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/sound/pci/ich.c70
1 files changed, 30 insertions, 40 deletions
diff --git a/sys/dev/sound/pci/ich.c b/sys/dev/sound/pci/ich.c
index a4d8aea..a4979eb 100644
--- a/sys/dev/sound/pci/ich.c
+++ b/sys/dev/sound/pci/ich.c
@@ -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;
- }
-#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;
+ ch->dtbl[i].buffer = base + (ch->blksz * (i % ch->blkcnt));
+ ch->dtbl[i].length = ICH_BDC_IOC | (ch->blksz / 2);
}
-#endif
}
static int
@@ -258,16 +247,16 @@ 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 */
+ case 1: /* record */
KASSERT(dir == PCMDIR_REC, ("wrong direction"));
- ch->regbase = ICH_REG_MC_BASE;
- ch->spdreg = sc->hasvrm? AC97_REGEXT_MADCRATE : 0;
+ ch->regbase = ICH_REG_PI_BASE;
+ ch->spdreg = sc->hasvra? AC97_REGEXT_LADCRATE : 0;
break;
- case 2: /* record */
+ case 2: /* mic */
KASSERT(dir == PCMDIR_REC, ("wrong direction"));
- ch->regbase = ICH_REG_PI_BASE;
- ch->spdreg = sc->hasvra? AC97_REGEXT_LADCRATE : 0;
+ ch->regbase = ICH_REG_MC_BASE;
+ ch->spdreg = sc->hasvrm? AC97_REGEXT_MADCRATE : 0;
break;
default:
@@ -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;
OpenPOWER on IntegriCloud