summaryrefslogtreecommitdiffstats
path: root/sound/soc/tegra
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/tegra')
-rw-r--r--sound/soc/tegra/Kconfig13
-rw-r--r--sound/soc/tegra/tegra20_i2s.c98
-rw-r--r--sound/soc/tegra/tegra20_i2s.h1
-rw-r--r--sound/soc/tegra/tegra20_spdif.c40
-rw-r--r--sound/soc/tegra/tegra20_spdif.h1
-rw-r--r--sound/soc/tegra/tegra30_ahub.c8
-rw-r--r--sound/soc/tegra/tegra30_i2s.c89
-rw-r--r--sound/soc/tegra/tegra30_i2s.h1
-rw-r--r--sound/soc/tegra/tegra_alc5632.c32
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.c12
-rw-r--r--sound/soc/tegra/tegra_pcm.c115
-rw-r--r--sound/soc/tegra/tegra_pcm.h2
-rw-r--r--sound/soc/tegra/tegra_wm8753.c8
-rw-r--r--sound/soc/tegra/tegra_wm8903.c259
-rw-r--r--sound/soc/tegra/trimslice.c30
15 files changed, 352 insertions, 357 deletions
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index c1c8e955f4d..02bcd308c18 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -1,7 +1,8 @@
config SND_SOC_TEGRA
tristate "SoC Audio for the Tegra System-on-Chip"
- depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA
+ depends on ARCH_TEGRA && (TEGRA_SYSTEM_DMA || TEGRA20_APB_DMA)
select REGMAP_MMIO
+ select SND_SOC_DMAENGINE_PCM if TEGRA20_APB_DMA
help
Say Y or M here if you want support for SoC audio on Tegra.
@@ -58,17 +59,9 @@ config SND_SOC_TEGRA_WM8753
Say Y or M here if you want to add support for SoC audio on Tegra
boards using the WM8753 codec, such as Whistler.
-config MACH_HAS_SND_SOC_TEGRA_WM8903
- bool
- help
- Machines that use the SND_SOC_TEGRA_WM8903 driver should select
- this config option, in order to allow the user to enable
- SND_SOC_TEGRA_WM8903.
-
config SND_SOC_TEGRA_WM8903
tristate "SoC Audio support for Tegra boards using a WM8903 codec"
depends on SND_SOC_TEGRA && I2C
- depends on MACH_HAS_SND_SOC_TEGRA_WM8903
select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
select SND_SOC_WM8903
@@ -79,7 +72,7 @@ config SND_SOC_TEGRA_WM8903
config SND_SOC_TEGRA_TRIMSLICE
tristate "SoC Audio support for TrimSlice board"
- depends on SND_SOC_TEGRA && MACH_TRIMSLICE && I2C
+ depends on SND_SOC_TEGRA && I2C
select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
select SND_SOC_TLV320AIC23
help
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index 0c7af63d444..0832e8afd73 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -46,23 +46,11 @@
#define DRV_NAME "tegra20-i2s"
-static inline void tegra20_i2s_write(struct tegra20_i2s *i2s, u32 reg, u32 val)
-{
- regmap_write(i2s->regmap, reg, val);
-}
-
-static inline u32 tegra20_i2s_read(struct tegra20_i2s *i2s, u32 reg)
-{
- u32 val;
- regmap_read(i2s->regmap, reg, &val);
- return val;
-}
-
static int tegra20_i2s_runtime_suspend(struct device *dev)
{
struct tegra20_i2s *i2s = dev_get_drvdata(dev);
- clk_disable(i2s->clk_i2s);
+ clk_disable_unprepare(i2s->clk_i2s);
return 0;
}
@@ -72,7 +60,7 @@ static int tegra20_i2s_runtime_resume(struct device *dev)
struct tegra20_i2s *i2s = dev_get_drvdata(dev);
int ret;
- ret = clk_enable(i2s->clk_i2s);
+ ret = clk_prepare_enable(i2s->clk_i2s);
if (ret) {
dev_err(dev, "clk_enable failed: %d\n", ret);
return ret;
@@ -85,6 +73,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
unsigned int fmt)
{
struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+ unsigned int mask, val;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
@@ -93,10 +82,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
return -EINVAL;
}
- i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_MASTER_ENABLE;
+ mask = TEGRA20_I2S_CTRL_MASTER_ENABLE;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
+ val = TEGRA20_I2S_CTRL_MASTER_ENABLE;
break;
case SND_SOC_DAIFMT_CBM_CFM:
break;
@@ -104,33 +93,35 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
return -EINVAL;
}
- i2s->reg_ctrl &= ~(TEGRA20_I2S_CTRL_BIT_FORMAT_MASK |
- TEGRA20_I2S_CTRL_LRCK_MASK);
+ mask |= TEGRA20_I2S_CTRL_BIT_FORMAT_MASK |
+ TEGRA20_I2S_CTRL_LRCK_MASK;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_DSP_A:
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
+ val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
+ val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
break;
case SND_SOC_DAIFMT_DSP_B:
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_R_LOW;
+ val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
+ val |= TEGRA20_I2S_CTRL_LRCK_R_LOW;
break;
case SND_SOC_DAIFMT_I2S:
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S;
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
+ val |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S;
+ val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
break;
case SND_SOC_DAIFMT_RIGHT_J:
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM;
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
+ val |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM;
+ val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
break;
case SND_SOC_DAIFMT_LEFT_J:
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM;
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
+ val |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM;
+ val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
break;
default:
return -EINVAL;
}
+ regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val);
+
return 0;
}
@@ -138,29 +129,34 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct device *dev = substream->pcm->card->dev;
+ struct device *dev = dai->dev;
struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
- u32 reg;
+ unsigned int mask, val;
int ret, sample_size, srate, i2sclock, bitcnt;
- i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_BIT_SIZE_MASK;
+ mask = TEGRA20_I2S_CTRL_BIT_SIZE_MASK;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_16;
+ val = TEGRA20_I2S_CTRL_BIT_SIZE_16;
sample_size = 16;
break;
case SNDRV_PCM_FORMAT_S24_LE:
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_24;
+ val = TEGRA20_I2S_CTRL_BIT_SIZE_24;
sample_size = 24;
break;
case SNDRV_PCM_FORMAT_S32_LE:
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_32;
+ val = TEGRA20_I2S_CTRL_BIT_SIZE_32;
sample_size = 32;
break;
default:
return -EINVAL;
}
+ mask |= TEGRA20_I2S_CTRL_FIFO_FORMAT_MASK;
+ val |= TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED;
+
+ regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val);
+
srate = params_rate(params);
/* Final "* 2" required by Tegra hardware */
@@ -175,42 +171,44 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream,
bitcnt = (i2sclock / (2 * srate)) - 1;
if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US)
return -EINVAL;
- reg = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
+ val = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
if (i2sclock % (2 * srate))
- reg |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE;
+ val |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE;
- tegra20_i2s_write(i2s, TEGRA20_I2S_TIMING, reg);
+ regmap_write(i2s->regmap, TEGRA20_I2S_TIMING, val);
- tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR,
- TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
- TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
+ regmap_write(i2s->regmap, TEGRA20_I2S_FIFO_SCR,
+ TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
+ TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
return 0;
}
static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s)
{
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO1_ENABLE;
- tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
+ regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
+ TEGRA20_I2S_CTRL_FIFO1_ENABLE,
+ TEGRA20_I2S_CTRL_FIFO1_ENABLE);
}
static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s)
{
- i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO1_ENABLE;
- tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
+ regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
+ TEGRA20_I2S_CTRL_FIFO1_ENABLE, 0);
}
static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s)
{
- i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO2_ENABLE;
- tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
+ regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
+ TEGRA20_I2S_CTRL_FIFO2_ENABLE,
+ TEGRA20_I2S_CTRL_FIFO2_ENABLE);
}
static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s)
{
- i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO2_ENABLE;
- tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
+ regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
+ TEGRA20_I2S_CTRL_FIFO2_ENABLE, 0);
}
static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -261,12 +259,14 @@ static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = {
static const struct snd_soc_dai_driver tegra20_i2s_dai_template = {
.probe = tegra20_i2s_probe,
.playback = {
+ .stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.capture = {
+ .stream_name = "Capture",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
@@ -412,8 +412,6 @@ static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev)
i2s->playback_dma_data.width = 32;
i2s->playback_dma_data.req_sel = dma_ch;
- i2s->reg_ctrl = TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED;
-
pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) {
ret = tegra20_i2s_runtime_resume(&pdev->dev);
diff --git a/sound/soc/tegra/tegra20_i2s.h b/sound/soc/tegra/tegra20_i2s.h
index a57efc6a597..c27069d24d7 100644
--- a/sound/soc/tegra/tegra20_i2s.h
+++ b/sound/soc/tegra/tegra20_i2s.h
@@ -158,7 +158,6 @@ struct tegra20_i2s {
struct tegra_pcm_dma_params capture_dma_data;
struct tegra_pcm_dma_params playback_dma_data;
struct regmap *regmap;
- u32 reg_ctrl;
};
#endif
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
index f9b57418bd0..3ebc8670ba0 100644
--- a/sound/soc/tegra/tegra20_spdif.c
+++ b/sound/soc/tegra/tegra20_spdif.c
@@ -37,24 +37,11 @@
#define DRV_NAME "tegra20-spdif"
-static inline void tegra20_spdif_write(struct tegra20_spdif *spdif, u32 reg,
- u32 val)
-{
- regmap_write(spdif->regmap, reg, val);
-}
-
-static inline u32 tegra20_spdif_read(struct tegra20_spdif *spdif, u32 reg)
-{
- u32 val;
- regmap_read(spdif->regmap, reg, &val);
- return val;
-}
-
static int tegra20_spdif_runtime_suspend(struct device *dev)
{
struct tegra20_spdif *spdif = dev_get_drvdata(dev);
- clk_disable(spdif->clk_spdif_out);
+ clk_disable_unprepare(spdif->clk_spdif_out);
return 0;
}
@@ -64,7 +51,7 @@ static int tegra20_spdif_runtime_resume(struct device *dev)
struct tegra20_spdif *spdif = dev_get_drvdata(dev);
int ret;
- ret = clk_enable(spdif->clk_spdif_out);
+ ret = clk_prepare_enable(spdif->clk_spdif_out);
if (ret) {
dev_err(dev, "clk_enable failed: %d\n", ret);
return ret;
@@ -77,21 +64,24 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct device *dev = substream->pcm->card->dev;
+ struct device *dev = dai->dev;
struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+ unsigned int mask, val;
int ret, spdifclock;
- spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_PACK;
- spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
+ mask = TEGRA20_SPDIF_CTRL_PACK |
+ TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
- spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_PACK;
- spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
+ val = TEGRA20_SPDIF_CTRL_PACK |
+ TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
break;
default:
return -EINVAL;
}
+ regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, mask, val);
+
switch (params_rate(params)) {
case 32000:
spdifclock = 4096000;
@@ -129,14 +119,15 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
static void tegra20_spdif_start_playback(struct tegra20_spdif *spdif)
{
- spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_TX_EN;
- tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl);
+ regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL,
+ TEGRA20_SPDIF_CTRL_TX_EN,
+ TEGRA20_SPDIF_CTRL_TX_EN);
}
static void tegra20_spdif_stop_playback(struct tegra20_spdif *spdif)
{
- spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_TX_EN;
- tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl);
+ regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL,
+ TEGRA20_SPDIF_CTRL_TX_EN, 0);
}
static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -181,6 +172,7 @@ static struct snd_soc_dai_driver tegra20_spdif_dai = {
.name = DRV_NAME,
.probe = tegra20_spdif_probe,
.playback = {
+ .stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
diff --git a/sound/soc/tegra/tegra20_spdif.h b/sound/soc/tegra/tegra20_spdif.h
index ed756527efe..b48d699fd58 100644
--- a/sound/soc/tegra/tegra20_spdif.h
+++ b/sound/soc/tegra/tegra20_spdif.h
@@ -465,7 +465,6 @@ struct tegra20_spdif {
struct tegra_pcm_dma_params capture_dma_data;
struct tegra_pcm_dma_params playback_dma_data;
struct regmap *regmap;
- u32 reg_ctrl;
};
#endif
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index f43edb364a1..bf5610122c7 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -56,8 +56,8 @@ static int tegra30_ahub_runtime_suspend(struct device *dev)
regcache_cache_only(ahub->regmap_apbif, true);
regcache_cache_only(ahub->regmap_ahub, true);
- clk_disable(ahub->clk_apbif);
- clk_disable(ahub->clk_d_audio);
+ clk_disable_unprepare(ahub->clk_apbif);
+ clk_disable_unprepare(ahub->clk_d_audio);
return 0;
}
@@ -77,12 +77,12 @@ static int tegra30_ahub_runtime_resume(struct device *dev)
{
int ret;
- ret = clk_enable(ahub->clk_d_audio);
+ ret = clk_prepare_enable(ahub->clk_d_audio);
if (ret) {
dev_err(dev, "clk_enable d_audio failed: %d\n", ret);
return ret;
}
- ret = clk_enable(ahub->clk_apbif);
+ ret = clk_prepare_enable(ahub->clk_apbif);
if (ret) {
dev_err(dev, "clk_enable apbif failed: %d\n", ret);
clk_disable(ahub->clk_d_audio);
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index 8596032985d..44184228d1f 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -44,25 +44,13 @@
#define DRV_NAME "tegra30-i2s"
-static inline void tegra30_i2s_write(struct tegra30_i2s *i2s, u32 reg, u32 val)
-{
- regmap_write(i2s->regmap, reg, val);
-}
-
-static inline u32 tegra30_i2s_read(struct tegra30_i2s *i2s, u32 reg)
-{
- u32 val;
- regmap_read(i2s->regmap, reg, &val);
- return val;
-}
-
static int tegra30_i2s_runtime_suspend(struct device *dev)
{
struct tegra30_i2s *i2s = dev_get_drvdata(dev);
regcache_cache_only(i2s->regmap, true);
- clk_disable(i2s->clk_i2s);
+ clk_disable_unprepare(i2s->clk_i2s);
return 0;
}
@@ -72,7 +60,7 @@ static int tegra30_i2s_runtime_resume(struct device *dev)
struct tegra30_i2s *i2s = dev_get_drvdata(dev);
int ret;
- ret = clk_enable(i2s->clk_i2s);
+ ret = clk_prepare_enable(i2s->clk_i2s);
if (ret) {
dev_err(dev, "clk_enable failed: %d\n", ret);
return ret;
@@ -128,6 +116,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
unsigned int fmt)
{
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+ unsigned int mask, val;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
@@ -136,10 +125,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
return -EINVAL;
}
- i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_MASTER_ENABLE;
+ mask = TEGRA30_I2S_CTRL_MASTER_ENABLE;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
+ val = TEGRA30_I2S_CTRL_MASTER_ENABLE;
break;
case SND_SOC_DAIFMT_CBM_CFM:
break;
@@ -147,33 +136,37 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
return -EINVAL;
}
- i2s->reg_ctrl &= ~(TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
- TEGRA30_I2S_CTRL_LRCK_MASK);
+ mask |= TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
+ TEGRA30_I2S_CTRL_LRCK_MASK;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_DSP_A:
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
+ val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
+ val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
break;
case SND_SOC_DAIFMT_DSP_B:
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
+ val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
+ val |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
break;
case SND_SOC_DAIFMT_I2S:
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
+ val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
+ val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
break;
case SND_SOC_DAIFMT_RIGHT_J:
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
+ val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
+ val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
break;
case SND_SOC_DAIFMT_LEFT_J:
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
+ val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
+ val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
break;
default:
return -EINVAL;
}
+ pm_runtime_get_sync(dai->dev);
+ regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
+ pm_runtime_put(dai->dev);
+
return 0;
}
@@ -181,24 +174,26 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct device *dev = substream->pcm->card->dev;
+ struct device *dev = dai->dev;
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
- u32 val;
+ unsigned int mask, val, reg;
int ret, sample_size, srate, i2sclock, bitcnt;
if (params_channels(params) != 2)
return -EINVAL;
- i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_BIT_SIZE_MASK;
+ mask = TEGRA30_I2S_CTRL_BIT_SIZE_MASK;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_16;
+ val = TEGRA30_I2S_CTRL_BIT_SIZE_16;
sample_size = 16;
break;
default:
return -EINVAL;
}
+ regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
+
srate = params_rate(params);
/* Final "* 2" required by Tegra hardware */
@@ -219,7 +214,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
if (i2sclock % (2 * srate))
val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
- tegra30_i2s_write(i2s, TEGRA30_I2S_TIMING, val);
+ regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val);
val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
(1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
@@ -229,15 +224,17 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
- tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_RX_CTRL, val);
+ reg = TEGRA30_I2S_CIF_RX_CTRL;
} else {
val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
- tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_TX_CTRL, val);
+ reg = TEGRA30_I2S_CIF_RX_CTRL;
}
+ regmap_write(i2s->regmap, reg, val);
+
val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
(1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
- tegra30_i2s_write(i2s, TEGRA30_I2S_OFFSET, val);
+ regmap_write(i2s->regmap, TEGRA30_I2S_OFFSET, val);
return 0;
}
@@ -245,29 +242,31 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s)
{
tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif);
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
- tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
+ regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
+ TEGRA30_I2S_CTRL_XFER_EN_TX,
+ TEGRA30_I2S_CTRL_XFER_EN_TX);
}
static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s)
{
tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif);
- i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
- tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
+ regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
+ TEGRA30_I2S_CTRL_XFER_EN_TX, 0);
}
static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s)
{
tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif);
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX;
- tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
+ regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
+ TEGRA30_I2S_CTRL_XFER_EN_RX,
+ TEGRA30_I2S_CTRL_XFER_EN_RX);
}
static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s)
{
tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif);
- i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
- tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
+ regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
+ TEGRA30_I2S_CTRL_XFER_EN_RX, 0);
}
static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -320,12 +319,14 @@ static struct snd_soc_dai_ops tegra30_i2s_dai_ops = {
static const struct snd_soc_dai_driver tegra30_i2s_dai_template = {
.probe = tegra30_i2s_probe,
.playback = {
+ .stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.capture = {
+ .stream_name = "Capture",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h
index 91adf29c7a8..34dc47b9581 100644
--- a/sound/soc/tegra/tegra30_i2s.h
+++ b/sound/soc/tegra/tegra30_i2s.h
@@ -236,7 +236,6 @@ struct tegra30_i2s {
enum tegra30_ahub_txcif playback_fifo_cif;
struct tegra_pcm_dma_params playback_dma_data;
struct regmap *regmap;
- u32 reg_ctrl;
};
#endif
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index 32de7006daf..e463529b38b 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -1,5 +1,5 @@
/*
- * tegra_alc5632.c -- Toshiba AC100(PAZ00) machine ASoC driver
+* tegra_alc5632.c -- Toshiba AC100(PAZ00) machine ASoC driver
*
* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
* Copyright (C) 2012 - NVIDIA, Inc.
@@ -33,11 +33,8 @@
#define DRV_NAME "tegra-alc5632"
-#define GPIO_HP_DET BIT(0)
-
struct tegra_alc5632 {
struct tegra_asoc_utils_data util_data;
- int gpio_requested;
int gpio_hp_det;
};
@@ -46,7 +43,7 @@ static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = codec_dai->codec;
struct snd_soc_card *card = codec->card;
struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card);
int srate, mclk;
@@ -108,9 +105,9 @@ static const struct snd_kcontrol_new tegra_alc5632_controls[] = {
static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_codec *codec = codec_dai->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- struct device_node *np = codec->card->dev->of_node;
struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card);
snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
@@ -119,14 +116,11 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
ARRAY_SIZE(tegra_alc5632_hs_jack_pins),
tegra_alc5632_hs_jack_pins);
- machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
-
if (gpio_is_valid(machine->gpio_hp_det)) {
tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det;
snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack,
1,
&tegra_alc5632_hp_jack_gpio);
- machine->gpio_requested |= GPIO_HP_DET;
}
snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1");
@@ -159,6 +153,7 @@ static struct snd_soc_card snd_soc_tegra_alc5632 = {
static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
struct snd_soc_card *card = &snd_soc_tegra_alc5632;
struct tegra_alc5632 *alc5632;
int ret;
@@ -181,6 +176,10 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
goto err;
}
+ alc5632->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
+ if (alc5632->gpio_hp_det == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
ret = snd_soc_of_parse_card_name(card, "nvidia,model");
if (ret)
goto err;
@@ -199,16 +198,16 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
goto err;
}
- tegra_alc5632_dai.cpu_dai_of_node = of_parse_phandle(
+ tegra_alc5632_dai.cpu_of_node = of_parse_phandle(
pdev->dev.of_node, "nvidia,i2s-controller", 0);
- if (!tegra_alc5632_dai.cpu_dai_of_node) {
+ if (!tegra_alc5632_dai.cpu_of_node) {
dev_err(&pdev->dev,
"Property 'nvidia,i2s-controller' missing or invalid\n");
ret = -EINVAL;
goto err;
}
- tegra_alc5632_dai.platform_of_node = tegra_alc5632_dai.cpu_dai_of_node;
+ tegra_alc5632_dai.platform_of_node = tegra_alc5632_dai.cpu_of_node;
ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev);
if (ret)
@@ -234,11 +233,8 @@ static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card);
- if (machine->gpio_requested & GPIO_HP_DET)
- snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack,
- 1,
- &tegra_alc5632_hp_jack_gpio);
- machine->gpio_requested = 0;
+ snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack, 1,
+ &tegra_alc5632_hp_jack_gpio);
snd_soc_unregister_card(card);
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index 9515ce58ea0..6872c77a119 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -69,9 +69,9 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
data->set_baseclock = 0;
data->set_mclk = 0;
- clk_disable(data->clk_cdev1);
- clk_disable(data->clk_pll_a_out0);
- clk_disable(data->clk_pll_a);
+ clk_disable_unprepare(data->clk_cdev1);
+ clk_disable_unprepare(data->clk_pll_a_out0);
+ clk_disable_unprepare(data->clk_pll_a);
err = clk_set_rate(data->clk_pll_a, new_baseclock);
if (err) {
@@ -87,19 +87,19 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
/* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */
- err = clk_enable(data->clk_pll_a);
+ err = clk_prepare_enable(data->clk_pll_a);
if (err) {
dev_err(data->dev, "Can't enable pll_a: %d\n", err);
return err;
}
- err = clk_enable(data->clk_pll_a_out0);
+ err = clk_prepare_enable(data->clk_pll_a_out0);
if (err) {
dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err);
return err;
}
- err = clk_enable(data->clk_cdev1);
+ err = clk_prepare_enable(data->clk_cdev1);
if (err) {
dev_err(data->dev, "Can't enable cdev1: %d\n", err);
return err;
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 127348dc09b..5658bcec193 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -36,6 +36,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
#include "tegra_pcm.h"
@@ -56,6 +57,7 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = {
.fifo_size = 4,
};
+#if defined(CONFIG_TEGRA_SYSTEM_DMA)
static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd)
{
struct snd_pcm_substream *substream = prtd->substream;
@@ -285,6 +287,119 @@ static struct snd_pcm_ops tegra_pcm_ops = {
.pointer = tegra_pcm_pointer,
.mmap = tegra_pcm_mmap,
};
+#else
+static int tegra_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct device *dev = rtd->platform->dev;
+ int ret;
+
+ /* Set HW params now that initialization is complete */
+ snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
+
+ ret = snd_dmaengine_pcm_open(substream, NULL, NULL);
+ if (ret) {
+ dev_err(dev, "dmaengine pcm open failed with err %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tegra_pcm_close(struct snd_pcm_substream *substream)
+{
+ snd_dmaengine_pcm_close(substream);
+ return 0;
+}
+
+static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct device *dev = rtd->platform->dev;
+ struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
+ struct tegra_pcm_dma_params *dmap;
+ struct dma_slave_config slave_config;
+ int ret;
+
+ dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
+ ret = snd_hwparams_to_dma_slave_config(substream, params,
+ &slave_config);
+ if (ret) {
+ dev_err(dev, "hw params config failed with err %d\n", ret);
+ return ret;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ slave_config.dst_addr = dmap->addr;
+ slave_config.src_maxburst = 0;
+ } else {
+ slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ slave_config.src_addr = dmap->addr;
+ slave_config.dst_maxburst = 0;
+ }
+ slave_config.slave_id = dmap->req_sel;
+
+ ret = dmaengine_slave_config(chan, &slave_config);
+ if (ret < 0) {
+ dev_err(dev, "dma slave config failed with err %d\n", ret);
+ return ret;
+ }
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ return 0;
+}
+
+static int tegra_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ snd_pcm_set_runtime_buffer(substream, NULL);
+ return 0;
+}
+
+static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ return snd_dmaengine_pcm_trigger(substream,
+ SNDRV_PCM_TRIGGER_START);
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ return snd_dmaengine_pcm_trigger(substream,
+ SNDRV_PCM_TRIGGER_STOP);
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+ runtime->dma_area,
+ runtime->dma_addr,
+ runtime->dma_bytes);
+}
+
+static struct snd_pcm_ops tegra_pcm_ops = {
+ .open = tegra_pcm_open,
+ .close = tegra_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = tegra_pcm_hw_params,
+ .hw_free = tegra_pcm_hw_free,
+ .trigger = tegra_pcm_trigger,
+ .pointer = snd_dmaengine_pcm_pointer,
+ .mmap = tegra_pcm_mmap,
+};
+#endif
static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
{
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h
index 985d418a35e..a3a450352dc 100644
--- a/sound/soc/tegra/tegra_pcm.h
+++ b/sound/soc/tegra/tegra_pcm.h
@@ -40,6 +40,7 @@ struct tegra_pcm_dma_params {
unsigned long req_sel;
};
+#if defined(CONFIG_TEGRA_SYSTEM_DMA)
struct tegra_runtime_data {
struct snd_pcm_substream *substream;
spinlock_t lock;
@@ -51,6 +52,7 @@ struct tegra_runtime_data {
struct tegra_dma_req dma_req[2];
struct tegra_dma_channel *dma_chan;
};
+#endif
int tegra_pcm_platform_register(struct device *dev);
void tegra_pcm_platform_unregister(struct device *dev);
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index 4e77026807a..ea9166d5c4e 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -57,7 +57,7 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = codec_dai->codec;
struct snd_soc_card *card = codec->card;
struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
int srate, mclk;
@@ -157,9 +157,9 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
goto err;
}
- tegra_wm8753_dai.cpu_dai_of_node = of_parse_phandle(
+ tegra_wm8753_dai.cpu_of_node = of_parse_phandle(
pdev->dev.of_node, "nvidia,i2s-controller", 0);
- if (!tegra_wm8753_dai.cpu_dai_of_node) {
+ if (!tegra_wm8753_dai.cpu_of_node) {
dev_err(&pdev->dev,
"Property 'nvidia,i2s-controller' missing or invalid\n");
ret = -EINVAL;
@@ -167,7 +167,7 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
}
tegra_wm8753_dai.platform_of_node =
- tegra_wm8753_dai.cpu_dai_of_node;
+ tegra_wm8753_dai.cpu_of_node;
ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
if (ret)
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index 3b6da91188a..d4f14e49234 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -28,8 +28,6 @@
*
*/
-#include <asm/mach-types.h>
-
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -50,16 +48,9 @@
#define DRV_NAME "tegra-snd-wm8903"
-#define GPIO_SPKR_EN BIT(0)
-#define GPIO_HP_MUTE BIT(1)
-#define GPIO_INT_MIC_EN BIT(2)
-#define GPIO_EXT_MIC_EN BIT(3)
-#define GPIO_HP_DET BIT(4)
-
struct tegra_wm8903 {
struct tegra_wm8903_platform_data pdata;
struct tegra_asoc_utils_data util_data;
- int gpio_requested;
};
static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
@@ -67,8 +58,7 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = codec_dai->codec;
struct snd_soc_card *card = codec->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
int srate, mclk;
@@ -95,24 +85,6 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
return err;
}
- err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
- if (err < 0) {
- dev_err(card->dev, "codec_dai fmt not set\n");
- return err;
- }
-
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
- if (err < 0) {
- dev_err(card->dev, "cpu_dai fmt not set\n");
- return err;
- }
-
err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
SND_SOC_CLOCK_IN);
if (err < 0) {
@@ -160,7 +132,7 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w,
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
struct tegra_wm8903_platform_data *pdata = &machine->pdata;
- if (!(machine->gpio_requested & GPIO_SPKR_EN))
+ if (!gpio_is_valid(pdata->gpio_spkr_en))
return 0;
gpio_set_value_cansleep(pdata->gpio_spkr_en,
@@ -177,7 +149,7 @@ static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w,
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
struct tegra_wm8903_platform_data *pdata = &machine->pdata;
- if (!(machine->gpio_requested & GPIO_HP_MUTE))
+ if (!gpio_is_valid(pdata->gpio_hp_mute))
return 0;
gpio_set_value_cansleep(pdata->gpio_hp_mute,
@@ -203,122 +175,18 @@ static const struct snd_soc_dapm_route harmony_audio_map[] = {
{"IN1L", NULL, "Mic Jack"},
};
-static const struct snd_soc_dapm_route seaboard_audio_map[] = {
- {"Headphone Jack", NULL, "HPOUTR"},
- {"Headphone Jack", NULL, "HPOUTL"},
- {"Int Spk", NULL, "ROP"},
- {"Int Spk", NULL, "RON"},
- {"Int Spk", NULL, "LOP"},
- {"Int Spk", NULL, "LON"},
- {"Mic Jack", NULL, "MICBIAS"},
- {"IN1R", NULL, "Mic Jack"},
-};
-
-static const struct snd_soc_dapm_route kaen_audio_map[] = {
- {"Headphone Jack", NULL, "HPOUTR"},
- {"Headphone Jack", NULL, "HPOUTL"},
- {"Int Spk", NULL, "ROP"},
- {"Int Spk", NULL, "RON"},
- {"Int Spk", NULL, "LOP"},
- {"Int Spk", NULL, "LON"},
- {"Mic Jack", NULL, "MICBIAS"},
- {"IN2R", NULL, "Mic Jack"},
-};
-
-static const struct snd_soc_dapm_route aebl_audio_map[] = {
- {"Headphone Jack", NULL, "HPOUTR"},
- {"Headphone Jack", NULL, "HPOUTL"},
- {"Int Spk", NULL, "LINEOUTR"},
- {"Int Spk", NULL, "LINEOUTL"},
- {"Mic Jack", NULL, "MICBIAS"},
- {"IN1R", NULL, "Mic Jack"},
-};
-
static const struct snd_kcontrol_new tegra_wm8903_controls[] = {
SOC_DAPM_PIN_SWITCH("Int Spk"),
};
static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_codec *codec = codec_dai->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
struct snd_soc_card *card = codec->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
struct tegra_wm8903_platform_data *pdata = &machine->pdata;
- struct device_node *np = card->dev->of_node;
- int ret;
-
- if (card->dev->platform_data) {
- memcpy(pdata, card->dev->platform_data, sizeof(*pdata));
- } else if (np) {
- /*
- * This part must be in init() rather than probe() in order to
- * guarantee that the WM8903 has been probed, and hence its
- * GPIO controller registered, which is a pre-condition for
- * of_get_named_gpio() to be able to map the phandles in the
- * properties to the controller node. Given this, all
- * pdata handling is in init() for consistency.
- */
- pdata->gpio_spkr_en = of_get_named_gpio(np,
- "nvidia,spkr-en-gpios", 0);
- pdata->gpio_hp_mute = of_get_named_gpio(np,
- "nvidia,hp-mute-gpios", 0);
- pdata->gpio_hp_det = of_get_named_gpio(np,
- "nvidia,hp-det-gpios", 0);
- pdata->gpio_int_mic_en = of_get_named_gpio(np,
- "nvidia,int-mic-en-gpios", 0);
- pdata->gpio_ext_mic_en = of_get_named_gpio(np,
- "nvidia,ext-mic-en-gpios", 0);
- } else {
- dev_err(card->dev, "No platform data supplied\n");
- return -EINVAL;
- }
-
- if (gpio_is_valid(pdata->gpio_spkr_en)) {
- ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
- if (ret) {
- dev_err(card->dev, "cannot get spkr_en gpio\n");
- return ret;
- }
- machine->gpio_requested |= GPIO_SPKR_EN;
-
- gpio_direction_output(pdata->gpio_spkr_en, 0);
- }
-
- if (gpio_is_valid(pdata->gpio_hp_mute)) {
- ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
- if (ret) {
- dev_err(card->dev, "cannot get hp_mute gpio\n");
- return ret;
- }
- machine->gpio_requested |= GPIO_HP_MUTE;
-
- gpio_direction_output(pdata->gpio_hp_mute, 1);
- }
-
- if (gpio_is_valid(pdata->gpio_int_mic_en)) {
- ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
- if (ret) {
- dev_err(card->dev, "cannot get int_mic_en gpio\n");
- return ret;
- }
- machine->gpio_requested |= GPIO_INT_MIC_EN;
-
- /* Disable int mic; enable signal is active-high */
- gpio_direction_output(pdata->gpio_int_mic_en, 0);
- }
-
- if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
- ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
- if (ret) {
- dev_err(card->dev, "cannot get ext_mic_en gpio\n");
- return ret;
- }
- machine->gpio_requested |= GPIO_EXT_MIC_EN;
-
- /* Enable ext mic; enable signal is active-low */
- gpio_direction_output(pdata->gpio_ext_mic_en, 0);
- }
if (gpio_is_valid(pdata->gpio_hp_det)) {
tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det;
@@ -330,7 +198,6 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack,
1,
&tegra_wm8903_hp_jack_gpio);
- machine->gpio_requested |= GPIO_HP_DET;
}
snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE,
@@ -366,6 +233,9 @@ static struct snd_soc_dai_link tegra_wm8903_dai = {
.codec_dai_name = "wm8903-hifi",
.init = tegra_wm8903_init,
.ops = &tegra_wm8903_ops,
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
};
static struct snd_soc_card snd_soc_tegra_wm8903 = {
@@ -385,8 +255,10 @@ static struct snd_soc_card snd_soc_tegra_wm8903 = {
static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
struct snd_soc_card *card = &snd_soc_tegra_wm8903;
struct tegra_wm8903 *machine;
+ struct tegra_wm8903_platform_data *pdata;
int ret;
if (!pdev->dev.platform_data && !pdev->dev.of_node) {
@@ -401,12 +273,42 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
ret = -ENOMEM;
goto err;
}
+ pdata = &machine->pdata;
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, machine);
- if (pdev->dev.of_node) {
+ if (pdev->dev.platform_data) {
+ memcpy(pdata, card->dev->platform_data, sizeof(*pdata));
+ } else if (np) {
+ pdata->gpio_spkr_en = of_get_named_gpio(np,
+ "nvidia,spkr-en-gpios", 0);
+ if (pdata->gpio_spkr_en == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ pdata->gpio_hp_mute = of_get_named_gpio(np,
+ "nvidia,hp-mute-gpios", 0);
+ if (pdata->gpio_hp_mute == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ pdata->gpio_hp_det = of_get_named_gpio(np,
+ "nvidia,hp-det-gpios", 0);
+ if (pdata->gpio_hp_det == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ pdata->gpio_int_mic_en = of_get_named_gpio(np,
+ "nvidia,int-mic-en-gpios", 0);
+ if (pdata->gpio_int_mic_en == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ pdata->gpio_ext_mic_en = of_get_named_gpio(np,
+ "nvidia,ext-mic-en-gpios", 0);
+ if (pdata->gpio_ext_mic_en == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ }
+
+ if (np) {
ret = snd_soc_of_parse_card_name(card, "nvidia,model");
if (ret)
goto err;
@@ -417,8 +319,8 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
goto err;
tegra_wm8903_dai.codec_name = NULL;
- tegra_wm8903_dai.codec_of_node = of_parse_phandle(
- pdev->dev.of_node, "nvidia,audio-codec", 0);
+ tegra_wm8903_dai.codec_of_node = of_parse_phandle(np,
+ "nvidia,audio-codec", 0);
if (!tegra_wm8903_dai.codec_of_node) {
dev_err(&pdev->dev,
"Property 'nvidia,audio-codec' missing or invalid\n");
@@ -427,9 +329,9 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
}
tegra_wm8903_dai.cpu_dai_name = NULL;
- tegra_wm8903_dai.cpu_dai_of_node = of_parse_phandle(
- pdev->dev.of_node, "nvidia,i2s-controller", 0);
- if (!tegra_wm8903_dai.cpu_dai_of_node) {
+ tegra_wm8903_dai.cpu_of_node = of_parse_phandle(np,
+ "nvidia,i2s-controller", 0);
+ if (!tegra_wm8903_dai.cpu_of_node) {
dev_err(&pdev->dev,
"Property 'nvidia,i2s-controller' missing or invalid\n");
ret = -EINVAL;
@@ -438,20 +340,47 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
tegra_wm8903_dai.platform_name = NULL;
tegra_wm8903_dai.platform_of_node =
- tegra_wm8903_dai.cpu_dai_of_node;
+ tegra_wm8903_dai.cpu_of_node;
} else {
- if (machine_is_harmony()) {
- card->dapm_routes = harmony_audio_map;
- card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map);
- } else if (machine_is_seaboard()) {
- card->dapm_routes = seaboard_audio_map;
- card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map);
- } else if (machine_is_kaen()) {
- card->dapm_routes = kaen_audio_map;
- card->num_dapm_routes = ARRAY_SIZE(kaen_audio_map);
- } else {
- card->dapm_routes = aebl_audio_map;
- card->num_dapm_routes = ARRAY_SIZE(aebl_audio_map);
+ card->dapm_routes = harmony_audio_map;
+ card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map);
+ }
+
+ if (gpio_is_valid(pdata->gpio_spkr_en)) {
+ ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_spkr_en,
+ GPIOF_OUT_INIT_LOW, "spkr_en");
+ if (ret) {
+ dev_err(card->dev, "cannot get spkr_en gpio\n");
+ return ret;
+ }
+ }
+
+ if (gpio_is_valid(pdata->gpio_hp_mute)) {
+ ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_hp_mute,
+ GPIOF_OUT_INIT_HIGH, "hp_mute");
+ if (ret) {
+ dev_err(card->dev, "cannot get hp_mute gpio\n");
+ return ret;
+ }
+ }
+
+ if (gpio_is_valid(pdata->gpio_int_mic_en)) {
+ /* Disable int mic; enable signal is active-high */
+ ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_int_mic_en,
+ GPIOF_OUT_INIT_LOW, "int_mic_en");
+ if (ret) {
+ dev_err(card->dev, "cannot get int_mic_en gpio\n");
+ return ret;
+ }
+ }
+
+ if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
+ /* Enable ext mic; enable signal is active-low */
+ ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_ext_mic_en,
+ GPIOF_OUT_INIT_LOW, "ext_mic_en");
+ if (ret) {
+ dev_err(card->dev, "cannot get ext_mic_en gpio\n");
+ return ret;
}
}
@@ -478,21 +407,9 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = &machine->pdata;
- if (machine->gpio_requested & GPIO_HP_DET)
- snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack,
- 1,
- &tegra_wm8903_hp_jack_gpio);
- if (machine->gpio_requested & GPIO_EXT_MIC_EN)
- gpio_free(pdata->gpio_ext_mic_en);
- if (machine->gpio_requested & GPIO_INT_MIC_EN)
- gpio_free(pdata->gpio_int_mic_en);
- if (machine->gpio_requested & GPIO_HP_MUTE)
- gpio_free(pdata->gpio_hp_mute);
- if (machine->gpio_requested & GPIO_SPKR_EN)
- gpio_free(pdata->gpio_spkr_en);
- machine->gpio_requested = 0;
+ snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, 1,
+ &tegra_wm8903_hp_jack_gpio);
snd_soc_unregister_card(card);
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
index 4a8d5b672c9..e69a4f7000d 100644
--- a/sound/soc/tegra/trimslice.c
+++ b/sound/soc/tegra/trimslice.c
@@ -52,8 +52,7 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = codec_dai->codec;
struct snd_soc_card *card = codec->card;
struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card);
int srate, mclk;
@@ -68,24 +67,6 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream,
return err;
}
- err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
- if (err < 0) {
- dev_err(card->dev, "codec_dai fmt not set\n");
- return err;
- }
-
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
- if (err < 0) {
- dev_err(card->dev, "cpu_dai fmt not set\n");
- return err;
- }
-
err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
SND_SOC_CLOCK_IN);
if (err < 0) {
@@ -121,6 +102,9 @@ static struct snd_soc_dai_link trimslice_tlv320aic23_dai = {
.cpu_dai_name = "tegra20-i2s.0",
.codec_dai_name = "tlv320aic23-hifi",
.ops = &trimslice_asoc_ops,
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
};
static struct snd_soc_card snd_soc_trimslice = {
@@ -162,9 +146,9 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
}
trimslice_tlv320aic23_dai.cpu_dai_name = NULL;
- trimslice_tlv320aic23_dai.cpu_dai_of_node = of_parse_phandle(
+ trimslice_tlv320aic23_dai.cpu_of_node = of_parse_phandle(
pdev->dev.of_node, "nvidia,i2s-controller", 0);
- if (!trimslice_tlv320aic23_dai.cpu_dai_of_node) {
+ if (!trimslice_tlv320aic23_dai.cpu_of_node) {
dev_err(&pdev->dev,
"Property 'nvidia,i2s-controller' missing or invalid\n");
ret = -EINVAL;
@@ -173,7 +157,7 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
trimslice_tlv320aic23_dai.platform_name = NULL;
trimslice_tlv320aic23_dai.platform_of_node =
- trimslice_tlv320aic23_dai.cpu_dai_of_node;
+ trimslice_tlv320aic23_dai.cpu_of_node;
}
ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev);