aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/tegra/Kconfig9
-rw-r--r--sound/soc/tegra/Makefile2
-rw-r--r--sound/soc/tegra/tegra_wm9712.c176
3 files changed, 187 insertions, 0 deletions
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 4b3a2b8cb788..dbc27ce1d4de 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -80,6 +80,15 @@ config SND_SOC_TEGRA_WM8903
80 boards using the WM8093 codec. Currently, the supported boards are 80 boards using the WM8093 codec. Currently, the supported boards are
81 Harmony, Ventana, Seaboard, Kaen, and Aebl. 81 Harmony, Ventana, Seaboard, Kaen, and Aebl.
82 82
83config SND_SOC_TEGRA_WM9712
84 tristate "SoC Audio support for Tegra boards using a WM9712 codec"
85 depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
86 select SND_SOC_TEGRA20_AC97
87 select SND_SOC_WM9712
88 help
89 Say Y or M here if you want to add support for SoC audio on Tegra
90 boards using the WM9712 (or compatible) codec.
91
83config SND_SOC_TEGRA_TRIMSLICE 92config SND_SOC_TEGRA_TRIMSLICE
84 tristate "SoC Audio support for TrimSlice board" 93 tristate "SoC Audio support for TrimSlice board"
85 depends on SND_SOC_TEGRA && I2C 94 depends on SND_SOC_TEGRA && I2C
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 02513d9edf22..416a14bde41b 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -20,10 +20,12 @@ obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o
20# Tegra machine Support 20# Tegra machine Support
21snd-soc-tegra-wm8753-objs := tegra_wm8753.o 21snd-soc-tegra-wm8753-objs := tegra_wm8753.o
22snd-soc-tegra-wm8903-objs := tegra_wm8903.o 22snd-soc-tegra-wm8903-objs := tegra_wm8903.o
23snd-soc-tegra-wm9712-objs := tegra_wm9712.o
23snd-soc-tegra-trimslice-objs := trimslice.o 24snd-soc-tegra-trimslice-objs := trimslice.o
24snd-soc-tegra-alc5632-objs := tegra_alc5632.o 25snd-soc-tegra-alc5632-objs := tegra_alc5632.o
25 26
26obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o 27obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o
27obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o 28obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
29obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o
28obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o 30obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
29obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o 31obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c
new file mode 100644
index 000000000000..cdbd2f0a23bc
--- /dev/null
+++ b/sound/soc/tegra/tegra_wm9712.c
@@ -0,0 +1,176 @@
1/*
2 * tegra20_wm9712.c - Tegra machine ASoC driver for boards using WM9712 codec.
3 *
4 * Copyright 2012 Lucas Stach <dev@lynxeye.de>
5 *
6 * Partly based on code copyright/by:
7 * Copyright 2011,2012 Toradex Inc.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <linux/gpio.h>
24#include <linux/of_gpio.h>
25
26#include <sound/core.h>
27#include <sound/jack.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/soc.h>
31
32#define DRV_NAME "tegra-snd-wm9712"
33
34struct tegra_wm9712 {
35 struct platform_device *codec;
36};
37
38static const struct snd_soc_dapm_widget tegra_wm9712_dapm_widgets[] = {
39 SND_SOC_DAPM_HP("Headphone", NULL),
40 SND_SOC_DAPM_LINE("LineIn", NULL),
41 SND_SOC_DAPM_MIC("Mic", NULL),
42};
43
44static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd)
45{
46 struct snd_soc_dai *codec_dai = rtd->codec_dai;
47 struct snd_soc_codec *codec = codec_dai->codec;
48 struct snd_soc_dapm_context *dapm = &codec->dapm;
49
50 snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
51
52 return snd_soc_dapm_sync(dapm);
53}
54
55static struct snd_soc_dai_link tegra_wm9712_dai = {
56 .name = "AC97 HiFi",
57 .stream_name = "AC97 HiFi",
58 .cpu_dai_name = "tegra-ac97-pcm",
59 .codec_dai_name = "wm9712-hifi",
60 .codec_name = "wm9712-codec",
61 .init = tegra_wm9712_init,
62};
63
64static struct snd_soc_card snd_soc_tegra_wm9712 = {
65 .name = "tegra-wm9712",
66 .owner = THIS_MODULE,
67 .dai_link = &tegra_wm9712_dai,
68 .num_links = 1,
69
70 .dapm_widgets = tegra_wm9712_dapm_widgets,
71 .num_dapm_widgets = ARRAY_SIZE(tegra_wm9712_dapm_widgets),
72 .fully_routed = true,
73};
74
75static int tegra_wm9712_driver_probe(struct platform_device *pdev)
76{
77 struct device_node *np = pdev->dev.of_node;
78 struct snd_soc_card *card = &snd_soc_tegra_wm9712;
79 struct tegra_wm9712 *machine;
80 int ret;
81
82 if (!pdev->dev.of_node) {
83 dev_err(&pdev->dev, "No platform data supplied\n");
84 return -EINVAL;
85 }
86
87 machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm9712),
88 GFP_KERNEL);
89 if (!machine) {
90 dev_err(&pdev->dev, "Can't allocate tegra_wm9712 struct\n");
91 return -ENOMEM;
92 }
93
94 card->dev = &pdev->dev;
95 platform_set_drvdata(pdev, card);
96 snd_soc_card_set_drvdata(card, machine);
97
98 machine->codec = platform_device_alloc("wm9712-codec", -1);
99 if (!machine->codec) {
100 dev_err(&pdev->dev, "Can't allocate wm9712 platform device\n");
101 return -ENOMEM;
102 }
103
104 ret = platform_device_add(machine->codec);
105 if (ret)
106 goto codec_put;
107
108 ret = snd_soc_of_parse_card_name(card, "nvidia,model");
109 if (ret)
110 goto codec_unregister;
111
112 ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
113 if (ret)
114 goto codec_unregister;
115
116 tegra_wm9712_dai.cpu_of_node = of_parse_phandle(np,
117 "nvidia,ac97-controller", 0);
118 if (!tegra_wm9712_dai.cpu_of_node) {
119 dev_err(&pdev->dev,
120 "Property 'nvidia,ac97-controller' missing or invalid\n");
121 ret = -EINVAL;
122 goto codec_unregister;
123 }
124
125 tegra_wm9712_dai.platform_of_node = tegra_wm9712_dai.cpu_of_node;
126
127 ret = snd_soc_register_card(card);
128 if (ret) {
129 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
130 ret);
131 goto codec_unregister;
132 }
133
134 return 0;
135
136codec_unregister:
137 platform_device_del(machine->codec);
138codec_put:
139 platform_device_put(machine->codec);
140 return ret;
141}
142
143static int tegra_wm9712_driver_remove(struct platform_device *pdev)
144{
145 struct snd_soc_card *card = platform_get_drvdata(pdev);
146 struct tegra_wm9712 *machine = snd_soc_card_get_drvdata(card);
147
148 snd_soc_unregister_card(card);
149
150 platform_device_unregister(machine->codec);
151
152 return 0;
153}
154
155static const struct of_device_id tegra_wm9712_of_match[] __devinitconst = {
156 { .compatible = "nvidia,tegra-audio-wm9712", },
157 {},
158};
159
160static struct platform_driver tegra_wm9712_driver = {
161 .driver = {
162 .name = DRV_NAME,
163 .owner = THIS_MODULE,
164 .pm = &snd_soc_pm_ops,
165 .of_match_table = tegra_wm9712_of_match,
166 },
167 .probe = tegra_wm9712_driver_probe,
168 .remove = tegra_wm9712_driver_remove,
169};
170module_platform_driver(tegra_wm9712_driver);
171
172MODULE_AUTHOR("Lucas Stach");
173MODULE_DESCRIPTION("Tegra+WM9712 machine ASoC driver");
174MODULE_LICENSE("GPL v2");
175MODULE_ALIAS("platform:" DRV_NAME);
176MODULE_DEVICE_TABLE(of, tegra_wm9712_of_match);