summaryrefslogtreecommitdiff
path: root/sound/soc
diff options
context:
space:
mode:
authorSumit Bhattacharya <sumitb@nvidia.com>2012-08-27 16:07:39 +0800
committerSimone Willett <swillett@nvidia.com>2012-09-04 17:10:33 -0700
commit49553e9c6dd0ef9dac304adc69c676b0b000d31f (patch)
tree988009ee9e4a159261fd655b562ebb9524d4deef /sound/soc
parentbad016421fc94642de2ad70a78d2917549d81541 (diff)
ASoC: Tegra: Add ALSA ctl to set DMA address
Add support for setting of DMA address through alsa control for AVP rendering. This is required to directly do DMA from IRAM to I2S. Bug 1024403 Change-Id: I6b79ae6e9a562160a19d238b817e1a8b407ac208 Signed-off-by: Sumit Bhattacharya <sumitb@nvidia.com> Reviewed-on: http://git-master/r/127436 (cherry picked from commit f270f46bef98a56f44432e608041adb617c22559) Signed-off-by: Chandrakanth Gorantla <cgorantla@nvidia.com> Change-Id: I195aae9043f967273283579f44d5367fe73d542f Reviewed-on: http://git-master/r/129159 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Scott Peterson <speterson@nvidia.com>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.c41
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.h1
-rw-r--r--sound/soc/tegra/tegra_pcm.c6
-rw-r--r--sound/soc/tegra/tegra_pcm.h1
4 files changed, 45 insertions, 4 deletions
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index 2c18a71b8b52..80d22d203fb6 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -86,8 +86,11 @@ static int tegra_set_avp_device(struct snd_kcontrol *kcontrol,
prtd = substream->runtime->private_data;
if (prtd->running)
return -EBUSY;
- if (prtd)
+ if (prtd) {
prtd->disable_intr = true;
+ if (data->avp_dma_addr || prtd->avp_dma_addr)
+ prtd->avp_dma_addr = data->avp_dma_addr;
+ }
}
}
data->avp_device_id = id;
@@ -121,6 +124,30 @@ static int tegra_get_dma_ch_id(struct snd_kcontrol *kcontrol,
return 0;
}
+static int tegra_set_dma_addr(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = data->card;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_pcm_substream *substream;
+ struct tegra_runtime_data *prtd;
+
+ data->avp_dma_addr = ucontrol->value.integer.value[0];
+
+ rtd = &card->rtd[data->avp_device_id];
+ substream = rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ if (!substream || !substream->runtime)
+ return 0;
+
+ prtd = substream->runtime->private_data;
+ if (!prtd)
+ return 0;
+
+ prtd->avp_dma_addr = data->avp_dma_addr;
+ return 1;
+}
+
static int tegra_get_dma_addr(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -128,6 +155,7 @@ static int tegra_get_dma_addr(struct snd_kcontrol *kcontrol,
struct snd_soc_card *card = data->card;
struct snd_soc_pcm_runtime *rtd;
struct snd_pcm_substream *substream;
+ struct tegra_runtime_data *prtd;
ucontrol->value.integer.value[0] = 0;
if (data->avp_device_id < 0)
@@ -138,7 +166,14 @@ static int tegra_get_dma_addr(struct snd_kcontrol *kcontrol,
if (!substream || !substream->runtime)
return 0;
- ucontrol->value.integer.value[0] = substream->runtime->dma_addr;
+ prtd = substream->runtime->private_data;
+ if (!prtd || !prtd->dma_chan)
+ return 0;
+
+ ucontrol->value.integer.value[0] = prtd->avp_dma_addr ?
+ prtd->avp_dma_addr :
+ substream->runtime->dma_addr;
+
return 0;
}
@@ -148,7 +183,7 @@ struct snd_kcontrol_new tegra_avp_controls[] = {
SOC_SINGLE_EXT("AVP DMA channel id", 0, 0, TEGRA_DMA_MAX_CHANNELS, \
0, tegra_get_dma_ch_id, NULL),
SOC_SINGLE_EXT("AVP DMA address", 0, 0, 0xFFFFFFFF, \
- 0, tegra_get_dma_addr, NULL),
+ 0, tegra_get_dma_addr, tegra_set_dma_addr),
};
int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
index ce379e3e513d..cd137967fcb0 100644
--- a/sound/soc/tegra/tegra_asoc_utils.h
+++ b/sound/soc/tegra/tegra_asoc_utils.h
@@ -43,6 +43,7 @@ struct tegra_asoc_utils_data {
int set_mclk;
int lock_count;
int avp_device_id;
+ unsigned int avp_dma_addr;
};
int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index f471fafff2ac..a7c9c0a110f9 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -70,7 +70,11 @@ static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd)
if (++prtd->dma_req_idx >= prtd->dma_req_count)
prtd->dma_req_idx -= prtd->dma_req_count;
- addr = buf->addr + prtd->dma_pos;
+ if (prtd->avp_dma_addr)
+ addr = prtd->avp_dma_addr + prtd->dma_pos;
+ else
+ addr = buf->addr + prtd->dma_pos;
+
prtd->dma_pos += dma_req->size;
if (prtd->dma_pos >= prtd->dma_pos_end)
prtd->dma_pos = 0;
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h
index b63de32023e8..5a9531b9fbf7 100644
--- a/sound/soc/tegra/tegra_pcm.h
+++ b/sound/soc/tegra/tegra_pcm.h
@@ -54,6 +54,7 @@ struct tegra_runtime_data {
struct tegra_dma_channel *dma_chan;
int dma_req_count;
int disable_intr;
+ unsigned int avp_dma_addr;
};
int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd);