Skip to content

Commit

Permalink
ASoC: davinci-pcm buildfixes
Browse files Browse the repository at this point in the history
This is a buildfix for the DaVinci PCM code, resyncing it with
the version in the DaVinci tree.  The notable change is using
current EDMA interfaces, which recently merged to mainline.
(The older interfaces never made it into mainline.)

NOTE:  open issue, the DMA should be to/from SRAM; see chip
errata for more info.  The artifacts are extremely easy to
hear on DM355 hardware (not yet supported in mainline), but
don't seem as audible on DM6446 hardwaare (which does have
mainline support).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
  • Loading branch information
David Brownell authored and Mark Brown committed May 15, 2009
1 parent 1ffafeb commit 82075af
Showing 1 changed file with 42 additions and 29 deletions.
71 changes: 42 additions & 29 deletions sound/soc/davinci/davinci-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <sound/soc.h>

#include <asm/dma.h>
#include <mach/edma.h>

#include "davinci-pcm.h"

Expand Down Expand Up @@ -51,7 +52,7 @@ struct davinci_runtime_data {
spinlock_t lock;
int period; /* current DMA period */
int master_lch; /* Master DMA channel */
int slave_lch; /* Slave DMA channel */
int slave_lch; /* linked parameter RAM reload slot */
struct davinci_pcm_dma_params *params; /* DMA params */
};

Expand Down Expand Up @@ -90,18 +91,18 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
dst_bidx = data_type;
}

davinci_set_dma_src_params(lch, src, INCR, W8BIT);
davinci_set_dma_dest_params(lch, dst, INCR, W8BIT);
davinci_set_dma_src_index(lch, src_bidx, 0);
davinci_set_dma_dest_index(lch, dst_bidx, 0);
davinci_set_dma_transfer_params(lch, data_type, count, 1, 0, ASYNC);
edma_set_src(lch, src, INCR, W8BIT);
edma_set_dest(lch, dst, INCR, W8BIT);
edma_set_src_index(lch, src_bidx, 0);
edma_set_dest_index(lch, dst_bidx, 0);
edma_set_transfer_params(lch, data_type, count, 1, 0, ASYNC);

prtd->period++;
if (unlikely(prtd->period >= runtime->periods))
prtd->period = 0;
}

static void davinci_pcm_dma_irq(int lch, u16 ch_status, void *data)
static void davinci_pcm_dma_irq(unsigned lch, u16 ch_status, void *data)
{
struct snd_pcm_substream *substream = data;
struct davinci_runtime_data *prtd = substream->runtime->private_data;
Expand All @@ -125,7 +126,7 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
struct davinci_runtime_data *prtd = substream->runtime->private_data;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct davinci_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data;
int tcc = TCC_ANY;
struct edmacc_param p_ram;
int ret;

if (!dma_data)
Expand All @@ -134,22 +135,34 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
prtd->params = dma_data;

/* Request master DMA channel */
ret = davinci_request_dma(prtd->params->channel, prtd->params->name,
ret = edma_alloc_channel(prtd->params->channel,
davinci_pcm_dma_irq, substream,
&prtd->master_lch, &tcc, EVENTQ_0);
if (ret)
EVENTQ_0);
if (ret < 0)
return ret;
prtd->master_lch = ret;

/* Request slave DMA channel */
ret = davinci_request_dma(PARAM_ANY, "Link",
NULL, NULL, &prtd->slave_lch, &tcc, EVENTQ_0);
if (ret) {
davinci_free_dma(prtd->master_lch);
/* Request parameter RAM reload slot */
ret = edma_alloc_slot(EDMA_SLOT_ANY);
if (ret < 0) {
edma_free_channel(prtd->master_lch);
return ret;
}

/* Link slave DMA channel in loopback */
davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch);
prtd->slave_lch = ret;

/* Issue transfer completion IRQ when the channel completes a
* transfer, then always reload from the same slot (by a kind
* of loopback link). The completion IRQ handler will update
* the reload slot with a new buffer.
*
* REVISIT save p_ram here after setting up everything except
* the buffer and its length (ccnt) ... use it as a template
* so davinci_pcm_enqueue_dma() takes less time in IRQ.
*/
edma_read_slot(prtd->slave_lch, &p_ram);
p_ram.opt |= TCINTEN | EDMA_TCC(prtd->master_lch);
p_ram.link_bcntrld = prtd->slave_lch << 5;
edma_write_slot(prtd->slave_lch, &p_ram);

return 0;
}
Expand All @@ -165,12 +178,12 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
davinci_start_dma(prtd->master_lch);
edma_start(prtd->master_lch);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
davinci_stop_dma(prtd->master_lch);
edma_stop(prtd->master_lch);
break;
default:
ret = -EINVAL;
Expand All @@ -185,14 +198,14 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
{
struct davinci_runtime_data *prtd = substream->runtime->private_data;
struct paramentry_descriptor temp;
struct edmacc_param temp;

prtd->period = 0;
davinci_pcm_enqueue_dma(substream);

/* Get slave channel dma params for master channel startup */
davinci_get_dma_params(prtd->slave_lch, &temp);
davinci_set_dma_params(prtd->master_lch, &temp);
/* Copy self-linked parameter RAM entry into master channel */
edma_read_slot(prtd->slave_lch, &temp);
edma_write_slot(prtd->master_lch, &temp);

return 0;
}
Expand All @@ -208,7 +221,7 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream)

spin_lock(&prtd->lock);

davinci_dma_getposition(prtd->master_lch, &src, &dst);
edma_get_position(prtd->master_lch, &src, &dst);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
count = src - runtime->dma_addr;
else
Expand Down Expand Up @@ -253,10 +266,10 @@ static int davinci_pcm_close(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct davinci_runtime_data *prtd = runtime->private_data;

davinci_dma_unlink_lch(prtd->slave_lch, prtd->slave_lch);
edma_unlink(prtd->slave_lch);

davinci_free_dma(prtd->slave_lch);
davinci_free_dma(prtd->master_lch);
edma_free_slot(prtd->slave_lch);
edma_free_channel(prtd->master_lch);

kfree(prtd);

Expand Down

0 comments on commit 82075af

Please sign in to comment.