diff options
Diffstat (limited to 'sound/soc/tegra')
-rw-r--r-- | sound/soc/tegra/Kconfig | 13 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_i2s.c | 98 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_i2s.h | 1 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_spdif.c | 40 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_spdif.h | 1 | ||||
-rw-r--r-- | sound/soc/tegra/tegra30_ahub.c | 8 | ||||
-rw-r--r-- | sound/soc/tegra/tegra30_i2s.c | 89 | ||||
-rw-r--r-- | sound/soc/tegra/tegra30_i2s.h | 1 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_alc5632.c | 32 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_asoc_utils.c | 12 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_pcm.c | 115 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_pcm.h | 2 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_wm8753.c | 8 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_wm8903.c | 259 | ||||
-rw-r--r-- | sound/soc/tegra/trimslice.c | 30 |
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); |