diff options
Diffstat (limited to 'sound/soc/tegra/tegra_asoc_utils.c')
-rw-r--r-- | sound/soc/tegra/tegra_asoc_utils.c | 97 |
1 files changed, 70 insertions, 27 deletions
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c index 6ab5b2d46a1f..99ba90d9fc7b 100644 --- a/sound/soc/tegra/tegra_asoc_utils.c +++ b/sound/soc/tegra/tegra_asoc_utils.c @@ -2,8 +2,7 @@ * tegra_asoc_utils.c - Harmony machine ASoC driver * * Author: Stephen Warren <swarren@nvidia.com> - * Copyright (C) 2010 - NVIDIA, Inc. - * + * Copyright (c) 2010-12, NVIDIA CORPORATION. All rights reserved. * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. @@ -87,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; @@ -122,6 +124,33 @@ 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; + + if (data->avp_device_id < 0) + return 0; + + 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) { @@ -129,6 +158,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) @@ -139,7 +169,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; } @@ -149,7 +186,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, @@ -342,28 +379,6 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, } #endif -#if !defined(CONFIG_ARCH_TEGRA_2x_SOC) -#if TEGRA30_I2S_MASTER_PLAYBACK - ret = clk_set_parent(data->clk_cdev1, data->clk_pll_a_out0); - if (ret) { - dev_err(data->dev, "Can't set clk cdev1/extern1 parent"); - goto err_put_out1; - } -#else - rate = clk_get_rate(data->clk_m); - - if(rate == 26000000) - clk_set_rate(data->clk_cdev1, 13000000); - - ret = clk_set_parent(data->clk_cdev1, data->clk_m); - if (ret) { - dev_err(data->dev, "Can't set clk cdev1/extern1 parent"); - goto err_put_out1; - } -#endif - -#endif - ret = clk_enable(data->clk_cdev1); if (ret) { dev_err(data->dev, "Can't enable clk cdev1/extern1"); @@ -402,6 +417,34 @@ err: } EXPORT_SYMBOL_GPL(tegra_asoc_utils_init); +#if !defined(CONFIG_ARCH_TEGRA_2x_SOC) +int tegra_asoc_utils_set_parent (struct tegra_asoc_utils_data *data, + int is_i2s_master) +{ + int ret = -ENODEV; + + if (is_i2s_master) { + ret = clk_set_parent(data->clk_cdev1, data->clk_pll_a_out0); + if (ret) { + dev_err(data->dev, "Can't set clk cdev1/extern1 parent"); + return ret; + } + } else { + if(clk_get_rate(data->clk_m) == 26000000) + clk_set_rate(data->clk_cdev1, 13000000); + + ret = clk_set_parent(data->clk_cdev1, data->clk_m); + if (ret) { + dev_err(data->dev, "Can't set clk cdev1/extern1 parent"); + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_parent); +#endif + void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data) { if (!IS_ERR(data->clk_out1)) |