aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/tegra/Kconfig10
-rw-r--r--sound/soc/tegra/Makefile2
-rw-r--r--sound/soc/tegra/tegra_wm8753.c224
3 files changed, 236 insertions, 0 deletions
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 5331c61faf01..c1c8e955f4d3 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -48,6 +48,16 @@ config SND_SOC_TEGRA30_I2S
48 Tegra30 I2S interface. You will also need to select the individual 48 Tegra30 I2S interface. You will also need to select the individual
49 machine drivers to support below. 49 machine drivers to support below.
50 50
51config SND_SOC_TEGRA_WM8753
52 tristate "SoC Audio support for Tegra boards using a WM8753 codec"
53 depends on SND_SOC_TEGRA && I2C
54 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
55 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
56 select SND_SOC_WM8753
57 help
58 Say Y or M here if you want to add support for SoC audio on Tegra
59 boards using the WM8753 codec, such as Whistler.
60
51config MACH_HAS_SND_SOC_TEGRA_WM8903 61config MACH_HAS_SND_SOC_TEGRA_WM8903
52 bool 62 bool
53 help 63 help
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 98704b48b62a..391e78a34c06 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -16,10 +16,12 @@ obj-$(CONFIG_SND_SOC_TEGRA30_AHUB) += snd-soc-tegra30-ahub.o
16obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o 16obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o
17 17
18# Tegra machine Support 18# Tegra machine Support
19snd-soc-tegra-wm8753-objs := tegra_wm8753.o
19snd-soc-tegra-wm8903-objs := tegra_wm8903.o 20snd-soc-tegra-wm8903-objs := tegra_wm8903.o
20snd-soc-tegra-trimslice-objs := trimslice.o 21snd-soc-tegra-trimslice-objs := trimslice.o
21snd-soc-tegra-alc5632-objs := tegra_alc5632.o 22snd-soc-tegra-alc5632-objs := tegra_alc5632.o
22 23
24obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o
23obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o 25obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
24obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o 26obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
25obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o 27obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
new file mode 100644
index 000000000000..4e77026807a2
--- /dev/null
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -0,0 +1,224 @@
1/*
2 * tegra_wm8753.c - Tegra machine ASoC driver for boards using WM8753 codec.
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010-2012 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
10 *
11 * Copyright 2007 Wolfson Microelectronics PLC.
12 * Author: Graeme Gregory
13 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#include <asm/mach-types.h>
32
33#include <linux/module.h>
34#include <linux/platform_device.h>
35#include <linux/slab.h>
36#include <linux/gpio.h>
37#include <linux/of_gpio.h>
38
39#include <sound/core.h>
40#include <sound/jack.h>
41#include <sound/pcm.h>
42#include <sound/pcm_params.h>
43#include <sound/soc.h>
44
45#include "../codecs/wm8753.h"
46
47#include "tegra_asoc_utils.h"
48
49#define DRV_NAME "tegra-snd-wm8753"
50
51struct tegra_wm8753 {
52 struct tegra_asoc_utils_data util_data;
53};
54
55static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
56 struct snd_pcm_hw_params *params)
57{
58 struct snd_soc_pcm_runtime *rtd = substream->private_data;
59 struct snd_soc_dai *codec_dai = rtd->codec_dai;
60 struct snd_soc_codec *codec = rtd->codec;
61 struct snd_soc_card *card = codec->card;
62 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
63 int srate, mclk;
64 int err;
65
66 srate = params_rate(params);
67 switch (srate) {
68 case 11025:
69 case 22050:
70 case 44100:
71 case 88200:
72 mclk = 11289600;
73 break;
74 default:
75 mclk = 12288000;
76 break;
77 }
78
79 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
80 if (err < 0) {
81 dev_err(card->dev, "Can't configure clocks\n");
82 return err;
83 }
84
85 err = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, mclk,
86 SND_SOC_CLOCK_IN);
87 if (err < 0) {
88 dev_err(card->dev, "codec_dai clock not set\n");
89 return err;
90 }
91
92 return 0;
93}
94
95static struct snd_soc_ops tegra_wm8753_ops = {
96 .hw_params = tegra_wm8753_hw_params,
97};
98
99static const struct snd_soc_dapm_widget tegra_wm8753_dapm_widgets[] = {
100 SND_SOC_DAPM_HP("Headphone Jack", NULL),
101 SND_SOC_DAPM_MIC("Mic Jack", NULL),
102};
103
104static struct snd_soc_dai_link tegra_wm8753_dai = {
105 .name = "WM8753",
106 .stream_name = "WM8753 PCM",
107 .codec_dai_name = "wm8753-hifi",
108 .ops = &tegra_wm8753_ops,
109 .dai_fmt = SND_SOC_DAIFMT_I2S |
110 SND_SOC_DAIFMT_NB_NF |
111 SND_SOC_DAIFMT_CBS_CFS,
112};
113
114static struct snd_soc_card snd_soc_tegra_wm8753 = {
115 .name = "tegra-wm8753",
116 .owner = THIS_MODULE,
117 .dai_link = &tegra_wm8753_dai,
118 .num_links = 1,
119
120 .dapm_widgets = tegra_wm8753_dapm_widgets,
121 .num_dapm_widgets = ARRAY_SIZE(tegra_wm8753_dapm_widgets),
122 .fully_routed = true,
123};
124
125static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
126{
127 struct snd_soc_card *card = &snd_soc_tegra_wm8753;
128 struct tegra_wm8753 *machine;
129 int ret;
130
131 machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm8753),
132 GFP_KERNEL);
133 if (!machine) {
134 dev_err(&pdev->dev, "Can't allocate tegra_wm8753 struct\n");
135 ret = -ENOMEM;
136 goto err;
137 }
138
139 card->dev = &pdev->dev;
140 platform_set_drvdata(pdev, card);
141 snd_soc_card_set_drvdata(card, machine);
142
143 ret = snd_soc_of_parse_card_name(card, "nvidia,model");
144 if (ret)
145 goto err;
146
147 ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
148 if (ret)
149 goto err;
150
151 tegra_wm8753_dai.codec_of_node = of_parse_phandle(
152 pdev->dev.of_node, "nvidia,audio-codec", 0);
153 if (!tegra_wm8753_dai.codec_of_node) {
154 dev_err(&pdev->dev,
155 "Property 'nvidia,audio-codec' missing or invalid\n");
156 ret = -EINVAL;
157 goto err;
158 }
159
160 tegra_wm8753_dai.cpu_dai_of_node = of_parse_phandle(
161 pdev->dev.of_node, "nvidia,i2s-controller", 0);
162 if (!tegra_wm8753_dai.cpu_dai_of_node) {
163 dev_err(&pdev->dev,
164 "Property 'nvidia,i2s-controller' missing or invalid\n");
165 ret = -EINVAL;
166 goto err;
167 }
168
169 tegra_wm8753_dai.platform_of_node =
170 tegra_wm8753_dai.cpu_dai_of_node;
171
172 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
173 if (ret)
174 goto err;
175
176 ret = snd_soc_register_card(card);
177 if (ret) {
178 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
179 ret);
180 goto err_fini_utils;
181 }
182
183 return 0;
184
185err_fini_utils:
186 tegra_asoc_utils_fini(&machine->util_data);
187err:
188 return ret;
189}
190
191static int __devexit tegra_wm8753_driver_remove(struct platform_device *pdev)
192{
193 struct snd_soc_card *card = platform_get_drvdata(pdev);
194 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
195
196 snd_soc_unregister_card(card);
197
198 tegra_asoc_utils_fini(&machine->util_data);
199
200 return 0;
201}
202
203static const struct of_device_id tegra_wm8753_of_match[] __devinitconst = {
204 { .compatible = "nvidia,tegra-audio-wm8753", },
205 {},
206};
207
208static struct platform_driver tegra_wm8753_driver = {
209 .driver = {
210 .name = DRV_NAME,
211 .owner = THIS_MODULE,
212 .pm = &snd_soc_pm_ops,
213 .of_match_table = tegra_wm8753_of_match,
214 },
215 .probe = tegra_wm8753_driver_probe,
216 .remove = __devexit_p(tegra_wm8753_driver_remove),
217};
218module_platform_driver(tegra_wm8753_driver);
219
220MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
221MODULE_DESCRIPTION("Tegra+WM8753 machine ASoC driver");
222MODULE_LICENSE("GPL");
223MODULE_ALIAS("platform:" DRV_NAME);
224MODULE_DEVICE_TABLE(of, tegra_wm8753_of_match);