static void ich_filldtbl(struct sc_chinfo *ch) { struct sc_info *sc = ch->parent; uint32_t base; int i; base = sndbuf_getbufaddr(ch->buffer); if ((ch->blksz * ch->blkcnt) > sndbuf_getmaxsize(ch->buffer)) ch->blksz = sndbuf_getmaxsize(ch->buffer) / ch->blkcnt; if ((sndbuf_getblksz(ch->buffer) != ch->blksz || sndbuf_getblkcnt(ch->buffer) != ch->blkcnt) && sndbuf_resize(ch->buffer, ch->blkcnt, ch->blksz) != 0) device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n", __func__, ch->blksz, ch->blkcnt); ch->blksz = sndbuf_getblksz(ch->buffer); for (i = 0; i < ICH_DTBL_LENGTH; i++) { ch->dtbl[i].buffer = base + (ch->blksz * (i % ch->blkcnt)); ch->dtbl[i].length = ICH_BDC_IOC | (ch->blksz / ch->parent->sample_size); } }
static int ichchan_free(kobj_t obj, void *data) { struct sc_chinfo *ch; struct sc_info *sc; ch = (struct sc_chinfo *)data; sc = (ch != NULL) ? ch->parent : NULL; if (ch != NULL && sc != NULL) { ICH_DMA_ATTR(sc, sndbuf_getbuf(ch->buffer), sndbuf_getmaxsize(ch->buffer), PAT_WRITE_BACK); } return (1); }
static void * ichchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { struct sc_info *sc = devinfo; struct sc_chinfo *ch; unsigned int num; ICH_LOCK(sc); num = sc->chnum++; ch = &sc->ch[num]; ch->num = num; ch->buffer = b; ch->channel = c; ch->parent = sc; ch->run = 0; ch->dtbl = sc->dtbl + (ch->num * ICH_DTBL_LENGTH); ch->desc_addr = sc->desc_addr + (ch->num * ICH_DTBL_LENGTH * sizeof(struct ich_desc)); ch->blkcnt = sc->blkcnt; ch->blksz = sc->bufsz / ch->blkcnt; switch(ch->num) { case 0: /* play */ KASSERT(dir == PCMDIR_PLAY, ("wrong direction")); ch->regbase = ICH_REG_PO_BASE; ch->spdreg = (sc->hasvra) ? AC97_REGEXT_FDACRATE : 0; ch->imask = ICH_GLOB_STA_POINT; break; case 1: /* record */ KASSERT(dir == PCMDIR_REC, ("wrong direction")); ch->regbase = ICH_REG_PI_BASE; ch->spdreg = (sc->hasvra) ? AC97_REGEXT_LADCRATE : 0; ch->imask = ICH_GLOB_STA_PIINT; break; case 2: /* mic */ KASSERT(dir == PCMDIR_REC, ("wrong direction")); ch->regbase = ICH_REG_MC_BASE; ch->spdreg = (sc->hasvrm) ? AC97_REGEXT_MADCRATE : 0; ch->imask = ICH_GLOB_STA_MINT; break; default: return (NULL); } if (sc->flags & ICH_FIXED_RATE) ch->spdreg = 0; ICH_UNLOCK(sc); if (sndbuf_alloc(ch->buffer, sc->chan_dmat, sc->bufsz) != 0) return (NULL); ICH_DMA_ATTR(sc, sndbuf_getbuf(ch->buffer), sndbuf_getmaxsize(ch->buffer), PAT_UNCACHEABLE); ICH_LOCK(sc); ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (uint32_t)(ch->desc_addr), 4); ICH_UNLOCK(sc); return (ch); }