summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorMarcel Ziswiler <marcel.ziswiler@toradex.com>2012-06-22 17:33:24 +0200
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2012-06-22 17:33:24 +0200
commit75cad4850b2edc0e6154fab59e201e24b78d6497 (patch)
treec15f9f38ec6d6bfbbbac59799a8e10c812d663d6 /sound
parent37440f3ed07a6f588b05b8f98d0b3025c1949371 (diff)
asoc: tegra2: ac97 audio capture functionality
Migrate AC97 audio capture aka record functionality.
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/tegra/tegra_pcm.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 3b475a24c9a8..5f2553b3dd66 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -42,6 +42,12 @@
#define DRV_NAME "tegra-pcm-audio"
+#ifdef CONFIG_SND_SOC_TEGRA20_AC97
+/* AC97 capture conversion buffer pointers and sizes */
+static uint *conv_buf[MAX_DMA_REQ_COUNT];
+static uint conv_size[MAX_DMA_REQ_COUNT];
+#endif /* CONFIG_SND_SOC_TEGRA20_AC97 */
+
static const struct snd_pcm_hardware tegra_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -67,18 +73,25 @@ static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd)
unsigned long addr;
dma_req = &prtd->dma_req[prtd->dma_req_idx];
- if (++prtd->dma_req_idx >= prtd->dma_req_count)
- prtd->dma_req_idx -= prtd->dma_req_count;
addr = buf->addr + prtd->dma_pos;
- prtd->dma_pos += dma_req->size;
- if (prtd->dma_pos >= prtd->dma_pos_end)
- prtd->dma_pos = 0;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
dma_req->source_addr = addr;
- else
+ else {
+#ifdef CONFIG_SND_SOC_TEGRA20_AC97
+ conv_buf[prtd->dma_req_idx] = (uint *)(buf->area + prtd->dma_pos);
+ conv_size[prtd->dma_req_idx] = dma_req->size;
+#endif /* CONFIG_SND_SOC_TEGRA20_AC97 */
dma_req->dest_addr = addr;
+ }
+
+ /* Do index and DMA position update last */
+ if (++prtd->dma_req_idx >= prtd->dma_req_count)
+ prtd->dma_req_idx -= prtd->dma_req_count;
+ prtd->dma_pos += dma_req->size;
+ if (prtd->dma_pos >= prtd->dma_pos_end)
+ prtd->dma_pos = 0;
tegra_dma_enqueue_req(prtd->dma_chan, dma_req);
}
@@ -96,6 +109,17 @@ static void dma_complete_callback(struct tegra_dma_req *req)
return;
}
+#ifdef CONFIG_SND_SOC_TEGRA20_AC97
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ while (conv_size[prtd->dma_req_idx]) {
+ /* Convert 20-bit AC97 sample to 32-bit */
+ *conv_buf[prtd->dma_req_idx] <<= 12;
+ conv_buf[prtd->dma_req_idx]++;
+ conv_size[prtd->dma_req_idx]-=4;
+ }
+ }
+#endif /* CONFIG_SND_SOC_TEGRA20_AC97 */
+
if (++prtd->period_index >= runtime->periods)
prtd->period_index = 0;