diff options
-rw-r--r-- | sound/soc/tegra/tegra_asoc_utils.c | 41 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_asoc_utils.h | 1 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_pcm.c | 6 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_pcm.h | 1 |
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); |