int sndbuf_pool_test(void) { sndbuf_t * lst[SNDBUF_POOL_SIZE]; sndbuf_t * buf; int i; int j = 0; do { for (i = 0; i < SNDBUF_POOL_SIZE; ++i) { buf = sndbuf_alloc(); if (buf == NULL) { DCC_LOG1(LOG_PANIC, "%d: sndbuf_alloc() failed!", i); return -1; } lst[i] = buf; } buf = sndbuf_alloc(); if (buf != NULL) { DCC_LOG2(LOG_PANIC, "%d: sndbuf_alloc() != NULL!", i, buf); return -1; } for (i = 0; i < SNDBUF_POOL_SIZE; ++i) { sndbuf_free(lst[i]); } } while (++j < 2); DCC_LOG(LOG_TRACE, "success."); return 0; }
static void * alschan_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; if (dir == PCMDIR_PLAY) { ch = &sc->pch; ch->gcr_fifo_status = ALS_GCR_FIFO0_STATUS; } else { ch = &sc->rch; ch->gcr_fifo_status = ALS_GCR_FIFO1_STATUS; } ch->dir = dir; ch->parent = sc; ch->channel = c; ch->bps = 1; ch->format = AFMT_U8; ch->speed = DSP_DEFAULT_SPEED; ch->buffer = b; if (sndbuf_alloc(ch->buffer, sc->parent_dmat, ALS_BUFFER_SIZE) != 0) { return NULL; } return ch; }
static void* via8233wr_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { struct via_info *via = devinfo; struct via_chinfo *ch = &via->rch[c->num]; ch->parent = via; ch->channel = c; ch->buffer = b; ch->dir = dir; ch->rbase = VIA_WR_BASE(c->num); snd_mtxlock(via->lock); via_wr(via, ch->rbase + VIA_WR_RP_SGD_FORMAT, WR_FIFO_ENABLE, 1); snd_mtxunlock(via->lock); if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0) return NULL; snd_mtxlock(via->lock); via8233chan_sgdinit(via, ch, c->num); via8233chan_reset(via, ch); snd_mtxunlock(via->lock); return ch; }
/* play channel interface */ static void * ds1pchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { struct sc_info *sc = devinfo; struct sc_pchinfo *ch; KASSERT(dir == PCMDIR_PLAY, ("ds1pchan_init: bad direction")); ch = &sc->pch[sc->pchn++]; ch->buffer = b; ch->parent = sc; ch->channel = c; ch->dir = dir; ch->fmt = SND_FORMAT(AFMT_U8, 1, 0); ch->spd = 8000; ch->run = 0; if (sndbuf_alloc(ch->buffer, sc->buffer_dmat, 0, sc->bufsz) != 0) return NULL; else { ch->lsnum = sc->pslotfree; ch->lslot = ds_allocpslot(sc); ch->rsnum = sc->pslotfree; ch->rslot = ds_allocpslot(sc); ds_setuppch(ch); return ch; } }
static void * cs4281chan_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 = (dir == PCMDIR_PLAY) ? &sc->pch : &sc->rch; ch->buffer = b; if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) != 0) { return NULL; } ch->parent = sc; ch->channel = c; ch->fmt = SND_FORMAT(AFMT_U8, 1, 0); ch->spd = DSP_DEFAULT_SPEED; ch->bps = 1; ch->blksz = sndbuf_getsize(ch->buffer); ch->dma_chan = (dir == PCMDIR_PLAY) ? CS4281_DMA_PLAY : CS4281_DMA_REC; ch->dma_setup = 0; adcdac_go(ch, 0); adcdac_prog(ch); return ch; }
static void * alschan_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; snd_mtxlock(sc->lock); if (dir == PCMDIR_PLAY) { ch = &sc->pch; ch->gcr_fifo_status = ALS_GCR_FIFO0_STATUS; } else { ch = &sc->rch; ch->gcr_fifo_status = ALS_GCR_FIFO1_STATUS; } ch->dir = dir; ch->parent = sc; ch->channel = c; ch->bps = 1; ch->format = SND_FORMAT(AFMT_U8, 1, 0); ch->speed = DSP_DEFAULT_SPEED; ch->buffer = b; snd_mtxunlock(sc->lock); if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) != 0) return NULL; return ch; }
static void* via8233dxs_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { struct via_info *via = devinfo; struct via_chinfo *ch = &via->pch[c->num]; ch->parent = via; ch->channel = c; ch->buffer = b; ch->dir = dir; /* * All cards apparently support DXS3, but not other DXS * channels. We therefore want to align first DXS channel to * DXS3. */ snd_mtxlock(via->lock); ch->rbase = VIA_DXS_BASE(NDXSCHANS - 1 - via->n_dxs_registered); via->n_dxs_registered++; snd_mtxunlock(via->lock); if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0) return NULL; snd_mtxlock(via->lock); via8233chan_sgdinit(via, ch, NWRCHANS + c->num); via8233chan_reset(via, ch); snd_mtxunlock(via->lock); return ch; }
/* channel interface */ static void * ad1816chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { struct ad1816_info *ad1816 = devinfo; struct ad1816_chinfo *ch = (dir == PCMDIR_PLAY)? &ad1816->pch : &ad1816->rch; ch->parent = ad1816; ch->channel = c; ch->buffer = b; if (sndbuf_alloc(ch->buffer, ad1816->parent_dmat, ad1816->bufsize) == -1) return NULL; return ch; }
/* * Playback / Record channel interface */ static void * atiixp_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { struct atiixp_info *sc = devinfo; struct atiixp_chinfo *ch; int num; atiixp_lock(sc); if (dir == PCMDIR_PLAY) { ch = &sc->pch; ch->linkptr_bit = ATI_REG_OUT_DMA_LINKPTR; ch->enable_bit = ATI_REG_CMD_OUT_DMA_EN | ATI_REG_CMD_SEND_EN; ch->flush_bit = ATI_REG_FIFO_OUT_FLUSH; ch->dma_dt_cur_bit = ATI_REG_OUT_DMA_DT_CUR; /* Native 32bit playback working properly */ ch->caps_32bit = 1; } else { ch = &sc->rch; ch->linkptr_bit = ATI_REG_IN_DMA_LINKPTR; ch->enable_bit = ATI_REG_CMD_IN_DMA_EN | ATI_REG_CMD_RECEIVE_EN; ch->flush_bit = ATI_REG_FIFO_IN_FLUSH; ch->dma_dt_cur_bit = ATI_REG_IN_DMA_DT_CUR; /* XXX Native 32bit recording appear to be broken */ ch->caps_32bit = 1; } ch->buffer = b; ch->parent = sc; ch->channel = c; ch->dir = dir; ch->dma_segs = sc->dma_segs; atiixp_unlock(sc); if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) == -1) return NULL; atiixp_lock(sc); num = sc->registered_channels++; ch->sgd_table = &sc->sgd_table[num * ch->dma_segs]; ch->sgd_addr = sc->sgd_addr + (num * ch->dma_segs * sizeof(struct atiixp_dma_op)); atiixp_disable_dma(sc, ch); atiixp_unlock(sc); return ch; }
/* channel interface */ static void * fm801ch_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { struct fm801_info *fm801 = (struct fm801_info *)devinfo; struct fm801_chinfo *ch = (dir == PCMDIR_PLAY)? &fm801->pch : &fm801->rch; DPRINT("fm801ch_init, direction = %d\n", dir); ch->parent = fm801; ch->channel = c; ch->buffer = b; ch->dir = dir; if (sndbuf_alloc(ch->buffer, fm801->parent_dmat, 0, fm801->bufsz) != 0) return NULL; return (void *)ch; }
/* * Initialize a PCM channel */ static void * au88x0_chan_init(kobj_t obj, void *arg, struct snd_dbuf *buf, struct pcm_channel *chan, int dir) { struct au88x0_info *aui = arg; struct au88x0_chan_info *auci = au88x0_channel(aui, dir); if (sndbuf_alloc(buf, aui->aui_dmat, aui->aui_bufsize) != 0) return (NULL); auci->auci_aui = aui; auci->auci_pcmchan = chan; auci->auci_buf = buf; auci->auci_dir = dir; return (auci); }
/* channel interface */ static void * ad1816chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { struct ad1816_info *ad1816 = devinfo; struct ad1816_chinfo *ch = (dir == PCMDIR_PLAY)? &ad1816->pch : &ad1816->rch; ch->dir = dir; ch->parent = ad1816; ch->channel = c; ch->buffer = b; if (sndbuf_alloc(ch->buffer, ad1816->parent_dmat, 0, ad1816->bufsize) != 0) return NULL; sndbuf_dmasetup(ch->buffer, (dir == PCMDIR_PLAY) ? ad1816->drq1 : ad1816->drq2); if (SND_DMA(ch->buffer)) sndbuf_dmasetdir(ch->buffer, dir); return ch; }
sndbuf_t * i2s_io(sndbuf_t * out_buf) { sndbuf_t * in_buf; sndbuf_t * buf; int idx; if (out_buf == NULL) { trace("txbuf = zero"); out_buf = (sndbuf_t *)&sndbuf_zero; } else { /* incerement the reference counter */ sndbuf_use(out_buf); } /* wait for the end of transfer cycle */ // tracef("%s(): wait ", __func__); thinkos_flag_wait(i2s.io_flag); __thinkos_flag_clr(i2s.io_flag); idx = i2s.rx.idx; /* get the input data buffer */ in_buf = i2s.rx.buf[idx]; /* alloc an empty buffer for next cycle */ buf = sndbuf_alloc(); if (buf == NULL) { tracef("%s(): sndbuf_alloc() failed!", __func__); } // tracef("%d <-- IN[%d] <-- %d", sndbuf_id(in_buf), idx, sndbuf_id(buf)); /* set the input buffer for next cycle */ i2s.rx.buf[idx] = (buf == NULL) ? &sndbuf_null : buf; idx = i2s.tx.idx; /* release the previouslly transmitted buffer */ sndbuf_free(i2s.tx.buf[idx]); /* set the output data buffer */ i2s.tx.buf[idx] = out_buf; return in_buf; }
static void * ua_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { device_t pa_dev; u_char *buf,*end; struct ua_info *sc = devinfo; struct ua_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; ch->parent = sc; ch->channel = c; ch->buffer = b; pa_dev = device_get_parent(sc->sc_dev); /* Create ua_playfmt[] & ua_recfmt[] */ uaudio_query_formats(pa_dev, (u_int32_t *)&ua_playfmt, (u_int32_t *)&ua_recfmt); if (ua_playfmt[0] == 0) { printf("%s channel supported format list invalid\n", dir == PCMDIR_PLAY? "play" : "record"); return NULL; } /* allocate PCM side DMA buffer */ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, UAUDIO_PCM_BUFF_SIZE) != 0) { return NULL; } buf = end = sndbuf_getbuf(b); end += sndbuf_getsize(b); uaudio_chan_set_param_pcm_dma_buff(pa_dev, buf, end, ch->channel); ch->dir = dir; #ifndef NO_RECORDING ch->hwch = 1; if (dir == PCMDIR_PLAY) ch->hwch = 2; #else ch->hwch = 2; #endif return ch; }
static void* via8233msgd_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { struct via_info *via = devinfo; struct via_chinfo *ch = &via->pch[c->num]; ch->parent = via; ch->channel = c; ch->buffer = b; ch->dir = dir; ch->rbase = VIA_MC_SGD_STATUS; if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0) return NULL; snd_mtxlock(via->lock); via8233chan_sgdinit(via, ch, NWRCHANS + c->num); via8233chan_reset(via, ch); snd_mtxunlock(via->lock); return ch; }
void net_rcv_task(void) { sndbuf_t * buf; uint32_t ts; int n; tracef("%s(): <%d> started...", __func__, thinkos_thread_self()); for (;;) { while ((buf = sndbuf_alloc()) == NULL) { tracef("%s(): sndbuf_alloc() failed!", __func__); thinkos_sleep(1000); } #if ENABLE_G711 n = g711_alaw_recv(0, buf, &ts); #else n = audio_recv(0, buf, &ts); #endif if (n != sndbuf_len) { tracef("%s(): (n=%d != sndbuf_len)!", __func__, n); } else { if (audio_drv.stream_enabled) { #if !DISABLE_JITBUF jitbuf_enqueue(&audio_drv.jitbuf, buf, ts); #endif } } #if DISABLE_JITBUF xfr_buf = buf; #else sndbuf_free(buf); #endif } }
/* record channel interface */ static void * ds1rchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { struct sc_info *sc = devinfo; struct sc_rchinfo *ch; KASSERT(dir == PCMDIR_REC, ("ds1rchan_init: bad direction")); ch = &sc->rch[sc->rchn]; ch->num = sc->rchn++; ch->buffer = b; ch->parent = sc; ch->channel = c; ch->dir = dir; ch->fmt = SND_FORMAT(AFMT_U8, 1, 0); ch->spd = 8000; if (sndbuf_alloc(ch->buffer, sc->buffer_dmat, 0, sc->bufsz) != 0) return NULL; else { ch->slot = (ch->num == DS1_RECPRIMARY)? sc->rbank + 2: sc->rbank; ds_setuprch(ch); return ch; } }
/* channel interface */ static void * viachan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) { struct via_info *via = devinfo; struct via_chinfo *ch; snd_mtxlock(via->lock); if (dir == PCMDIR_PLAY) { ch = &via->pch; ch->base = VIA_PLAY_DMAOPS_BASE; ch->count = VIA_PLAY_DMAOPS_COUNT; ch->ctrl = VIA_PLAY_CONTROL; ch->mode = VIA_PLAY_MODE; ch->sgd_addr = via->sgd_addr; ch->sgd_table = &via->sgd_table[0]; } else { ch = &via->rch; ch->base = VIA_RECORD_DMAOPS_BASE; ch->count = VIA_RECORD_DMAOPS_COUNT; ch->ctrl = VIA_RECORD_CONTROL; ch->mode = VIA_RECORD_MODE; ch->sgd_addr = via->sgd_addr + sizeof(struct via_dma_op) * SEGS_PER_CHAN; ch->sgd_table = &via->sgd_table[SEGS_PER_CHAN]; } ch->parent = via; ch->channel = c; ch->buffer = b; ch->dir = dir; snd_mtxunlock(via->lock); if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0) return NULL; return ch; }
void audio_io_task(void) { sndbuf_t * out_buf; sndbuf_t * in_buf; uint32_t ts = 0; int i; tracef("%s(): <%d> started...", __func__, thinkos_thread_self()); tonegen_init(&tonegen, 0, 0); spectrum_init(&audio_tx_sa, SAMPLE_RATE); spectrum_init(&audio_rx_sa, SAMPLE_RATE); for (;;) { #if DISABLE_JITBUF out_buf = xfr_buf; #else out_buf = jitbuf_dequeue(&audio_drv.jitbuf); #endif if (audio_drv.tone_mode == TONE_DAC) { if (out_buf == NULL) { if ((out_buf = sndbuf_alloc()) != NULL) tonegen_apply(&tonegen, out_buf); else out_buf = (sndbuf_t *)&sndbuf_zero; } } else { if (out_buf == NULL) { #if 0 tracef("%s(): out_buf == NULL!", __func__); #endif out_buf = (sndbuf_t *)&sndbuf_zero; } } spectrum_rec(&audio_tx_sa, out_buf); in_buf = i2s_io(out_buf); for (i = 0; i < SNDBUF_LEN; i++) in_buf->data[i] = FxaIirApply(&iir_hp_120hz, in_buf->data[i]); // in_buf->data[i] = FxaIirApply(&iir_hp_240hz, in_buf->data[i]); led_flash(LED_I2S, 100); if (in_buf != &sndbuf_null) { if (audio_drv.tone_mode == TONE_ADC) tonegen_apply(&tonegen, in_buf); spectrum_rec(&audio_rx_sa, in_buf); } if (audio_drv.stream_enabled) { #if ENABLE_G711 if (g711_alaw_send(0, in_buf, ts) < 0) { tracef("%s(): net_send() failed!", __func__); } #else if (audio_send(0, in_buf, ts) < 0) { tracef("%s(): net_send() failed!", __func__); } #endif led_flash(LED_NET, 100); } ts += SNDBUF_LEN; sndbuf_free(in_buf); sndbuf_free(out_buf); } }
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->flags & ICH_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0), sc->bufsz) != 0) return (NULL); ICH_LOCK(sc); ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (uint32_t)(ch->desc_addr), 4); ICH_UNLOCK(sc); return (ch); }
sndbuf_t * sndbuf_calloc(void) { return sndbuf_clear(sndbuf_alloc()); }