aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorMike Rapoport <mike@compulab.co.il>2011-04-26 04:52:42 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-05-03 13:42:44 -0400
commit1307394afd2d6cf8f41f5e691b43ffc9e027630c (patch)
treecdcd4b03aa7ff2424bba047666a211400042a104 /sound/soc
parent9b1b937c77f94f8c94874351a2d5ba92cd99f1ec (diff)
ASoC: tegra: TrimSlice machine support
Signed-off-by: Mike Rapoport <mike@compulab.co.il> Acked-by: Stephen Warren <swarren@nvidia.com> Acked-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/tegra/Kconfig8
-rw-r--r--sound/soc/tegra/Makefile2
-rw-r--r--sound/soc/tegra/trimslice.c228
3 files changed, 238 insertions, 0 deletions
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 0f5bd8298a0a..035d39a4beb4 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -30,3 +30,11 @@ config SND_SOC_TEGRA_WM8903
30 boards using the WM8093 codec. Currently, the supported boards are 30 boards using the WM8093 codec. Currently, the supported boards are
31 Harmony, Ventana, Seaboard, Kaen, and Aebl. 31 Harmony, Ventana, Seaboard, Kaen, and Aebl.
32 32
33config SND_SOC_TEGRA_TRIMSLICE
34 tristate "SoC Audio support for TrimSlice board"
35 depends on SND_SOC_TEGRA && MACH_TRIMSLICE && I2C
36 select SND_SOC_TEGRA_I2S
37 select SND_SOC_TLV320AIC23
38 help
39 Say Y or M here if you want to add support for SoC audio on the
40 TrimSlice platform.
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 13bef8d572c9..fa6574d92a31 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -11,5 +11,7 @@ obj-$(CONFIG_SND_SOC_TEGRA_I2S) += snd-soc-tegra-i2s.o
11 11
12# Tegra machine Support 12# Tegra machine Support
13snd-soc-tegra-wm8903-objs := tegra_wm8903.o 13snd-soc-tegra-wm8903-objs := tegra_wm8903.o
14snd-soc-tegra-trimslice-objs := trimslice.o
14 15
15obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o 16obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
17obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
new file mode 100644
index 000000000000..8fc07e9adf2e
--- /dev/null
+++ b/sound/soc/tegra/trimslice.c
@@ -0,0 +1,228 @@
1/*
2 * trimslice.c - TrimSlice machine ASoC driver
3 *
4 * Copyright (C) 2011 - CompuLab, Ltd.
5 * Author: Mike Rapoport <mike@compulab.co.il>
6 *
7 * Based on code copyright/by:
8 * Author: Stephen Warren <swarren@nvidia.com>
9 * Copyright (C) 2010-2011 - NVIDIA, Inc.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * version 2 as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 * 02110-1301 USA
24 *
25 */
26
27#include <asm/mach-types.h>
28
29#include <linux/module.h>
30#include <linux/platform_device.h>
31#include <linux/slab.h>
32
33#include <sound/core.h>
34#include <sound/jack.h>
35#include <sound/pcm.h>
36#include <sound/pcm_params.h>
37#include <sound/soc.h>
38
39#include "../codecs/tlv320aic23.h"
40
41#include "tegra_das.h"
42#include "tegra_i2s.h"
43#include "tegra_pcm.h"
44#include "tegra_asoc_utils.h"
45
46#define DRV_NAME "tegra-snd-trimslice"
47
48struct tegra_trimslice {
49 struct tegra_asoc_utils_data util_data;
50};
51
52static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream,
53 struct snd_pcm_hw_params *params)
54{
55 struct snd_soc_pcm_runtime *rtd = substream->private_data;
56 struct snd_soc_dai *codec_dai = rtd->codec_dai;
57 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
58 struct snd_soc_codec *codec = rtd->codec;
59 struct snd_soc_card *card = codec->card;
60 struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card);
61 int srate, mclk;
62 int err;
63
64 srate = params_rate(params);
65 mclk = 128 * srate;
66
67 err = tegra_asoc_utils_set_rate(&trimslice->util_data, srate, mclk);
68 if (err < 0) {
69 dev_err(card->dev, "Can't configure clocks\n");
70 return err;
71 }
72
73 err = snd_soc_dai_set_fmt(codec_dai,
74 SND_SOC_DAIFMT_I2S |
75 SND_SOC_DAIFMT_NB_NF |
76 SND_SOC_DAIFMT_CBS_CFS);
77 if (err < 0) {
78 dev_err(card->dev, "codec_dai fmt not set\n");
79 return err;
80 }
81
82 err = snd_soc_dai_set_fmt(cpu_dai,
83 SND_SOC_DAIFMT_I2S |
84 SND_SOC_DAIFMT_NB_NF |
85 SND_SOC_DAIFMT_CBS_CFS);
86 if (err < 0) {
87 dev_err(card->dev, "cpu_dai fmt not set\n");
88 return err;
89 }
90
91 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
92 SND_SOC_CLOCK_IN);
93 if (err < 0) {
94 dev_err(card->dev, "codec_dai clock not set\n");
95 return err;
96 }
97
98 return 0;
99}
100
101static struct snd_soc_ops trimslice_asoc_ops = {
102 .hw_params = trimslice_asoc_hw_params,
103};
104
105static const struct snd_soc_dapm_widget trimslice_dapm_widgets[] = {
106 SND_SOC_DAPM_HP("Line Out", NULL),
107 SND_SOC_DAPM_LINE("Line In", NULL),
108};
109
110static const struct snd_soc_dapm_route trimslice_audio_map[] = {
111 {"Line Out", NULL, "LOUT"},
112 {"Line Out", NULL, "ROUT"},
113
114 {"LLINEIN", NULL, "Line In"},
115 {"RLINEIN", NULL, "Line In"},
116};
117
118static int trimslice_asoc_init(struct snd_soc_pcm_runtime *rtd)
119{
120 struct snd_soc_codec *codec = rtd->codec;
121 struct snd_soc_dapm_context *dapm = &codec->dapm;
122
123 snd_soc_dapm_nc_pin(dapm, "LHPOUT");
124 snd_soc_dapm_nc_pin(dapm, "RHPOUT");
125 snd_soc_dapm_nc_pin(dapm, "MICIN");
126
127 snd_soc_dapm_sync(dapm);
128
129 return 0;
130}
131
132static struct snd_soc_dai_link trimslice_tlv320aic23_dai = {
133 .name = "TLV320AIC23",
134 .stream_name = "AIC23",
135 .codec_name = "tlv320aic23-codec.2-001a",
136 .platform_name = "tegra-pcm-audio",
137 .cpu_dai_name = "tegra-i2s.0",
138 .codec_dai_name = "tlv320aic23-hifi",
139 .init = trimslice_asoc_init,
140 .ops = &trimslice_asoc_ops,
141};
142
143static struct snd_soc_card snd_soc_trimslice = {
144 .name = "tegra-trimslice",
145 .dai_link = &trimslice_tlv320aic23_dai,
146 .num_links = 1,
147
148 .dapm_widgets = trimslice_dapm_widgets,
149 .num_dapm_widgets = ARRAY_SIZE(trimslice_dapm_widgets),
150 .dapm_routes = trimslice_audio_map,
151 .num_dapm_routes = ARRAY_SIZE(trimslice_audio_map),
152};
153
154static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
155{
156 struct snd_soc_card *card = &snd_soc_trimslice;
157 struct tegra_trimslice *trimslice;
158 int ret;
159
160 trimslice = kzalloc(sizeof(struct tegra_trimslice), GFP_KERNEL);
161 if (!trimslice) {
162 dev_err(&pdev->dev, "Can't allocate tegra_trimslice\n");
163 return -ENOMEM;
164 }
165
166 ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev);
167 if (ret)
168 goto err_free_trimslice;
169
170 card->dev = &pdev->dev;
171 platform_set_drvdata(pdev, card);
172 snd_soc_card_set_drvdata(card, trimslice);
173
174 ret = snd_soc_register_card(card);
175 if (ret) {
176 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
177 ret);
178 goto err_fini_utils;
179 }
180
181 return 0;
182
183err_fini_utils:
184 tegra_asoc_utils_fini(&trimslice->util_data);
185err_free_trimslice:
186 kfree(trimslice);
187 return ret;
188}
189
190static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev)
191{
192 struct snd_soc_card *card = platform_get_drvdata(pdev);
193 struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card);
194
195 snd_soc_unregister_card(card);
196
197 tegra_asoc_utils_fini(&trimslice->util_data);
198
199 kfree(trimslice);
200
201 return 0;
202}
203
204static struct platform_driver tegra_snd_trimslice_driver = {
205 .driver = {
206 .name = DRV_NAME,
207 .owner = THIS_MODULE,
208 },
209 .probe = tegra_snd_trimslice_probe,
210 .remove = __devexit_p(tegra_snd_trimslice_remove),
211};
212
213static int __init snd_tegra_trimslice_init(void)
214{
215 return platform_driver_register(&tegra_snd_trimslice_driver);
216}
217module_init(snd_tegra_trimslice_init);
218
219static void __exit snd_tegra_trimslice_exit(void)
220{
221 platform_driver_unregister(&tegra_snd_trimslice_driver);
222}
223module_exit(snd_tegra_trimslice_exit);
224
225MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
226MODULE_DESCRIPTION("Trimslice machine ASoC driver");
227MODULE_LICENSE("GPL");
228MODULE_ALIAS("platform:" DRV_NAME);