static void audio_buffdone(void *data) { struct snd_pcm_substream *substream = data; struct runtime_data *prtd; pr_debug("Entered %s\n", __func__); if (!substream) return; prtd = substream->runtime->private_data; if (prtd->state & ST_RUNNING) { snd_pcm_period_elapsed(substream); if (!samsung_dma_has_circular()) { spin_lock(&prtd->lock); prtd->dma_loaded--; if (!samsung_dma_has_infiniteloop()) dma_enqueue(substream); spin_unlock(&prtd->lock); } } }
/* dma_enqueue * * place a dma buffer onto the queue for the dma system * to handle. */ static void dma_enqueue(struct snd_pcm_substream *substream) { struct runtime_data *prtd = substream->runtime->private_data; dma_addr_t pos = prtd->dma_pos; unsigned int limit; struct samsung_dma_prep dma_info; pr_debug("Entered %s\n", __func__); limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period; pr_debug("%s: loaded %d, limit %d\n", __func__, prtd->dma_loaded, limit); dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE); dma_info.direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); dma_info.fp = audio_buffdone; dma_info.fp_param = substream; dma_info.period = prtd->dma_period; dma_info.len = prtd->dma_period*limit; if (samsung_dma_has_infiniteloop()) { dma_info.buf = prtd->dma_pos; dma_info.infiniteloop = limit; prtd->params->ops->prepare(prtd->params->ch, &dma_info); } else { dma_info.infiniteloop = 0; while (prtd->dma_loaded < limit) { pr_debug("dma_loaded: %d\n", prtd->dma_loaded); if ((pos + dma_info.period) > prtd->dma_end) { dma_info.period = prtd->dma_end - pos; pr_debug("%s: corrected dma len %ld\n", __func__, dma_info.period); } dma_info.buf = pos; prtd->params->ops->prepare(prtd->params->ch, &dma_info); prtd->dma_loaded++; pos += prtd->dma_period; if (pos >= prtd->dma_end) pos = prtd->dma_start; } prtd->dma_pos = pos; } }