aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-13 13:06:58 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-13 13:06:58 -0400
commitbe3bfbba8f7f6c8f32e8444ef895433701a3f801 (patch)
treedfd00be7d15dbf8353f188f2505426411cb18d06 /sound/soc
parent20272c8994cf1e1f8ed745a2ea161dd9ad3889f2 (diff)
parent7dc85076f83253fcffae99e6d5e6ce77840f8841 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (33 commits) ALSA: ASoC codec: remove unused #include <version.h> ALSA: ASoC: update email address for Liam Girdwood ALSA: hda: corrected invalid mixer values ALSA: hda: add mixers for analog mixer on 92hd75xx codecs ALSA: ASoC: Add destination and source port for DMA on OMAP1 ALSA: ASoC: Drop device registration from GTA01 lm4857 driver ALSA: ASoC: Fix build of GTA01 audio driver ALSA: ASoC: Add widgets before setting endpoints on GTA01 ALSA: ASoC: Fix inverted input PGA mute bits in WM8903 ALSA: ASoC: OMAP: Set DMA stream name at runtime in McBSP DAI driver ALSA: ASoC: OMAP: Add support for OMAP2430 and OMAP34xx in McBSP DAI driver ALSA: ASoC: OMAP: Add multilink support to McBSP DAI driver ALSA: ASoC: Make TLV320AIC26 user-visible ALSA: ASoC - clean up Kconfig for TLV320AIC2 ALSA: ASoC: Make WM8510 microphone input a DAPM mixer ALSA: ASoC: Implement WM8510 bias level control ALSA: ASoC: Remove unused AUDIO_NAME define from codec drivers ALSA: ASoC: tlv320aic3x: Use uniform tlv320aic naming ALSA: ASoC: Add WM8510 SPI support ALSA: ASoC: Add WM8753 SPI support ...
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/at91/Kconfig17
-rw-r--r--sound/soc/at91/Makefile5
-rw-r--r--sound/soc/at91/at91-ssc.c2
-rw-r--r--sound/soc/at91/eti_b1_wm8731.c349
-rw-r--r--sound/soc/blackfin/Kconfig16
-rw-r--r--sound/soc/blackfin/Makefile3
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c42
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c1
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c240
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c47
-rw-r--r--sound/soc/blackfin/bf5xx-sport.h2
-rw-r--r--sound/soc/codecs/Kconfig11
-rw-r--r--sound/soc/codecs/Makefile4
-rw-r--r--sound/soc/codecs/ac97.c3
-rw-r--r--sound/soc/codecs/ad1980.c1
-rw-r--r--sound/soc/codecs/ad73311.c107
-rw-r--r--sound/soc/codecs/ad73311.h90
-rw-r--r--sound/soc/codecs/ak4535.c1
-rw-r--r--sound/soc/codecs/ssm2602.c1
-rw-r--r--sound/soc/codecs/tlv320aic23.c714
-rw-r--r--sound/soc/codecs/tlv320aic23.h122
-rw-r--r--sound/soc/codecs/tlv320aic3x.c5
-rw-r--r--sound/soc/codecs/uda1380.c1
-rw-r--r--sound/soc/codecs/wm8510.c111
-rw-r--r--sound/soc/codecs/wm8510.h1
-rw-r--r--sound/soc/codecs/wm8580.c2
-rw-r--r--sound/soc/codecs/wm8731.c1
-rw-r--r--sound/soc/codecs/wm8750.c1
-rw-r--r--sound/soc/codecs/wm8753.c75
-rw-r--r--sound/soc/codecs/wm8753.h4
-rw-r--r--sound/soc/codecs/wm8900.c1
-rw-r--r--sound/soc/codecs/wm8903.c4
-rw-r--r--sound/soc/codecs/wm8971.c1
-rw-r--r--sound/soc/codecs/wm8990.c1
-rw-r--r--sound/soc/codecs/wm9712.c3
-rw-r--r--sound/soc/codecs/wm9713.c3
-rw-r--r--sound/soc/omap/Kconfig8
-rw-r--r--sound/soc/omap/Makefile2
-rw-r--r--sound/soc/omap/n810.c6
-rw-r--r--sound/soc/omap/omap-mcbsp.c181
-rw-r--r--sound/soc/omap/omap-mcbsp.h16
-rw-r--r--sound/soc/omap/omap-pcm.c4
-rw-r--r--sound/soc/omap/osk5912.c232
-rw-r--r--sound/soc/pxa/corgi.c6
-rw-r--r--sound/soc/pxa/em-x270.c2
-rw-r--r--sound/soc/pxa/poodle.c6
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c4
-rw-r--r--sound/soc/pxa/spitz.c16
-rw-r--r--sound/soc/pxa/tosa.c6
-rw-r--r--sound/soc/s3c24xx/neo1973_wm8753.c72
-rw-r--r--sound/soc/soc-core.c5
-rw-r--r--sound/soc/soc-dapm.c25
52 files changed, 1998 insertions, 585 deletions
diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig
index 905186502e00..85a883299c2e 100644
--- a/sound/soc/at91/Kconfig
+++ b/sound/soc/at91/Kconfig
@@ -8,20 +8,3 @@ config SND_AT91_SOC
8 8
9config SND_AT91_SOC_SSC 9config SND_AT91_SOC_SSC
10 tristate 10 tristate
11
12config SND_AT91_SOC_ETI_B1_WM8731
13 tristate "SoC Audio support for WM8731-based Endrelia ETI-B1 boards"
14 depends on SND_AT91_SOC && (MACH_ETI_B1 || MACH_ETI_C1)
15 select SND_AT91_SOC_SSC
16 select SND_SOC_WM8731
17 help
18 Say Y if you want to add support for SoC audio on WM8731-based
19 Endrelia Technologies Inc ETI-B1 or ETI-C1 boards.
20
21config SND_AT91_SOC_ETI_SLAVE
22 bool "Run codec in slave Mode on Endrelia boards"
23 depends on SND_AT91_SOC_ETI_B1_WM8731
24 default n
25 help
26 Say Y if you want to run with the AT91 SSC generating the BCLK
27 and LRC signals on Endrelia boards.
diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile
index f23da17cc328..b817f11df286 100644
--- a/sound/soc/at91/Makefile
+++ b/sound/soc/at91/Makefile
@@ -4,8 +4,3 @@ snd-soc-at91-ssc-objs := at91-ssc.o
4 4
5obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o 5obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
6obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o 6obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o
7
8# AT91 Machine Support
9snd-soc-eti-b1-wm8731-objs := eti_b1_wm8731.o
10
11obj-$(CONFIG_SND_AT91_SOC_ETI_B1_WM8731) += snd-soc-eti-b1-wm8731.o
diff --git a/sound/soc/at91/at91-ssc.c b/sound/soc/at91/at91-ssc.c
index a5b1a79ebffb..1b61cc461261 100644
--- a/sound/soc/at91/at91-ssc.c
+++ b/sound/soc/at91/at91-ssc.c
@@ -5,7 +5,7 @@
5 * Endrelia Technologies Inc. 5 * Endrelia Technologies Inc.
6 * 6 *
7 * Based on pxa2xx Platform drivers by 7 * Based on pxa2xx Platform drivers by
8 * Liam Girdwood <liam.girdwood@wolfsonmicro.com> 8 * Liam Girdwood <lrg@slimlogic.co.uk>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the 11 * under the terms of the GNU General Public License as published by the
diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c
deleted file mode 100644
index 684781e4088b..000000000000
--- a/sound/soc/at91/eti_b1_wm8731.c
+++ /dev/null
@@ -1,349 +0,0 @@
1/*
2 * eti_b1_wm8731 -- SoC audio for AT91RM9200-based Endrelia ETI_B1 board.
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 * Created: Mar 29, 2006
7 *
8 * Based on corgi.c by:
9 *
10 * Copyright 2005 Wolfson Microelectronics PLC.
11 * Copyright 2005 Openedhand Ltd.
12 *
13 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
14 * Richard Purdie <richard@openedhand.com>
15 *
16 * This program is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the
18 * Free Software Foundation; either version 2 of the License, or (at your
19 * option) any later version.
20 *
21 */
22
23#include <linux/module.h>
24#include <linux/moduleparam.h>
25#include <linux/kernel.h>
26#include <linux/clk.h>
27#include <linux/timer.h>
28#include <linux/interrupt.h>
29#include <linux/platform_device.h>
30#include <sound/core.h>
31#include <sound/pcm.h>
32#include <sound/soc.h>
33#include <sound/soc-dapm.h>
34
35#include <mach/hardware.h>
36#include <mach/gpio.h>
37
38#include "../codecs/wm8731.h"
39#include "at91-pcm.h"
40#include "at91-ssc.h"
41
42#if 0
43#define DBG(x...) printk(KERN_INFO "eti_b1_wm8731: " x)
44#else
45#define DBG(x...)
46#endif
47
48static struct clk *pck1_clk;
49static struct clk *pllb_clk;
50
51
52static int eti_b1_startup(struct snd_pcm_substream *substream)
53{
54 struct snd_soc_pcm_runtime *rtd = substream->private_data;
55 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
56 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
57 int ret;
58
59 /* cpu clock is the AT91 master clock sent to the SSC */
60 ret = snd_soc_dai_set_sysclk(cpu_dai, AT91_SYSCLK_MCK,
61 60000000, SND_SOC_CLOCK_IN);
62 if (ret < 0)
63 return ret;
64
65 /* codec system clock is supplied by PCK1, set to 12MHz */
66 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
67 12000000, SND_SOC_CLOCK_IN);
68 if (ret < 0)
69 return ret;
70
71 /* Start PCK1 clock. */
72 clk_enable(pck1_clk);
73 DBG("pck1 started\n");
74
75 return 0;
76}
77
78static void eti_b1_shutdown(struct snd_pcm_substream *substream)
79{
80 /* Stop PCK1 clock. */
81 clk_disable(pck1_clk);
82 DBG("pck1 stopped\n");
83}
84
85static int eti_b1_hw_params(struct snd_pcm_substream *substream,
86 struct snd_pcm_hw_params *params)
87{
88 struct snd_soc_pcm_runtime *rtd = substream->private_data;
89 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
90 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
91 int ret;
92
93#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
94 unsigned int rate;
95 int cmr_div, period;
96
97 /* set codec DAI configuration */
98 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
99 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
100 if (ret < 0)
101 return ret;
102
103 /* set cpu DAI configuration */
104 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
105 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
106 if (ret < 0)
107 return ret;
108
109 /*
110 * The SSC clock dividers depend on the sample rate. The CMR.DIV
111 * field divides the system master clock MCK to drive the SSC TK
112 * signal which provides the codec BCLK. The TCMR.PERIOD and
113 * RCMR.PERIOD fields further divide the BCLK signal to drive
114 * the SSC TF and RF signals which provide the codec DACLRC and
115 * ADCLRC clocks.
116 *
117 * The dividers were determined through trial and error, where a
118 * CMR.DIV value is chosen such that the resulting BCLK value is
119 * divisible, or almost divisible, by (2 * sample rate), and then
120 * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
121 */
122 rate = params_rate(params);
123
124 switch (rate) {
125 case 8000:
126 cmr_div = 25; /* BCLK = 60MHz/(2*25) = 1.2MHz */
127 period = 74; /* LRC = BCLK/(2*(74+1)) = 8000Hz */
128 break;
129 case 32000:
130 cmr_div = 7; /* BCLK = 60MHz/(2*7) ~= 4.28571428MHz */
131 period = 66; /* LRC = BCLK/(2*(66+1)) = 31982.942Hz */
132 break;
133 case 48000:
134 cmr_div = 13; /* BCLK = 60MHz/(2*13) ~= 2.3076923MHz */
135 period = 23; /* LRC = BCLK/(2*(23+1)) = 48076.923Hz */
136 break;
137 default:
138 printk(KERN_WARNING "unsupported rate %d on ETI-B1 board\n", rate);
139 return -EINVAL;
140 }
141
142 /* set the MCK divider for BCLK */
143 ret = snd_soc_dai_set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div);
144 if (ret < 0)
145 return ret;
146
147 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
148 /* set the BCLK divider for DACLRC */
149 ret = snd_soc_dai_set_clkdiv(cpu_dai,
150 AT91SSC_TCMR_PERIOD, period);
151 } else {
152 /* set the BCLK divider for ADCLRC */
153 ret = snd_soc_dai_set_clkdiv(cpu_dai,
154 AT91SSC_RCMR_PERIOD, period);
155 }
156 if (ret < 0)
157 return ret;
158
159#else /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
160 /*
161 * Codec in Master Mode.
162 */
163
164 /* set codec DAI configuration */
165 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
166 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
167 if (ret < 0)
168 return ret;
169
170 /* set cpu DAI configuration */
171 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
172 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
173 if (ret < 0)
174 return ret;
175
176#endif /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
177
178 return 0;
179}
180
181static struct snd_soc_ops eti_b1_ops = {
182 .startup = eti_b1_startup,
183 .hw_params = eti_b1_hw_params,
184 .shutdown = eti_b1_shutdown,
185};
186
187
188static const struct snd_soc_dapm_widget eti_b1_dapm_widgets[] = {
189 SND_SOC_DAPM_MIC("Int Mic", NULL),
190 SND_SOC_DAPM_SPK("Ext Spk", NULL),
191};
192
193static const struct snd_soc_dapm_route intercon[] = {
194
195 /* speaker connected to LHPOUT */
196 {"Ext Spk", NULL, "LHPOUT"},
197
198 /* mic is connected to Mic Jack, with WM8731 Mic Bias */
199 {"MICIN", NULL, "Mic Bias"},
200 {"Mic Bias", NULL, "Int Mic"},
201};
202
203/*
204 * Logic for a wm8731 as connected on a Endrelia ETI-B1 board.
205 */
206static int eti_b1_wm8731_init(struct snd_soc_codec *codec)
207{
208 DBG("eti_b1_wm8731_init() called\n");
209
210 /* Add specific widgets */
211 snd_soc_dapm_new_controls(codec, eti_b1_dapm_widgets,
212 ARRAY_SIZE(eti_b1_dapm_widgets));
213
214 /* Set up specific audio path interconnects */
215 snd_soc_dapm_add_route(codec, intercon, ARRAY_SIZE(intercon));
216
217 /* not connected */
218 snd_soc_dapm_disable_pin(codec, "RLINEIN");
219 snd_soc_dapm_disable_pin(codec, "LLINEIN");
220
221 /* always connected */
222 snd_soc_dapm_enable_pin(codec, "Int Mic");
223 snd_soc_dapm_enable_pin(codec, "Ext Spk");
224
225 snd_soc_dapm_sync(codec);
226
227 return 0;
228}
229
230static struct snd_soc_dai_link eti_b1_dai = {
231 .name = "WM8731",
232 .stream_name = "WM8731 PCM",
233 .cpu_dai = &at91_ssc_dai[1],
234 .codec_dai = &wm8731_dai,
235 .init = eti_b1_wm8731_init,
236 .ops = &eti_b1_ops,
237};
238
239static struct snd_soc_machine snd_soc_machine_eti_b1 = {
240 .name = "ETI_B1_WM8731",
241 .dai_link = &eti_b1_dai,
242 .num_links = 1,
243};
244
245static struct wm8731_setup_data eti_b1_wm8731_setup = {
246 .i2c_bus = 0,
247 .i2c_address = 0x1a,
248};
249
250static struct snd_soc_device eti_b1_snd_devdata = {
251 .machine = &snd_soc_machine_eti_b1,
252 .platform = &at91_soc_platform,
253 .codec_dev = &soc_codec_dev_wm8731,
254 .codec_data = &eti_b1_wm8731_setup,
255};
256
257static struct platform_device *eti_b1_snd_device;
258
259static int __init eti_b1_init(void)
260{
261 int ret;
262 struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
263
264 if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) {
265 DBG("SSC1 memory region is busy\n");
266 return -EBUSY;
267 }
268
269 ssc->base = ioremap(AT91RM9200_BASE_SSC1, SZ_16K);
270 if (!ssc->base) {
271 DBG("SSC1 memory ioremap failed\n");
272 ret = -ENOMEM;
273 goto fail_release_mem;
274 }
275
276 ssc->pid = AT91RM9200_ID_SSC1;
277
278 eti_b1_snd_device = platform_device_alloc("soc-audio", -1);
279 if (!eti_b1_snd_device) {
280 DBG("platform device allocation failed\n");
281 ret = -ENOMEM;
282 goto fail_io_unmap;
283 }
284
285 platform_set_drvdata(eti_b1_snd_device, &eti_b1_snd_devdata);
286 eti_b1_snd_devdata.dev = &eti_b1_snd_device->dev;
287
288 ret = platform_device_add(eti_b1_snd_device);
289 if (ret) {
290 DBG("platform device add failed\n");
291 platform_device_put(eti_b1_snd_device);
292 goto fail_io_unmap;
293 }
294
295 at91_set_A_periph(AT91_PIN_PB6, 0); /* TF1 */
296 at91_set_A_periph(AT91_PIN_PB7, 0); /* TK1 */
297 at91_set_A_periph(AT91_PIN_PB8, 0); /* TD1 */
298 at91_set_A_periph(AT91_PIN_PB9, 0); /* RD1 */
299/* at91_set_A_periph(AT91_PIN_PB10, 0);*/ /* RK1 */
300 at91_set_A_periph(AT91_PIN_PB11, 0); /* RF1 */
301
302 /*
303 * Set PCK1 parent to PLLB and its rate to 12 Mhz.
304 */
305 pllb_clk = clk_get(NULL, "pllb");
306 pck1_clk = clk_get(NULL, "pck1");
307
308 clk_set_parent(pck1_clk, pllb_clk);
309 clk_set_rate(pck1_clk, 12000000);
310
311 DBG("MCLK rate %luHz\n", clk_get_rate(pck1_clk));
312
313 /* assign the GPIO pin to PCK1 */
314 at91_set_B_periph(AT91_PIN_PA24, 0);
315
316#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
317 printk(KERN_INFO "eti_b1_wm8731: Codec in Slave Mode\n");
318#else
319 printk(KERN_INFO "eti_b1_wm8731: Codec in Master Mode\n");
320#endif
321 return ret;
322
323fail_io_unmap:
324 iounmap(ssc->base);
325fail_release_mem:
326 release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
327 return ret;
328}
329
330static void __exit eti_b1_exit(void)
331{
332 struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
333
334 clk_put(pck1_clk);
335 clk_put(pllb_clk);
336
337 platform_device_unregister(eti_b1_snd_device);
338
339 iounmap(ssc->base);
340 release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
341}
342
343module_init(eti_b1_init);
344module_exit(eti_b1_exit);
345
346/* Module information */
347MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
348MODULE_DESCRIPTION("ALSA SoC ETI-B1-WM8731");
349MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index f98331d099e7..dc006206f622 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -17,6 +17,22 @@ config SND_BF5XX_SOC_SSM2602
17 help 17 help
18 Say Y if you want to add support for SoC audio on BF527-EZKIT. 18 Say Y if you want to add support for SoC audio on BF527-EZKIT.
19 19
20config SND_BF5XX_SOC_AD73311
21 tristate "SoC AD73311 Audio support for Blackfin"
22 depends on SND_BF5XX_I2S
23 select SND_BF5XX_SOC_I2S
24 select SND_SOC_AD73311
25 help
26 Say Y if you want to add support for AD73311 codec on Blackfin.
27
28config SND_BFIN_AD73311_SE
29 int "PF pin for AD73311L Chip Select"
30 depends on SND_BF5XX_SOC_AD73311
31 default 4
32 help
33 Enter the GPIO used to control AD73311's SE pin. Acceptable
34 values are 0 to 7
35
20config SND_BF5XX_AC97 36config SND_BF5XX_AC97
21 tristate "SoC AC97 Audio for the ADI BF5xx chip" 37 tristate "SoC AC97 Audio for the ADI BF5xx chip"
22 depends on BLACKFIN && SND_SOC 38 depends on BLACKFIN && SND_SOC
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile
index 9ea8bd9e0ba3..97bb37a6359c 100644
--- a/sound/soc/blackfin/Makefile
+++ b/sound/soc/blackfin/Makefile
@@ -14,7 +14,8 @@ obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o
14# Blackfin Machine Support 14# Blackfin Machine Support
15snd-ad1980-objs := bf5xx-ad1980.o 15snd-ad1980-objs := bf5xx-ad1980.o
16snd-ssm2602-objs := bf5xx-ssm2602.o 16snd-ssm2602-objs := bf5xx-ssm2602.o
17 17snd-ad73311-objs := bf5xx-ad73311.o
18 18
19obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o 19obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
20obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o 20obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
21obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 51f4907c4831..25e50d2ea1ec 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -56,6 +56,7 @@ static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
56 sport->tx_pos += runtime->period_size; 56 sport->tx_pos += runtime->period_size;
57 if (sport->tx_pos >= runtime->buffer_size) 57 if (sport->tx_pos >= runtime->buffer_size)
58 sport->tx_pos %= runtime->buffer_size; 58 sport->tx_pos %= runtime->buffer_size;
59 sport->tx_delay_pos = sport->tx_pos;
59 } else { 60 } else {
60 bf5xx_ac97_to_pcm( 61 bf5xx_ac97_to_pcm(
61 (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos, 62 (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos,
@@ -72,7 +73,15 @@ static void bf5xx_dma_irq(void *data)
72 struct snd_pcm_substream *pcm = data; 73 struct snd_pcm_substream *pcm = data;
73#if defined(CONFIG_SND_MMAP_SUPPORT) 74#if defined(CONFIG_SND_MMAP_SUPPORT)
74 struct snd_pcm_runtime *runtime = pcm->runtime; 75 struct snd_pcm_runtime *runtime = pcm->runtime;
76 struct sport_device *sport = runtime->private_data;
75 bf5xx_mmap_copy(pcm, runtime->period_size); 77 bf5xx_mmap_copy(pcm, runtime->period_size);
78 if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK) {
79 if (sport->once == 0) {
80 snd_pcm_period_elapsed(pcm);
81 bf5xx_mmap_copy(pcm, runtime->period_size);
82 sport->once = 1;
83 }
84 }
76#endif 85#endif
77 snd_pcm_period_elapsed(pcm); 86 snd_pcm_period_elapsed(pcm);
78} 87}
@@ -114,6 +123,10 @@ static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
114 123
115static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) 124static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
116{ 125{
126 struct snd_pcm_runtime *runtime = substream->runtime;
127
128 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
129 memset(runtime->dma_area, 0, runtime->buffer_size);
117 snd_pcm_lib_free_pages(substream); 130 snd_pcm_lib_free_pages(substream);
118 return 0; 131 return 0;
119} 132}
@@ -127,16 +140,11 @@ static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
127 * SPORT working in TMD mode(include AC97). 140 * SPORT working in TMD mode(include AC97).
128 */ 141 */
129#if defined(CONFIG_SND_MMAP_SUPPORT) 142#if defined(CONFIG_SND_MMAP_SUPPORT)
130 size_t size = bf5xx_pcm_hardware.buffer_bytes_max
131 * sizeof(struct ac97_frame) / 4;
132 /*clean up intermediate buffer*/
133 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 143 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
134 memset(sport->tx_dma_buf, 0, size);
135 sport_set_tx_callback(sport, bf5xx_dma_irq, substream); 144 sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
136 sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods, 145 sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods,
137 runtime->period_size * sizeof(struct ac97_frame)); 146 runtime->period_size * sizeof(struct ac97_frame));
138 } else { 147 } else {
139 memset(sport->rx_dma_buf, 0, size);
140 sport_set_rx_callback(sport, bf5xx_dma_irq, substream); 148 sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
141 sport_config_rx_dma(sport, sport->rx_dma_buf, runtime->periods, 149 sport_config_rx_dma(sport, sport->rx_dma_buf, runtime->periods,
142 runtime->period_size * sizeof(struct ac97_frame)); 150 runtime->period_size * sizeof(struct ac97_frame));
@@ -164,8 +172,12 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
164 pr_debug("%s enter\n", __func__); 172 pr_debug("%s enter\n", __func__);
165 switch (cmd) { 173 switch (cmd) {
166 case SNDRV_PCM_TRIGGER_START: 174 case SNDRV_PCM_TRIGGER_START:
167 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 175 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
176 bf5xx_mmap_copy(substream, runtime->period_size);
177 snd_pcm_period_elapsed(substream);
178 sport->tx_delay_pos = 0;
168 sport_tx_start(sport); 179 sport_tx_start(sport);
180 }
169 else 181 else
170 sport_rx_start(sport); 182 sport_rx_start(sport);
171 break; 183 break;
@@ -198,7 +210,7 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
198 210
199#if defined(CONFIG_SND_MMAP_SUPPORT) 211#if defined(CONFIG_SND_MMAP_SUPPORT)
200 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 212 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
201 curr = sport->tx_pos; 213 curr = sport->tx_delay_pos;
202 else 214 else
203 curr = sport->rx_pos; 215 curr = sport->rx_pos;
204#else 216#else
@@ -237,6 +249,21 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
237 return ret; 249 return ret;
238} 250}
239 251
252static int bf5xx_pcm_close(struct snd_pcm_substream *substream)
253{
254 struct snd_pcm_runtime *runtime = substream->runtime;
255 struct sport_device *sport = runtime->private_data;
256
257 pr_debug("%s enter\n", __func__);
258 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
259 sport->once = 0;
260 memset(sport->tx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
261 } else
262 memset(sport->rx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
263
264 return 0;
265}
266
240#ifdef CONFIG_SND_MMAP_SUPPORT 267#ifdef CONFIG_SND_MMAP_SUPPORT
241static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, 268static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
242 struct vm_area_struct *vma) 269 struct vm_area_struct *vma)
@@ -272,6 +299,7 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
272 299
273struct snd_pcm_ops bf5xx_pcm_ac97_ops = { 300struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
274 .open = bf5xx_pcm_open, 301 .open = bf5xx_pcm_open,
302 .close = bf5xx_pcm_close,
275 .ioctl = snd_pcm_lib_ioctl, 303 .ioctl = snd_pcm_lib_ioctl,
276 .hw_params = bf5xx_pcm_hw_params, 304 .hw_params = bf5xx_pcm_hw_params,
277 .hw_free = bf5xx_pcm_hw_free, 305 .hw_free = bf5xx_pcm_hw_free,
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index c782e311fd56..5e5aafb6485f 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -129,7 +129,6 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data)
129 struct ac97_frame *nextwrite; 129 struct ac97_frame *nextwrite;
130 130
131 sport_incfrag(sport, &nextfrag, 1); 131 sport_incfrag(sport, &nextfrag, 1);
132 sport_incfrag(sport, &nextfrag, 1);
133 132
134 nextwrite = (struct ac97_frame *)(sport->tx_buf + \ 133 nextwrite = (struct ac97_frame *)(sport->tx_buf + \
135 nextfrag * sport->tx_fragsize); 134 nextfrag * sport->tx_fragsize);
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
new file mode 100644
index 000000000000..622c9b909532
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -0,0 +1,240 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-ad73311.c
3 * Author: Cliff Cai <Cliff.Cai@analog.com>
4 *
5 * Created: Thur Sep 25 2008
6 * Description: Board driver for ad73311 sound chip
7 *
8 * Modified:
9 * Copyright 2008 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/module.h>
30#include <linux/moduleparam.h>
31#include <linux/device.h>
32#include <linux/delay.h>
33#include <linux/gpio.h>
34
35#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/soc.h>
38#include <sound/soc-dapm.h>
39#include <sound/pcm_params.h>
40
41#include <asm/blackfin.h>
42#include <asm/cacheflush.h>
43#include <asm/irq.h>
44#include <asm/dma.h>
45#include <asm/portmux.h>
46
47#include "../codecs/ad73311.h"
48#include "bf5xx-sport.h"
49#include "bf5xx-i2s-pcm.h"
50#include "bf5xx-i2s.h"
51
52#if CONFIG_SND_BF5XX_SPORT_NUM == 0
53#define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1
54#define bfin_read_SPORT_TCR1 bfin_read_SPORT0_TCR1
55#define bfin_write_SPORT_TCR2 bfin_write_SPORT0_TCR2
56#define bfin_write_SPORT_TX16 bfin_write_SPORT0_TX16
57#define bfin_read_SPORT_STAT bfin_read_SPORT0_STAT
58#else
59#define bfin_write_SPORT_TCR1 bfin_write_SPORT1_TCR1
60#define bfin_read_SPORT_TCR1 bfin_read_SPORT1_TCR1
61#define bfin_write_SPORT_TCR2 bfin_write_SPORT1_TCR2
62#define bfin_write_SPORT_TX16 bfin_write_SPORT1_TX16
63#define bfin_read_SPORT_STAT bfin_read_SPORT1_STAT
64#endif
65
66#define GPIO_SE CONFIG_SND_BFIN_AD73311_SE
67
68static struct snd_soc_machine bf5xx_ad73311;
69
70static int snd_ad73311_startup(void)
71{
72 pr_debug("%s enter\n", __func__);
73
74 /* Pull up SE pin on AD73311L */
75 gpio_set_value(GPIO_SE, 1);
76 return 0;
77}
78
79static int snd_ad73311_configure(void)
80{
81 unsigned short ctrl_regs[6];
82 unsigned short status = 0;
83 int count = 0;
84
85 /* DMCLK = MCLK = 16.384 MHz
86 * SCLK = DMCLK/8 = 2.048 MHz
87 * Sample Rate = DMCLK/2048 = 8 KHz
88 */
89 ctrl_regs[0] = AD_CONTROL | AD_WRITE | CTRL_REG_B | REGB_MCDIV(0) | \
90 REGB_SCDIV(0) | REGB_DIRATE(0);
91 ctrl_regs[1] = AD_CONTROL | AD_WRITE | CTRL_REG_C | REGC_PUDEV | \
92 REGC_PUADC | REGC_PUDAC | REGC_PUREF | REGC_REFUSE ;
93 ctrl_regs[2] = AD_CONTROL | AD_WRITE | CTRL_REG_D | REGD_OGS(2) | \
94 REGD_IGS(2);
95 ctrl_regs[3] = AD_CONTROL | AD_WRITE | CTRL_REG_E | REGE_DA(0x1f);
96 ctrl_regs[4] = AD_CONTROL | AD_WRITE | CTRL_REG_F | REGF_SEEN ;
97 ctrl_regs[5] = AD_CONTROL | AD_WRITE | CTRL_REG_A | REGA_MODE_DATA;
98
99 local_irq_disable();
100 snd_ad73311_startup();
101 udelay(1);
102
103 bfin_write_SPORT_TCR1(TFSR);
104 bfin_write_SPORT_TCR2(0xF);
105 SSYNC();
106
107 /* SPORT Tx Register is a 8 x 16 FIFO, all the data can be put to
108 * FIFO before enable SPORT to transfer the data
109 */
110 for (count = 0; count < 6; count++)
111 bfin_write_SPORT_TX16(ctrl_regs[count]);
112 SSYNC();
113 bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() | TSPEN);
114 SSYNC();
115
116 /* When TUVF is set, the data is already send out */
117 while (!(status & TUVF) && count++ < 10000) {
118 udelay(1);
119 status = bfin_read_SPORT_STAT();
120 SSYNC();
121 }
122 bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() & ~TSPEN);
123 SSYNC();
124 local_irq_enable();
125
126 if (count == 10000) {
127 printk(KERN_ERR "ad73311: failed to configure codec\n");
128 return -1;
129 }
130 return 0;
131}
132
133static int bf5xx_probe(struct platform_device *pdev)
134{
135 int err;
136 if (gpio_request(GPIO_SE, "AD73311_SE")) {
137 printk(KERN_ERR "%s: Failed ro request GPIO_%d\n", __func__, GPIO_SE);
138 return -EBUSY;
139 }
140
141 gpio_direction_output(GPIO_SE, 0);
142
143 err = snd_ad73311_configure();
144 if (err < 0)
145 return -EFAULT;
146
147 return 0;
148}
149
150static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream)
151{
152 struct snd_soc_pcm_runtime *rtd = substream->private_data;
153 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
154
155 pr_debug("%s enter\n", __func__);
156 cpu_dai->private_data = sport_handle;
157 return 0;
158}
159
160static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
161 struct snd_pcm_hw_params *params)
162{
163 struct snd_soc_pcm_runtime *rtd = substream->private_data;
164 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
165 int ret = 0;
166
167 pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
168 params_format(params));
169
170 /* set cpu DAI configuration */
171 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
172 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
173 if (ret < 0)
174 return ret;
175
176 return 0;
177}
178
179
180static struct snd_soc_ops bf5xx_ad73311_ops = {
181 .startup = bf5xx_ad73311_startup,
182 .hw_params = bf5xx_ad73311_hw_params,
183};
184
185static struct snd_soc_dai_link bf5xx_ad73311_dai = {
186 .name = "ad73311",
187 .stream_name = "AD73311",
188 .cpu_dai = &bf5xx_i2s_dai,
189 .codec_dai = &ad73311_dai,
190 .ops = &bf5xx_ad73311_ops,
191};
192
193static struct snd_soc_machine bf5xx_ad73311 = {
194 .name = "bf5xx_ad73311",
195 .probe = bf5xx_probe,
196 .dai_link = &bf5xx_ad73311_dai,
197 .num_links = 1,
198};
199
200static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
201 .machine = &bf5xx_ad73311,
202 .platform = &bf5xx_i2s_soc_platform,
203 .codec_dev = &soc_codec_dev_ad73311,
204};
205
206static struct platform_device *bf52x_ad73311_snd_device;
207
208static int __init bf5xx_ad73311_init(void)
209{
210 int ret;
211
212 pr_debug("%s enter\n", __func__);
213 bf52x_ad73311_snd_device = platform_device_alloc("soc-audio", -1);
214 if (!bf52x_ad73311_snd_device)
215 return -ENOMEM;
216
217 platform_set_drvdata(bf52x_ad73311_snd_device, &bf5xx_ad73311_snd_devdata);
218 bf5xx_ad73311_snd_devdata.dev = &bf52x_ad73311_snd_device->dev;
219 ret = platform_device_add(bf52x_ad73311_snd_device);
220
221 if (ret)
222 platform_device_put(bf52x_ad73311_snd_device);
223
224 return ret;
225}
226
227static void __exit bf5xx_ad73311_exit(void)
228{
229 pr_debug("%s enter\n", __func__);
230 platform_device_unregister(bf52x_ad73311_snd_device);
231}
232
233module_init(bf5xx_ad73311_init);
234module_exit(bf5xx_ad73311_exit);
235
236/* Module information */
237MODULE_AUTHOR("Cliff Cai");
238MODULE_DESCRIPTION("ALSA SoC AD73311 Blackfin");
239MODULE_LICENSE("GPL");
240
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 43a4092eeb89..827587f08180 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -70,6 +70,13 @@ static struct sport_param sport_params[2] = {
70 } 70 }
71}; 71};
72 72
73static u16 sport_req[][7] = {
74 { P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
75 P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0},
76 { P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
77 P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0},
78};
79
73static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, 80static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
74 unsigned int fmt) 81 unsigned int fmt)
75{ 82{
@@ -78,6 +85,14 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
78 /* interface format:support I2S,slave mode */ 85 /* interface format:support I2S,slave mode */
79 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 86 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
80 case SND_SOC_DAIFMT_I2S: 87 case SND_SOC_DAIFMT_I2S:
88 bf5xx_i2s.tcr1 |= TFSR | TCKFE;
89 bf5xx_i2s.rcr1 |= RFSR | RCKFE;
90 bf5xx_i2s.tcr2 |= TSFSE;
91 bf5xx_i2s.rcr2 |= RSFSE;
92 break;
93 case SND_SOC_DAIFMT_DSP_A:
94 bf5xx_i2s.tcr1 |= TFSR;
95 bf5xx_i2s.rcr1 |= RFSR;
81 break; 96 break;
82 case SND_SOC_DAIFMT_LEFT_J: 97 case SND_SOC_DAIFMT_LEFT_J:
83 ret = -EINVAL; 98 ret = -EINVAL;
@@ -127,14 +142,17 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
127 case SNDRV_PCM_FORMAT_S16_LE: 142 case SNDRV_PCM_FORMAT_S16_LE:
128 bf5xx_i2s.tcr2 |= 15; 143 bf5xx_i2s.tcr2 |= 15;
129 bf5xx_i2s.rcr2 |= 15; 144 bf5xx_i2s.rcr2 |= 15;
145 sport_handle->wdsize = 2;
130 break; 146 break;
131 case SNDRV_PCM_FORMAT_S24_LE: 147 case SNDRV_PCM_FORMAT_S24_LE:
132 bf5xx_i2s.tcr2 |= 23; 148 bf5xx_i2s.tcr2 |= 23;
133 bf5xx_i2s.rcr2 |= 23; 149 bf5xx_i2s.rcr2 |= 23;
150 sport_handle->wdsize = 3;
134 break; 151 break;
135 case SNDRV_PCM_FORMAT_S32_LE: 152 case SNDRV_PCM_FORMAT_S32_LE:
136 bf5xx_i2s.tcr2 |= 31; 153 bf5xx_i2s.tcr2 |= 31;
137 bf5xx_i2s.rcr2 |= 31; 154 bf5xx_i2s.rcr2 |= 31;
155 sport_handle->wdsize = 4;
138 break; 156 break;
139 } 157 }
140 158
@@ -145,17 +163,17 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
145 * need to configure both of them at the time when the first 163 * need to configure both of them at the time when the first
146 * stream is opened. 164 * stream is opened.
147 * 165 *
148 * CPU DAI format:I2S, slave mode. 166 * CPU DAI:slave mode.
149 */ 167 */
150 ret = sport_config_rx(sport_handle, RFSR | RCKFE, 168 ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
151 RSFSE|bf5xx_i2s.rcr2, 0, 0); 169 bf5xx_i2s.rcr2, 0, 0);
152 if (ret) { 170 if (ret) {
153 pr_err("SPORT is busy!\n"); 171 pr_err("SPORT is busy!\n");
154 return -EBUSY; 172 return -EBUSY;
155 } 173 }
156 174
157 ret = sport_config_tx(sport_handle, TFSR | TCKFE, 175 ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1,
158 TSFSE|bf5xx_i2s.tcr2, 0, 0); 176 bf5xx_i2s.tcr2, 0, 0);
159 if (ret) { 177 if (ret) {
160 pr_err("SPORT is busy!\n"); 178 pr_err("SPORT is busy!\n");
161 return -EBUSY; 179 return -EBUSY;
@@ -174,13 +192,6 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream)
174static int bf5xx_i2s_probe(struct platform_device *pdev, 192static int bf5xx_i2s_probe(struct platform_device *pdev,
175 struct snd_soc_dai *dai) 193 struct snd_soc_dai *dai)
176{ 194{
177 u16 sport_req[][7] = {
178 { P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
179 P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0},
180 { P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
181 P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0},
182 };
183
184 pr_debug("%s enter\n", __func__); 195 pr_debug("%s enter\n", __func__);
185 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { 196 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
186 pr_err("Requesting Peripherals failed\n"); 197 pr_err("Requesting Peripherals failed\n");
@@ -198,6 +209,13 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
198 return 0; 209 return 0;
199} 210}
200 211
212static void bf5xx_i2s_remove(struct platform_device *pdev,
213 struct snd_soc_dai *dai)
214{
215 pr_debug("%s enter\n", __func__);
216 peripheral_free_list(&sport_req[sport_num][0]);
217}
218
201#ifdef CONFIG_PM 219#ifdef CONFIG_PM
202static int bf5xx_i2s_suspend(struct platform_device *dev, 220static int bf5xx_i2s_suspend(struct platform_device *dev,
203 struct snd_soc_dai *dai) 221 struct snd_soc_dai *dai)
@@ -263,15 +281,16 @@ struct snd_soc_dai bf5xx_i2s_dai = {
263 .id = 0, 281 .id = 0,
264 .type = SND_SOC_DAI_I2S, 282 .type = SND_SOC_DAI_I2S,
265 .probe = bf5xx_i2s_probe, 283 .probe = bf5xx_i2s_probe,
284 .remove = bf5xx_i2s_remove,
266 .suspend = bf5xx_i2s_suspend, 285 .suspend = bf5xx_i2s_suspend,
267 .resume = bf5xx_i2s_resume, 286 .resume = bf5xx_i2s_resume,
268 .playback = { 287 .playback = {
269 .channels_min = 2, 288 .channels_min = 1,
270 .channels_max = 2, 289 .channels_max = 2,
271 .rates = BF5XX_I2S_RATES, 290 .rates = BF5XX_I2S_RATES,
272 .formats = BF5XX_I2S_FORMATS,}, 291 .formats = BF5XX_I2S_FORMATS,},
273 .capture = { 292 .capture = {
274 .channels_min = 2, 293 .channels_min = 1,
275 .channels_max = 2, 294 .channels_max = 2,
276 .rates = BF5XX_I2S_RATES, 295 .rates = BF5XX_I2S_RATES,
277 .formats = BF5XX_I2S_FORMATS,}, 296 .formats = BF5XX_I2S_FORMATS,},
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h
index 4c163454bbf8..fcadcc081f7f 100644
--- a/sound/soc/blackfin/bf5xx-sport.h
+++ b/sound/soc/blackfin/bf5xx-sport.h
@@ -123,6 +123,8 @@ struct sport_device {
123 int rx_pos; 123 int rx_pos;
124 unsigned int tx_buffer_size; 124 unsigned int tx_buffer_size;
125 unsigned int rx_buffer_size; 125 unsigned int rx_buffer_size;
126 int tx_delay_pos;
127 int once;
126#endif 128#endif
127 void *private_data; 129 void *private_data;
128}; 130};
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index e0b9869df0f1..4975d8573e4f 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -3,9 +3,11 @@ config SND_SOC_ALL_CODECS
3 depends on I2C 3 depends on I2C
4 select SPI 4 select SPI
5 select SPI_MASTER 5 select SPI_MASTER
6 select SND_SOC_AD73311
6 select SND_SOC_AK4535 7 select SND_SOC_AK4535
7 select SND_SOC_CS4270 8 select SND_SOC_CS4270
8 select SND_SOC_SSM2602 9 select SND_SOC_SSM2602
10 select SND_SOC_TLV320AIC23
9 select SND_SOC_TLV320AIC26 11 select SND_SOC_TLV320AIC26
10 select SND_SOC_TLV320AIC3X 12 select SND_SOC_TLV320AIC3X
11 select SND_SOC_UDA1380 13 select SND_SOC_UDA1380
@@ -34,6 +36,9 @@ config SND_SOC_AC97_CODEC
34config SND_SOC_AD1980 36config SND_SOC_AD1980
35 tristate 37 tristate
36 38
39config SND_SOC_AD73311
40 tristate
41
37config SND_SOC_AK4535 42config SND_SOC_AK4535
38 tristate 43 tristate
39 44
@@ -58,9 +63,13 @@ config SND_SOC_CS4270_VD33_ERRATA
58config SND_SOC_SSM2602 63config SND_SOC_SSM2602
59 tristate 64 tristate
60 65
66config SND_SOC_TLV320AIC23
67 tristate
68 depends on I2C
69
61config SND_SOC_TLV320AIC26 70config SND_SOC_TLV320AIC26
62 tristate "TI TLV320AIC26 Codec support" 71 tristate "TI TLV320AIC26 Codec support"
63 depends on SND_SOC && SPI 72 depends on SPI
64 73
65config SND_SOC_TLV320AIC3X 74config SND_SOC_TLV320AIC3X
66 tristate 75 tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index f977978a3409..90f0a585fc70 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,8 +1,10 @@
1snd-soc-ac97-objs := ac97.o 1snd-soc-ac97-objs := ac97.o
2snd-soc-ad1980-objs := ad1980.o 2snd-soc-ad1980-objs := ad1980.o
3snd-soc-ad73311-objs := ad73311.o
3snd-soc-ak4535-objs := ak4535.o 4snd-soc-ak4535-objs := ak4535.o
4snd-soc-cs4270-objs := cs4270.o 5snd-soc-cs4270-objs := cs4270.o
5snd-soc-ssm2602-objs := ssm2602.o 6snd-soc-ssm2602-objs := ssm2602.o
7snd-soc-tlv320aic23-objs := tlv320aic23.o
6snd-soc-tlv320aic26-objs := tlv320aic26.o 8snd-soc-tlv320aic26-objs := tlv320aic26.o
7snd-soc-tlv320aic3x-objs := tlv320aic3x.o 9snd-soc-tlv320aic3x-objs := tlv320aic3x.o
8snd-soc-uda1380-objs := uda1380.o 10snd-soc-uda1380-objs := uda1380.o
@@ -20,9 +22,11 @@ snd-soc-wm9713-objs := wm9713.o
20 22
21obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o 23obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
22obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o 24obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
25obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
23obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 26obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
24obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 27obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
25obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o 28obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
29obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
26obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o 30obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
27obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o 31obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
28obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o 32obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 61fd96ca7bc7..bd1ebdc6c86c 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -2,8 +2,7 @@
2 * ac97.c -- ALSA Soc AC97 codec support 2 * ac97.c -- ALSA Soc AC97 codec support
3 * 3 *
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 4e09c1f2c063..1397b8e06c0b 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -13,7 +13,6 @@
13 13
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/version.h>
17#include <linux/kernel.h> 16#include <linux/kernel.h>
18#include <linux/device.h> 17#include <linux/device.h>
19#include <sound/core.h> 18#include <sound/core.h>
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
new file mode 100644
index 000000000000..37af8607b00a
--- /dev/null
+++ b/sound/soc/codecs/ad73311.c
@@ -0,0 +1,107 @@
1/*
2 * ad73311.c -- ALSA Soc AD73311 codec support
3 *
4 * Copyright: Analog Device Inc.
5 * Author: Cliff Cai <cliff.cai@analog.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * Revision history
13 * 25th Sep 2008 Initial version.
14 */
15
16#include <linux/init.h>
17#include <linux/module.h>
18#include <linux/version.h>
19#include <linux/kernel.h>
20#include <linux/device.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/ac97_codec.h>
24#include <sound/initval.h>
25#include <sound/soc.h>
26
27#include "ad73311.h"
28
29struct snd_soc_dai ad73311_dai = {
30 .name = "AD73311",
31 .playback = {
32 .stream_name = "Playback",
33 .channels_min = 1,
34 .channels_max = 1,
35 .rates = SNDRV_PCM_RATE_8000,
36 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
37 .capture = {
38 .stream_name = "Capture",
39 .channels_min = 1,
40 .channels_max = 1,
41 .rates = SNDRV_PCM_RATE_8000,
42 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
43};
44EXPORT_SYMBOL_GPL(ad73311_dai);
45
46static int ad73311_soc_probe(struct platform_device *pdev)
47{
48 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
49 struct snd_soc_codec *codec;
50 int ret = 0;
51
52 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
53 if (codec == NULL)
54 return -ENOMEM;
55 mutex_init(&codec->mutex);
56 codec->name = "AD73311";
57 codec->owner = THIS_MODULE;
58 codec->dai = &ad73311_dai;
59 codec->num_dai = 1;
60 socdev->codec = codec;
61 INIT_LIST_HEAD(&codec->dapm_widgets);
62 INIT_LIST_HEAD(&codec->dapm_paths);
63
64 /* register pcms */
65 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
66 if (ret < 0) {
67 printk(KERN_ERR "ad73311: failed to create pcms\n");
68 goto pcm_err;
69 }
70
71 ret = snd_soc_register_card(socdev);
72 if (ret < 0) {
73 printk(KERN_ERR "ad73311: failed to register card\n");
74 goto register_err;
75 }
76
77 return ret;
78
79register_err:
80 snd_soc_free_pcms(socdev);
81pcm_err:
82 kfree(socdev->codec);
83 socdev->codec = NULL;
84 return ret;
85}
86
87static int ad73311_soc_remove(struct platform_device *pdev)
88{
89 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
90 struct snd_soc_codec *codec = socdev->codec;
91
92 if (codec == NULL)
93 return 0;
94 snd_soc_free_pcms(socdev);
95 kfree(codec);
96 return 0;
97}
98
99struct snd_soc_codec_device soc_codec_dev_ad73311 = {
100 .probe = ad73311_soc_probe,
101 .remove = ad73311_soc_remove,
102};
103EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);
104
105MODULE_DESCRIPTION("ASoC ad73311 driver");
106MODULE_AUTHOR("Cliff Cai ");
107MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad73311.h b/sound/soc/codecs/ad73311.h
new file mode 100644
index 000000000000..507ce0c30edf
--- /dev/null
+++ b/sound/soc/codecs/ad73311.h
@@ -0,0 +1,90 @@
1/*
2 * File: sound/soc/codec/ad73311.h
3 * Based on:
4 * Author: Cliff Cai <cliff.cai@analog.com>
5 *
6 * Created: Thur Sep 25, 2008
7 * Description: definitions for AD73311 registers
8 *
9 *
10 * Modified:
11 * Copyright 2006 Analog Devices Inc.
12 *
13 * Bugs: Enter bugs at http://blackfin.uclinux.org/
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, see the file COPYING, or write
27 * to the Free Software Foundation, Inc.,
28 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 */
30
31#ifndef __AD73311_H__
32#define __AD73311_H__
33
34#define AD_CONTROL 0x8000
35#define AD_DATA 0x0000
36#define AD_READ 0x4000
37#define AD_WRITE 0x0000
38
39/* Control register A */
40#define CTRL_REG_A (0 << 8)
41
42#define REGA_MODE_PRO 0x00
43#define REGA_MODE_DATA 0x01
44#define REGA_MODE_MIXED 0x03
45#define REGA_DLB 0x04
46#define REGA_SLB 0x08
47#define REGA_DEVC(x) ((x & 0x7) << 4)
48#define REGA_RESET 0x80
49
50/* Control register B */
51#define CTRL_REG_B (1 << 8)
52
53#define REGB_DIRATE(x) (x & 0x3)
54#define REGB_SCDIV(x) ((x & 0x3) << 2)
55#define REGB_MCDIV(x) ((x & 0x7) << 4)
56#define REGB_CEE (1 << 7)
57
58/* Control register C */
59#define CTRL_REG_C (2 << 8)
60
61#define REGC_PUDEV (1 << 0)
62#define REGC_PUADC (1 << 3)
63#define REGC_PUDAC (1 << 4)
64#define REGC_PUREF (1 << 5)
65#define REGC_REFUSE (1 << 6)
66
67/* Control register D */
68#define CTRL_REG_D (3 << 8)
69
70#define REGD_IGS(x) (x & 0x7)
71#define REGD_RMOD (1 << 3)
72#define REGD_OGS(x) ((x & 0x7) << 4)
73#define REGD_MUTE (x << 7)
74
75/* Control register E */
76#define CTRL_REG_E (4 << 8)
77
78#define REGE_DA(x) (x & 0x1f)
79#define REGE_IBYP (1 << 5)
80
81/* Control register F */
82#define CTRL_REG_F (5 << 8)
83
84#define REGF_SEEN (1 << 5)
85#define REGF_INV (1 << 6)
86#define REGF_ALB (1 << 7)
87
88extern struct snd_soc_dai ad73311_dai;
89extern struct snd_soc_codec_device soc_codec_dev_ad73311;
90#endif
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 088cf9927720..2a89b5888e11 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -28,7 +28,6 @@
28 28
29#include "ak4535.h" 29#include "ak4535.h"
30 30
31#define AUDIO_NAME "ak4535"
32#define AK4535_VERSION "0.3" 31#define AK4535_VERSION "0.3"
33 32
34struct snd_soc_codec_device soc_codec_dev_ak4535; 33struct snd_soc_codec_device soc_codec_dev_ak4535;
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 940ce1c3522e..44ef0dacd564 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -42,7 +42,6 @@
42 42
43#include "ssm2602.h" 43#include "ssm2602.h"
44 44
45#define AUDIO_NAME "ssm2602"
46#define SSM2602_VERSION "0.1" 45#define SSM2602_VERSION "0.1"
47 46
48struct snd_soc_codec_device soc_codec_dev_ssm2602; 47struct snd_soc_codec_device soc_codec_dev_ssm2602;
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
new file mode 100644
index 000000000000..bac7815e00fb
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -0,0 +1,714 @@
1/*
2 * ALSA SoC TLV320AIC23 codec driver
3 *
4 * Author: Arun KS, <arunks@mistralsolutions.com>
5 * Copyright: (C) 2008 Mistral Solutions Pvt Ltd.,
6 *
7 * Based on sound/soc/codecs/wm8731.c by Richard Purdie
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * Notes:
14 * The AIC23 is a driver for a low power stereo audio
15 * codec tlv320aic23
16 *
17 * The machine layer should disable unsupported inputs/outputs by
18 * snd_soc_dapm_disable_pin(codec, "LHPOUT"), etc.
19 */
20
21#include <linux/module.h>
22#include <linux/moduleparam.h>
23#include <linux/init.h>
24#include <linux/delay.h>
25#include <linux/pm.h>
26#include <linux/i2c.h>
27#include <linux/platform_device.h>
28#include <sound/core.h>
29#include <sound/pcm.h>
30#include <sound/pcm_params.h>
31#include <sound/soc.h>
32#include <sound/soc-dapm.h>
33#include <sound/tlv.h>
34#include <sound/initval.h>
35
36#include "tlv320aic23.h"
37
38#define AIC23_VERSION "0.1"
39
40struct tlv320aic23_srate_reg_info {
41 u32 sample_rate;
42 u8 control; /* SR3, SR2, SR1, SR0 and BOSR */
43 u8 divider; /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
44};
45
46/*
47 * AIC23 register cache
48 */
49static const u16 tlv320aic23_reg[] = {
50 0x0097, 0x0097, 0x00F9, 0x00F9, /* 0 */
51 0x001A, 0x0004, 0x0007, 0x0001, /* 4 */
52 0x0020, 0x0000, 0x0000, 0x0000, /* 8 */
53 0x0000, 0x0000, 0x0000, 0x0000, /* 12 */
54};
55
56/*
57 * read tlv320aic23 register cache
58 */
59static inline unsigned int tlv320aic23_read_reg_cache(struct snd_soc_codec
60 *codec, unsigned int reg)
61{
62 u16 *cache = codec->reg_cache;
63 if (reg >= ARRAY_SIZE(tlv320aic23_reg))
64 return -1;
65 return cache[reg];
66}
67
68/*
69 * write tlv320aic23 register cache
70 */
71static inline void tlv320aic23_write_reg_cache(struct snd_soc_codec *codec,
72 u8 reg, u16 value)
73{
74 u16 *cache = codec->reg_cache;
75 if (reg >= ARRAY_SIZE(tlv320aic23_reg))
76 return;
77 cache[reg] = value;
78}
79
80/*
81 * write to the tlv320aic23 register space
82 */
83static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
84 unsigned int value)
85{
86
87 u8 data;
88
89 /* TLV320AIC23 has 7 bit address and 9 bits of data
90 * so we need to switch one data bit into reg and rest
91 * of data into val
92 */
93
94 if ((reg < 0 || reg > 9) && (reg != 15)) {
95 printk(KERN_WARNING "%s Invalid register R%d\n", __func__, reg);
96 return -1;
97 }
98
99 data = (reg << 1) | (value >> 8 & 0x01);
100
101 tlv320aic23_write_reg_cache(codec, reg, value);
102
103 if (codec->hw_write(codec->control_data, data,
104 (value & 0xff)) == 0)
105 return 0;
106
107 printk(KERN_ERR "%s cannot write %03x to register R%d\n", __func__,
108 value, reg);
109
110 return -EIO;
111}
112
113static const char *rec_src_text[] = { "Line", "Mic" };
114static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
115
116static const struct soc_enum rec_src_enum =
117 SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
118
119static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls =
120SOC_DAPM_ENUM("Input Select", rec_src_enum);
121
122static const struct soc_enum tlv320aic23_rec_src =
123 SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
124static const struct soc_enum tlv320aic23_deemph =
125 SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text);
126
127static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0);
128static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0);
129static const DECLARE_TLV_DB_SCALE(sidetone_vol_tlv, -1800, 300, 0);
130
131static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
132 struct snd_ctl_elem_value *ucontrol)
133{
134 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
135 u16 val, reg;
136
137 val = (ucontrol->value.integer.value[0] & 0x07);
138
139 /* linear conversion to userspace
140 * 000 = -6db
141 * 001 = -9db
142 * 010 = -12db
143 * 011 = -18db (Min)
144 * 100 = 0db (Max)
145 */
146 val = (val >= 4) ? 4 : (3 - val);
147
148 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (~0x1C0);
149 tlv320aic23_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
150
151 return 0;
152}
153
154static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
155 struct snd_ctl_elem_value *ucontrol)
156{
157 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
158 u16 val;
159
160 val = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (0x1C0);
161 val = val >> 6;
162 val = (val >= 4) ? 4 : (3 - val);
163 ucontrol->value.integer.value[0] = val;
164 return 0;
165
166}
167
168#define SOC_TLV320AIC23_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
169{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
170 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
171 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
172 .tlv.p = (tlv_array), \
173 .info = snd_soc_info_volsw, .get = snd_soc_tlv320aic23_get_volsw,\
174 .put = snd_soc_tlv320aic23_put_volsw, \
175 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
176
177static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
178 SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL,
179 TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv),
180 SOC_SINGLE("Digital Playback Switch", TLV320AIC23_DIGT, 3, 1, 1),
181 SOC_DOUBLE_R("Line Input Switch", TLV320AIC23_LINVOL,
182 TLV320AIC23_RINVOL, 7, 1, 0),
183 SOC_DOUBLE_R_TLV("Line Input Volume", TLV320AIC23_LINVOL,
184 TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv),
185 SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1),
186 SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0),
187 SOC_TLV320AIC23_SINGLE_TLV("Sidetone Volume", TLV320AIC23_ANLG,
188 6, 4, 0, sidetone_vol_tlv),
189 SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph),
190};
191
192/* add non dapm controls */
193static int tlv320aic23_add_controls(struct snd_soc_codec *codec)
194{
195
196 int err, i;
197
198 for (i = 0; i < ARRAY_SIZE(tlv320aic23_snd_controls); i++) {
199 err = snd_ctl_add(codec->card,
200 snd_soc_cnew(&tlv320aic23_snd_controls[i],
201 codec, NULL));
202 if (err < 0)
203 return err;
204 }
205
206 return 0;
207
208}
209
210/* PGA Mixer controls for Line and Mic switch */
211static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = {
212 SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0),
213 SOC_DAPM_SINGLE("Mic Sidetone Switch", TLV320AIC23_ANLG, 5, 1, 0),
214 SOC_DAPM_SINGLE("Playback Switch", TLV320AIC23_ANLG, 4, 1, 0),
215};
216
217static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
218 SND_SOC_DAPM_DAC("DAC", "Playback", TLV320AIC23_PWR, 3, 1),
219 SND_SOC_DAPM_ADC("ADC", "Capture", TLV320AIC23_PWR, 2, 1),
220 SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
221 &tlv320aic23_rec_src_mux_controls),
222 SND_SOC_DAPM_MIXER("Output Mixer", TLV320AIC23_PWR, 4, 1,
223 &tlv320aic23_output_mixer_controls[0],
224 ARRAY_SIZE(tlv320aic23_output_mixer_controls)),
225 SND_SOC_DAPM_PGA("Line Input", TLV320AIC23_PWR, 0, 1, NULL, 0),
226 SND_SOC_DAPM_PGA("Mic Input", TLV320AIC23_PWR, 1, 1, NULL, 0),
227
228 SND_SOC_DAPM_OUTPUT("LHPOUT"),
229 SND_SOC_DAPM_OUTPUT("RHPOUT"),
230 SND_SOC_DAPM_OUTPUT("LOUT"),
231 SND_SOC_DAPM_OUTPUT("ROUT"),
232
233 SND_SOC_DAPM_INPUT("LLINEIN"),
234 SND_SOC_DAPM_INPUT("RLINEIN"),
235
236 SND_SOC_DAPM_INPUT("MICIN"),
237};
238
239static const struct snd_soc_dapm_route intercon[] = {
240 /* Output Mixer */
241 {"Output Mixer", "Line Bypass Switch", "Line Input"},
242 {"Output Mixer", "Playback Switch", "DAC"},
243 {"Output Mixer", "Mic Sidetone Switch", "Mic Input"},
244
245 /* Outputs */
246 {"RHPOUT", NULL, "Output Mixer"},
247 {"LHPOUT", NULL, "Output Mixer"},
248 {"LOUT", NULL, "Output Mixer"},
249 {"ROUT", NULL, "Output Mixer"},
250
251 /* Inputs */
252 {"Line Input", "NULL", "LLINEIN"},
253 {"Line Input", "NULL", "RLINEIN"},
254
255 {"Mic Input", "NULL", "MICIN"},
256
257 /* input mux */
258 {"Capture Source", "Line", "Line Input"},
259 {"Capture Source", "Mic", "Mic Input"},
260 {"ADC", NULL, "Capture Source"},
261
262};
263
264/* tlv320aic23 related */
265static const struct tlv320aic23_srate_reg_info srate_reg_info[] = {
266 {4000, 0x06, 1}, /* 4000 */
267 {8000, 0x06, 0}, /* 8000 */
268 {16000, 0x0C, 1}, /* 16000 */
269 {22050, 0x11, 1}, /* 22050 */
270 {24000, 0x00, 1}, /* 24000 */
271 {32000, 0x0C, 0}, /* 32000 */
272 {44100, 0x11, 0}, /* 44100 */
273 {48000, 0x00, 0}, /* 48000 */
274 {88200, 0x1F, 0}, /* 88200 */
275 {96000, 0x0E, 0}, /* 96000 */
276};
277
278static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
279{
280 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
281 ARRAY_SIZE(tlv320aic23_dapm_widgets));
282
283 /* set up audio path interconnects */
284 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
285
286 snd_soc_dapm_new_widgets(codec);
287 return 0;
288}
289
290static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
291 struct snd_pcm_hw_params *params)
292{
293 struct snd_soc_pcm_runtime *rtd = substream->private_data;
294 struct snd_soc_device *socdev = rtd->socdev;
295 struct snd_soc_codec *codec = socdev->codec;
296 u16 iface_reg, data;
297 u8 count = 0;
298
299 iface_reg =
300 tlv320aic23_read_reg_cache(codec,
301 TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
302
303 /* Search for the right sample rate */
304 /* Verify what happens if the rate is not supported
305 * now it goes to 96Khz */
306 while ((srate_reg_info[count].sample_rate != params_rate(params)) &&
307 (count < ARRAY_SIZE(srate_reg_info))) {
308 count++;
309 }
310
311 data = (srate_reg_info[count].divider << TLV320AIC23_CLKIN_SHIFT) |
312 (srate_reg_info[count]. control << TLV320AIC23_BOSR_SHIFT) |
313 TLV320AIC23_USB_CLK_ON;
314
315 tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
316
317 switch (params_format(params)) {
318 case SNDRV_PCM_FORMAT_S16_LE:
319 break;
320 case SNDRV_PCM_FORMAT_S20_3LE:
321 iface_reg |= (0x01 << 2);
322 break;
323 case SNDRV_PCM_FORMAT_S24_LE:
324 iface_reg |= (0x02 << 2);
325 break;
326 case SNDRV_PCM_FORMAT_S32_LE:
327 iface_reg |= (0x03 << 2);
328 break;
329 }
330 tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
331
332 return 0;
333}
334
335static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream)
336{
337 struct snd_soc_pcm_runtime *rtd = substream->private_data;
338 struct snd_soc_device *socdev = rtd->socdev;
339 struct snd_soc_codec *codec = socdev->codec;
340
341 /* set active */
342 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
343
344 return 0;
345}
346
347static void tlv320aic23_shutdown(struct snd_pcm_substream *substream)
348{
349 struct snd_soc_pcm_runtime *rtd = substream->private_data;
350 struct snd_soc_device *socdev = rtd->socdev;
351 struct snd_soc_codec *codec = socdev->codec;
352
353 /* deactivate */
354 if (!codec->active) {
355 udelay(50);
356 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
357 }
358}
359
360static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
361{
362 struct snd_soc_codec *codec = dai->codec;
363 u16 reg;
364
365 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT);
366 if (mute)
367 reg |= TLV320AIC23_DACM_MUTE;
368
369 else
370 reg &= ~TLV320AIC23_DACM_MUTE;
371
372 tlv320aic23_write(codec, TLV320AIC23_DIGT, reg);
373
374 return 0;
375}
376
377static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
378 unsigned int fmt)
379{
380 struct snd_soc_codec *codec = codec_dai->codec;
381 u16 iface_reg;
382
383 iface_reg =
384 tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
385
386 /* set master/slave audio interface */
387 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
388 case SND_SOC_DAIFMT_CBM_CFM:
389 iface_reg |= TLV320AIC23_MS_MASTER;
390 break;
391 case SND_SOC_DAIFMT_CBS_CFS:
392 break;
393 default:
394 return -EINVAL;
395
396 }
397
398 /* interface format */
399 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
400 case SND_SOC_DAIFMT_I2S:
401 iface_reg |= TLV320AIC23_FOR_I2S;
402 break;
403 case SND_SOC_DAIFMT_DSP_A:
404 iface_reg |= TLV320AIC23_FOR_DSP;
405 break;
406 case SND_SOC_DAIFMT_RIGHT_J:
407 break;
408 case SND_SOC_DAIFMT_LEFT_J:
409 iface_reg |= TLV320AIC23_FOR_LJUST;
410 break;
411 default:
412 return -EINVAL;
413
414 }
415
416 tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
417
418 return 0;
419}
420
421static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
422 int clk_id, unsigned int freq, int dir)
423{
424 struct snd_soc_codec *codec = codec_dai->codec;
425
426 switch (freq) {
427 case 12000000:
428 return 0;
429 }
430 return -EINVAL;
431}
432
433static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
434 enum snd_soc_bias_level level)
435{
436 u16 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_PWR) & 0xff7f;
437
438 switch (level) {
439 case SND_SOC_BIAS_ON:
440 /* vref/mid, osc on, dac unmute */
441 tlv320aic23_write(codec, TLV320AIC23_PWR, reg);
442 break;
443 case SND_SOC_BIAS_PREPARE:
444 break;
445 case SND_SOC_BIAS_STANDBY:
446 /* everything off except vref/vmid, */
447 tlv320aic23_write(codec, TLV320AIC23_PWR, reg | 0x0040);
448 break;
449 case SND_SOC_BIAS_OFF:
450 /* everything off, dac mute, inactive */
451 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
452 tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff);
453 break;
454 }
455 codec->bias_level = level;
456 return 0;
457}
458
459#define AIC23_RATES SNDRV_PCM_RATE_8000_96000
460#define AIC23_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
461 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
462
463struct snd_soc_dai tlv320aic23_dai = {
464 .name = "tlv320aic23",
465 .playback = {
466 .stream_name = "Playback",
467 .channels_min = 2,
468 .channels_max = 2,
469 .rates = AIC23_RATES,
470 .formats = AIC23_FORMATS,},
471 .capture = {
472 .stream_name = "Capture",
473 .channels_min = 2,
474 .channels_max = 2,
475 .rates = AIC23_RATES,
476 .formats = AIC23_FORMATS,},
477 .ops = {
478 .prepare = tlv320aic23_pcm_prepare,
479 .hw_params = tlv320aic23_hw_params,
480 .shutdown = tlv320aic23_shutdown,
481 },
482 .dai_ops = {
483 .digital_mute = tlv320aic23_mute,
484 .set_fmt = tlv320aic23_set_dai_fmt,
485 .set_sysclk = tlv320aic23_set_dai_sysclk,
486 }
487};
488EXPORT_SYMBOL_GPL(tlv320aic23_dai);
489
490static int tlv320aic23_suspend(struct platform_device *pdev,
491 pm_message_t state)
492{
493 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
494 struct snd_soc_codec *codec = socdev->codec;
495
496 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
497 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
498
499 return 0;
500}
501
502static int tlv320aic23_resume(struct platform_device *pdev)
503{
504 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
505 struct snd_soc_codec *codec = socdev->codec;
506 int i;
507 u16 reg;
508
509 /* Sync reg_cache with the hardware */
510 for (reg = 0; reg < ARRAY_SIZE(tlv320aic23_reg); i++) {
511 u16 val = tlv320aic23_read_reg_cache(codec, reg);
512 tlv320aic23_write(codec, reg, val);
513 }
514
515 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
516 tlv320aic23_set_bias_level(codec, codec->suspend_bias_level);
517
518 return 0;
519}
520
521/*
522 * initialise the AIC23 driver
523 * register the mixer and dsp interfaces with the kernel
524 */
525static int tlv320aic23_init(struct snd_soc_device *socdev)
526{
527 struct snd_soc_codec *codec = socdev->codec;
528 int ret = 0;
529 u16 reg;
530
531 codec->name = "tlv320aic23";
532 codec->owner = THIS_MODULE;
533 codec->read = tlv320aic23_read_reg_cache;
534 codec->write = tlv320aic23_write;
535 codec->set_bias_level = tlv320aic23_set_bias_level;
536 codec->dai = &tlv320aic23_dai;
537 codec->num_dai = 1;
538 codec->reg_cache_size = ARRAY_SIZE(tlv320aic23_reg);
539 codec->reg_cache =
540 kmemdup(tlv320aic23_reg, sizeof(tlv320aic23_reg), GFP_KERNEL);
541 if (codec->reg_cache == NULL)
542 return -ENOMEM;
543
544 /* Reset codec */
545 tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
546
547 /* register pcms */
548 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
549 if (ret < 0) {
550 printk(KERN_ERR "tlv320aic23: failed to create pcms\n");
551 goto pcm_err;
552 }
553
554 /* power on device */
555 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
556
557 tlv320aic23_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
558
559 /* Unmute input */
560 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_LINVOL);
561 tlv320aic23_write(codec, TLV320AIC23_LINVOL,
562 (reg & (~TLV320AIC23_LIM_MUTED)) |
563 (TLV320AIC23_LRS_ENABLED));
564
565 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_RINVOL);
566 tlv320aic23_write(codec, TLV320AIC23_RINVOL,
567 (reg & (~TLV320AIC23_LIM_MUTED)) |
568 TLV320AIC23_LRS_ENABLED);
569
570 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG);
571 tlv320aic23_write(codec, TLV320AIC23_ANLG,
572 (reg) & (~TLV320AIC23_BYPASS_ON) &
573 (~TLV320AIC23_MICM_MUTED));
574
575 /* Default output volume */
576 tlv320aic23_write(codec, TLV320AIC23_LCHNVOL,
577 TLV320AIC23_DEFAULT_OUT_VOL &
578 TLV320AIC23_OUT_VOL_MASK);
579 tlv320aic23_write(codec, TLV320AIC23_RCHNVOL,
580 TLV320AIC23_DEFAULT_OUT_VOL &
581 TLV320AIC23_OUT_VOL_MASK);
582
583 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1);
584
585 tlv320aic23_add_controls(codec);
586 tlv320aic23_add_widgets(codec);
587 ret = snd_soc_register_card(socdev);
588 if (ret < 0) {
589 printk(KERN_ERR "tlv320aic23: failed to register card\n");
590 goto card_err;
591 }
592
593 return ret;
594
595card_err:
596 snd_soc_free_pcms(socdev);
597 snd_soc_dapm_free(socdev);
598pcm_err:
599 kfree(codec->reg_cache);
600 return ret;
601}
602static struct snd_soc_device *tlv320aic23_socdev;
603
604#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
605/*
606 * If the i2c layer weren't so broken, we could pass this kind of data
607 * around
608 */
609static int tlv320aic23_codec_probe(struct i2c_client *i2c,
610 const struct i2c_device_id *i2c_id)
611{
612 struct snd_soc_device *socdev = tlv320aic23_socdev;
613 struct snd_soc_codec *codec = socdev->codec;
614 int ret;
615
616 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
617 return -EINVAL;
618
619 i2c_set_clientdata(i2c, codec);
620 codec->control_data = i2c;
621
622 ret = tlv320aic23_init(socdev);
623 if (ret < 0) {
624 printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n");
625 goto err;
626 }
627 return ret;
628
629err:
630 kfree(codec);
631 kfree(i2c);
632 return ret;
633}
634static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
635{
636 put_device(&i2c->dev);
637 return 0;
638}
639
640static const struct i2c_device_id tlv320aic23_id[] = {
641 {"tlv320aic23", 0},
642 {}
643};
644
645MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
646
647static struct i2c_driver tlv320aic23_i2c_driver = {
648 .driver = {
649 .name = "tlv320aic23",
650 },
651 .probe = tlv320aic23_codec_probe,
652 .remove = __exit_p(tlv320aic23_i2c_remove),
653 .id_table = tlv320aic23_id,
654};
655
656#endif
657
658static int tlv320aic23_probe(struct platform_device *pdev)
659{
660 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
661 struct snd_soc_codec *codec;
662 int ret = 0;
663
664 printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
665
666 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
667 if (codec == NULL)
668 return -ENOMEM;
669
670 socdev->codec = codec;
671 mutex_init(&codec->mutex);
672 INIT_LIST_HEAD(&codec->dapm_widgets);
673 INIT_LIST_HEAD(&codec->dapm_paths);
674
675 tlv320aic23_socdev = socdev;
676#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
677 codec->hw_write = (hw_write_t) i2c_smbus_write_byte_data;
678 codec->hw_read = NULL;
679 ret = i2c_add_driver(&tlv320aic23_i2c_driver);
680 if (ret != 0)
681 printk(KERN_ERR "can't add i2c driver");
682#endif
683 return ret;
684}
685
686static int tlv320aic23_remove(struct platform_device *pdev)
687{
688 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
689 struct snd_soc_codec *codec = socdev->codec;
690
691 if (codec->control_data)
692 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
693
694 snd_soc_free_pcms(socdev);
695 snd_soc_dapm_free(socdev);
696#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
697 i2c_del_driver(&tlv320aic23_i2c_driver);
698#endif
699 kfree(codec->reg_cache);
700 kfree(codec);
701
702 return 0;
703}
704struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = {
705 .probe = tlv320aic23_probe,
706 .remove = tlv320aic23_remove,
707 .suspend = tlv320aic23_suspend,
708 .resume = tlv320aic23_resume,
709};
710EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
711
712MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
713MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
714MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h
new file mode 100644
index 000000000000..79d1faf8e570
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic23.h
@@ -0,0 +1,122 @@
1/*
2 * ALSA SoC TLV320AIC23 codec driver
3 *
4 * Author: Arun KS, <arunks@mistralsolutions.com>
5 * Copyright: (C) 2008 Mistral Solutions Pvt Ltd
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _TLV320AIC23_H
13#define _TLV320AIC23_H
14
15/* Codec TLV320AIC23 */
16#define TLV320AIC23_LINVOL 0x00
17#define TLV320AIC23_RINVOL 0x01
18#define TLV320AIC23_LCHNVOL 0x02
19#define TLV320AIC23_RCHNVOL 0x03
20#define TLV320AIC23_ANLG 0x04
21#define TLV320AIC23_DIGT 0x05
22#define TLV320AIC23_PWR 0x06
23#define TLV320AIC23_DIGT_FMT 0x07
24#define TLV320AIC23_SRATE 0x08
25#define TLV320AIC23_ACTIVE 0x09
26#define TLV320AIC23_RESET 0x0F
27
28/* Left (right) line input volume control register */
29#define TLV320AIC23_LRS_ENABLED 0x0100
30#define TLV320AIC23_LIM_MUTED 0x0080
31#define TLV320AIC23_LIV_DEFAULT 0x0017
32#define TLV320AIC23_LIV_MAX 0x001f
33#define TLV320AIC23_LIV_MIN 0x0000
34
35/* Left (right) channel headphone volume control register */
36#define TLV320AIC23_LZC_ON 0x0080
37#define TLV320AIC23_LHV_DEFAULT 0x0079
38#define TLV320AIC23_LHV_MAX 0x007f
39#define TLV320AIC23_LHV_MIN 0x0000
40
41/* Analog audio path control register */
42#define TLV320AIC23_STA_REG(x) ((x)<<6)
43#define TLV320AIC23_STE_ENABLED 0x0020
44#define TLV320AIC23_DAC_SELECTED 0x0010
45#define TLV320AIC23_BYPASS_ON 0x0008
46#define TLV320AIC23_INSEL_MIC 0x0004
47#define TLV320AIC23_MICM_MUTED 0x0002
48#define TLV320AIC23_MICB_20DB 0x0001
49
50/* Digital audio path control register */
51#define TLV320AIC23_DACM_MUTE 0x0008
52#define TLV320AIC23_DEEMP_32K 0x0002
53#define TLV320AIC23_DEEMP_44K 0x0004
54#define TLV320AIC23_DEEMP_48K 0x0006
55#define TLV320AIC23_ADCHP_ON 0x0001
56
57/* Power control down register */
58#define TLV320AIC23_DEVICE_PWR_OFF 0x0080
59#define TLV320AIC23_CLK_OFF 0x0040
60#define TLV320AIC23_OSC_OFF 0x0020
61#define TLV320AIC23_OUT_OFF 0x0010
62#define TLV320AIC23_DAC_OFF 0x0008
63#define TLV320AIC23_ADC_OFF 0x0004
64#define TLV320AIC23_MIC_OFF 0x0002
65#define TLV320AIC23_LINE_OFF 0x0001
66
67/* Digital audio interface register */
68#define TLV320AIC23_MS_MASTER 0x0040
69#define TLV320AIC23_LRSWAP_ON 0x0020
70#define TLV320AIC23_LRP_ON 0x0010
71#define TLV320AIC23_IWL_16 0x0000
72#define TLV320AIC23_IWL_20 0x0004
73#define TLV320AIC23_IWL_24 0x0008
74#define TLV320AIC23_IWL_32 0x000C
75#define TLV320AIC23_FOR_I2S 0x0002
76#define TLV320AIC23_FOR_DSP 0x0003
77#define TLV320AIC23_FOR_LJUST 0x0001
78
79/* Sample rate control register */
80#define TLV320AIC23_CLKOUT_HALF 0x0080
81#define TLV320AIC23_CLKIN_HALF 0x0040
82#define TLV320AIC23_BOSR_384fs 0x0002 /* BOSR_272fs in USB mode */
83#define TLV320AIC23_USB_CLK_ON 0x0001
84#define TLV320AIC23_SR_MASK 0xf
85#define TLV320AIC23_CLKOUT_SHIFT 7
86#define TLV320AIC23_CLKIN_SHIFT 6
87#define TLV320AIC23_SR_SHIFT 2
88#define TLV320AIC23_BOSR_SHIFT 1
89
90/* Digital interface register */
91#define TLV320AIC23_ACT_ON 0x0001
92
93/*
94 * AUDIO related MACROS
95 */
96
97#define TLV320AIC23_DEFAULT_OUT_VOL 0x70
98#define TLV320AIC23_DEFAULT_IN_VOLUME 0x10
99
100#define TLV320AIC23_OUT_VOL_MIN TLV320AIC23_LHV_MIN
101#define TLV320AIC23_OUT_VOL_MAX TLV320AIC23_LHV_MAX
102#define TLV320AIC23_OUT_VO_RANGE (TLV320AIC23_OUT_VOL_MAX - \
103 TLV320AIC23_OUT_VOL_MIN)
104#define TLV320AIC23_OUT_VOL_MASK TLV320AIC23_OUT_VOL_MAX
105
106#define TLV320AIC23_IN_VOL_MIN TLV320AIC23_LIV_MIN
107#define TLV320AIC23_IN_VOL_MAX TLV320AIC23_LIV_MAX
108#define TLV320AIC23_IN_VOL_RANGE (TLV320AIC23_IN_VOL_MAX - \
109 TLV320AIC23_IN_VOL_MIN)
110#define TLV320AIC23_IN_VOL_MASK TLV320AIC23_IN_VOL_MAX
111
112#define TLV320AIC23_SIDETONE_MASK 0x1c0
113#define TLV320AIC23_SIDETONE_0 0x100
114#define TLV320AIC23_SIDETONE_6 0x000
115#define TLV320AIC23_SIDETONE_9 0x040
116#define TLV320AIC23_SIDETONE_12 0x080
117#define TLV320AIC23_SIDETONE_18 0x0c0
118
119extern struct snd_soc_dai tlv320aic23_dai;
120extern struct snd_soc_codec_device soc_codec_dev_tlv320aic23;
121
122#endif /* _TLV320AIC23_H */
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 566a427c928f..05336ed7e493 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -48,7 +48,6 @@
48 48
49#include "tlv320aic3x.h" 49#include "tlv320aic3x.h"
50 50
51#define AUDIO_NAME "aic3x"
52#define AIC3X_VERSION "0.2" 51#define AIC3X_VERSION "0.2"
53 52
54/* codec private data */ 53/* codec private data */
@@ -991,7 +990,7 @@ EXPORT_SYMBOL_GPL(aic3x_headset_detected);
991 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) 990 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
992 991
993struct snd_soc_dai aic3x_dai = { 992struct snd_soc_dai aic3x_dai = {
994 .name = "aic3x", 993 .name = "tlv320aic3x",
995 .playback = { 994 .playback = {
996 .stream_name = "Playback", 995 .stream_name = "Playback",
997 .channels_min = 1, 996 .channels_min = 1,
@@ -1055,7 +1054,7 @@ static int aic3x_init(struct snd_soc_device *socdev)
1055 struct aic3x_setup_data *setup = socdev->codec_data; 1054 struct aic3x_setup_data *setup = socdev->codec_data;
1056 int reg, ret = 0; 1055 int reg, ret = 0;
1057 1056
1058 codec->name = "aic3x"; 1057 codec->name = "tlv320aic3x";
1059 codec->owner = THIS_MODULE; 1058 codec->owner = THIS_MODULE;
1060 codec->read = aic3x_read_reg_cache; 1059 codec->read = aic3x_read_reg_cache;
1061 codec->write = aic3x_write; 1060 codec->write = aic3x_write;
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index d206d7f892b6..a69ee72a7af5 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -36,7 +36,6 @@
36#include "uda1380.h" 36#include "uda1380.h"
37 37
38#define UDA1380_VERSION "0.6" 38#define UDA1380_VERSION "0.6"
39#define AUDIO_NAME "uda1380"
40 39
41/* 40/*
42 * uda1380 register cache 41 * uda1380 register cache
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 9a37c8d95ed2..d8ca2da8d634 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright 2006 Wolfson Microelectronics PLC. 4 * Copyright 2006 Wolfson Microelectronics PLC.
5 * 5 *
6 * Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 6 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -18,6 +18,7 @@
18#include <linux/pm.h> 18#include <linux/pm.h>
19#include <linux/i2c.h> 19#include <linux/i2c.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/spi/spi.h>
21#include <sound/core.h> 22#include <sound/core.h>
22#include <sound/pcm.h> 23#include <sound/pcm.h>
23#include <sound/pcm_params.h> 24#include <sound/pcm_params.h>
@@ -27,7 +28,6 @@
27 28
28#include "wm8510.h" 29#include "wm8510.h"
29 30
30#define AUDIO_NAME "wm8510"
31#define WM8510_VERSION "0.6" 31#define WM8510_VERSION "0.6"
32 32
33struct snd_soc_codec_device soc_codec_dev_wm8510; 33struct snd_soc_codec_device soc_codec_dev_wm8510;
@@ -55,6 +55,9 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
55 0x0001, 55 0x0001,
56}; 56};
57 57
58#define WM8510_POWER1_BIASEN 0x08
59#define WM8510_POWER1_BUFIOEN 0x10
60
58/* 61/*
59 * read wm8510 register cache 62 * read wm8510 register cache
60 */ 63 */
@@ -224,9 +227,9 @@ SND_SOC_DAPM_PGA("SpkN Out", WM8510_POWER3, 5, 0, NULL, 0),
224SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0), 227SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0),
225SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0), 228SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0),
226 229
227SND_SOC_DAPM_PGA("Mic PGA", WM8510_POWER2, 2, 0, 230SND_SOC_DAPM_MIXER("Mic PGA", WM8510_POWER2, 2, 0,
228 &wm8510_micpga_controls[0], 231 &wm8510_micpga_controls[0],
229 ARRAY_SIZE(wm8510_micpga_controls)), 232 ARRAY_SIZE(wm8510_micpga_controls)),
230SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0, 233SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0,
231 &wm8510_boost_controls[0], 234 &wm8510_boost_controls[0],
232 ARRAY_SIZE(wm8510_boost_controls)), 235 ARRAY_SIZE(wm8510_boost_controls)),
@@ -526,23 +529,35 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute)
526static int wm8510_set_bias_level(struct snd_soc_codec *codec, 529static int wm8510_set_bias_level(struct snd_soc_codec *codec,
527 enum snd_soc_bias_level level) 530 enum snd_soc_bias_level level)
528{ 531{
532 u16 power1 = wm8510_read_reg_cache(codec, WM8510_POWER1) & ~0x3;
529 533
530 switch (level) { 534 switch (level) {
531 case SND_SOC_BIAS_ON: 535 case SND_SOC_BIAS_ON:
532 wm8510_write(codec, WM8510_POWER1, 0x1ff);
533 wm8510_write(codec, WM8510_POWER2, 0x1ff);
534 wm8510_write(codec, WM8510_POWER3, 0x1ff);
535 break;
536 case SND_SOC_BIAS_PREPARE: 536 case SND_SOC_BIAS_PREPARE:
537 power1 |= 0x1; /* VMID 50k */
538 wm8510_write(codec, WM8510_POWER1, power1);
539 break;
540
537 case SND_SOC_BIAS_STANDBY: 541 case SND_SOC_BIAS_STANDBY:
542 power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN;
543
544 if (codec->bias_level == SND_SOC_BIAS_OFF) {
545 /* Initial cap charge at VMID 5k */
546 wm8510_write(codec, WM8510_POWER1, power1 | 0x3);
547 mdelay(100);
548 }
549
550 power1 |= 0x2; /* VMID 500k */
551 wm8510_write(codec, WM8510_POWER1, power1);
538 break; 552 break;
553
539 case SND_SOC_BIAS_OFF: 554 case SND_SOC_BIAS_OFF:
540 /* everything off, dac mute, inactive */ 555 wm8510_write(codec, WM8510_POWER1, 0);
541 wm8510_write(codec, WM8510_POWER1, 0x0); 556 wm8510_write(codec, WM8510_POWER2, 0);
542 wm8510_write(codec, WM8510_POWER2, 0x0); 557 wm8510_write(codec, WM8510_POWER3, 0);
543 wm8510_write(codec, WM8510_POWER3, 0x0);
544 break; 558 break;
545 } 559 }
560
546 codec->bias_level = level; 561 codec->bias_level = level;
547 return 0; 562 return 0;
548} 563}
@@ -640,6 +655,7 @@ static int wm8510_init(struct snd_soc_device *socdev)
640 } 655 }
641 656
642 /* power on device */ 657 /* power on device */
658 codec->bias_level = SND_SOC_BIAS_OFF;
643 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 659 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
644 wm8510_add_controls(codec); 660 wm8510_add_controls(codec);
645 wm8510_add_widgets(codec); 661 wm8510_add_widgets(codec);
@@ -747,6 +763,62 @@ err_driver:
747} 763}
748#endif 764#endif
749 765
766#if defined(CONFIG_SPI_MASTER)
767static int __devinit wm8510_spi_probe(struct spi_device *spi)
768{
769 struct snd_soc_device *socdev = wm8510_socdev;
770 struct snd_soc_codec *codec = socdev->codec;
771 int ret;
772
773 codec->control_data = spi;
774
775 ret = wm8510_init(socdev);
776 if (ret < 0)
777 dev_err(&spi->dev, "failed to initialise WM8510\n");
778
779 return ret;
780}
781
782static int __devexit wm8510_spi_remove(struct spi_device *spi)
783{
784 return 0;
785}
786
787static struct spi_driver wm8510_spi_driver = {
788 .driver = {
789 .name = "wm8510",
790 .bus = &spi_bus_type,
791 .owner = THIS_MODULE,
792 },
793 .probe = wm8510_spi_probe,
794 .remove = __devexit_p(wm8510_spi_remove),
795};
796
797static int wm8510_spi_write(struct spi_device *spi, const char *data, int len)
798{
799 struct spi_transfer t;
800 struct spi_message m;
801 u8 msg[2];
802
803 if (len <= 0)
804 return 0;
805
806 msg[0] = data[0];
807 msg[1] = data[1];
808
809 spi_message_init(&m);
810 memset(&t, 0, (sizeof t));
811
812 t.tx_buf = &msg[0];
813 t.len = len;
814
815 spi_message_add_tail(&t, &m);
816 spi_sync(spi, &m);
817
818 return len;
819}
820#endif /* CONFIG_SPI_MASTER */
821
750static int wm8510_probe(struct platform_device *pdev) 822static int wm8510_probe(struct platform_device *pdev)
751{ 823{
752 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 824 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -772,8 +844,14 @@ static int wm8510_probe(struct platform_device *pdev)
772 codec->hw_write = (hw_write_t)i2c_master_send; 844 codec->hw_write = (hw_write_t)i2c_master_send;
773 ret = wm8510_add_i2c_device(pdev, setup); 845 ret = wm8510_add_i2c_device(pdev, setup);
774 } 846 }
775#else 847#endif
776 /* Add other interfaces here */ 848#if defined(CONFIG_SPI_MASTER)
849 if (setup->spi) {
850 codec->hw_write = (hw_write_t)wm8510_spi_write;
851 ret = spi_register_driver(&wm8510_spi_driver);
852 if (ret != 0)
853 printk(KERN_ERR "can't add spi driver");
854 }
777#endif 855#endif
778 856
779 if (ret != 0) 857 if (ret != 0)
@@ -796,6 +874,9 @@ static int wm8510_remove(struct platform_device *pdev)
796 i2c_unregister_device(codec->control_data); 874 i2c_unregister_device(codec->control_data);
797 i2c_del_driver(&wm8510_i2c_driver); 875 i2c_del_driver(&wm8510_i2c_driver);
798#endif 876#endif
877#if defined(CONFIG_SPI_MASTER)
878 spi_unregister_driver(&wm8510_spi_driver);
879#endif
799 kfree(codec); 880 kfree(codec);
800 881
801 return 0; 882 return 0;
diff --git a/sound/soc/codecs/wm8510.h b/sound/soc/codecs/wm8510.h
index c53683960456..bdefcf5c69ff 100644
--- a/sound/soc/codecs/wm8510.h
+++ b/sound/soc/codecs/wm8510.h
@@ -94,6 +94,7 @@
94#define WM8510_MCLKDIV_12 (7 << 5) 94#define WM8510_MCLKDIV_12 (7 << 5)
95 95
96struct wm8510_setup_data { 96struct wm8510_setup_data {
97 int spi;
97 int i2c_bus; 98 int i2c_bus;
98 unsigned short i2c_address; 99 unsigned short i2c_address;
99}; 100};
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index df1ffbe305bf..627ebfb4209b 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -18,7 +18,6 @@
18 18
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/moduleparam.h> 20#include <linux/moduleparam.h>
21#include <linux/version.h>
22#include <linux/kernel.h> 21#include <linux/kernel.h>
23#include <linux/init.h> 22#include <linux/init.h>
24#include <linux/delay.h> 23#include <linux/delay.h>
@@ -36,7 +35,6 @@
36 35
37#include "wm8580.h" 36#include "wm8580.h"
38 37
39#define AUDIO_NAME "wm8580"
40#define WM8580_VERSION "0.1" 38#define WM8580_VERSION "0.1"
41 39
42struct pll_state { 40struct pll_state {
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 7b64d9a7ff76..7f8a7e36b33e 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -29,7 +29,6 @@
29 29
30#include "wm8731.h" 30#include "wm8731.h"
31 31
32#define AUDIO_NAME "wm8731"
33#define WM8731_VERSION "0.13" 32#define WM8731_VERSION "0.13"
34 33
35struct snd_soc_codec_device soc_codec_dev_wm8731; 34struct snd_soc_codec_device soc_codec_dev_wm8731;
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 4892e398a598..9b7296ee5b08 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -29,7 +29,6 @@
29 29
30#include "wm8750.h" 30#include "wm8750.h"
31 31
32#define AUDIO_NAME "WM8750"
33#define WM8750_VERSION "0.12" 32#define WM8750_VERSION "0.12"
34 33
35/* codec private data */ 34/* codec private data */
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 8c4df44f3345..d426eaa22185 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -2,8 +2,7 @@
2 * wm8753.c -- WM8753 ALSA Soc Audio driver 2 * wm8753.c -- WM8753 ALSA Soc Audio driver
3 * 3 *
4 * Copyright 2003 Wolfson Microelectronics PLC. 4 * Copyright 2003 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
@@ -40,6 +39,7 @@
40#include <linux/pm.h> 39#include <linux/pm.h>
41#include <linux/i2c.h> 40#include <linux/i2c.h>
42#include <linux/platform_device.h> 41#include <linux/platform_device.h>
42#include <linux/spi/spi.h>
43#include <sound/core.h> 43#include <sound/core.h>
44#include <sound/pcm.h> 44#include <sound/pcm.h>
45#include <sound/pcm_params.h> 45#include <sound/pcm_params.h>
@@ -51,7 +51,6 @@
51 51
52#include "wm8753.h" 52#include "wm8753.h"
53 53
54#define AUDIO_NAME "wm8753"
55#define WM8753_VERSION "0.16" 54#define WM8753_VERSION "0.16"
56 55
57static int caps_charge = 2000; 56static int caps_charge = 2000;
@@ -1719,6 +1718,63 @@ err_driver:
1719} 1718}
1720#endif 1719#endif
1721 1720
1721#if defined(CONFIG_SPI_MASTER)
1722static int __devinit wm8753_spi_probe(struct spi_device *spi)
1723{
1724 struct snd_soc_device *socdev = wm8753_socdev;
1725 struct snd_soc_codec *codec = socdev->codec;
1726 int ret;
1727
1728 codec->control_data = spi;
1729
1730 ret = wm8753_init(socdev);
1731 if (ret < 0)
1732 dev_err(&spi->dev, "failed to initialise WM8753\n");
1733
1734 return ret;
1735}
1736
1737static int __devexit wm8753_spi_remove(struct spi_device *spi)
1738{
1739 return 0;
1740}
1741
1742static struct spi_driver wm8753_spi_driver = {
1743 .driver = {
1744 .name = "wm8753",
1745 .bus = &spi_bus_type,
1746 .owner = THIS_MODULE,
1747 },
1748 .probe = wm8753_spi_probe,
1749 .remove = __devexit_p(wm8753_spi_remove),
1750};
1751
1752static int wm8753_spi_write(struct spi_device *spi, const char *data, int len)
1753{
1754 struct spi_transfer t;
1755 struct spi_message m;
1756 u8 msg[2];
1757
1758 if (len <= 0)
1759 return 0;
1760
1761 msg[0] = data[0];
1762 msg[1] = data[1];
1763
1764 spi_message_init(&m);
1765 memset(&t, 0, (sizeof t));
1766
1767 t.tx_buf = &msg[0];
1768 t.len = len;
1769
1770 spi_message_add_tail(&t, &m);
1771 spi_sync(spi, &m);
1772
1773 return len;
1774}
1775#endif
1776
1777
1722static int wm8753_probe(struct platform_device *pdev) 1778static int wm8753_probe(struct platform_device *pdev)
1723{ 1779{
1724 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1780 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -1753,8 +1809,14 @@ static int wm8753_probe(struct platform_device *pdev)
1753 codec->hw_write = (hw_write_t)i2c_master_send; 1809 codec->hw_write = (hw_write_t)i2c_master_send;
1754 ret = wm8753_add_i2c_device(pdev, setup); 1810 ret = wm8753_add_i2c_device(pdev, setup);
1755 } 1811 }
1756#else 1812#endif
1757 /* Add other interfaces here */ 1813#if defined(CONFIG_SPI_MASTER)
1814 if (setup->spi) {
1815 codec->hw_write = (hw_write_t)wm8753_spi_write;
1816 ret = spi_register_driver(&wm8753_spi_driver);
1817 if (ret != 0)
1818 printk(KERN_ERR "can't add spi driver");
1819 }
1758#endif 1820#endif
1759 1821
1760 if (ret != 0) { 1822 if (ret != 0) {
@@ -1798,6 +1860,9 @@ static int wm8753_remove(struct platform_device *pdev)
1798 i2c_unregister_device(codec->control_data); 1860 i2c_unregister_device(codec->control_data);
1799 i2c_del_driver(&wm8753_i2c_driver); 1861 i2c_del_driver(&wm8753_i2c_driver);
1800#endif 1862#endif
1863#if defined(CONFIG_SPI_MASTER)
1864 spi_unregister_driver(&wm8753_spi_driver);
1865#endif
1801 kfree(codec->private_data); 1866 kfree(codec->private_data);
1802 kfree(codec); 1867 kfree(codec);
1803 1868
diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h
index 7defde069f1d..f55704ce931b 100644
--- a/sound/soc/codecs/wm8753.h
+++ b/sound/soc/codecs/wm8753.h
@@ -2,8 +2,7 @@
2 * wm8753.h -- audio driver for WM8753 2 * wm8753.h -- audio driver for WM8753
3 * 3 *
4 * Copyright 2003 Wolfson Microelectronics PLC. 4 * Copyright 2003 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
@@ -79,6 +78,7 @@
79#define WM8753_ADCTL2 0x3f 78#define WM8753_ADCTL2 0x3f
80 79
81struct wm8753_setup_data { 80struct wm8753_setup_data {
81 int spi;
82 int i2c_bus; 82 int i2c_bus;
83 unsigned short i2c_address; 83 unsigned short i2c_address;
84}; 84};
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 0b8c6d38b48f..3b326c9b5586 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -18,7 +18,6 @@
18 18
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/moduleparam.h> 20#include <linux/moduleparam.h>
21#include <linux/version.h>
22#include <linux/kernel.h> 21#include <linux/kernel.h>
23#include <linux/init.h> 22#include <linux/init.h>
24#include <linux/delay.h> 23#include <linux/delay.h>
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index a3f54ec4226e..ce40d7877605 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -653,14 +653,14 @@ static const struct snd_kcontrol_new wm8903_snd_controls[] = {
653 653
654/* Input PGAs - No TLV since the scale depends on PGA mode */ 654/* Input PGAs - No TLV since the scale depends on PGA mode */
655SOC_SINGLE("Left Input PGA Switch", WM8903_ANALOGUE_LEFT_INPUT_0, 655SOC_SINGLE("Left Input PGA Switch", WM8903_ANALOGUE_LEFT_INPUT_0,
656 7, 1, 0), 656 7, 1, 1),
657SOC_SINGLE("Left Input PGA Volume", WM8903_ANALOGUE_LEFT_INPUT_0, 657SOC_SINGLE("Left Input PGA Volume", WM8903_ANALOGUE_LEFT_INPUT_0,
658 0, 31, 0), 658 0, 31, 0),
659SOC_SINGLE("Left Input PGA Common Mode Switch", WM8903_ANALOGUE_LEFT_INPUT_1, 659SOC_SINGLE("Left Input PGA Common Mode Switch", WM8903_ANALOGUE_LEFT_INPUT_1,
660 6, 1, 0), 660 6, 1, 0),
661 661
662SOC_SINGLE("Right Input PGA Switch", WM8903_ANALOGUE_RIGHT_INPUT_0, 662SOC_SINGLE("Right Input PGA Switch", WM8903_ANALOGUE_RIGHT_INPUT_0,
663 7, 1, 0), 663 7, 1, 1),
664SOC_SINGLE("Right Input PGA Volume", WM8903_ANALOGUE_RIGHT_INPUT_0, 664SOC_SINGLE("Right Input PGA Volume", WM8903_ANALOGUE_RIGHT_INPUT_0,
665 0, 31, 0), 665 0, 31, 0),
666SOC_SINGLE("Right Input PGA Common Mode Switch", WM8903_ANALOGUE_RIGHT_INPUT_1, 666SOC_SINGLE("Right Input PGA Common Mode Switch", WM8903_ANALOGUE_RIGHT_INPUT_1,
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 974a4cd0f3fd..f41a578ddd4f 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -29,7 +29,6 @@
29 29
30#include "wm8971.h" 30#include "wm8971.h"
31 31
32#define AUDIO_NAME "wm8971"
33#define WM8971_VERSION "0.9" 32#define WM8971_VERSION "0.9"
34 33
35#define WM8971_REG_COUNT 43 34#define WM8971_REG_COUNT 43
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 63410d7b5efb..572d22b0880b 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -30,7 +30,6 @@
30 30
31#include "wm8990.h" 31#include "wm8990.h"
32 32
33#define AUDIO_NAME "wm8990"
34#define WM8990_VERSION "0.2" 33#define WM8990_VERSION "0.2"
35 34
36/* codec private data */ 35/* codec private data */
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 2f1c91b1d556..ffb471e420e2 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -2,8 +2,7 @@
2 * wm9712.c -- ALSA Soc WM9712 codec support 2 * wm9712.c -- ALSA Soc WM9712 codec support
3 * 3 *
4 * Copyright 2006 Wolfson Microelectronics PLC. 4 * Copyright 2006 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 441d0580db1f..aba402b3c999 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -2,8 +2,7 @@
2 * wm9713.c -- ALSA Soc WM9713 codec support 2 * wm9713.c -- ALSA Soc WM9713 codec support
3 * 3 *
4 * Copyright 2006 Wolfson Microelectronics PLC. 4 * Copyright 2006 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index aea27e70043c..8b7766b998d7 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -13,3 +13,11 @@ config SND_OMAP_SOC_N810
13 select SND_SOC_TLV320AIC3X 13 select SND_SOC_TLV320AIC3X
14 help 14 help
15 Say Y if you want to add support for SoC audio on Nokia N810. 15 Say Y if you want to add support for SoC audio on Nokia N810.
16
17config SND_OMAP_SOC_OSK5912
18 tristate "SoC Audio support for omap osk5912"
19 depends on SND_OMAP_SOC && MACH_OMAP_OSK
20 select SND_OMAP_SOC_MCBSP
21 select SND_SOC_TLV320AIC23
22 help
23 Say Y if you want to add support for SoC audio on osk5912.
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index d8d8d58075e3..e09d1f297f64 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -7,5 +7,7 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
7 7
8# OMAP Machine Support 8# OMAP Machine Support
9snd-soc-n810-objs := n810.o 9snd-soc-n810-objs := n810.o
10snd-soc-osk5912-objs := osk5912.o
10 11
11obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o 12obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
13obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index d166b6b2a60d..fae3ad36e0bf 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -247,9 +247,9 @@ static int n810_aic33_init(struct snd_soc_codec *codec)
247 int i, err; 247 int i, err;
248 248
249 /* Not connected */ 249 /* Not connected */
250 snd_soc_dapm_disable_pin(codec, "MONO_LOUT"); 250 snd_soc_dapm_nc_pin(codec, "MONO_LOUT");
251 snd_soc_dapm_disable_pin(codec, "HPLCOM"); 251 snd_soc_dapm_nc_pin(codec, "HPLCOM");
252 snd_soc_dapm_disable_pin(codec, "HPRCOM"); 252 snd_soc_dapm_nc_pin(codec, "HPRCOM");
253 253
254 /* Add N810 specific controls */ 254 /* Add N810 specific controls */
255 for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) { 255 for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) {
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 35310e16d7f3..0a063a98a661 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -59,12 +59,7 @@ static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
59 * Stream DMA parameters. DMA request line and port address are set runtime 59 * Stream DMA parameters. DMA request line and port address are set runtime
60 * since they are different between OMAP1 and later OMAPs 60 * since they are different between OMAP1 and later OMAPs
61 */ 61 */
62static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2] = { 62static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
63{
64 { .name = "I2S PCM Stereo out", },
65 { .name = "I2S PCM Stereo in", },
66},
67};
68 63
69#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) 64#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
70static const int omap1_dma_reqs[][2] = { 65static const int omap1_dma_reqs[][2] = {
@@ -84,11 +79,22 @@ static const unsigned long omap1_mcbsp_port[][2] = {
84static const int omap1_dma_reqs[][2] = {}; 79static const int omap1_dma_reqs[][2] = {};
85static const unsigned long omap1_mcbsp_port[][2] = {}; 80static const unsigned long omap1_mcbsp_port[][2] = {};
86#endif 81#endif
87#if defined(CONFIG_ARCH_OMAP2420) 82
88static const int omap2420_dma_reqs[][2] = { 83#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
84static const int omap24xx_dma_reqs[][2] = {
89 { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX }, 85 { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX },
90 { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX }, 86 { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX },
87#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
88 { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX },
89 { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX },
90 { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX },
91#endif
91}; 92};
93#else
94static const int omap24xx_dma_reqs[][2] = {};
95#endif
96
97#if defined(CONFIG_ARCH_OMAP2420)
92static const unsigned long omap2420_mcbsp_port[][2] = { 98static const unsigned long omap2420_mcbsp_port[][2] = {
93 { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1, 99 { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
94 OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 }, 100 OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
@@ -96,10 +102,43 @@ static const unsigned long omap2420_mcbsp_port[][2] = {
96 OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 }, 102 OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
97}; 103};
98#else 104#else
99static const int omap2420_dma_reqs[][2] = {};
100static const unsigned long omap2420_mcbsp_port[][2] = {}; 105static const unsigned long omap2420_mcbsp_port[][2] = {};
101#endif 106#endif
102 107
108#if defined(CONFIG_ARCH_OMAP2430)
109static const unsigned long omap2430_mcbsp_port[][2] = {
110 { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
111 OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
112 { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
113 OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
114 { OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
115 OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
116 { OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
117 OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
118 { OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
119 OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
120};
121#else
122static const unsigned long omap2430_mcbsp_port[][2] = {};
123#endif
124
125#if defined(CONFIG_ARCH_OMAP34XX)
126static const unsigned long omap34xx_mcbsp_port[][2] = {
127 { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
128 OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
129 { OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
130 OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
131 { OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
132 OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
133 { OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
134 OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
135 { OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
136 OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
137};
138#else
139static const unsigned long omap34xx_mcbsp_port[][2] = {};
140#endif
141
103static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream) 142static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
104{ 143{
105 struct snd_soc_pcm_runtime *rtd = substream->private_data; 144 struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -167,14 +206,19 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
167 dma = omap1_dma_reqs[bus_id][substream->stream]; 206 dma = omap1_dma_reqs[bus_id][substream->stream];
168 port = omap1_mcbsp_port[bus_id][substream->stream]; 207 port = omap1_mcbsp_port[bus_id][substream->stream];
169 } else if (cpu_is_omap2420()) { 208 } else if (cpu_is_omap2420()) {
170 dma = omap2420_dma_reqs[bus_id][substream->stream]; 209 dma = omap24xx_dma_reqs[bus_id][substream->stream];
171 port = omap2420_mcbsp_port[bus_id][substream->stream]; 210 port = omap2420_mcbsp_port[bus_id][substream->stream];
211 } else if (cpu_is_omap2430()) {
212 dma = omap24xx_dma_reqs[bus_id][substream->stream];
213 port = omap2430_mcbsp_port[bus_id][substream->stream];
214 } else if (cpu_is_omap343x()) {
215 dma = omap24xx_dma_reqs[bus_id][substream->stream];
216 port = omap34xx_mcbsp_port[bus_id][substream->stream];
172 } else { 217 } else {
173 /*
174 * TODO: Add support for 2430 and 3430
175 */
176 return -ENODEV; 218 return -ENODEV;
177 } 219 }
220 omap_mcbsp_dai_dma_params[id][substream->stream].name =
221 substream->stream ? "Audio Capture" : "Audio Playback";
178 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; 222 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
179 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; 223 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
180 cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream]; 224 cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
@@ -245,6 +289,11 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
245 regs->rcr2 |= RDATDLY(1); 289 regs->rcr2 |= RDATDLY(1);
246 regs->xcr2 |= XDATDLY(1); 290 regs->xcr2 |= XDATDLY(1);
247 break; 291 break;
292 case SND_SOC_DAIFMT_DSP_A:
293 /* 0-bit data delay */
294 regs->rcr2 |= RDATDLY(0);
295 regs->xcr2 |= XDATDLY(0);
296 break;
248 default: 297 default:
249 /* Unsupported data format */ 298 /* Unsupported data format */
250 return -EINVAL; 299 return -EINVAL;
@@ -310,7 +359,7 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
310 int clk_id) 359 int clk_id)
311{ 360{
312 int sel_bit; 361 int sel_bit;
313 u16 reg; 362 u16 reg, reg_devconf1 = OMAP243X_CONTROL_DEVCONF1;
314 363
315 if (cpu_class_is_omap1()) { 364 if (cpu_class_is_omap1()) {
316 /* OMAP1's can use only external source clock */ 365 /* OMAP1's can use only external source clock */
@@ -320,6 +369,12 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
320 return 0; 369 return 0;
321 } 370 }
322 371
372 if (cpu_is_omap2420() && mcbsp_data->bus_id > 1)
373 return -EINVAL;
374
375 if (cpu_is_omap343x())
376 reg_devconf1 = OMAP343X_CONTROL_DEVCONF1;
377
323 switch (mcbsp_data->bus_id) { 378 switch (mcbsp_data->bus_id) {
324 case 0: 379 case 0:
325 reg = OMAP2_CONTROL_DEVCONF0; 380 reg = OMAP2_CONTROL_DEVCONF0;
@@ -329,20 +384,26 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
329 reg = OMAP2_CONTROL_DEVCONF0; 384 reg = OMAP2_CONTROL_DEVCONF0;
330 sel_bit = 6; 385 sel_bit = 6;
331 break; 386 break;
332 /* TODO: Support for ports 3 - 5 in OMAP2430 and OMAP34xx */ 387 case 2:
388 reg = reg_devconf1;
389 sel_bit = 0;
390 break;
391 case 3:
392 reg = reg_devconf1;
393 sel_bit = 2;
394 break;
395 case 4:
396 reg = reg_devconf1;
397 sel_bit = 4;
398 break;
333 default: 399 default:
334 return -EINVAL; 400 return -EINVAL;
335 } 401 }
336 402
337 if (cpu_class_is_omap2()) { 403 if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK)
338 if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK) { 404 omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
339 omap_ctrl_writel(omap_ctrl_readl(reg) & 405 else
340 ~(1 << sel_bit), reg); 406 omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
341 } else {
342 omap_ctrl_writel(omap_ctrl_readl(reg) |
343 (1 << sel_bit), reg);
344 }
345 }
346 407
347 return 0; 408 return 0;
348} 409}
@@ -376,37 +437,49 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
376 return err; 437 return err;
377} 438}
378 439
379struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS] = { 440#define OMAP_MCBSP_DAI_BUILDER(link_id) \
380{ 441{ \
381 .name = "omap-mcbsp-dai", 442 .name = "omap-mcbsp-dai-(link_id)", \
382 .id = 0, 443 .id = (link_id), \
383 .type = SND_SOC_DAI_I2S, 444 .type = SND_SOC_DAI_I2S, \
384 .playback = { 445 .playback = { \
385 .channels_min = 2, 446 .channels_min = 2, \
386 .channels_max = 2, 447 .channels_max = 2, \
387 .rates = OMAP_MCBSP_RATES, 448 .rates = OMAP_MCBSP_RATES, \
388 .formats = SNDRV_PCM_FMTBIT_S16_LE, 449 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
389 }, 450 }, \
390 .capture = { 451 .capture = { \
391 .channels_min = 2, 452 .channels_min = 2, \
392 .channels_max = 2, 453 .channels_max = 2, \
393 .rates = OMAP_MCBSP_RATES, 454 .rates = OMAP_MCBSP_RATES, \
394 .formats = SNDRV_PCM_FMTBIT_S16_LE, 455 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
395 }, 456 }, \
396 .ops = { 457 .ops = { \
397 .startup = omap_mcbsp_dai_startup, 458 .startup = omap_mcbsp_dai_startup, \
398 .shutdown = omap_mcbsp_dai_shutdown, 459 .shutdown = omap_mcbsp_dai_shutdown, \
399 .trigger = omap_mcbsp_dai_trigger, 460 .trigger = omap_mcbsp_dai_trigger, \
400 .hw_params = omap_mcbsp_dai_hw_params, 461 .hw_params = omap_mcbsp_dai_hw_params, \
401 }, 462 }, \
402 .dai_ops = { 463 .dai_ops = { \
403 .set_fmt = omap_mcbsp_dai_set_dai_fmt, 464 .set_fmt = omap_mcbsp_dai_set_dai_fmt, \
404 .set_clkdiv = omap_mcbsp_dai_set_clkdiv, 465 .set_clkdiv = omap_mcbsp_dai_set_clkdiv, \
405 .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, 466 .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, \
406 }, 467 }, \
407 .private_data = &mcbsp_data[0].bus_id, 468 .private_data = &mcbsp_data[(link_id)].bus_id, \
408}, 469}
470
471struct snd_soc_dai omap_mcbsp_dai[] = {
472 OMAP_MCBSP_DAI_BUILDER(0),
473 OMAP_MCBSP_DAI_BUILDER(1),
474#if NUM_LINKS >= 3
475 OMAP_MCBSP_DAI_BUILDER(2),
476#endif
477#if NUM_LINKS == 5
478 OMAP_MCBSP_DAI_BUILDER(3),
479 OMAP_MCBSP_DAI_BUILDER(4),
480#endif
409}; 481};
482
410EXPORT_SYMBOL_GPL(omap_mcbsp_dai); 483EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
411 484
412MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>"); 485MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index ed8afb550671..df7ad13ba73d 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -38,11 +38,17 @@ enum omap_mcbsp_div {
38 OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */ 38 OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */
39}; 39};
40 40
41/* 41#if defined(CONFIG_ARCH_OMAP2420)
42 * REVISIT: Preparation for the ASoC v2. Let the number of available links to 42#define NUM_LINKS 2
43 * be same than number of McBSP ports found in OMAP(s) we are compiling for. 43#endif
44 */ 44#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
45#define NUM_LINKS 1 45#undef NUM_LINKS
46#define NUM_LINKS 3
47#endif
48#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
49#undef NUM_LINKS
50#define NUM_LINKS 5
51#endif
46 52
47extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; 53extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS];
48 54
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 690bfeaec4a0..e9084fdd2082 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -97,7 +97,7 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
97 prtd->dma_data = dma_data; 97 prtd->dma_data = dma_data;
98 err = omap_request_dma(dma_data->dma_req, dma_data->name, 98 err = omap_request_dma(dma_data->dma_req, dma_data->name,
99 omap_pcm_dma_irq, substream, &prtd->dma_ch); 99 omap_pcm_dma_irq, substream, &prtd->dma_ch);
100 if (!cpu_is_omap1510()) { 100 if (!err & !cpu_is_omap1510()) {
101 /* 101 /*
102 * Link channel with itself so DMA doesn't need any 102 * Link channel with itself so DMA doesn't need any
103 * reprogramming while looping the buffer 103 * reprogramming while looping the buffer
@@ -147,12 +147,14 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
147 dma_params.src_or_dst_synch = OMAP_DMA_DST_SYNC; 147 dma_params.src_or_dst_synch = OMAP_DMA_DST_SYNC;
148 dma_params.src_start = runtime->dma_addr; 148 dma_params.src_start = runtime->dma_addr;
149 dma_params.dst_start = dma_data->port_addr; 149 dma_params.dst_start = dma_data->port_addr;
150 dma_params.dst_port = OMAP_DMA_PORT_MPUI;
150 } else { 151 } else {
151 dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT; 152 dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT;
152 dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC; 153 dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
153 dma_params.src_or_dst_synch = OMAP_DMA_SRC_SYNC; 154 dma_params.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
154 dma_params.src_start = dma_data->port_addr; 155 dma_params.src_start = dma_data->port_addr;
155 dma_params.dst_start = runtime->dma_addr; 156 dma_params.dst_start = runtime->dma_addr;
157 dma_params.src_port = OMAP_DMA_PORT_MPUI;
156 } 158 }
157 /* 159 /*
158 * Set DMA transfer frame size equal to ALSA period size and frame 160 * Set DMA transfer frame size equal to ALSA period size and frame
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
new file mode 100644
index 000000000000..0fe733796898
--- /dev/null
+++ b/sound/soc/omap/osk5912.c
@@ -0,0 +1,232 @@
1/*
2 * osk5912.c -- SoC audio for OSK 5912
3 *
4 * Copyright (C) 2008 Mistral Solutions
5 *
6 * Contact: Arun KS <arunks@mistralsolutions.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/clk.h>
25#include <linux/platform_device.h>
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/soc.h>
29#include <sound/soc-dapm.h>
30
31#include <asm/mach-types.h>
32#include <mach/hardware.h>
33#include <linux/gpio.h>
34#include <mach/mcbsp.h>
35
36#include "omap-mcbsp.h"
37#include "omap-pcm.h"
38#include "../codecs/tlv320aic23.h"
39
40#define CODEC_CLOCK 12000000
41
42static struct clk *tlv320aic23_mclk;
43
44static int osk_startup(struct snd_pcm_substream *substream)
45{
46 return clk_enable(tlv320aic23_mclk);
47}
48
49static void osk_shutdown(struct snd_pcm_substream *substream)
50{
51 clk_disable(tlv320aic23_mclk);
52}
53
54static int osk_hw_params(struct snd_pcm_substream *substream,
55 struct snd_pcm_hw_params *params)
56{
57 struct snd_soc_pcm_runtime *rtd = substream->private_data;
58 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
59 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
60 int err;
61
62 /* Set codec DAI configuration */
63 err = snd_soc_dai_set_fmt(codec_dai,
64 SND_SOC_DAIFMT_DSP_A |
65 SND_SOC_DAIFMT_NB_IF |
66 SND_SOC_DAIFMT_CBM_CFM);
67 if (err < 0) {
68 printk(KERN_ERR "can't set codec DAI configuration\n");
69 return err;
70 }
71
72 /* Set cpu DAI configuration */
73 err = snd_soc_dai_set_fmt(cpu_dai,
74 SND_SOC_DAIFMT_DSP_A |
75 SND_SOC_DAIFMT_NB_IF |
76 SND_SOC_DAIFMT_CBM_CFM);
77 if (err < 0) {
78 printk(KERN_ERR "can't set cpu DAI configuration\n");
79 return err;
80 }
81
82 /* Set the codec system clock for DAC and ADC */
83 err =
84 snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
85
86 if (err < 0) {
87 printk(KERN_ERR "can't set codec system clock\n");
88 return err;
89 }
90
91 return err;
92}
93
94static struct snd_soc_ops osk_ops = {
95 .startup = osk_startup,
96 .hw_params = osk_hw_params,
97 .shutdown = osk_shutdown,
98};
99
100static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
101 SND_SOC_DAPM_HP("Headphone Jack", NULL),
102 SND_SOC_DAPM_LINE("Line In", NULL),
103 SND_SOC_DAPM_MIC("Mic Jack", NULL),
104};
105
106static const struct snd_soc_dapm_route audio_map[] = {
107 {"Headphone Jack", NULL, "LHPOUT"},
108 {"Headphone Jack", NULL, "RHPOUT"},
109
110 {"LLINEIN", NULL, "Line In"},
111 {"RLINEIN", NULL, "Line In"},
112
113 {"MICIN", NULL, "Mic Jack"},
114};
115
116static int osk_tlv320aic23_init(struct snd_soc_codec *codec)
117{
118
119 /* Add osk5912 specific widgets */
120 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
121 ARRAY_SIZE(tlv320aic23_dapm_widgets));
122
123 /* Set up osk5912 specific audio path audio_map */
124 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
125
126 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
127 snd_soc_dapm_enable_pin(codec, "Line In");
128 snd_soc_dapm_enable_pin(codec, "Mic Jack");
129
130 snd_soc_dapm_sync(codec);
131
132 return 0;
133}
134
135/* Digital audio interface glue - connects codec <--> CPU */
136static struct snd_soc_dai_link osk_dai = {
137 .name = "TLV320AIC23",
138 .stream_name = "AIC23",
139 .cpu_dai = &omap_mcbsp_dai[0],
140 .codec_dai = &tlv320aic23_dai,
141 .init = osk_tlv320aic23_init,
142 .ops = &osk_ops,
143};
144
145/* Audio machine driver */
146static struct snd_soc_machine snd_soc_machine_osk = {
147 .name = "OSK5912",
148 .dai_link = &osk_dai,
149 .num_links = 1,
150};
151
152/* Audio subsystem */
153static struct snd_soc_device osk_snd_devdata = {
154 .machine = &snd_soc_machine_osk,
155 .platform = &omap_soc_platform,
156 .codec_dev = &soc_codec_dev_tlv320aic23,
157};
158
159static struct platform_device *osk_snd_device;
160
161static int __init osk_soc_init(void)
162{
163 int err;
164 u32 curRate;
165 struct device *dev;
166
167 if (!(machine_is_omap_osk()))
168 return -ENODEV;
169
170 osk_snd_device = platform_device_alloc("soc-audio", -1);
171 if (!osk_snd_device)
172 return -ENOMEM;
173
174 platform_set_drvdata(osk_snd_device, &osk_snd_devdata);
175 osk_snd_devdata.dev = &osk_snd_device->dev;
176 *(unsigned int *)osk_dai.cpu_dai->private_data = 0; /* McBSP1 */
177 err = platform_device_add(osk_snd_device);
178 if (err)
179 goto err1;
180
181 dev = &osk_snd_device->dev;
182
183 tlv320aic23_mclk = clk_get(dev, "mclk");
184 if (IS_ERR(tlv320aic23_mclk)) {
185 printk(KERN_ERR "Could not get mclk clock\n");
186 return -ENODEV;
187 }
188
189 if (clk_get_usecount(tlv320aic23_mclk) > 0) {
190 /* MCLK is already in use */
191 printk(KERN_WARNING
192 "MCLK in use at %d Hz. We change it to %d Hz\n",
193 (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK);
194 }
195
196 /*
197 * Configure 12 MHz output on MCLK.
198 */
199 curRate = (uint) clk_get_rate(tlv320aic23_mclk);
200 if (curRate != CODEC_CLOCK) {
201 if (clk_set_rate(tlv320aic23_mclk, CODEC_CLOCK)) {
202 printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
203 err = -ECANCELED;
204 goto err1;
205 }
206 }
207
208 printk(KERN_INFO "MCLK = %d [%d], usecount = %d\n",
209 (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK,
210 clk_get_usecount(tlv320aic23_mclk));
211
212 return 0;
213err1:
214 clk_put(tlv320aic23_mclk);
215 platform_device_del(osk_snd_device);
216 platform_device_put(osk_snd_device);
217
218 return err;
219
220}
221
222static void __exit osk_soc_exit(void)
223{
224 platform_device_unregister(osk_snd_device);
225}
226
227module_init(osk_soc_init);
228module_exit(osk_soc_exit);
229
230MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
231MODULE_DESCRIPTION("ALSA SoC OSK 5912");
232MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 1a8373de7f3a..2718eaf7895f 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -4,7 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -281,8 +281,8 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
281{ 281{
282 int i, err; 282 int i, err;
283 283
284 snd_soc_dapm_disable_pin(codec, "LLINEIN"); 284 snd_soc_dapm_nc_pin(codec, "LLINEIN");
285 snd_soc_dapm_disable_pin(codec, "RLINEIN"); 285 snd_soc_dapm_nc_pin(codec, "RLINEIN");
286 286
287 /* Add corgi specific controls */ 287 /* Add corgi specific controls */
288 for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) { 288 for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c
index d9c3f7b28be2..e6ff6929ab4b 100644
--- a/sound/soc/pxa/em-x270.c
+++ b/sound/soc/pxa/em-x270.c
@@ -9,7 +9,7 @@
9 * Copyright 2005 Wolfson Microelectronics PLC. 9 * Copyright 2005 Wolfson Microelectronics PLC.
10 * Copyright 2005 Openedhand Ltd. 10 * Copyright 2005 Openedhand Ltd.
11 * 11 *
12 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 12 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
13 * Richard Purdie <richard@openedhand.com> 13 * Richard Purdie <richard@openedhand.com>
14 * 14 *
15 * This program is free software; you can redistribute it and/or modify it 15 * This program is free software; you can redistribute it and/or modify it
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index f84f7d8db09a..4d9930c52789 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -4,7 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -242,8 +242,8 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
242{ 242{
243 int i, err; 243 int i, err;
244 244
245 snd_soc_dapm_disable_pin(codec, "LLINEIN"); 245 snd_soc_dapm_nc_pin(codec, "LLINEIN");
246 snd_soc_dapm_disable_pin(codec, "RLINEIN"); 246 snd_soc_dapm_nc_pin(codec, "RLINEIN");
247 snd_soc_dapm_enable_pin(codec, "MICIN"); 247 snd_soc_dapm_enable_pin(codec, "MICIN");
248 248
249 /* Add poodle specific controls */ 249 /* Add poodle specific controls */
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 2fb58298513b..e758034db5c3 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com 6 * lrg@slimlogic.co.uk
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 9 * under the terms of the GNU General Public License as published by the
@@ -405,6 +405,6 @@ module_init(pxa2xx_i2s_init);
405module_exit(pxa2xx_i2s_exit); 405module_exit(pxa2xx_i2s_exit);
406 406
407/* Module information */ 407/* Module information */
408MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); 408MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
409MODULE_DESCRIPTION("pxa2xx I2S SoC Interface"); 409MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
410MODULE_LICENSE("GPL"); 410MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index 9a70b00fc30e..d307b6757e95 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -4,7 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -281,13 +281,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
281 int i, err; 281 int i, err;
282 282
283 /* NC codec pins */ 283 /* NC codec pins */
284 snd_soc_dapm_disable_pin(codec, "RINPUT1"); 284 snd_soc_dapm_nc_pin(codec, "RINPUT1");
285 snd_soc_dapm_disable_pin(codec, "LINPUT2"); 285 snd_soc_dapm_nc_pin(codec, "LINPUT2");
286 snd_soc_dapm_disable_pin(codec, "RINPUT2"); 286 snd_soc_dapm_nc_pin(codec, "RINPUT2");
287 snd_soc_dapm_disable_pin(codec, "LINPUT3"); 287 snd_soc_dapm_nc_pin(codec, "LINPUT3");
288 snd_soc_dapm_disable_pin(codec, "RINPUT3"); 288 snd_soc_dapm_nc_pin(codec, "RINPUT3");
289 snd_soc_dapm_disable_pin(codec, "OUT3"); 289 snd_soc_dapm_nc_pin(codec, "OUT3");
290 snd_soc_dapm_disable_pin(codec, "MONO1"); 290 snd_soc_dapm_nc_pin(codec, "MONO1");
291 291
292 /* Add spitz specific controls */ 292 /* Add spitz specific controls */
293 for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) { 293 for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index 2baaa750f123..afefe41b8c46 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -4,7 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -190,8 +190,8 @@ static int tosa_ac97_init(struct snd_soc_codec *codec)
190{ 190{
191 int i, err; 191 int i, err;
192 192
193 snd_soc_dapm_disable_pin(codec, "OUT3"); 193 snd_soc_dapm_nc_pin(codec, "OUT3");
194 snd_soc_dapm_disable_pin(codec, "MONOOUT"); 194 snd_soc_dapm_nc_pin(codec, "MONOOUT");
195 195
196 /* add tosa specific controls */ 196 /* add tosa specific controls */
197 for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) { 197 for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) {
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 73a50e93a9a2..87ddfefcc2fb 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -511,21 +511,20 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
511 DBG("Entered %s\n", __func__); 511 DBG("Entered %s\n", __func__);
512 512
513 /* set up NC codec pins */ 513 /* set up NC codec pins */
514 snd_soc_dapm_disable_pin(codec, "LOUT2"); 514 snd_soc_dapm_nc_pin(codec, "LOUT2");
515 snd_soc_dapm_disable_pin(codec, "ROUT2"); 515 snd_soc_dapm_nc_pin(codec, "ROUT2");
516 snd_soc_dapm_disable_pin(codec, "OUT3"); 516 snd_soc_dapm_nc_pin(codec, "OUT3");
517 snd_soc_dapm_disable_pin(codec, "OUT4"); 517 snd_soc_dapm_nc_pin(codec, "OUT4");
518 snd_soc_dapm_disable_pin(codec, "LINE1"); 518 snd_soc_dapm_nc_pin(codec, "LINE1");
519 snd_soc_dapm_disable_pin(codec, "LINE2"); 519 snd_soc_dapm_nc_pin(codec, "LINE2");
520
521
522 /* set endpoints to default mode */
523 set_scenario_endpoints(codec, NEO_AUDIO_OFF);
524 520
525 /* Add neo1973 specific widgets */ 521 /* Add neo1973 specific widgets */
526 snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets, 522 snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
527 ARRAY_SIZE(wm8753_dapm_widgets)); 523 ARRAY_SIZE(wm8753_dapm_widgets));
528 524
525 /* set endpoints to default mode */
526 set_scenario_endpoints(codec, NEO_AUDIO_OFF);
527
529 /* add neo1973 specific controls */ 528 /* add neo1973 specific controls */
530 for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) { 529 for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) {
531 err = snd_ctl_add(codec->card, 530 err = snd_ctl_add(codec->card,
@@ -603,6 +602,8 @@ static int lm4857_i2c_probe(struct i2c_client *client,
603{ 602{
604 DBG("Entered %s\n", __func__); 603 DBG("Entered %s\n", __func__);
605 604
605 i2c = client;
606
606 lm4857_write_regs(); 607 lm4857_write_regs();
607 return 0; 608 return 0;
608} 609}
@@ -611,6 +612,8 @@ static int lm4857_i2c_remove(struct i2c_client *client)
611{ 612{
612 DBG("Entered %s\n", __func__); 613 DBG("Entered %s\n", __func__);
613 614
615 i2c = NULL;
616
614 return 0; 617 return 0;
615} 618}
616 619
@@ -650,7 +653,7 @@ static void lm4857_shutdown(struct i2c_client *dev)
650} 653}
651 654
652static const struct i2c_device_id lm4857_i2c_id[] = { 655static const struct i2c_device_id lm4857_i2c_id[] = {
653 { "neo1973_lm4857", 0 } 656 { "neo1973_lm4857", 0 },
654 { } 657 { }
655}; 658};
656 659
@@ -668,48 +671,6 @@ static struct i2c_driver lm4857_i2c_driver = {
668}; 671};
669 672
670static struct platform_device *neo1973_snd_device; 673static struct platform_device *neo1973_snd_device;
671static struct i2c_client *lm4857_client;
672
673static int __init neo1973_add_lm4857_device(struct platform_device *pdev,
674 int i2c_bus,
675 unsigned short i2c_address)
676{
677 struct i2c_board_info info;
678 struct i2c_adapter *adapter;
679 struct i2c_client *client;
680 int ret;
681
682 ret = i2c_add_driver(&lm4857_i2c_driver);
683 if (ret != 0) {
684 dev_err(&pdev->dev, "can't add lm4857 driver\n");
685 return ret;
686 }
687
688 memset(&info, 0, sizeof(struct i2c_board_info));
689 info.addr = i2c_address;
690 strlcpy(info.type, "neo1973_lm4857", I2C_NAME_SIZE);
691
692 adapter = i2c_get_adapter(i2c_bus);
693 if (!adapter) {
694 dev_err(&pdev->dev, "can't get i2c adapter %d\n", i2c_bus);
695 goto err_driver;
696 }
697
698 client = i2c_new_device(adapter, &info);
699 i2c_put_adapter(adapter);
700 if (!client) {
701 dev_err(&pdev->dev, "can't add lm4857 device at 0x%x\n",
702 (unsigned int)info.addr);
703 goto err_driver;
704 }
705
706 lm4857_client = client;
707 return 0;
708
709err_driver:
710 i2c_del_driver(&lm4857_i2c_driver);
711 return -ENODEV;
712}
713 674
714static int __init neo1973_init(void) 675static int __init neo1973_init(void)
715{ 676{
@@ -736,8 +697,8 @@ static int __init neo1973_init(void)
736 return ret; 697 return ret;
737 } 698 }
738 699
739 ret = neo1973_add_lm4857_device(neo1973_snd_device, 700 ret = i2c_add_driver(&lm4857_i2c_driver);
740 neo1973_wm8753_setup, 0x7C); 701
741 if (ret != 0) 702 if (ret != 0)
742 platform_device_unregister(neo1973_snd_device); 703 platform_device_unregister(neo1973_snd_device);
743 704
@@ -748,7 +709,6 @@ static void __exit neo1973_exit(void)
748{ 709{
749 DBG("Entered %s\n", __func__); 710 DBG("Entered %s\n", __func__);
750 711
751 i2c_unregister_device(lm4857_client);
752 i2c_del_driver(&lm4857_i2c_driver); 712 i2c_del_driver(&lm4857_i2c_driver);
753 platform_device_unregister(neo1973_snd_device); 713 platform_device_unregister(neo1973_snd_device);
754} 714}
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index ad381138fc2e..462e635dfc74 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -4,8 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Author: Liam Girdwood 7 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
8 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
9 * with code, comments and ideas from :- 8 * with code, comments and ideas from :-
10 * Richard Purdie <richard@openedhand.com> 9 * Richard Purdie <richard@openedhand.com>
11 * 10 *
@@ -1886,7 +1885,7 @@ module_init(snd_soc_init);
1886module_exit(snd_soc_exit); 1885module_exit(snd_soc_exit);
1887 1886
1888/* Module information */ 1887/* Module information */
1889MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); 1888MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
1890MODULE_DESCRIPTION("ALSA SoC Core"); 1889MODULE_DESCRIPTION("ALSA SoC Core");
1891MODULE_LICENSE("GPL"); 1890MODULE_LICENSE("GPL");
1892MODULE_ALIAS("platform:soc-audio"); 1891MODULE_ALIAS("platform:soc-audio");
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 9ca9c08610fa..efbd0b37810a 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2,8 +2,7 @@
2 * soc-dapm.c -- ALSA SoC Dynamic Audio Power Management 2 * soc-dapm.c -- ALSA SoC Dynamic Audio Power Management
3 * 3 *
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
@@ -1484,6 +1483,26 @@ int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin)
1484EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); 1483EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
1485 1484
1486/** 1485/**
1486 * snd_soc_dapm_nc_pin - permanently disable pin.
1487 * @codec: SoC codec
1488 * @pin: pin name
1489 *
1490 * Marks the specified pin as being not connected, disabling it along
1491 * any parent or child widgets. At present this is identical to
1492 * snd_soc_dapm_disable_pin() but in future it will be extended to do
1493 * additional things such as disabling controls which only affect
1494 * paths through the pin.
1495 *
1496 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1497 * do any widget power switching.
1498 */
1499int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin)
1500{
1501 return snd_soc_dapm_set_pin(codec, pin, 0);
1502}
1503EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
1504
1505/**
1487 * snd_soc_dapm_get_pin_status - get audio pin status 1506 * snd_soc_dapm_get_pin_status - get audio pin status
1488 * @codec: audio codec 1507 * @codec: audio codec
1489 * @pin: audio signal pin endpoint (or start point) 1508 * @pin: audio signal pin endpoint (or start point)
@@ -1521,6 +1540,6 @@ void snd_soc_dapm_free(struct snd_soc_device *socdev)
1521EXPORT_SYMBOL_GPL(snd_soc_dapm_free); 1540EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
1522 1541
1523/* Module information */ 1542/* Module information */
1524MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); 1543MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
1525MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC"); 1544MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
1526MODULE_LICENSE("GPL"); 1545MODULE_LICENSE("GPL");