summaryrefslogtreecommitdiff
path: root/sound/soc
diff options
context:
space:
mode:
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);