static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip, struct snd_pcm_substream *substream, enum dma_transfer_direction direction) { struct dma_chan *chan; struct dw_cyclic_desc *cdesc; struct snd_pcm_runtime *runtime = substream->runtime; unsigned long buffer_len, period_len; /* * We don't do DMA on "complex" transfers, i.e. with * non-halfword-aligned buffers or lengths. */ if (runtime->dma_addr & 1 || runtime->buffer_size & 1) { dev_dbg(&chip->pdev->dev, "too complex transfer\n"); return -EINVAL; } if (direction == DMA_MEM_TO_DEV) chan = chip->dma.tx_chan; else chan = chip->dma.rx_chan; buffer_len = frames_to_bytes(runtime, runtime->buffer_size); period_len = frames_to_bytes(runtime, runtime->period_size); cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, period_len, direction); if (IS_ERR(cdesc)) { dev_dbg(&chip->pdev->dev, "could not prepare cyclic DMA\n"); return PTR_ERR(cdesc); } if (direction == DMA_MEM_TO_DEV) { cdesc->period_callback = atmel_ac97c_dma_playback_period_done; set_bit(DMA_TX_READY, &chip->flags); } else { cdesc->period_callback = atmel_ac97c_dma_capture_period_done; set_bit(DMA_RX_READY, &chip->flags); } cdesc->period_callback_param = chip; return 0; }
/* pointer callback */ static snd_pcm_uframes_t snd_bcm2835_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct bcm2835_alsa_stream *alsa_stream = runtime->private_data; audio_info(" .. IN\n"); audio_debug("pcm_pointer... (%d) hwptr=%d appl=%d pos=%d\n", 0, frames_to_bytes(runtime, runtime->status->hw_ptr), frames_to_bytes(runtime, runtime->control->appl_ptr), alsa_stream->pos); audio_info(" .. OUT\n"); return snd_pcm_indirect_playback_pointer(substream, &alsa_stream->pcm_indirect, alsa_stream->pos); }
int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_pcm_runtime *runtime = substream->runtime; struct tegra_runtime_data *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct tegra_pcm_dma_params * dmap; unsigned long flags; int i; dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if (!dmap) return 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: prtd->dma_pos = 0; prtd->dma_pos_end = frames_to_bytes(runtime, runtime->periods * runtime->period_size); prtd->period_index = 0; prtd->dma_req_idx = 0; if (prtd->disable_intr) { prtd->dma_req_count = 1; prtd->dma_req[0].complete = NULL; } else if (!prtd->dma_req[0].complete) { prtd->dma_req[0].complete = dma_complete_callback; prtd->dma_req_count = (MAX_DMA_REQ_COUNT <= runtime->periods) ? MAX_DMA_REQ_COUNT : runtime->periods; } /* Fall-through */ case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: spin_lock_irqsave(&prtd->lock, flags); prtd->running = 1; spin_unlock_irqrestore(&prtd->lock, flags); for (i = 0; i < prtd->dma_req_count; i++) tegra_pcm_queue_dma(prtd); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: spin_lock_irqsave(&prtd->lock, flags); prtd->running = 0; spin_unlock_irqrestore(&prtd->lock, flags); tegra_dma_cancel(prtd->dma_chan); for (i = 0; i < prtd->dma_req_count; i++) { if (prtd->dma_req[i].complete && (prtd->dma_req[i].status == -TEGRA_DMA_REQ_ERROR_ABORTED)) prtd->dma_req[i].complete(&prtd->dma_req[i]); } break; default: return -EINVAL; } return 0; }
static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_pcm_runtime *runtime = substream->runtime; struct tegra_runtime_data *prtd = runtime->private_data; unsigned long flags; switch (cmd) { case SNDRV_PCM_TRIGGER_START: prtd->dma_pos = 0; prtd->dma_pos_end = frames_to_bytes(runtime, runtime->periods * runtime->period_size); prtd->period_index = 0; prtd->dma_req_idx = 0; case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: spin_lock_irqsave(&prtd->lock, flags); prtd->running = 1; #if 0 if( prtd->dma_chan ){ prtd->pcm_timeout_tick = jiffies; del_timer(&prtd->pcm_timeout); prtd->pcm_timeout.function = pcm_timeout_func; prtd->pcm_timeout.expires = jiffies + msecs_to_jiffies((runtime->period_size/(runtime->rate/1000))*runtime->periods*2); prtd->pcm_timeout.data = (unsigned long)prtd; add_timer(&prtd->pcm_timeout); prtd->callback_time = jiffies; } #endif spin_unlock_irqrestore(&prtd->lock, flags); if( prtd->dma_chan ){ tegra_pcm_queue_dma(prtd); tegra_pcm_queue_dma(prtd); } break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: spin_lock_irqsave(&prtd->lock, flags); prtd->running = 0; #if 0 if( prtd->dma_chan ){ del_timer(&prtd->pcm_timeout); } #endif spin_unlock_irqrestore(&prtd->lock, flags); if( prtd->dma_chan ){ tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[0]); tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[1]); } break; default: return -EINVAL; } return 0; }
static int i2sirx_i2so_mix_copy ( struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, void __user *buf, snd_pcm_uframes_t frames ) { __u8 *read_src; __u32 size_bytes; __u32 offset_bytes; struct snd_pcm_runtime *runtime = substream->runtime; if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { printk("%s,%d\n", __FUNCTION__, __LINE__); } else { offset_bytes = frames_to_bytes(runtime, pos); read_src = i2sirx_i2so_mix_ring_base_get() + offset_bytes; size_bytes = frames_to_bytes(runtime, frames); /* For debug. */ if (1 == ali_alsa_i2sirx_i2so_mix_out_dump_en_get()) { ali_alsa_dump_data("/data/data/ali_alsa_mix_out_dump.pcm", read_src, size_bytes); } if (copy_to_user(buf, read_src, size_bytes)) { printk("%s,%d\n", __FUNCTION__, __LINE__); return(-EFAULT); } } return 0; }
/* * prepare playback/capture channel */ static int snd_nm256_pcm_prepare(snd_pcm_substream_t *substream) { nm256_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; nm256_stream_t *s = (nm256_stream_t*)runtime->private_data; snd_assert(s, return -ENXIO); s->dma_size = frames_to_bytes(runtime, substream->runtime->buffer_size); s->period_size = frames_to_bytes(runtime, substream->runtime->period_size); s->periods = substream->runtime->periods; s->cur_period = 0; spin_lock_irq(&chip->reg_lock); s->running = 0; snd_nm256_set_format(chip, s, substream); spin_unlock_irq(&chip->reg_lock); return 0; }
static void do_filter_regions (sw_sample * sample, SweepFilterRegion func, sw_param_set pset, gpointer custom_data) { sw_sounddata * sounddata = sample->sounddata; sw_format * f = sounddata->format; GList * gl; sw_sel * sel; sw_framecount_t sel_total, run_total; sw_framecount_t offset, remaining, n; gpointer d; gint percent; gboolean active = TRUE; sel_total = sounddata_selection_nr_frames (sounddata) / 100; if (sel_total == 0) sel_total = 1; run_total = 0; for (gl = sounddata->sels; active && gl; gl = gl->next) { sel = (sw_sel *)gl->data; offset = 0; remaining = sel->sel_end - sel->sel_start; while (active && remaining > 0) { g_mutex_lock (&sample->ops_mutex); if (sample->edit_state == SWEEP_EDIT_STATE_CANCEL) { active = FALSE; } else { d = sounddata->data + (int)frames_to_bytes (f, sel->sel_start + offset); n = MIN(remaining, 1024); func (d, sounddata->format, n, pset, custom_data); remaining -= n; offset += n; run_total += n; percent = run_total / sel_total; sample_set_progress_percent (sample, percent); #ifdef DEBUG g_print ("completed %d / %d frames, %d%%\n", run_total, sel_total, percent); #endif } g_mutex_unlock (&sample->ops_mutex); } } }
/* * prepare playback/capture channel */ static int snd_nm256_pcm_prepare(struct snd_pcm_substream *substream) { struct nm256 *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct nm256_stream *s = runtime->private_data; if (snd_BUG_ON(!s)) return -ENXIO; s->dma_size = frames_to_bytes(runtime, substream->runtime->buffer_size); s->period_size = frames_to_bytes(runtime, substream->runtime->period_size); s->periods = substream->runtime->periods; s->cur_period = 0; spin_lock_irq(&chip->reg_lock); s->running = 0; snd_nm256_set_format(chip, s, substream); spin_unlock_irq(&chip->reg_lock); return 0; }
static void read_in_urb_mode3(struct snd_usb_caiaqdev *dev, const struct urb *urb, const struct usb_iso_packet_descriptor *iso) { unsigned char *usb_buf = urb->transfer_buffer + iso->offset; int stream, i; /* paranoia check */ if (iso->actual_length % (BYTES_PER_SAMPLE_USB * CHANNELS_PER_STREAM)) return; for (i = 0; i < iso->actual_length;) { for (stream = 0; stream < dev->n_streams; stream++) { struct snd_pcm_substream *sub = dev->sub_capture[stream]; char *audio_buf = NULL; int c, n, sz = 0; if (sub && !dev->input_panic) { struct snd_pcm_runtime *rt = sub->runtime; audio_buf = rt->dma_area; sz = frames_to_bytes(rt, rt->buffer_size); } for (c = 0; c < CHANNELS_PER_STREAM; c++) { /* 3 audio data bytes, followed by 1 check byte */ if (audio_buf) { for (n = 0; n < BYTES_PER_SAMPLE; n++) { audio_buf[dev->audio_in_buf_pos[stream]++] = usb_buf[i+n]; if (dev->audio_in_buf_pos[stream] == sz) dev->audio_in_buf_pos[stream] = 0; } dev->period_in_count[stream] += BYTES_PER_SAMPLE; } i += BYTES_PER_SAMPLE; if (usb_buf[i] != ((stream << 1) | c) && !dev->first_packet) { if (!dev->input_panic) printk(" EXPECTED: %02x got %02x, c %d, stream %d, i %d\n", ((stream << 1) | c), usb_buf[i], c, stream, i); dev->input_panic = 1; } i++; } } } if (dev->first_packet > 0) dev->first_packet--; }
static int davinci_pcm_copy(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames) { struct snd_pcm_runtime *runtime = substream->runtime; if (copy_from_user(local_buffer + hwoff, buf, frames_to_bytes(runtime, frames))) { printk(KERN_ERR "ERROR COPY_FROM_USER\n"); return -EFAULT; } return 0; }
static int snd_pcm_silence(snd_pcm_substream_t *substream, int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) { snd_pcm_runtime_t *runtime = substream->runtime; unsigned char * TempWriteLevel; pcm_hw_t *chip = snd_pcm_substream_chip(substream); char *hwbuf; int totalbytes; if(channel != -1) return -EINVAL; hwbuf = runtime->dma_area + frames_to_bytes(runtime, pos); totalbytes = frames_to_bytes(runtime, count); chip->NumberOfBytesCopied += totalbytes; snd_pcm_format_set_silence(runtime->format, hwbuf, totalbytes); /*Update Write Pointer STAPI WORK */ DEBUG_PRINT(("Silence \n")); DEBUG_PRINT(("Current Write Ptr=%x, Size =%d \n", chip->WritePointer, (count *runtime->channels))); TempWriteLevel = chip->WritePointer + (count *runtime->channels); if((U32)TempWriteLevel>(runtime->dma_addr +runtime->dma_bytes)) { U32 MaxAllowedWritePointer = (U32)runtime->dma_addr +(U32)runtime->dma_bytes; U32 Diff; U32 RemainingBytes; Diff = (U32)MaxAllowedWritePointer - (U32)chip->WritePointer; RemainingBytes = count *runtime->channels - Diff; chip->WritePointer = chip->WritePointer + RemainingBytes; } else { chip->WritePointer = TempWriteLevel; } DEBUG_PRINT(("Updated Write Ptr=%x \n", chip->WritePointer)); return 0; }
static int saudio_data_trigger_process(struct saudio_stream *stream, struct saudio_msg *msg) { int32_t result = 0; struct sblock blk = { 0 }; struct cmd_common *common = NULL; struct snd_pcm_runtime *runtime = stream->substream->runtime; ADEBUG(); if (stream->stream_id == SNDRV_PCM_STREAM_PLAYBACK) { stream->periods_avail = snd_pcm_playback_avail(runtime) / runtime->period_size; } else { stream->periods_avail = snd_pcm_capture_avail(runtime) / runtime->period_size; } pr_debug("saudio.c:stream->periods_avail is %d,block count is %d", stream->periods_avail, sblock_get_free_count(stream->dst, stream->channel)); stream->periods_tosend = runtime->periods - stream->periods_avail; ADEBUG(); while (stream->periods_tosend) { result = sblock_get(stream->dst, stream->channel, &blk, 0); if (result) { break; } stream->last_getblk_count++; common = (struct cmd_common *)blk.addr; blk.length = frames_to_bytes(runtime, runtime->period_size); common->command = SAUDIO_DATA_PCM; common->sub_cmd = stream->stream_id; common->reserved1 = stream->substream->dma_buffer.addr + stream->period * blk.length; sblock_send(stream->dst, stream->channel, &blk); stream->period++; stream->period = stream->period % runtime->periods; stream->periods_tosend--; } pr_debug(":sblock_getblock_count trigger is %d \n", stream->last_getblk_count); return result; }
cubeb_resampler_speex::cubeb_resampler_speex(SpeexResamplerState * r, cubeb_stream * s, cubeb_stream_params params, uint32_t out_rate, cubeb_data_callback cb, long max_count, void * ptr) : speex_resampler(r) , stream(s) , stream_params(params) , data_callback(cb) , user_ptr(ptr) , buffer_frame_count(max_count) , resampling_ratio(static_cast<float>(params.rate) / out_rate) , leftover_frame_size(static_cast<uint32_t>(ceilf(1 / resampling_ratio * 2) + 1)) , leftover_frame_count(0) , leftover_frames_buffer(auto_array<uint8_t>(frames_to_bytes(params, leftover_frame_size))) , resampling_src_buffer(auto_array<uint8_t>(frames_to_bytes(params, frame_count_at_rate(buffer_frame_count, resampling_ratio)))) { assert(r); }
static int snd_bcm2835_pcm_copy(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count) { int ret; struct snd_pcm_runtime *runtime = substream->runtime; bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; audio_info(" .. IN\n"); audio_debug("copy.......... (%d) hwptr=%d appl=%d pos=%d\n", frames_to_bytes(runtime, count), frames_to_bytes(runtime, runtime-> status-> hw_ptr), frames_to_bytes(runtime, runtime->control->appl_ptr), alsa_stream->pos); ret = bcm2835_audio_write(alsa_stream, frames_to_bytes(runtime, count), src); audio_info(" .. OUT\n"); return ret; }
static int loopback_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct loopback_pcm *dpcm = runtime->private_data; struct loopback_cable *cable = dpcm->cable; int bps, salign; salign = (snd_pcm_format_width(runtime->format) * runtime->channels) / 8; bps = salign * runtime->rate; if (bps <= 0 || salign <= 0) return -EINVAL; dpcm->buf_pos = 0; dpcm->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { dpcm->silent_size = dpcm->pcm_buffer_size; snd_pcm_format_set_silence(runtime->format, runtime->dma_area, runtime->buffer_size * runtime->channels); } dpcm->irq_pos = 0; dpcm->period_update_pending = 0; dpcm->pcm_bps = bps; dpcm->pcm_salign = salign; dpcm->pcm_period_size = frames_to_bytes(runtime, runtime->period_size); mutex_lock(&dpcm->loopback->cable_lock); if (!(cable->valid & ~(1 << substream->stream)) || (get_setup(dpcm)->notify && substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) params_change(substream); cable->valid |= 1 << substream->stream; mutex_unlock(&dpcm->loopback->cable_lock); return 0; }
static snd_pcm_uframes_t snd_card_saudio_pcm_pointer(struct snd_pcm_substream *substream) { const struct snd_saudio *saudio = snd_pcm_substream_chip(substream); const int stream_id = substream->pstr->stream; const int dev = substream->pcm->device; struct snd_pcm_runtime *runtime = substream->runtime; struct saudio_stream *stream = (struct saudio_stream *)&(saudio->dev_ctrl[dev].stream[stream_id]); unsigned int offset; offset = stream->hwptr_done * frames_to_bytes(runtime, runtime->period_size); return bytes_to_frames(runtime, offset); }
static snd_pcm_uframes_t vaudio_snd_pointer (struct snd_pcm_substream* substream) { const NkVaudio chip = snd_pcm_substream_chip(substream); const int stream_id = substream->pstr->stream; const int dev = substream->pcm->device; struct vaudio_stream* s = &chip->s[dev][stream_id]; struct snd_pcm_runtime* runtime = substream->runtime; unsigned int offset; ADEBUG(); offset = s->hwptr_done * frames_to_bytes(runtime, runtime->period_size); return bytes_to_frames(runtime, offset); }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Function Name: PcmPlaybackPrepare * * Description: Prepare PCM playback device, next call is Trigger or Close * *------------------------------------------------------------ */ static int PcmPlaybackPrepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; brcm_alsa_chip_t *chip = snd_pcm_substream_chip(substream); BRCM_AUDIO_Param_Prepare_t parm_prepare; aTrace(LOG_ALSA_INTERFACE, "ALSA-CAPH playback_prepare " "stream=%d period=%d period_size=%d," "bufsize=%d start_threshold=%ld stop_threshold=%ld" " frame_bits %d rate=%d ch=%d\n", substream->number, (int)runtime->periods, (int)runtime->period_size, (int)runtime->buffer_size, runtime->start_threshold, runtime->stop_threshold, runtime->frame_bits, runtime->rate, runtime->channels); chip->streamCtl[substream->number].stream_hw_ptr = 0; parm_prepare.drv_handle = substream->runtime->private_data; parm_prepare.cbParams.pfCallBack = AUDIO_DRIVER_InterruptPeriodCB; parm_prepare.cbParams.pPrivateData = (void *)substream; parm_prepare.period_count = runtime->periods; parm_prepare.period_bytes = frames_to_bytes(runtime, runtime->period_size); parm_prepare.buf_param.buf_size = runtime->dma_bytes; /*virtual address */ parm_prepare.buf_param.pBuf = runtime->dma_area; /* physical address */ parm_prepare.buf_param.phy_addr = (UInt32) (runtime->dma_addr); aTrace(LOG_ALSA_INTERFACE, "buf_size = %d pBuf=0x%lx phy_addr=0x%x\n", runtime->dma_bytes, (UInt32) runtime->dma_area, runtime->dma_addr); parm_prepare.drv_config.sample_rate = runtime->rate; parm_prepare.drv_config.num_channel = runtime->channels; parm_prepare.drv_config.bits_per_sample = 16; parm_prepare.drv_config.instanceId = substream->number; parm_prepare.drv_config.arm2sp_mixMode = chip->pi32SpeechMixOption[substream->number]; parm_prepare.stream = substream->number; AUDIO_Ctrl_Trigger(ACTION_AUD_SetPrePareParameters, &parm_prepare, NULL, 0); /* DEBUG("\n%lx:playback_prepare period bytes=%d, periods =%d, buffersize=%d\n",jiffies, g_brcm_alsa_chip->period_bytes[0], runtime->periods, runtime->dma_bytes); */ return 0; }
static int atmel_abdac_prepare_dma(struct atmel_abdac *dac, struct snd_pcm_substream *substream, enum dma_data_direction direction) { struct dma_chan *chan = dac->dma.chan; struct dw_cyclic_desc *cdesc; struct snd_pcm_runtime *runtime = substream->runtime; unsigned long buffer_len, period_len; /* * We don't do DMA on "complex" transfers, i.e. with * non-halfword-aligned buffers or lengths. */ if (runtime->dma_addr & 1 || runtime->buffer_size & 1) { dev_dbg(&dac->pdev->dev, "too complex transfer\n"); return -EINVAL; } buffer_len = frames_to_bytes(runtime, runtime->buffer_size); period_len = frames_to_bytes(runtime, runtime->period_size); cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, period_len, DMA_TO_DEVICE); if (IS_ERR(cdesc)) { dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n"); return PTR_ERR(cdesc); } cdesc->period_callback = atmel_abdac_dma_period_done; cdesc->period_callback_param = dac; dac->dma.cdesc = cdesc; set_bit(DMA_READY, &dac->flags); return 0; }
static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; unsigned int sample_size = runtime->sample_bits / 8; void *buf = runtime->dma_area; struct bf5xx_i2s_pcm_data *dma_data; unsigned int offset, size; dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if (dma_data->tdm_mode) { offset = pos * 8 * sample_size; size = count * 8 * sample_size; } else { offset = frames_to_bytes(runtime, pos); size = frames_to_bytes(runtime, count); } snd_pcm_format_set_silence(runtime->format, buf + offset, size); return 0; }
static inline void play_buffer_done (void *arg) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)arg; struct snd_pcm_runtime *runtime = substream->runtime; struct pcm_runtime_data *prtd = substream->runtime->private_data; int size, period_offset, rtbuffersize; rtbuffersize = frames_to_bytes(runtime, runtime->buffer_size); down(&prtd->buf_done_sem); if ((frames_to_bytes(runtime, prtd->cur_pos) + TEGRA_DEFAULT_BUFFER_SIZE) > rtbuffersize) { size = rtbuffersize - frames_to_bytes(runtime, prtd->cur_pos); } else { size = TEGRA_DEFAULT_BUFFER_SIZE; } prtd->cur_pos += bytes_to_frames(runtime, size); if (prtd->cur_pos < prtd->last_pos) { period_offset = (runtime->buffer_size + prtd->cur_pos) - prtd->last_pos; } else { period_offset = prtd->cur_pos - prtd->last_pos; } if (period_offset >= runtime->period_size) { prtd->last_pos = prtd->cur_pos; snd_pcm_period_elapsed(substream); } if (prtd->cur_pos >= runtime->buffer_size) { prtd->cur_pos -= runtime->buffer_size; } }
int PcmPlaybackSilence(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) { struct snd_pcm_runtime *runtime = substream->runtime; char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, pos); snd_pcm_format_set_silence(runtime->format, hwbuf, count * runtime->channels); /** * Set DMA engine ready bit according to pos and count */ aTrace(LOG_ALSA_INTERFACE, "%s: stream = %d, Called\n", __func__, substream->number); return 0; }
static irqreturn_t mxs_pcm_dma_irq(int irq, void *dev_id) { struct snd_pcm_substream *substream = dev_id; struct snd_pcm_runtime *runtime = substream->runtime; struct mxs_runtime_data *prtd = substream->runtime->private_data; struct mxs_dma_info dma_info; void *pdma; unsigned long prev_appl_offset, appl_count, cont, appl_ptr_bytes; mxs_dma_get_info(prtd->dma_ch, &dma_info); if (dma_info.status) { printk(KERN_WARNING "%s: DMA audio channel %d (%s) error\n", __func__, prtd->params->dma_ch, prtd->params->name); mxs_dma_ack_irq(prtd->dma_ch); } else { if ((prtd->params->dma_ch == MXS_DMA_CHANNEL_AHB_APBX_SPDIF) && (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) && (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) && ((prtd->format == SNDRV_PCM_FORMAT_S24_LE) || (prtd->format == SNDRV_PCM_FORMAT_S20_3LE))) { appl_ptr_bytes = frames_to_bytes(runtime, runtime->control->appl_ptr); appl_count = appl_ptr_bytes - prtd->appl_ptr_bytes; prev_appl_offset = prtd->appl_ptr_bytes % prtd->dma_totsize; cont = prtd->dma_totsize - prev_appl_offset; if (appl_count > cont) { pdma = runtime->dma_area + prev_appl_offset; memmove(pdma + 1, pdma, cont - 1); pdma = runtime->dma_area; memmove(pdma + 1, pdma, appl_count - cont - 1); } else { pdma = runtime->dma_area + prev_appl_offset; memmove(pdma + 1, pdma, appl_count - 1); } prtd->appl_ptr_bytes = appl_ptr_bytes; } mxs_dma_ack_irq(prtd->dma_ch); snd_pcm_period_elapsed(substream); } return IRQ_HANDLED; }
/* prepare playback callback */ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream) { emu10k1_t *emu = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; int channel = substream->pcm->device - emu->p16v_device_offset; u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel)); u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size); int i; u32 tmp; //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base); //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->p16v_buffer.addr, emu->p16v_buffer.area, emu->p16v_buffer.bytes); tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); switch (runtime->rate) { case 44100: snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080); break; case 96000: snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040); break; case 192000: snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020); break; case 48000: default: snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000); break; } /* FIXME: Check emu->buffer.size before actually writing to it. */ for(i=0; i < runtime->periods; i++) { table_base[i*2]=runtime->dma_addr+(i*period_size_bytes); table_base[(i*2)+1]=period_size_bytes<<16; } snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel)); snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19); snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0); snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr); //snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0); snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0); snd_emu10k1_ptr20_write(emu, 0x08, channel, 0); return 0; }
static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data) { struct hsw_pcm_data *pcm_data = data; struct snd_pcm_substream *substream = pcm_data->substream; struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; u32 pos; pos = frames_to_bytes(runtime, (runtime->control->appl_ptr % runtime->buffer_size)); dev_dbg(rtd->dev, "PCM: App pointer %d bytes\n", pos); /* let alsa know we have play a period */ snd_pcm_period_elapsed(substream); return pos; }
static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(rtd->platform); struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); struct sst_hsw *hsw = pdata->hsw; snd_pcm_uframes_t offset; offset = bytes_to_frames(runtime, sst_hsw_get_dsp_position(hsw, pcm_data->stream)); dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n", frames_to_bytes(runtime, (u32)offset)); return offset; }
static void audio_dma_irq(void *data) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data; struct snd_pcm_runtime *runtime = substream->runtime; struct mxc_runtime_data *prtd = runtime->private_data; prtd->dma_active = 0; prtd->periods++; prtd->periods %= runtime->periods; dbg("irq per %d offset %x\n", prtd->periods, frames_to_bytes(runtime, runtime->period_size) * prtd->periods); if (prtd->active) snd_pcm_period_elapsed(substream); dma_new_period(substream); }
static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev, const struct urb *urb, const struct usb_iso_packet_descriptor *iso) { unsigned char *usb_buf = urb->transfer_buffer + iso->offset; unsigned char check_byte; struct snd_pcm_substream *sub; int stream, i; for (i = 0; i < iso->actual_length;) { if (i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 0) { for (stream = 0; stream < dev->n_streams; stream++, i++) { if (dev->first_packet) continue; check_byte = MAKE_CHECKBYTE(dev, stream, i); if ((usb_buf[i] & 0x3f) != check_byte) dev->input_panic = 1; if (usb_buf[i] & 0x80) dev->output_panic = 1; } } dev->first_packet = 0; for (stream = 0; stream < dev->n_streams; stream++, i++) { sub = dev->sub_capture[stream]; if (dev->input_panic) usb_buf[i] = 0; if (sub) { struct snd_pcm_runtime *rt = sub->runtime; char *audio_buf = rt->dma_area; int sz = frames_to_bytes(rt, rt->buffer_size); audio_buf[dev->audio_in_buf_pos[stream]++] = usb_buf[i]; dev->period_in_count[stream]++; if (dev->audio_in_buf_pos[stream] == sz) dev->audio_in_buf_pos[stream] = 0; } } } }
static int dma_new_period(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct mxc_runtime_data *prtd = runtime->private_data; unsigned int dma_size = frames_to_bytes(runtime, runtime->period_size); unsigned int offset = dma_size * prtd->period; int ret = 0; mxc_dma_requestbuf_t sdma_request; if (!prtd->active) return 0; memset(&sdma_request, 0, sizeof(mxc_dma_requestbuf_t)); dbg("period pos ALSA %x DMA %x\n", runtime->periods, prtd->period); dbg("period size ALSA %x DMA %x Offset %x dmasize %x\n", (unsigned int)runtime->period_size, runtime->dma_bytes, offset, dma_size); dbg("DMA addr %x\n", runtime->dma_addr + offset); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) sdma_request.src_addr = (dma_addr_t) (runtime->dma_addr + offset); else sdma_request.dst_addr = (dma_addr_t) (runtime->dma_addr + offset); sdma_request.num_of_bytes = dma_size; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { mxc_dma_config(prtd->dma_wchannel, &sdma_request, 1, MXC_DMA_MODE_WRITE); ret = mxc_dma_enable(prtd->dma_wchannel); } else { mxc_dma_config(prtd->dma_wchannel, &sdma_request, 1, MXC_DMA_MODE_READ); ret = mxc_dma_enable(prtd->dma_wchannel); } prtd->dma_active = 1; prtd->period++; prtd->period %= runtime->periods; return ret; }
static irqreturn_t bcm2835_playback_fifo_irq(int irq, void *dev_id) { bcm2835_alsa_stream_t *alsa_stream = (bcm2835_alsa_stream_t *) dev_id; uint32_t consumed = 0; int new_period = 0; audio_info(" .. IN\n"); audio_info("alsa_stream=%p substream=%p\n", alsa_stream, alsa_stream ? alsa_stream->substream : 0); if (alsa_stream->open) consumed = bcm2835_audio_retrieve_buffers(alsa_stream); /* We get called only if playback was triggered, So, the number of buffers we retrieve in * each iteration are the buffers that have been played out already */ if (alsa_stream->period_size) { if ((alsa_stream->pos / alsa_stream->period_size) != ((alsa_stream->pos + consumed) / alsa_stream->period_size)) new_period = 1; } audio_debug("updating pos cur: %d + %d max:%d period_bytes:%d, hw_ptr: %d new_period:%d\n", alsa_stream->pos, consumed, alsa_stream->buffer_size, (int)(alsa_stream->period_size*alsa_stream->substream->runtime->periods), frames_to_bytes(alsa_stream->substream->runtime, alsa_stream->substream->runtime->status->hw_ptr), new_period); if (alsa_stream->buffer_size) { alsa_stream->pos += consumed &~ (1<<30); alsa_stream->pos %= alsa_stream->buffer_size; } if (alsa_stream->substream) { if (new_period) snd_pcm_period_elapsed(alsa_stream->substream); } else { audio_warning(" unexpected NULL substream\n"); } audio_info(" .. OUT\n"); return IRQ_HANDLED; }