Thread (44 messages) flat view 44 messages, 10 authors, 2011-08-25
STALE5474d

[PATCH 14/15] ASoC: Samsung: Update DMA interface

From: jassisinghbrar@gmail.com (Jassi Brar)
Date: 2011-08-08 19:27:44
Also in: linux-samsung-soc

On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim [off-list ref] wrote:
?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;
- ? ? ? int ret;
+ ? ? ? struct samsung_dma_prep_info dma_info;

? ? ? ?pr_debug("Entered %s\n", __func__);

- ? ? ? if (s3c_dma_has_circular())
- ? ? ? ? ? ? ? limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
- ? ? ? else
- ? ? ? ? ? ? ? limit = prtd->dma_limit;
+ ? ? ? limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
'dma_limit' is rendered useless, so you might want to remove it from
'struct runtime_data'
as well.
? ? ? ?pr_debug("%s: loaded %d, limit %d\n",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?__func__, prtd->dma_loaded, limit);

- ? ? ? while (prtd->dma_loaded < limit) {
- ? ? ? ? ? ? ? unsigned long len = prtd->dma_period;
+ ? ? ? dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
+ ? ? ? dma_info.direction =
+ ? ? ? ? ? ? ? (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+ ? ? ? ? ? ? ? ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ ? ? ? dma_info.fp = audio_buffdone;
+ ? ? ? dma_info.fp_param = substream;
+ ? ? ? dma_info.period = prtd->dma_period;
+ ? ? ? dma_info.len = prtd->dma_period*limit;

+ ? ? ? while (prtd->dma_loaded < limit) {
? ? ? ? ? ? ? ?pr_debug("dma_loaded: %d\n", prtd->dma_loaded);

- ? ? ? ? ? ? ? if ((pos + len) > prtd->dma_end) {
- ? ? ? ? ? ? ? ? ? ? ? len ?= prtd->dma_end - pos;
- ? ? ? ? ? ? ? ? ? ? ? pr_debug("%s: corrected dma len %ld\n", __func__, len);
+ ? ? ? ? ? ? ? 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);
? ? ? ? ? ? ? ?}

- ? ? ? ? ? ? ? ret = s3c2410_dma_enqueue(prtd->params->channel,
- ? ? ? ? ? ? ? ? ? ? ? substream, pos, len);
+ ? ? ? ? ? ? ? dma_info.buf = pos;
+ ? ? ? ? ? ? ? prtd->params->ops->prepare(prtd->params->ch, &dma_info);

- ? ? ? ? ? ? ? if (ret == 0) {
- ? ? ? ? ? ? ? ? ? ? ? prtd->dma_loaded++;
- ? ? ? ? ? ? ? ? ? ? ? pos += prtd->dma_period;
- ? ? ? ? ? ? ? ? ? ? ? if (pos >= prtd->dma_end)
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pos = prtd->dma_start;
- ? ? ? ? ? ? ? } else
- ? ? ? ? ? ? ? ? ? ? ? break;
+ ? ? ? ? ? ? ? prtd->dma_loaded++;
+ ? ? ? ? ? ? ? pos += prtd->dma_period;
+ ? ? ? ? ? ? ? if (pos >= prtd->dma_end)
+ ? ? ? ? ? ? ? ? ? ? ? pos = prtd->dma_start;
? ? ? ?}

? ? ? ?prtd->dma_pos = pos;
?}

-static void audio_buffdone(struct s3c2410_dma_chan *channel,
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? void *dev_id, int size,
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? enum s3c2410_dma_buffresult result)
+static void audio_buffdone(void *data)
?{
- ? ? ? struct snd_pcm_substream *substream = dev_id;
- ? ? ? struct runtime_data *prtd;
+ ? ? ? struct snd_pcm_substream *substream = data;
+ ? ? ? struct runtime_data *prtd = substream->runtime->private_data;

? ? ? ?pr_debug("Entered %s\n", __func__);

- ? ? ? if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
- ? ? ? ? ? ? ? return;
-
- ? ? ? prtd = substream->runtime->private_data;
+ ? ? ? if (prtd->state & ST_RUNNING) {
+ ? ? ? ? ? ? ? prtd->dma_pos += prtd->dma_period;
+ ? ? ? ? ? ? ? if (prtd->dma_pos >= prtd->dma_end)
+ ? ? ? ? ? ? ? ? ? ? ? prtd->dma_pos = prtd->dma_start;

- ? ? ? if (substream)
- ? ? ? ? ? ? ? snd_pcm_period_elapsed(substream);
+ ? ? ? ? ? ? ? if (substream)
+ ? ? ? ? ? ? ? ? ? ? ? snd_pcm_period_elapsed(substream);

- ? ? ? spin_lock(&prtd->lock);
- ? ? ? if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
- ? ? ? ? ? ? ? prtd->dma_loaded--;
- ? ? ? ? ? ? ? dma_enqueue(substream);
+ ? ? ? ? ? ? ? spin_lock(&prtd->lock);
+ ? ? ? ? ? ? ? if (!samsung_dma_has_circular()) {
+ ? ? ? ? ? ? ? ? ? ? ? prtd->dma_loaded--;
+ ? ? ? ? ? ? ? ? ? ? ? dma_enqueue(substream);
+ ? ? ? ? ? ? ? }
+ ? ? ? ? ? ? ? spin_unlock(&prtd->lock);
? ? ? ?}
-
- ? ? ? spin_unlock(&prtd->lock);
?}
Since we set integer-constraint on number of periods, you could also
discard bothering fractional boundaries. That would make things a lot
simpler.


quoted hunk ↗ jump to hunk
@@ -265,14 +250,14 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
? ? ? ?case SNDRV_PCM_TRIGGER_RESUME:
? ? ? ?case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
? ? ? ? ? ? ? ?prtd->state |= ST_RUNNING;
- ? ? ? ? ? ? ? s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
+ ? ? ? ? ? ? ? prtd->params->ops->trigger(prtd->params->ch);
? ? ? ? ? ? ? ?break;

? ? ? ?case SNDRV_PCM_TRIGGER_STOP:
? ? ? ?case SNDRV_PCM_TRIGGER_SUSPEND:
? ? ? ?case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
? ? ? ? ? ? ? ?prtd->state &= ~ST_RUNNING;
- ? ? ? ? ? ? ? s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STOP);
+ ? ? ? ? ? ? ? prtd->params->ops->stop(prtd->params->ch);
? ? ? ? ? ? ? ?break;
I wish you agreed and used
       prtd->params->ops->cmd(ch, enum some_cmd_options)
rather than having 4 separate callbacks
      prtd->params->ops->trigger(prtd->params->ch)
      prtd->params->ops->stop(prtd->params->ch)
     prtd->params->ops->flush(prtd->params->ch)
     prtd->params->ops->started(prtd->params->ch)

quoted hunk ↗ jump to hunk
@@ -291,21 +276,12 @@ dma_pointer(struct snd_pcm_substream *substream)
? ? ? ?struct snd_pcm_runtime *runtime = substream->runtime;
? ? ? ?struct runtime_data *prtd = runtime->private_data;
? ? ? ?unsigned long res;
- ? ? ? dma_addr_t src, dst;

? ? ? ?pr_debug("Entered %s\n", __func__);

- ? ? ? spin_lock(&prtd->lock);
- ? ? ? s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
-
- ? ? ? if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- ? ? ? ? ? ? ? res = dst - prtd->dma_start;
- ? ? ? else
- ? ? ? ? ? ? ? res = src - prtd->dma_start;
-
- ? ? ? spin_unlock(&prtd->lock);
+ ? ? ? res = prtd->dma_pos - prtd->dma_start;

- ? ? ? pr_debug("Pointer %x %x\n", src, dst);
+ ? ? ? pr_debug("Pointer offset: %lu\n", res);

? ? ? ?/* we seem to be getting the odd error from the pcm library due
? ? ? ? * to out-of-bounds pointers. this is maybe due to the dma engine
Isn't this a regression ?
dma_pointer() doesn't really return actual location of DMA activity anymore.
Now it simply tells the last period done.
This would affect latencies in a bad way.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help