aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/Kconfig19
-rw-r--r--sound/soc/Makefile3
-rw-r--r--sound/soc/at32/Kconfig34
-rw-r--r--sound/soc/at32/Makefile11
-rw-r--r--sound/soc/at32/at32-pcm.c491
-rw-r--r--sound/soc/at32/at32-pcm.h79
-rw-r--r--sound/soc/at32/at32-ssc.c849
-rw-r--r--sound/soc/at32/at32-ssc.h59
-rw-r--r--sound/soc/at32/playpaq_wm8510.c522
-rw-r--r--sound/soc/at91/Kconfig2
-rw-r--r--sound/soc/at91/at91-pcm.c6
-rw-r--r--sound/soc/at91/at91-ssc.c12
-rw-r--r--sound/soc/at91/at91-ssc.h2
-rw-r--r--sound/soc/at91/eti_b1_wm8731.c53
-rw-r--r--sound/soc/au1x/Kconfig32
-rw-r--r--sound/soc/au1x/Makefile13
-rw-r--r--sound/soc/au1x/dbdma2.c421
-rw-r--r--sound/soc/au1x/psc-ac97.c387
-rw-r--r--sound/soc/au1x/psc-i2s.c414
-rw-r--r--sound/soc/au1x/psc.h53
-rw-r--r--sound/soc/au1x/sample-ac97.c144
-rw-r--r--sound/soc/codecs/Kconfig22
-rw-r--r--sound/soc/codecs/Makefile8
-rw-r--r--sound/soc/codecs/ac97.c31
-rw-r--r--sound/soc/codecs/ac97.h2
-rw-r--r--sound/soc/codecs/ak4535.c696
-rw-r--r--sound/soc/codecs/ak4535.h46
-rw-r--r--sound/soc/codecs/cs4270.c8
-rw-r--r--sound/soc/codecs/cs4270.h2
-rw-r--r--sound/soc/codecs/tlv320aic3x.c384
-rw-r--r--sound/soc/codecs/tlv320aic3x.h55
-rw-r--r--sound/soc/codecs/uda1380.c852
-rw-r--r--sound/soc/codecs/uda1380.h89
-rw-r--r--sound/soc/codecs/wm8510.c817
-rw-r--r--sound/soc/codecs/wm8510.h103
-rw-r--r--sound/soc/codecs/wm8731.c79
-rw-r--r--sound/soc/codecs/wm8731.h2
-rw-r--r--sound/soc/codecs/wm8750.c87
-rw-r--r--sound/soc/codecs/wm8750.h2
-rw-r--r--sound/soc/codecs/wm8753.c183
-rw-r--r--sound/soc/codecs/wm8753.h2
-rw-r--r--sound/soc/codecs/wm8990.c1626
-rw-r--r--sound/soc/codecs/wm8990.h832
-rw-r--r--sound/soc/codecs/wm9712.c53
-rw-r--r--sound/soc/codecs/wm9712.h2
-rw-r--r--sound/soc/codecs/wm9713.c79
-rw-r--r--sound/soc/codecs/wm9713.h2
-rw-r--r--sound/soc/davinci/Kconfig2
-rw-r--r--sound/soc/davinci/davinci-evm.c40
-rw-r--r--sound/soc/davinci/davinci-i2s.c16
-rw-r--r--sound/soc/davinci/davinci-i2s.h2
-rw-r--r--sound/soc/davinci/davinci-pcm.c2
-rw-r--r--sound/soc/fsl/Kconfig6
-rw-r--r--sound/soc/fsl/fsl_dma.c2
-rw-r--r--sound/soc/fsl/fsl_dma.h2
-rw-r--r--sound/soc/fsl/fsl_ssi.c24
-rw-r--r--sound/soc/fsl/fsl_ssi.h4
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c72
-rw-r--r--sound/soc/omap/Kconfig4
-rw-r--r--sound/soc/omap/n810.c106
-rw-r--r--sound/soc/omap/omap-mcbsp.c16
-rw-r--r--sound/soc/omap/omap-mcbsp.h2
-rw-r--r--sound/soc/omap/omap-pcm.c2
-rw-r--r--sound/soc/pxa/Kconfig11
-rw-r--r--sound/soc/pxa/Makefile3
-rw-r--r--sound/soc/pxa/corgi.c70
-rw-r--r--sound/soc/pxa/em-x270.c102
-rw-r--r--sound/soc/pxa/poodle.c50
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c18
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.h2
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c17
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.h2
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c2
-rw-r--r--sound/soc/pxa/spitz.c91
-rw-r--r--sound/soc/pxa/tosa.c47
-rw-r--r--sound/soc/s3c24xx/Kconfig4
-rw-r--r--sound/soc/s3c24xx/neo1973_wm8753.c237
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.c15
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.h2
-rw-r--r--sound/soc/s3c24xx/s3c2443-ac97.c15
-rw-r--r--sound/soc/s3c24xx/s3c24xx-ac97.h2
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c25
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.h2
-rw-r--r--sound/soc/s3c24xx/s3c24xx-pcm.c6
-rw-r--r--sound/soc/s3c24xx/smdk2443_wm9710.c3
-rw-r--r--sound/soc/sh/Kconfig5
-rw-r--r--sound/soc/sh/dma-sh7760.c2
-rw-r--r--sound/soc/sh/hac.c2
-rw-r--r--sound/soc/sh/sh7760-ac97.c4
-rw-r--r--sound/soc/sh/ssi.c8
-rw-r--r--sound/soc/soc-core.c443
-rw-r--r--sound/soc/soc-dapm.c344
92 files changed, 10345 insertions, 1161 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 18f28ac4bfe8..f743530add8f 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -2,15 +2,8 @@
2# SoC audio configuration 2# SoC audio configuration
3# 3#
4 4
5menu "System on Chip audio support" 5menuconfig SND_SOC
6 depends on SND!=n
7
8config SND_SOC_AC97_BUS
9 bool
10
11config SND_SOC
12 tristate "ALSA for SoC audio support" 6 tristate "ALSA for SoC audio support"
13 depends on SND
14 select SND_PCM 7 select SND_PCM
15 ---help--- 8 ---help---
16 9
@@ -23,8 +16,15 @@ config SND_SOC
23 This ASoC audio support can also be built as a module. If so, the module 16 This ASoC audio support can also be built as a module. If so, the module
24 will be called snd-soc-core. 17 will be called snd-soc-core.
25 18
19if SND_SOC
20
21config SND_SOC_AC97_BUS
22 bool
23
26# All the supported Soc's 24# All the supported Soc's
25source "sound/soc/at32/Kconfig"
27source "sound/soc/at91/Kconfig" 26source "sound/soc/at91/Kconfig"
27source "sound/soc/au1x/Kconfig"
28source "sound/soc/pxa/Kconfig" 28source "sound/soc/pxa/Kconfig"
29source "sound/soc/s3c24xx/Kconfig" 29source "sound/soc/s3c24xx/Kconfig"
30source "sound/soc/sh/Kconfig" 30source "sound/soc/sh/Kconfig"
@@ -35,4 +35,5 @@ source "sound/soc/omap/Kconfig"
35# Supported codecs 35# Supported codecs
36source "sound/soc/codecs/Kconfig" 36source "sound/soc/codecs/Kconfig"
37 37
38endmenu 38endif # SND_SOC
39
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 782db2127108..933a66d30804 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,4 +1,5 @@
1snd-soc-core-objs := soc-core.o soc-dapm.o 1snd-soc-core-objs := soc-core.o soc-dapm.o
2 2
3obj-$(CONFIG_SND_SOC) += snd-soc-core.o 3obj-$(CONFIG_SND_SOC) += snd-soc-core.o
4obj-$(CONFIG_SND_SOC) += codecs/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/ omap/ 4obj-$(CONFIG_SND_SOC) += codecs/ at32/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/
5obj-$(CONFIG_SND_SOC) += omap/ au1x/
diff --git a/sound/soc/at32/Kconfig b/sound/soc/at32/Kconfig
new file mode 100644
index 000000000000..b0765e86c085
--- /dev/null
+++ b/sound/soc/at32/Kconfig
@@ -0,0 +1,34 @@
1config SND_AT32_SOC
2 tristate "SoC Audio for the Atmel AT32 System-on-a-Chip"
3 depends on AVR32 && SND_SOC
4 help
5 Say Y or M if you want to add support for codecs attached to
6 the AT32 SSC interface. You will also need to
7 to select the audio interfaces to support below.
8
9
10config SND_AT32_SOC_SSC
11 tristate
12
13
14
15config SND_AT32_SOC_PLAYPAQ
16 tristate "SoC Audio support for PlayPaq with WM8510"
17 depends on SND_AT32_SOC && BOARD_PLAYPAQ
18 select SND_AT32_SOC_SSC
19 select SND_SOC_WM8510
20 help
21 Say Y or M here if you want to add support for SoC audio
22 on the LRS PlayPaq.
23
24
25
26config SND_AT32_SOC_PLAYPAQ_SLAVE
27 bool "Run CODEC on PlayPaq in slave mode"
28 depends on SND_AT32_SOC_PLAYPAQ
29 default n
30 help
31 Say Y if you want to run with the AT32 SSC generating the BCLK
32 and FRAME signals on the PlayPaq. Unless you want to play
33 with the AT32 as the SSC master, you probably want to say N here,
34 as this will give you better sound quality.
diff --git a/sound/soc/at32/Makefile b/sound/soc/at32/Makefile
new file mode 100644
index 000000000000..c03e55ececeb
--- /dev/null
+++ b/sound/soc/at32/Makefile
@@ -0,0 +1,11 @@
1# AT32 Platform Support
2snd-soc-at32-objs := at32-pcm.o
3snd-soc-at32-ssc-objs := at32-ssc.o
4
5obj-$(CONFIG_SND_AT32_SOC) += snd-soc-at32.o
6obj-$(CONFIG_SND_AT32_SOC_SSC) += snd-soc-at32-ssc.o
7
8# AT32 Machine Support
9snd-soc-playpaq-objs := playpaq_wm8510.o
10
11obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
diff --git a/sound/soc/at32/at32-pcm.c b/sound/soc/at32/at32-pcm.c
new file mode 100644
index 000000000000..435f1daf177c
--- /dev/null
+++ b/sound/soc/at32/at32-pcm.c
@@ -0,0 +1,491 @@
1/* sound/soc/at32/at32-pcm.c
2 * ASoC PCM interface for Atmel AT32 SoC
3 *
4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org>
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 * Note that this is basically a port of the sound/soc/at91-pcm.c to
12 * the AVR32 kernel. Thanks to Frank Mandarino for that code.
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/platform_device.h>
18#include <linux/slab.h>
19#include <linux/dma-mapping.h>
20#include <linux/atmel_pdc.h>
21
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26
27#include "at32-pcm.h"
28
29
30
31/*--------------------------------------------------------------------------*\
32 * Hardware definition
33\*--------------------------------------------------------------------------*/
34/* TODO: These values were taken from the AT91 platform driver, check
35 * them against real values for AT32
36 */
37static const struct snd_pcm_hardware at32_pcm_hardware = {
38 .info = (SNDRV_PCM_INFO_MMAP |
39 SNDRV_PCM_INFO_MMAP_VALID |
40 SNDRV_PCM_INFO_INTERLEAVED |
41 SNDRV_PCM_INFO_BLOCK_TRANSFER |
42 SNDRV_PCM_INFO_PAUSE),
43
44 .formats = SNDRV_PCM_FMTBIT_S16,
45 .period_bytes_min = 32,
46 .period_bytes_max = 8192, /* 512 frames * 16 bytes / frame */
47 .periods_min = 2,
48 .periods_max = 1024,
49 .buffer_bytes_max = 32 * 1024,
50};
51
52
53
54/*--------------------------------------------------------------------------*\
55 * Data types
56\*--------------------------------------------------------------------------*/
57struct at32_runtime_data {
58 struct at32_pcm_dma_params *params;
59 dma_addr_t dma_buffer; /* physical address of DMA buffer */
60 dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
61 size_t period_size;
62
63 dma_addr_t period_ptr; /* physical address of next period */
64 int periods; /* period index of period_ptr */
65
66 /* Save PDC registers (for power management) */
67 u32 pdc_xpr_save;
68 u32 pdc_xcr_save;
69 u32 pdc_xnpr_save;
70 u32 pdc_xncr_save;
71};
72
73
74
75/*--------------------------------------------------------------------------*\
76 * Helper functions
77\*--------------------------------------------------------------------------*/
78static int at32_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
79{
80 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
81 struct snd_dma_buffer *dmabuf = &substream->dma_buffer;
82 size_t size = at32_pcm_hardware.buffer_bytes_max;
83
84 dmabuf->dev.type = SNDRV_DMA_TYPE_DEV;
85 dmabuf->dev.dev = pcm->card->dev;
86 dmabuf->private_data = NULL;
87 dmabuf->area = dma_alloc_coherent(pcm->card->dev, size,
88 &dmabuf->addr, GFP_KERNEL);
89 pr_debug("at32_pcm: preallocate_dma_buffer: "
90 "area=%p, addr=%p, size=%ld\n",
91 (void *)dmabuf->area, (void *)dmabuf->addr, size);
92
93 if (!dmabuf->area)
94 return -ENOMEM;
95
96 dmabuf->bytes = size;
97 return 0;
98}
99
100
101
102/*--------------------------------------------------------------------------*\
103 * ISR
104\*--------------------------------------------------------------------------*/
105static void at32_pcm_dma_irq(u32 ssc_sr, struct snd_pcm_substream *substream)
106{
107 struct snd_pcm_runtime *rtd = substream->runtime;
108 struct at32_runtime_data *prtd = rtd->private_data;
109 struct at32_pcm_dma_params *params = prtd->params;
110 static int count;
111
112 count++;
113 if (ssc_sr & params->mask->ssc_endbuf) {
114 pr_warning("at32-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
115 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
116 "underrun" : "overrun", params->name, ssc_sr, count);
117
118 /* re-start the PDC */
119 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
120 params->mask->pdc_disable);
121 prtd->period_ptr += prtd->period_size;
122 if (prtd->period_ptr >= prtd->dma_buffer_end)
123 prtd->period_ptr = prtd->dma_buffer;
124
125
126 ssc_writex(params->ssc->regs, params->pdc->xpr,
127 prtd->period_ptr);
128 ssc_writex(params->ssc->regs, params->pdc->xcr,
129 prtd->period_size / params->pdc_xfer_size);
130 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
131 params->mask->pdc_enable);
132 }
133
134
135 if (ssc_sr & params->mask->ssc_endx) {
136 /* Load the PDC next pointer and counter registers */
137 prtd->period_ptr += prtd->period_size;
138 if (prtd->period_ptr >= prtd->dma_buffer_end)
139 prtd->period_ptr = prtd->dma_buffer;
140 ssc_writex(params->ssc->regs, params->pdc->xnpr,
141 prtd->period_ptr);
142 ssc_writex(params->ssc->regs, params->pdc->xncr,
143 prtd->period_size / params->pdc_xfer_size);
144 }
145
146
147 snd_pcm_period_elapsed(substream);
148}
149
150
151
152/*--------------------------------------------------------------------------*\
153 * PCM operations
154\*--------------------------------------------------------------------------*/
155static int at32_pcm_hw_params(struct snd_pcm_substream *substream,
156 struct snd_pcm_hw_params *params)
157{
158 struct snd_pcm_runtime *runtime = substream->runtime;
159 struct at32_runtime_data *prtd = runtime->private_data;
160 struct snd_soc_pcm_runtime *rtd = substream->private_data;
161
162 /* this may get called several times by oss emulation
163 * with different params
164 */
165 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
166 runtime->dma_bytes = params_buffer_bytes(params);
167
168 prtd->params = rtd->dai->cpu_dai->dma_data;
169 prtd->params->dma_intr_handler = at32_pcm_dma_irq;
170
171 prtd->dma_buffer = runtime->dma_addr;
172 prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
173 prtd->period_size = params_period_bytes(params);
174
175 pr_debug("hw_params: DMA for %s initialized "
176 "(dma_bytes=%ld, period_size=%ld)\n",
177 prtd->params->name, runtime->dma_bytes, prtd->period_size);
178
179 return 0;
180}
181
182
183
184static int at32_pcm_hw_free(struct snd_pcm_substream *substream)
185{
186 struct at32_runtime_data *prtd = substream->runtime->private_data;
187 struct at32_pcm_dma_params *params = prtd->params;
188
189 if (params != NULL) {
190 ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
191 params->mask->pdc_disable);
192 prtd->params->dma_intr_handler = NULL;
193 }
194
195 return 0;
196}
197
198
199
200static int at32_pcm_prepare(struct snd_pcm_substream *substream)
201{
202 struct at32_runtime_data *prtd = substream->runtime->private_data;
203 struct at32_pcm_dma_params *params = prtd->params;
204
205 ssc_writex(params->ssc->regs, SSC_IDR,
206 params->mask->ssc_endx | params->mask->ssc_endbuf);
207 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
208 params->mask->pdc_disable);
209
210 return 0;
211}
212
213
214static int at32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
215{
216 struct snd_pcm_runtime *rtd = substream->runtime;
217 struct at32_runtime_data *prtd = rtd->private_data;
218 struct at32_pcm_dma_params *params = prtd->params;
219 int ret = 0;
220
221 pr_debug("at32_pcm_trigger: buffer_size = %ld, "
222 "dma_area = %p, dma_bytes = %ld\n",
223 rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
224
225 switch (cmd) {
226 case SNDRV_PCM_TRIGGER_START:
227 prtd->period_ptr = prtd->dma_buffer;
228
229 ssc_writex(params->ssc->regs, params->pdc->xpr,
230 prtd->period_ptr);
231 ssc_writex(params->ssc->regs, params->pdc->xcr,
232 prtd->period_size / params->pdc_xfer_size);
233
234 prtd->period_ptr += prtd->period_size;
235 ssc_writex(params->ssc->regs, params->pdc->xnpr,
236 prtd->period_ptr);
237 ssc_writex(params->ssc->regs, params->pdc->xncr,
238 prtd->period_size / params->pdc_xfer_size);
239
240 pr_debug("trigger: period_ptr=%lx, xpr=%x, "
241 "xcr=%d, xnpr=%x, xncr=%d\n",
242 (unsigned long)prtd->period_ptr,
243 ssc_readx(params->ssc->regs, params->pdc->xpr),
244 ssc_readx(params->ssc->regs, params->pdc->xcr),
245 ssc_readx(params->ssc->regs, params->pdc->xnpr),
246 ssc_readx(params->ssc->regs, params->pdc->xncr));
247
248 ssc_writex(params->ssc->regs, SSC_IER,
249 params->mask->ssc_endx | params->mask->ssc_endbuf);
250 ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
251 params->mask->pdc_enable);
252
253 pr_debug("sr=%x, imr=%x\n",
254 ssc_readx(params->ssc->regs, SSC_SR),
255 ssc_readx(params->ssc->regs, SSC_IER));
256 break; /* SNDRV_PCM_TRIGGER_START */
257
258
259
260 case SNDRV_PCM_TRIGGER_STOP:
261 case SNDRV_PCM_TRIGGER_SUSPEND:
262 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
263 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
264 params->mask->pdc_disable);
265 break;
266
267
268 case SNDRV_PCM_TRIGGER_RESUME:
269 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
270 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
271 params->mask->pdc_enable);
272 break;
273
274 default:
275 ret = -EINVAL;
276 }
277
278 return ret;
279}
280
281
282
283static snd_pcm_uframes_t at32_pcm_pointer(struct snd_pcm_substream *substream)
284{
285 struct snd_pcm_runtime *runtime = substream->runtime;
286 struct at32_runtime_data *prtd = runtime->private_data;
287 struct at32_pcm_dma_params *params = prtd->params;
288 dma_addr_t ptr;
289 snd_pcm_uframes_t x;
290
291 ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
292 x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
293
294 if (x == runtime->buffer_size)
295 x = 0;
296
297 return x;
298}
299
300
301
302static int at32_pcm_open(struct snd_pcm_substream *substream)
303{
304 struct snd_pcm_runtime *runtime = substream->runtime;
305 struct at32_runtime_data *prtd;
306 int ret = 0;
307
308 snd_soc_set_runtime_hwparams(substream, &at32_pcm_hardware);
309
310 /* ensure that buffer size is a multiple of period size */
311 ret = snd_pcm_hw_constraint_integer(runtime,
312 SNDRV_PCM_HW_PARAM_PERIODS);
313 if (ret < 0)
314 goto out;
315
316 prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
317 if (prtd == NULL) {
318 ret = -ENOMEM;
319 goto out;
320 }
321 runtime->private_data = prtd;
322
323
324out:
325 return ret;
326}
327
328
329
330static int at32_pcm_close(struct snd_pcm_substream *substream)
331{
332 struct at32_runtime_data *prtd = substream->runtime->private_data;
333
334 kfree(prtd);
335 return 0;
336}
337
338
339static int at32_pcm_mmap(struct snd_pcm_substream *substream,
340 struct vm_area_struct *vma)
341{
342 return remap_pfn_range(vma, vma->vm_start,
343 substream->dma_buffer.addr >> PAGE_SHIFT,
344 vma->vm_end - vma->vm_start, vma->vm_page_prot);
345}
346
347
348
349static struct snd_pcm_ops at32_pcm_ops = {
350 .open = at32_pcm_open,
351 .close = at32_pcm_close,
352 .ioctl = snd_pcm_lib_ioctl,
353 .hw_params = at32_pcm_hw_params,
354 .hw_free = at32_pcm_hw_free,
355 .prepare = at32_pcm_prepare,
356 .trigger = at32_pcm_trigger,
357 .pointer = at32_pcm_pointer,
358 .mmap = at32_pcm_mmap,
359};
360
361
362
363/*--------------------------------------------------------------------------*\
364 * ASoC platform driver
365\*--------------------------------------------------------------------------*/
366static u64 at32_pcm_dmamask = 0xffffffff;
367
368static int at32_pcm_new(struct snd_card *card,
369 struct snd_soc_dai *dai,
370 struct snd_pcm *pcm)
371{
372 int ret = 0;
373
374 if (!card->dev->dma_mask)
375 card->dev->dma_mask = &at32_pcm_dmamask;
376 if (!card->dev->coherent_dma_mask)
377 card->dev->coherent_dma_mask = 0xffffffff;
378
379 if (dai->playback.channels_min) {
380 ret = at32_pcm_preallocate_dma_buffer(
381 pcm, SNDRV_PCM_STREAM_PLAYBACK);
382 if (ret)
383 goto out;
384 }
385
386 if (dai->capture.channels_min) {
387 pr_debug("at32-pcm: Allocating PCM capture DMA buffer\n");
388 ret = at32_pcm_preallocate_dma_buffer(
389 pcm, SNDRV_PCM_STREAM_CAPTURE);
390 if (ret)
391 goto out;
392 }
393
394
395out:
396 return ret;
397}
398
399
400
401static void at32_pcm_free_dma_buffers(struct snd_pcm *pcm)
402{
403 struct snd_pcm_substream *substream;
404 struct snd_dma_buffer *buf;
405 int stream;
406
407 for (stream = 0; stream < 2; stream++) {
408 substream = pcm->streams[stream].substream;
409 if (substream == NULL)
410 continue;
411
412 buf = &substream->dma_buffer;
413 if (!buf->area)
414 continue;
415 dma_free_coherent(pcm->card->dev, buf->bytes,
416 buf->area, buf->addr);
417 buf->area = NULL;
418 }
419}
420
421
422
423#ifdef CONFIG_PM
424static int at32_pcm_suspend(struct platform_device *pdev,
425 struct snd_soc_dai *dai)
426{
427 struct snd_pcm_runtime *runtime = dai->runtime;
428 struct at32_runtime_data *prtd;
429 struct at32_pcm_dma_params *params;
430
431 if (runtime == NULL)
432 return 0;
433 prtd = runtime->private_data;
434 params = prtd->params;
435
436 /* Disable the PDC and save the PDC registers */
437 ssc_writex(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable);
438
439 prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
440 prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
441 prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
442 prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
443
444 return 0;
445}
446
447
448
449static int at32_pcm_resume(struct platform_device *pdev,
450 struct snd_soc_dai *dai)
451{
452 struct snd_pcm_runtime *runtime = dai->runtime;
453 struct at32_runtime_data *prtd;
454 struct at32_pcm_dma_params *params;
455
456 if (runtime == NULL)
457 return 0;
458 prtd = runtime->private_data;
459 params = prtd->params;
460
461 /* Restore the PDC registers and enable the PDC */
462 ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
463 ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
464 ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
465 ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
466
467 ssc_writex(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable);
468 return 0;
469}
470#else /* CONFIG_PM */
471# define at32_pcm_suspend NULL
472# define at32_pcm_resume NULL
473#endif /* CONFIG_PM */
474
475
476
477struct snd_soc_platform at32_soc_platform = {
478 .name = "at32-audio",
479 .pcm_ops = &at32_pcm_ops,
480 .pcm_new = at32_pcm_new,
481 .pcm_free = at32_pcm_free_dma_buffers,
482 .suspend = at32_pcm_suspend,
483 .resume = at32_pcm_resume,
484};
485EXPORT_SYMBOL_GPL(at32_soc_platform);
486
487
488
489MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
490MODULE_DESCRIPTION("Atmel AT32 PCM module");
491MODULE_LICENSE("GPL");
diff --git a/sound/soc/at32/at32-pcm.h b/sound/soc/at32/at32-pcm.h
new file mode 100644
index 000000000000..2a52430417da
--- /dev/null
+++ b/sound/soc/at32/at32-pcm.h
@@ -0,0 +1,79 @@
1/* sound/soc/at32/at32-pcm.h
2 * ASoC PCM interface for Atmel AT32 SoC
3 *
4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org>
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 __SOUND_SOC_AT32_AT32_PCM_H
13#define __SOUND_SOC_AT32_AT32_PCM_H __FILE__
14
15#include <linux/atmel-ssc.h>
16
17
18/*
19 * Registers and status bits that are required by the PCM driver
20 * TODO: Is ptcr really used?
21 */
22struct at32_pdc_regs {
23 u32 xpr; /* PDC RX/TX pointer */
24 u32 xcr; /* PDC RX/TX counter */
25 u32 xnpr; /* PDC next RX/TX pointer */
26 u32 xncr; /* PDC next RX/TX counter */
27 u32 ptcr; /* PDC transfer control */
28};
29
30
31
32/*
33 * SSC mask info
34 */
35struct at32_ssc_mask {
36 u32 ssc_enable; /* SSC RX/TX enable */
37 u32 ssc_disable; /* SSC RX/TX disable */
38 u32 ssc_endx; /* SSC ENDTX or ENDRX */
39 u32 ssc_endbuf; /* SSC TXBUFF or RXBUFF */
40 u32 pdc_enable; /* PDC RX/TX enable */
41 u32 pdc_disable; /* PDC RX/TX disable */
42};
43
44
45
46/*
47 * This structure, shared between the PCM driver and the interface,
48 * contains all information required by the PCM driver to perform the
49 * PDC DMA operation. All fields except dma_intr_handler() are initialized
50 * by the interface. The dms_intr_handler() pointer is set by the PCM
51 * driver and called by the interface SSC interrupt handler if it is
52 * non-NULL.
53 */
54struct at32_pcm_dma_params {
55 char *name; /* stream identifier */
56 int pdc_xfer_size; /* PDC counter increment in bytes */
57 struct ssc_device *ssc; /* SSC device for stream */
58 struct at32_pdc_regs *pdc; /* PDC register info */
59 struct at32_ssc_mask *mask; /* SSC mask info */
60 struct snd_pcm_substream *substream;
61 void (*dma_intr_handler) (u32, struct snd_pcm_substream *);
62};
63
64
65
66/*
67 * The AT32 ASoC platform driver
68 */
69extern struct snd_soc_platform at32_soc_platform;
70
71
72
73/*
74 * SSC register access (since ssc_writel() / ssc_readl() require literal name)
75 */
76#define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
77#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
78
79#endif /* __SOUND_SOC_AT32_AT32_PCM_H */
diff --git a/sound/soc/at32/at32-ssc.c b/sound/soc/at32/at32-ssc.c
new file mode 100644
index 000000000000..4ef6492c902e
--- /dev/null
+++ b/sound/soc/at32/at32-ssc.c
@@ -0,0 +1,849 @@
1/* sound/soc/at32/at32-ssc.c
2 * ASoC platform driver for AT32 using SSC as DAI
3 *
4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org>
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 * Note that this is basically a port of the sound/soc/at91-ssc.c to
12 * the AVR32 kernel. Thanks to Frank Mandarino for that code.
13 */
14
15/* #define DEBUG */
16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/interrupt.h>
20#include <linux/device.h>
21#include <linux/delay.h>
22#include <linux/clk.h>
23#include <linux/io.h>
24#include <linux/atmel_pdc.h>
25#include <linux/atmel-ssc.h>
26
27#include <sound/core.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/initval.h>
31#include <sound/soc.h>
32
33#include "at32-pcm.h"
34#include "at32-ssc.h"
35
36
37
38/*-------------------------------------------------------------------------*\
39 * Constants
40\*-------------------------------------------------------------------------*/
41#define NUM_SSC_DEVICES 3
42
43/*
44 * SSC direction masks
45 */
46#define SSC_DIR_MASK_UNUSED 0
47#define SSC_DIR_MASK_PLAYBACK 1
48#define SSC_DIR_MASK_CAPTURE 2
49
50/*
51 * SSC register values that Atmel left out of <linux/atmel-ssc.h>. These
52 * are expected to be used with SSC_BF
53 */
54/* START bit field values */
55#define SSC_START_CONTINUOUS 0
56#define SSC_START_TX_RX 1
57#define SSC_START_LOW_RF 2
58#define SSC_START_HIGH_RF 3
59#define SSC_START_FALLING_RF 4
60#define SSC_START_RISING_RF 5
61#define SSC_START_LEVEL_RF 6
62#define SSC_START_EDGE_RF 7
63#define SSS_START_COMPARE_0 8
64
65/* CKI bit field values */
66#define SSC_CKI_FALLING 0
67#define SSC_CKI_RISING 1
68
69/* CKO bit field values */
70#define SSC_CKO_NONE 0
71#define SSC_CKO_CONTINUOUS 1
72#define SSC_CKO_TRANSFER 2
73
74/* CKS bit field values */
75#define SSC_CKS_DIV 0
76#define SSC_CKS_CLOCK 1
77#define SSC_CKS_PIN 2
78
79/* FSEDGE bit field values */
80#define SSC_FSEDGE_POSITIVE 0
81#define SSC_FSEDGE_NEGATIVE 1
82
83/* FSOS bit field values */
84#define SSC_FSOS_NONE 0
85#define SSC_FSOS_NEGATIVE 1
86#define SSC_FSOS_POSITIVE 2
87#define SSC_FSOS_LOW 3
88#define SSC_FSOS_HIGH 4
89#define SSC_FSOS_TOGGLE 5
90
91#define START_DELAY 1
92
93
94
95/*-------------------------------------------------------------------------*\
96 * Module data
97\*-------------------------------------------------------------------------*/
98/*
99 * SSC PDC registered required by the PCM DMA engine
100 */
101static struct at32_pdc_regs pdc_tx_reg = {
102 .xpr = SSC_PDC_TPR,
103 .xcr = SSC_PDC_TCR,
104 .xnpr = SSC_PDC_TNPR,
105 .xncr = SSC_PDC_TNCR,
106};
107
108
109
110static struct at32_pdc_regs pdc_rx_reg = {
111 .xpr = SSC_PDC_RPR,
112 .xcr = SSC_PDC_RCR,
113 .xnpr = SSC_PDC_RNPR,
114 .xncr = SSC_PDC_RNCR,
115};
116
117
118
119/*
120 * SSC and PDC status bits for transmit and receive
121 */
122static struct at32_ssc_mask ssc_tx_mask = {
123 .ssc_enable = SSC_BIT(CR_TXEN),
124 .ssc_disable = SSC_BIT(CR_TXDIS),
125 .ssc_endx = SSC_BIT(SR_ENDTX),
126 .ssc_endbuf = SSC_BIT(SR_TXBUFE),
127 .pdc_enable = SSC_BIT(PDC_PTCR_TXTEN),
128 .pdc_disable = SSC_BIT(PDC_PTCR_TXTDIS),
129};
130
131
132
133static struct at32_ssc_mask ssc_rx_mask = {
134 .ssc_enable = SSC_BIT(CR_RXEN),
135 .ssc_disable = SSC_BIT(CR_RXDIS),
136 .ssc_endx = SSC_BIT(SR_ENDRX),
137 .ssc_endbuf = SSC_BIT(SR_RXBUFF),
138 .pdc_enable = SSC_BIT(PDC_PTCR_RXTEN),
139 .pdc_disable = SSC_BIT(PDC_PTCR_RXTDIS),
140};
141
142
143
144/*
145 * DMA parameters for each SSC
146 */
147static struct at32_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
148 {
149 {
150 .name = "SSC0 PCM out",
151 .pdc = &pdc_tx_reg,
152 .mask = &ssc_tx_mask,
153 },
154 {
155 .name = "SSC0 PCM in",
156 .pdc = &pdc_rx_reg,
157 .mask = &ssc_rx_mask,
158 },
159 },
160 {
161 {
162 .name = "SSC1 PCM out",
163 .pdc = &pdc_tx_reg,
164 .mask = &ssc_tx_mask,
165 },
166 {
167 .name = "SSC1 PCM in",
168 .pdc = &pdc_rx_reg,
169 .mask = &ssc_rx_mask,
170 },
171 },
172 {
173 {
174 .name = "SSC2 PCM out",
175 .pdc = &pdc_tx_reg,
176 .mask = &ssc_tx_mask,
177 },
178 {
179 .name = "SSC2 PCM in",
180 .pdc = &pdc_rx_reg,
181 .mask = &ssc_rx_mask,
182 },
183 },
184};
185
186
187
188static struct at32_ssc_info ssc_info[NUM_SSC_DEVICES] = {
189 {
190 .name = "ssc0",
191 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
192 .dir_mask = SSC_DIR_MASK_UNUSED,
193 .initialized = 0,
194 },
195 {
196 .name = "ssc1",
197 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
198 .dir_mask = SSC_DIR_MASK_UNUSED,
199 .initialized = 0,
200 },
201 {
202 .name = "ssc2",
203 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
204 .dir_mask = SSC_DIR_MASK_UNUSED,
205 .initialized = 0,
206 },
207};
208
209
210
211
212/*-------------------------------------------------------------------------*\
213 * ISR
214\*-------------------------------------------------------------------------*/
215/*
216 * SSC interrupt handler. Passes PDC interrupts to the DMA interrupt
217 * handler in the PCM driver.
218 */
219static irqreturn_t at32_ssc_interrupt(int irq, void *dev_id)
220{
221 struct at32_ssc_info *ssc_p = dev_id;
222 struct at32_pcm_dma_params *dma_params;
223 u32 ssc_sr;
224 u32 ssc_substream_mask;
225 int i;
226
227 ssc_sr = (ssc_readl(ssc_p->ssc->regs, SR) &
228 ssc_readl(ssc_p->ssc->regs, IMR));
229
230 /*
231 * Loop through substreams attached to this SSC. If a DMA-related
232 * interrupt occured on that substream, call the DMA interrupt
233 * handler function, if one has been registered in the dma_param
234 * structure by the PCM driver.
235 */
236 for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
237 dma_params = ssc_p->dma_params[i];
238
239 if ((dma_params != NULL) &&
240 (dma_params->dma_intr_handler != NULL)) {
241 ssc_substream_mask = (dma_params->mask->ssc_endx |
242 dma_params->mask->ssc_endbuf);
243 if (ssc_sr & ssc_substream_mask) {
244 dma_params->dma_intr_handler(ssc_sr,
245 dma_params->
246 substream);
247 }
248 }
249 }
250
251
252 return IRQ_HANDLED;
253}
254
255/*-------------------------------------------------------------------------*\
256 * DAI functions
257\*-------------------------------------------------------------------------*/
258/*
259 * Startup. Only that one substream allowed in each direction.
260 */
261static int at32_ssc_startup(struct snd_pcm_substream *substream)
262{
263 struct snd_soc_pcm_runtime *rtd = substream->private_data;
264 struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
265 int dir_mask;
266
267 dir_mask = ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
268 SSC_DIR_MASK_PLAYBACK : SSC_DIR_MASK_CAPTURE);
269
270 spin_lock_irq(&ssc_p->lock);
271 if (ssc_p->dir_mask & dir_mask) {
272 spin_unlock_irq(&ssc_p->lock);
273 return -EBUSY;
274 }
275 ssc_p->dir_mask |= dir_mask;
276 spin_unlock_irq(&ssc_p->lock);
277
278 return 0;
279}
280
281
282
283/*
284 * Shutdown. Clear DMA parameters and shutdown the SSC if there
285 * are no other substreams open.
286 */
287static void at32_ssc_shutdown(struct snd_pcm_substream *substream)
288{
289 struct snd_soc_pcm_runtime *rtd = substream->private_data;
290 struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
291 struct at32_pcm_dma_params *dma_params;
292 int dir_mask;
293
294 dma_params = ssc_p->dma_params[substream->stream];
295
296 if (dma_params != NULL) {
297 ssc_writel(dma_params->ssc->regs, CR,
298 dma_params->mask->ssc_disable);
299 pr_debug("%s disabled SSC_SR=0x%08x\n",
300 (substream->stream ? "receiver" : "transmit"),
301 ssc_readl(ssc_p->ssc->regs, SR));
302
303 dma_params->ssc = NULL;
304 dma_params->substream = NULL;
305 ssc_p->dma_params[substream->stream] = NULL;
306 }
307
308
309 dir_mask = 1 << substream->stream;
310 spin_lock_irq(&ssc_p->lock);
311 ssc_p->dir_mask &= ~dir_mask;
312 if (!ssc_p->dir_mask) {
313 /* Shutdown the SSC clock */
314 pr_debug("at32-ssc: Stopping user %d clock\n",
315 ssc_p->ssc->user);
316 clk_disable(ssc_p->ssc->clk);
317
318 if (ssc_p->initialized) {
319 free_irq(ssc_p->ssc->irq, ssc_p);
320 ssc_p->initialized = 0;
321 }
322
323 /* Reset the SSC */
324 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
325
326 /* clear the SSC dividers */
327 ssc_p->cmr_div = 0;
328 ssc_p->tcmr_period = 0;
329 ssc_p->rcmr_period = 0;
330 }
331 spin_unlock_irq(&ssc_p->lock);
332}
333
334
335
336/*
337 * Set the SSC system clock rate
338 */
339static int at32_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
340 int clk_id, unsigned int freq, int dir)
341{
342 /* TODO: What the heck do I do here? */
343 return 0;
344}
345
346
347
348/*
349 * Record DAI format for use by hw_params()
350 */
351static int at32_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
352 unsigned int fmt)
353{
354 struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
355
356 ssc_p->daifmt = fmt;
357 return 0;
358}
359
360
361
362/*
363 * Record SSC clock dividers for use in hw_params()
364 */
365static int at32_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
366 int div_id, int div)
367{
368 struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
369
370 switch (div_id) {
371 case AT32_SSC_CMR_DIV:
372 /*
373 * The same master clock divider is used for both
374 * transmit and receive, so if a value has already
375 * been set, it must match this value
376 */
377 if (ssc_p->cmr_div == 0)
378 ssc_p->cmr_div = div;
379 else if (div != ssc_p->cmr_div)
380 return -EBUSY;
381 break;
382
383 case AT32_SSC_TCMR_PERIOD:
384 ssc_p->tcmr_period = div;
385 break;
386
387 case AT32_SSC_RCMR_PERIOD:
388 ssc_p->rcmr_period = div;
389 break;
390
391 default:
392 return -EINVAL;
393 }
394
395 return 0;
396}
397
398
399
400/*
401 * Configure the SSC
402 */
403static int at32_ssc_hw_params(struct snd_pcm_substream *substream,
404 struct snd_pcm_hw_params *params)
405{
406 struct snd_soc_pcm_runtime *rtd = substream->private_data;
407 int id = rtd->dai->cpu_dai->id;
408 struct at32_ssc_info *ssc_p = &ssc_info[id];
409 struct at32_pcm_dma_params *dma_params;
410 int channels, bits;
411 u32 tfmr, rfmr, tcmr, rcmr;
412 int start_event;
413 int ret;
414
415
416 /*
417 * Currently, there is only one set of dma_params for each direction.
418 * If more are added, this code will have to be changed to select
419 * the proper set
420 */
421 dma_params = &ssc_dma_params[id][substream->stream];
422 dma_params->ssc = ssc_p->ssc;
423 dma_params->substream = substream;
424
425 ssc_p->dma_params[substream->stream] = dma_params;
426
427
428 /*
429 * The cpu_dai->dma_data field is only used to communicate the
430 * appropriate DMA parameters to the PCM driver's hw_params()
431 * function. It should not be used for other purposes as it
432 * is common to all substreams.
433 */
434 rtd->dai->cpu_dai->dma_data = dma_params;
435
436 channels = params_channels(params);
437
438
439 /*
440 * Determine sample size in bits and the PDC increment
441 */
442 switch (params_format(params)) {
443 case SNDRV_PCM_FORMAT_S8:
444 bits = 8;
445 dma_params->pdc_xfer_size = 1;
446 break;
447
448 case SNDRV_PCM_FORMAT_S16:
449 bits = 16;
450 dma_params->pdc_xfer_size = 2;
451 break;
452
453 case SNDRV_PCM_FORMAT_S24:
454 bits = 24;
455 dma_params->pdc_xfer_size = 4;
456 break;
457
458 case SNDRV_PCM_FORMAT_S32:
459 bits = 32;
460 dma_params->pdc_xfer_size = 4;
461 break;
462
463 default:
464 pr_warning("at32-ssc: Unsupported PCM format %d",
465 params_format(params));
466 return -EINVAL;
467 }
468 pr_debug("at32-ssc: bits = %d, pdc_xfer_size = %d, channels = %d\n",
469 bits, dma_params->pdc_xfer_size, channels);
470
471
472 /*
473 * The SSC only supports up to 16-bit samples in I2S format, due
474 * to the size of the Frame Mode Register FSLEN field.
475 */
476 if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
477 if (bits > 16) {
478 pr_warning("at32-ssc: "
479 "sample size %d is too large for I2S\n",
480 bits);
481 return -EINVAL;
482 }
483
484
485 /*
486 * Compute the SSC register settings
487 */
488 switch (ssc_p->daifmt & (SND_SOC_DAIFMT_FORMAT_MASK |
489 SND_SOC_DAIFMT_MASTER_MASK)) {
490 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
491 /*
492 * I2S format, SSC provides BCLK and LRS clocks.
493 *
494 * The SSC transmit and receive clocks are generated from the
495 * MCK divider, and the BCLK signal is output on the SSC TK line
496 */
497 pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME master\n");
498 rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
499 SSC_BF(RCMR_STTDLY, START_DELAY) |
500 SSC_BF(RCMR_START, SSC_START_FALLING_RF) |
501 SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
502 SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
503 SSC_BF(RCMR_CKS, SSC_CKS_DIV));
504
505 rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
506 SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) |
507 SSC_BF(RFMR_FSLEN, bits - 1) |
508 SSC_BF(RFMR_DATNB, channels - 1) |
509 SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
510
511 tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
512 SSC_BF(TCMR_STTDLY, START_DELAY) |
513 SSC_BF(TCMR_START, SSC_START_FALLING_RF) |
514 SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
515 SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
516 SSC_BF(TCMR_CKS, SSC_CKS_DIV));
517
518 tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
519 SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) |
520 SSC_BF(TFMR_FSLEN, bits - 1) |
521 SSC_BF(TFMR_DATNB, channels - 1) | SSC_BIT(TFMR_MSBF) |
522 SSC_BF(TFMR_DATLEN, bits - 1));
523 break;
524
525
526 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
527 /*
528 * I2S format, CODEC supplies BCLK and LRC clock.
529 *
530 * The SSC transmit clock is obtained from the BCLK signal
531 * on the TK line, and the SSC receive clock is generated from
532 * the transmit clock.
533 *
534 * For single channel data, one sample is transferred on the
535 * falling edge of the LRC clock. For two channel data, one
536 * sample is transferred on both edges of the LRC clock.
537 */
538 pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME slave\n");
539 start_event = ((channels == 1) ?
540 SSC_START_FALLING_RF : SSC_START_EDGE_RF);
541
542 rcmr = (SSC_BF(RCMR_STTDLY, START_DELAY) |
543 SSC_BF(RCMR_START, start_event) |
544 SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
545 SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
546 SSC_BF(RCMR_CKS, SSC_CKS_CLOCK));
547
548 rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
549 SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) |
550 SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
551
552 tcmr = (SSC_BF(TCMR_STTDLY, START_DELAY) |
553 SSC_BF(TCMR_START, start_event) |
554 SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
555 SSC_BF(TCMR_CKO, SSC_CKO_NONE) |
556 SSC_BF(TCMR_CKS, SSC_CKS_PIN));
557
558 tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
559 SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) |
560 SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
561 break;
562
563
564 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
565 /*
566 * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
567 *
568 * The SSC transmit and receive clocks are generated from the
569 * MCK divider, and the BCLK signal is output on the SSC TK line
570 */
571 pr_debug("at32-ssc: SSC mode is DSP A BCLK / FRAME master\n");
572 rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
573 SSC_BF(RCMR_STTDLY, 1) |
574 SSC_BF(RCMR_START, SSC_START_RISING_RF) |
575 SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
576 SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
577 SSC_BF(RCMR_CKS, SSC_CKS_DIV));
578
579 rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
580 SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) |
581 SSC_BF(RFMR_DATNB, channels - 1) |
582 SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
583
584 tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
585 SSC_BF(TCMR_STTDLY, 1) |
586 SSC_BF(TCMR_START, SSC_START_RISING_RF) |
587 SSC_BF(TCMR_CKI, SSC_CKI_RISING) |
588 SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
589 SSC_BF(TCMR_CKS, SSC_CKS_DIV));
590
591 tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
592 SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) |
593 SSC_BF(TFMR_DATNB, channels - 1) |
594 SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
595 break;
596
597
598 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
599 default:
600 pr_warning("at32-ssc: unsupported DAI format 0x%x\n",
601 ssc_p->daifmt);
602 return -EINVAL;
603 break;
604 }
605 pr_debug("at32-ssc: RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
606 rcmr, rfmr, tcmr, tfmr);
607
608
609 if (!ssc_p->initialized) {
610 /* enable peripheral clock */
611 pr_debug("at32-ssc: Starting clock\n");
612 clk_enable(ssc_p->ssc->clk);
613
614 /* Reset the SSC and its PDC registers */
615 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
616
617 ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
618 ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
619 ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
620 ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
621
622 ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
623 ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
624 ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
625 ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
626
627 ret = request_irq(ssc_p->ssc->irq, at32_ssc_interrupt, 0,
628 ssc_p->name, ssc_p);
629 if (ret < 0) {
630 pr_warning("at32-ssc: request irq failed (%d)\n", ret);
631 pr_debug("at32-ssc: Stopping clock\n");
632 clk_disable(ssc_p->ssc->clk);
633 return ret;
634 }
635
636 ssc_p->initialized = 1;
637 }
638
639 /* Set SSC clock mode register */
640 ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div);
641
642 /* set receive clock mode and format */
643 ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);
644 ssc_writel(ssc_p->ssc->regs, RFMR, rfmr);
645
646 /* set transmit clock mode and format */
647 ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
648 ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
649
650 pr_debug("at32-ssc: SSC initialized\n");
651 return 0;
652}
653
654
655
656static int at32_ssc_prepare(struct snd_pcm_substream *substream)
657{
658 struct snd_soc_pcm_runtime *rtd = substream->private_data;
659 struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
660 struct at32_pcm_dma_params *dma_params;
661
662 dma_params = ssc_p->dma_params[substream->stream];
663
664 ssc_writel(dma_params->ssc->regs, CR, dma_params->mask->ssc_enable);
665
666 return 0;
667}
668
669
670
671#ifdef CONFIG_PM
672static int at32_ssc_suspend(struct platform_device *pdev,
673 struct snd_soc_dai *cpu_dai)
674{
675 struct at32_ssc_info *ssc_p;
676
677 if (!cpu_dai->active)
678 return 0;
679
680 ssc_p = &ssc_info[cpu_dai->id];
681
682 /* Save the status register before disabling transmit and receive */
683 ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
684 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS));
685
686 /* Save the current interrupt mask, then disable unmasked interrupts */
687 ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR);
688 ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr);
689
690 ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR);
691 ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR);
692 ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR);
693 ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR);
694 ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR);
695
696 return 0;
697}
698
699
700
701static int at32_ssc_resume(struct platform_device *pdev,
702 struct snd_soc_dai *cpu_dai)
703{
704 struct at32_ssc_info *ssc_p;
705 u32 cr;
706
707 if (!cpu_dai->active)
708 return 0;
709
710 ssc_p = &ssc_info[cpu_dai->id];
711
712 /* restore SSC register settings */
713 ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
714 ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr);
715 ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr);
716 ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr);
717 ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr);
718
719 /* re-enable interrupts */
720 ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr);
721
722 /* Re-enable recieve and transmit as appropriate */
723 cr = 0;
724 cr |=
725 (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0;
726 cr |=
727 (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0;
728 ssc_writel(ssc_p->ssc->regs, CR, cr);
729
730 return 0;
731}
732#else /* CONFIG_PM */
733# define at32_ssc_suspend NULL
734# define at32_ssc_resume NULL
735#endif /* CONFIG_PM */
736
737
738#define AT32_SSC_RATES \
739 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
740 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
741 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
742
743
744#define AT32_SSC_FORMATS \
745 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16 | \
746 SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_S32)
747
748
749struct snd_soc_dai at32_ssc_dai[NUM_SSC_DEVICES] = {
750 {
751 .name = "at32-ssc0",
752 .id = 0,
753 .type = SND_SOC_DAI_PCM,
754 .suspend = at32_ssc_suspend,
755 .resume = at32_ssc_resume,
756 .playback = {
757 .channels_min = 1,
758 .channels_max = 2,
759 .rates = AT32_SSC_RATES,
760 .formats = AT32_SSC_FORMATS,
761 },
762 .capture = {
763 .channels_min = 1,
764 .channels_max = 2,
765 .rates = AT32_SSC_RATES,
766 .formats = AT32_SSC_FORMATS,
767 },
768 .ops = {
769 .startup = at32_ssc_startup,
770 .shutdown = at32_ssc_shutdown,
771 .prepare = at32_ssc_prepare,
772 .hw_params = at32_ssc_hw_params,
773 },
774 .dai_ops = {
775 .set_sysclk = at32_ssc_set_dai_sysclk,
776 .set_fmt = at32_ssc_set_dai_fmt,
777 .set_clkdiv = at32_ssc_set_dai_clkdiv,
778 },
779 .private_data = &ssc_info[0],
780 },
781 {
782 .name = "at32-ssc1",
783 .id = 1,
784 .type = SND_SOC_DAI_PCM,
785 .suspend = at32_ssc_suspend,
786 .resume = at32_ssc_resume,
787 .playback = {
788 .channels_min = 1,
789 .channels_max = 2,
790 .rates = AT32_SSC_RATES,
791 .formats = AT32_SSC_FORMATS,
792 },
793 .capture = {
794 .channels_min = 1,
795 .channels_max = 2,
796 .rates = AT32_SSC_RATES,
797 .formats = AT32_SSC_FORMATS,
798 },
799 .ops = {
800 .startup = at32_ssc_startup,
801 .shutdown = at32_ssc_shutdown,
802 .prepare = at32_ssc_prepare,
803 .hw_params = at32_ssc_hw_params,
804 },
805 .dai_ops = {
806 .set_sysclk = at32_ssc_set_dai_sysclk,
807 .set_fmt = at32_ssc_set_dai_fmt,
808 .set_clkdiv = at32_ssc_set_dai_clkdiv,
809 },
810 .private_data = &ssc_info[1],
811 },
812 {
813 .name = "at32-ssc2",
814 .id = 2,
815 .type = SND_SOC_DAI_PCM,
816 .suspend = at32_ssc_suspend,
817 .resume = at32_ssc_resume,
818 .playback = {
819 .channels_min = 1,
820 .channels_max = 2,
821 .rates = AT32_SSC_RATES,
822 .formats = AT32_SSC_FORMATS,
823 },
824 .capture = {
825 .channels_min = 1,
826 .channels_max = 2,
827 .rates = AT32_SSC_RATES,
828 .formats = AT32_SSC_FORMATS,
829 },
830 .ops = {
831 .startup = at32_ssc_startup,
832 .shutdown = at32_ssc_shutdown,
833 .prepare = at32_ssc_prepare,
834 .hw_params = at32_ssc_hw_params,
835 },
836 .dai_ops = {
837 .set_sysclk = at32_ssc_set_dai_sysclk,
838 .set_fmt = at32_ssc_set_dai_fmt,
839 .set_clkdiv = at32_ssc_set_dai_clkdiv,
840 },
841 .private_data = &ssc_info[2],
842 },
843};
844EXPORT_SYMBOL_GPL(at32_ssc_dai);
845
846
847MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
848MODULE_DESCRIPTION("AT32 SSC ASoC Interface");
849MODULE_LICENSE("GPL");
diff --git a/sound/soc/at32/at32-ssc.h b/sound/soc/at32/at32-ssc.h
new file mode 100644
index 000000000000..3c052dbbe460
--- /dev/null
+++ b/sound/soc/at32/at32-ssc.h
@@ -0,0 +1,59 @@
1/* sound/soc/at32/at32-ssc.h
2 * ASoC SSC interface for Atmel AT32 SoC
3 *
4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org>
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 __SOUND_SOC_AT32_AT32_SSC_H
13#define __SOUND_SOC_AT32_AT32_SSC_H __FILE__
14
15#include <linux/types.h>
16#include <linux/atmel-ssc.h>
17
18#include "at32-pcm.h"
19
20
21
22struct at32_ssc_state {
23 u32 ssc_cmr;
24 u32 ssc_rcmr;
25 u32 ssc_rfmr;
26 u32 ssc_tcmr;
27 u32 ssc_tfmr;
28 u32 ssc_sr;
29 u32 ssc_imr;
30};
31
32
33
34struct at32_ssc_info {
35 char *name;
36 struct ssc_device *ssc;
37 spinlock_t lock; /* lock for dir_mask */
38 unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
39 unsigned short initialized; /* true if SSC has been initialized */
40 unsigned short daifmt;
41 unsigned short cmr_div;
42 unsigned short tcmr_period;
43 unsigned short rcmr_period;
44 struct at32_pcm_dma_params *dma_params[2];
45 struct at32_ssc_state ssc_state;
46};
47
48
49/* SSC divider ids */
50#define AT32_SSC_CMR_DIV 0 /* MCK divider for BCLK */
51#define AT32_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
52#define AT32_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
53
54
55extern struct snd_soc_dai at32_ssc_dai[];
56
57
58
59#endif /* __SOUND_SOC_AT32_AT32_SSC_H */
diff --git a/sound/soc/at32/playpaq_wm8510.c b/sound/soc/at32/playpaq_wm8510.c
new file mode 100644
index 000000000000..fee5f8e58957
--- /dev/null
+++ b/sound/soc/at32/playpaq_wm8510.c
@@ -0,0 +1,522 @@
1/* sound/soc/at32/playpaq_wm8510.c
2 * ASoC machine driver for PlayPaq using WM8510 codec
3 *
4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org>
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 * This code is largely inspired by sound/soc/at91/eti_b1_wm8731.c
12 *
13 * NOTE: If you don't have the AT32 enhanced portmux configured (which
14 * isn't currently in the mainline or Atmel patched kernel), you will
15 * need to set the MCLK pin (PA30) to peripheral A in your board initialization
16 * code. Something like:
17 * at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0);
18 *
19 */
20
21/* #define DEBUG */
22
23#include <linux/module.h>
24#include <linux/moduleparam.h>
25#include <linux/version.h>
26#include <linux/kernel.h>
27#include <linux/errno.h>
28#include <linux/clk.h>
29#include <linux/timer.h>
30#include <linux/interrupt.h>
31#include <linux/platform_device.h>
32
33#include <sound/core.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36#include <sound/soc.h>
37#include <sound/soc-dapm.h>
38
39#include <asm/arch/at32ap700x.h>
40#include <asm/arch/portmux.h>
41
42#include "../codecs/wm8510.h"
43#include "at32-pcm.h"
44#include "at32-ssc.h"
45
46
47/*-------------------------------------------------------------------------*\
48 * constants
49\*-------------------------------------------------------------------------*/
50#define MCLK_PIN GPIO_PIN_PA(30)
51#define MCLK_PERIPH GPIO_PERIPH_A
52
53
54/*-------------------------------------------------------------------------*\
55 * data types
56\*-------------------------------------------------------------------------*/
57/* SSC clocking data */
58struct ssc_clock_data {
59 /* CMR div */
60 unsigned int cmr_div;
61
62 /* Frame period (as needed by xCMR.PERIOD) */
63 unsigned int period;
64
65 /* The SSC clock rate these settings where calculated for */
66 unsigned long ssc_rate;
67};
68
69
70/*-------------------------------------------------------------------------*\
71 * module data
72\*-------------------------------------------------------------------------*/
73static struct clk *_gclk0;
74static struct clk *_pll0;
75
76#define CODEC_CLK (_gclk0)
77
78
79/*-------------------------------------------------------------------------*\
80 * Sound SOC operations
81\*-------------------------------------------------------------------------*/
82#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
83static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock(
84 struct snd_pcm_hw_params *params,
85 struct snd_soc_dai *cpu_dai)
86{
87 struct at32_ssc_info *ssc_p = cpu_dai->private_data;
88 struct ssc_device *ssc = ssc_p->ssc;
89 struct ssc_clock_data cd;
90 unsigned int rate, width_bits, channels;
91 unsigned int bitrate, ssc_div;
92 unsigned actual_rate;
93
94
95 /*
96 * Figure out required bitrate
97 */
98 rate = params_rate(params);
99 channels = params_channels(params);
100 width_bits = snd_pcm_format_physical_width(params_format(params));
101 bitrate = rate * width_bits * channels;
102
103
104 /*
105 * Figure out required SSC divider and period for required bitrate
106 */
107 cd.ssc_rate = clk_get_rate(ssc->clk);
108 ssc_div = cd.ssc_rate / bitrate;
109 cd.cmr_div = ssc_div / 2;
110 if (ssc_div & 1) {
111 /* round cmr_div up */
112 cd.cmr_div++;
113 }
114 cd.period = width_bits - 1;
115
116
117 /*
118 * Find actual rate, compare to requested rate
119 */
120 actual_rate = (cd.ssc_rate / (cd.cmr_div * 2)) / (2 * (cd.period + 1));
121 pr_debug("playpaq_wm8510: Request rate = %d, actual rate = %d\n",
122 rate, actual_rate);
123
124
125 return cd;
126}
127#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
128
129
130
131static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream,
132 struct snd_pcm_hw_params *params)
133{
134 struct snd_soc_pcm_runtime *rtd = substream->private_data;
135 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
136 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
137 struct at32_ssc_info *ssc_p = cpu_dai->private_data;
138 struct ssc_device *ssc = ssc_p->ssc;
139 unsigned int pll_out = 0, bclk = 0, mclk_div = 0;
140 int ret;
141
142
143 /* Due to difficulties with getting the correct clocks from the AT32's
144 * PLL0, we're going to let the CODEC be in charge of all the clocks
145 */
146#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
147 const unsigned int fmt = (SND_SOC_DAIFMT_I2S |
148 SND_SOC_DAIFMT_NB_NF |
149 SND_SOC_DAIFMT_CBM_CFM);
150#else
151 struct ssc_clock_data cd;
152 const unsigned int fmt = (SND_SOC_DAIFMT_I2S |
153 SND_SOC_DAIFMT_NB_NF |
154 SND_SOC_DAIFMT_CBS_CFS);
155#endif
156
157 if (ssc == NULL) {
158 pr_warning("playpaq_wm8510_hw_params: ssc is NULL!\n");
159 return -EINVAL;
160 }
161
162
163 /*
164 * Figure out PLL and BCLK dividers for WM8510
165 */
166 switch (params_rate(params)) {
167 case 48000:
168 pll_out = 12288000;
169 mclk_div = WM8510_MCLKDIV_1;
170 bclk = WM8510_BCLKDIV_8;
171 break;
172
173 case 44100:
174 pll_out = 11289600;
175 mclk_div = WM8510_MCLKDIV_1;
176 bclk = WM8510_BCLKDIV_8;
177 break;
178
179 case 22050:
180 pll_out = 11289600;
181 mclk_div = WM8510_MCLKDIV_2;
182 bclk = WM8510_BCLKDIV_8;
183 break;
184
185 case 16000:
186 pll_out = 12288000;
187 mclk_div = WM8510_MCLKDIV_3;
188 bclk = WM8510_BCLKDIV_8;
189 break;
190
191 case 11025:
192 pll_out = 11289600;
193 mclk_div = WM8510_MCLKDIV_4;
194 bclk = WM8510_BCLKDIV_8;
195 break;
196
197 case 8000:
198 pll_out = 12288000;
199 mclk_div = WM8510_MCLKDIV_6;
200 bclk = WM8510_BCLKDIV_8;
201 break;
202
203 default:
204 pr_warning("playpaq_wm8510: Unsupported sample rate %d\n",
205 params_rate(params));
206 return -EINVAL;
207 }
208
209
210 /*
211 * set CPU and CODEC DAI configuration
212 */
213 ret = snd_soc_dai_set_fmt(codec_dai, fmt);
214 if (ret < 0) {
215 pr_warning("playpaq_wm8510: "
216 "Failed to set CODEC DAI format (%d)\n",
217 ret);
218 return ret;
219 }
220 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
221 if (ret < 0) {
222 pr_warning("playpaq_wm8510: "
223 "Failed to set CPU DAI format (%d)\n",
224 ret);
225 return ret;
226 }
227
228
229 /*
230 * Set CPU clock configuration
231 */
232#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
233 cd = playpaq_wm8510_calc_ssc_clock(params, cpu_dai);
234 pr_debug("playpaq_wm8510: cmr_div = %d, period = %d\n",
235 cd.cmr_div, cd.period);
236 ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_CMR_DIV, cd.cmr_div);
237 if (ret < 0) {
238 pr_warning("playpaq_wm8510: Failed to set CPU CMR_DIV (%d)\n",
239 ret);
240 return ret;
241 }
242 ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_TCMR_PERIOD,
243 cd.period);
244 if (ret < 0) {
245 pr_warning("playpaq_wm8510: "
246 "Failed to set CPU transmit period (%d)\n",
247 ret);
248 return ret;
249 }
250#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
251
252
253 /*
254 * Set CODEC clock configuration
255 */
256 pr_debug("playpaq_wm8510: "
257 "pll_in = %ld, pll_out = %u, bclk = %x, mclk = %x\n",
258 clk_get_rate(CODEC_CLK), pll_out, bclk, mclk_div);
259
260
261#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
262 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_BCLKDIV, bclk);
263 if (ret < 0) {
264 pr_warning
265 ("playpaq_wm8510: Failed to set CODEC DAI BCLKDIV (%d)\n",
266 ret);
267 return ret;
268 }
269#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
270
271
272 ret = snd_soc_dai_set_pll(codec_dai, 0,
273 clk_get_rate(CODEC_CLK), pll_out);
274 if (ret < 0) {
275 pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n",
276 ret);
277 return ret;
278 }
279
280
281 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_MCLKDIV, mclk_div);
282 if (ret < 0) {
283 pr_warning("playpaq_wm8510: Failed to set CODEC MCLKDIV (%d)\n",
284 ret);
285 return ret;
286 }
287
288
289 return 0;
290}
291
292
293
294static struct snd_soc_ops playpaq_wm8510_ops = {
295 .hw_params = playpaq_wm8510_hw_params,
296};
297
298
299
300static const struct snd_soc_dapm_widget playpaq_dapm_widgets[] = {
301 SND_SOC_DAPM_MIC("Int Mic", NULL),
302 SND_SOC_DAPM_SPK("Ext Spk", NULL),
303};
304
305
306
307static const char *intercon[][3] = {
308 /* speaker connected to SPKOUT */
309 {"Ext Spk", NULL, "SPKOUTP"},
310 {"Ext Spk", NULL, "SPKOUTN"},
311
312 {"Mic Bias", NULL, "Int Mic"},
313 {"MICN", NULL, "Mic Bias"},
314 {"MICP", NULL, "Mic Bias"},
315
316 /* Terminator */
317 {NULL, NULL, NULL},
318};
319
320
321
322static int playpaq_wm8510_init(struct snd_soc_codec *codec)
323{
324 int i;
325
326 /*
327 * Add DAPM widgets
328 */
329 for (i = 0; i < ARRAY_SIZE(playpaq_dapm_widgets); i++)
330 snd_soc_dapm_new_control(codec, &playpaq_dapm_widgets[i]);
331
332
333
334 /*
335 * Setup audio path interconnects
336 */
337 for (i = 0; intercon[i][0] != NULL; i++) {
338 snd_soc_dapm_connect_input(codec,
339 intercon[i][0],
340 intercon[i][1], intercon[i][2]);
341 }
342
343
344 /* always connected pins */
345 snd_soc_dapm_enable_pin(codec, "Int Mic");
346 snd_soc_dapm_enable_pin(codec, "Ext Spk");
347 snd_soc_dapm_sync(codec);
348
349
350
351 /* Make CSB show PLL rate */
352 snd_soc_dai_set_clkdiv(codec->dai, WM8510_OPCLKDIV,
353 WM8510_OPCLKDIV_1 | 4);
354
355 return 0;
356}
357
358
359
360static struct snd_soc_dai_link playpaq_wm8510_dai = {
361 .name = "WM8510",
362 .stream_name = "WM8510 PCM",
363 .cpu_dai = &at32_ssc_dai[0],
364 .codec_dai = &wm8510_dai,
365 .init = playpaq_wm8510_init,
366 .ops = &playpaq_wm8510_ops,
367};
368
369
370
371static struct snd_soc_machine snd_soc_machine_playpaq = {
372 .name = "LRS_PlayPaq_WM8510",
373 .dai_link = &playpaq_wm8510_dai,
374 .num_links = 1,
375};
376
377
378
379static struct wm8510_setup_data playpaq_wm8510_setup = {
380 .i2c_address = 0x1a,
381};
382
383
384
385static struct snd_soc_device playpaq_wm8510_snd_devdata = {
386 .machine = &snd_soc_machine_playpaq,
387 .platform = &at32_soc_platform,
388 .codec_dev = &soc_codec_dev_wm8510,
389 .codec_data = &playpaq_wm8510_setup,
390};
391
392static struct platform_device *playpaq_snd_device;
393
394
395static int __init playpaq_asoc_init(void)
396{
397 int ret = 0;
398 struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data;
399 struct ssc_device *ssc = NULL;
400
401
402 /*
403 * Request SSC device
404 */
405 ssc = ssc_request(0);
406 if (IS_ERR(ssc)) {
407 ret = PTR_ERR(ssc);
408 ssc = NULL;
409 goto err_ssc;
410 }
411 ssc_p->ssc = ssc;
412
413
414 /*
415 * Configure MCLK for WM8510
416 */
417 _gclk0 = clk_get(NULL, "gclk0");
418 if (IS_ERR(_gclk0)) {
419 _gclk0 = NULL;
420 goto err_gclk0;
421 }
422 _pll0 = clk_get(NULL, "pll0");
423 if (IS_ERR(_pll0)) {
424 _pll0 = NULL;
425 goto err_pll0;
426 }
427 if (clk_set_parent(_gclk0, _pll0)) {
428 pr_warning("snd-soc-playpaq: "
429 "Failed to set PLL0 as parent for DAC clock\n");
430 goto err_set_clk;
431 }
432 clk_set_rate(CODEC_CLK, 12000000);
433 clk_enable(CODEC_CLK);
434
435#if defined CONFIG_AT32_ENHANCED_PORTMUX
436 at32_select_periph(MCLK_PIN, MCLK_PERIPH, 0);
437#endif
438
439
440 /*
441 * Create and register platform device
442 */
443 playpaq_snd_device = platform_device_alloc("soc-audio", 0);
444 if (playpaq_snd_device == NULL) {
445 ret = -ENOMEM;
446 goto err_device_alloc;
447 }
448
449 platform_set_drvdata(playpaq_snd_device, &playpaq_wm8510_snd_devdata);
450 playpaq_wm8510_snd_devdata.dev = &playpaq_snd_device->dev;
451
452 ret = platform_device_add(playpaq_snd_device);
453 if (ret) {
454 pr_warning("playpaq_wm8510: platform_device_add failed (%d)\n",
455 ret);
456 goto err_device_add;
457 }
458
459 return 0;
460
461
462err_device_add:
463 if (playpaq_snd_device != NULL) {
464 platform_device_put(playpaq_snd_device);
465 playpaq_snd_device = NULL;
466 }
467err_device_alloc:
468err_set_clk:
469 if (_pll0 != NULL) {
470 clk_put(_pll0);
471 _pll0 = NULL;
472 }
473err_pll0:
474 if (_gclk0 != NULL) {
475 clk_put(_gclk0);
476 _gclk0 = NULL;
477 }
478err_gclk0:
479 if (ssc != NULL) {
480 ssc_free(ssc);
481 ssc = NULL;
482 }
483err_ssc:
484 return ret;
485}
486
487
488static void __exit playpaq_asoc_exit(void)
489{
490 struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data;
491 struct ssc_device *ssc;
492
493 if (ssc_p != NULL) {
494 ssc = ssc_p->ssc;
495 if (ssc != NULL)
496 ssc_free(ssc);
497 ssc_p->ssc = NULL;
498 }
499
500 if (_gclk0 != NULL) {
501 clk_put(_gclk0);
502 _gclk0 = NULL;
503 }
504 if (_pll0 != NULL) {
505 clk_put(_pll0);
506 _pll0 = NULL;
507 }
508
509#if defined CONFIG_AT32_ENHANCED_PORTMUX
510 at32_free_pin(MCLK_PIN);
511#endif
512
513 platform_device_unregister(playpaq_snd_device);
514 playpaq_snd_device = NULL;
515}
516
517module_init(playpaq_asoc_init);
518module_exit(playpaq_asoc_exit);
519
520MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
521MODULE_DESCRIPTION("ASoC machine driver for LRS PlayPaq");
522MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig
index 5cb93fd3a407..905186502e00 100644
--- a/sound/soc/at91/Kconfig
+++ b/sound/soc/at91/Kconfig
@@ -1,6 +1,6 @@
1config SND_AT91_SOC 1config SND_AT91_SOC
2 tristate "SoC Audio for the Atmel AT91 System-on-Chip" 2 tristate "SoC Audio for the Atmel AT91 System-on-Chip"
3 depends on ARCH_AT91 && SND_SOC 3 depends on ARCH_AT91
4 help 4 help
5 Say Y or M if you want to add support for codecs attached to 5 Say Y or M if you want to add support for codecs attached to
6 the AT91 SSC interface. You will also need 6 the AT91 SSC interface. You will also need
diff --git a/sound/soc/at91/at91-pcm.c b/sound/soc/at91/at91-pcm.c
index ccac6bd2889c..d47492b2b6e5 100644
--- a/sound/soc/at91/at91-pcm.c
+++ b/sound/soc/at91/at91-pcm.c
@@ -318,7 +318,7 @@ static int at91_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
318static u64 at91_pcm_dmamask = 0xffffffff; 318static u64 at91_pcm_dmamask = 0xffffffff;
319 319
320static int at91_pcm_new(struct snd_card *card, 320static int at91_pcm_new(struct snd_card *card,
321 struct snd_soc_codec_dai *dai, struct snd_pcm *pcm) 321 struct snd_soc_dai *dai, struct snd_pcm *pcm)
322{ 322{
323 int ret = 0; 323 int ret = 0;
324 324
@@ -367,7 +367,7 @@ static void at91_pcm_free_dma_buffers(struct snd_pcm *pcm)
367 367
368#ifdef CONFIG_PM 368#ifdef CONFIG_PM
369static int at91_pcm_suspend(struct platform_device *pdev, 369static int at91_pcm_suspend(struct platform_device *pdev,
370 struct snd_soc_cpu_dai *dai) 370 struct snd_soc_dai *dai)
371{ 371{
372 struct snd_pcm_runtime *runtime = dai->runtime; 372 struct snd_pcm_runtime *runtime = dai->runtime;
373 struct at91_runtime_data *prtd; 373 struct at91_runtime_data *prtd;
@@ -392,7 +392,7 @@ static int at91_pcm_suspend(struct platform_device *pdev,
392} 392}
393 393
394static int at91_pcm_resume(struct platform_device *pdev, 394static int at91_pcm_resume(struct platform_device *pdev,
395 struct snd_soc_cpu_dai *dai) 395 struct snd_soc_dai *dai)
396{ 396{
397 struct snd_pcm_runtime *runtime = dai->runtime; 397 struct snd_pcm_runtime *runtime = dai->runtime;
398 struct at91_runtime_data *prtd; 398 struct at91_runtime_data *prtd;
diff --git a/sound/soc/at91/at91-ssc.c b/sound/soc/at91/at91-ssc.c
index bc35d00a38f8..c3625b665c5a 100644
--- a/sound/soc/at91/at91-ssc.c
+++ b/sound/soc/at91/at91-ssc.c
@@ -281,7 +281,7 @@ static void at91_ssc_shutdown(struct snd_pcm_substream *substream)
281/* 281/*
282 * Record the SSC system clock rate. 282 * Record the SSC system clock rate.
283 */ 283 */
284static int at91_ssc_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, 284static int at91_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
285 int clk_id, unsigned int freq, int dir) 285 int clk_id, unsigned int freq, int dir)
286{ 286{
287 /* 287 /*
@@ -303,7 +303,7 @@ static int at91_ssc_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
303/* 303/*
304 * Record the DAI format for use in hw_params(). 304 * Record the DAI format for use in hw_params().
305 */ 305 */
306static int at91_ssc_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai, 306static int at91_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
307 unsigned int fmt) 307 unsigned int fmt)
308{ 308{
309 struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; 309 struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
@@ -315,7 +315,7 @@ static int at91_ssc_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
315/* 315/*
316 * Record SSC clock dividers for use in hw_params(). 316 * Record SSC clock dividers for use in hw_params().
317 */ 317 */
318static int at91_ssc_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai, 318static int at91_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
319 int div_id, int div) 319 int div_id, int div)
320{ 320{
321 struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; 321 struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
@@ -634,7 +634,7 @@ static int at91_ssc_prepare(struct snd_pcm_substream *substream)
634 634
635#ifdef CONFIG_PM 635#ifdef CONFIG_PM
636static int at91_ssc_suspend(struct platform_device *pdev, 636static int at91_ssc_suspend(struct platform_device *pdev,
637 struct snd_soc_cpu_dai *cpu_dai) 637 struct snd_soc_dai *cpu_dai)
638{ 638{
639 struct at91_ssc_info *ssc_p; 639 struct at91_ssc_info *ssc_p;
640 640
@@ -662,7 +662,7 @@ static int at91_ssc_suspend(struct platform_device *pdev,
662} 662}
663 663
664static int at91_ssc_resume(struct platform_device *pdev, 664static int at91_ssc_resume(struct platform_device *pdev,
665 struct snd_soc_cpu_dai *cpu_dai) 665 struct snd_soc_dai *cpu_dai)
666{ 666{
667 struct at91_ssc_info *ssc_p; 667 struct at91_ssc_info *ssc_p;
668 668
@@ -700,7 +700,7 @@ static int at91_ssc_resume(struct platform_device *pdev,
700#define AT91_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ 700#define AT91_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
701 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 701 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
702 702
703struct snd_soc_cpu_dai at91_ssc_dai[NUM_SSC_DEVICES] = { 703struct snd_soc_dai at91_ssc_dai[NUM_SSC_DEVICES] = {
704 { .name = "at91-ssc0", 704 { .name = "at91-ssc0",
705 .id = 0, 705 .id = 0,
706 .type = SND_SOC_DAI_PCM, 706 .type = SND_SOC_DAI_PCM,
diff --git a/sound/soc/at91/at91-ssc.h b/sound/soc/at91/at91-ssc.h
index b188f973df9f..6b7bf382d06f 100644
--- a/sound/soc/at91/at91-ssc.h
+++ b/sound/soc/at91/at91-ssc.h
@@ -21,7 +21,7 @@
21#define AT91SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */ 21#define AT91SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
22#define AT91SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */ 22#define AT91SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
23 23
24extern struct snd_soc_cpu_dai at91_ssc_dai[]; 24extern struct snd_soc_dai at91_ssc_dai[];
25 25
26#endif /* _AT91_SSC_H */ 26#endif /* _AT91_SSC_H */
27 27
diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c
index 1347dcf3f80b..d532de954241 100644
--- a/sound/soc/at91/eti_b1_wm8731.c
+++ b/sound/soc/at91/eti_b1_wm8731.c
@@ -53,18 +53,18 @@ static struct clk *pllb_clk;
53static int eti_b1_startup(struct snd_pcm_substream *substream) 53static int eti_b1_startup(struct snd_pcm_substream *substream)
54{ 54{
55 struct snd_soc_pcm_runtime *rtd = substream->private_data; 55 struct snd_soc_pcm_runtime *rtd = substream->private_data;
56 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 56 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
57 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 57 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
58 int ret; 58 int ret;
59 59
60 /* cpu clock is the AT91 master clock sent to the SSC */ 60 /* cpu clock is the AT91 master clock sent to the SSC */
61 ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, AT91_SYSCLK_MCK, 61 ret = snd_soc_dai_set_sysclk(cpu_dai, AT91_SYSCLK_MCK,
62 60000000, SND_SOC_CLOCK_IN); 62 60000000, SND_SOC_CLOCK_IN);
63 if (ret < 0) 63 if (ret < 0)
64 return ret; 64 return ret;
65 65
66 /* codec system clock is supplied by PCK1, set to 12MHz */ 66 /* codec system clock is supplied by PCK1, set to 12MHz */
67 ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK, 67 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
68 12000000, SND_SOC_CLOCK_IN); 68 12000000, SND_SOC_CLOCK_IN);
69 if (ret < 0) 69 if (ret < 0)
70 return ret; 70 return ret;
@@ -87,8 +87,8 @@ static int eti_b1_hw_params(struct snd_pcm_substream *substream,
87 struct snd_pcm_hw_params *params) 87 struct snd_pcm_hw_params *params)
88{ 88{
89 struct snd_soc_pcm_runtime *rtd = substream->private_data; 89 struct snd_soc_pcm_runtime *rtd = substream->private_data;
90 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 90 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
91 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 91 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
92 int ret; 92 int ret;
93 93
94#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE 94#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
@@ -96,13 +96,13 @@ static int eti_b1_hw_params(struct snd_pcm_substream *substream,
96 int cmr_div, period; 96 int cmr_div, period;
97 97
98 /* set codec DAI configuration */ 98 /* set codec DAI configuration */
99 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 99 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
100 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 100 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
101 if (ret < 0) 101 if (ret < 0)
102 return ret; 102 return ret;
103 103
104 /* set cpu DAI configuration */ 104 /* set cpu DAI configuration */
105 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 105 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
106 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 106 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
107 if (ret < 0) 107 if (ret < 0)
108 return ret; 108 return ret;
@@ -141,17 +141,17 @@ static int eti_b1_hw_params(struct snd_pcm_substream *substream,
141 } 141 }
142 142
143 /* set the MCK divider for BCLK */ 143 /* set the MCK divider for BCLK */
144 ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div); 144 ret = snd_soc_dai_set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div);
145 if (ret < 0) 145 if (ret < 0)
146 return ret; 146 return ret;
147 147
148 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 148 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
149 /* set the BCLK divider for DACLRC */ 149 /* set the BCLK divider for DACLRC */
150 ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, 150 ret = snd_soc_dai_set_clkdiv(cpu_dai,
151 AT91SSC_TCMR_PERIOD, period); 151 AT91SSC_TCMR_PERIOD, period);
152 } else { 152 } else {
153 /* set the BCLK divider for ADCLRC */ 153 /* set the BCLK divider for ADCLRC */
154 ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, 154 ret = snd_soc_dai_set_clkdiv(cpu_dai,
155 AT91SSC_RCMR_PERIOD, period); 155 AT91SSC_RCMR_PERIOD, period);
156 } 156 }
157 if (ret < 0) 157 if (ret < 0)
@@ -163,13 +163,13 @@ static int eti_b1_hw_params(struct snd_pcm_substream *substream,
163 */ 163 */
164 164
165 /* set codec DAI configuration */ 165 /* set codec DAI configuration */
166 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 166 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
167 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 167 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
168 if (ret < 0) 168 if (ret < 0)
169 return ret; 169 return ret;
170 170
171 /* set cpu DAI configuration */ 171 /* set cpu DAI configuration */
172 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 172 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
173 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 173 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
174 if (ret < 0) 174 if (ret < 0)
175 return ret; 175 return ret;
@@ -191,7 +191,7 @@ static const struct snd_soc_dapm_widget eti_b1_dapm_widgets[] = {
191 SND_SOC_DAPM_SPK("Ext Spk", NULL), 191 SND_SOC_DAPM_SPK("Ext Spk", NULL),
192}; 192};
193 193
194static const char *intercon[][3] = { 194static const struct snd_soc_dapm_route intercon[] = {
195 195
196 /* speaker connected to LHPOUT */ 196 /* speaker connected to LHPOUT */
197 {"Ext Spk", NULL, "LHPOUT"}, 197 {"Ext Spk", NULL, "LHPOUT"},
@@ -199,9 +199,6 @@ static const char *intercon[][3] = {
199 /* mic is connected to Mic Jack, with WM8731 Mic Bias */ 199 /* mic is connected to Mic Jack, with WM8731 Mic Bias */
200 {"MICIN", NULL, "Mic Bias"}, 200 {"MICIN", NULL, "Mic Bias"},
201 {"Mic Bias", NULL, "Int Mic"}, 201 {"Mic Bias", NULL, "Int Mic"},
202
203 /* terminator */
204 {NULL, NULL, NULL},
205}; 202};
206 203
207/* 204/*
@@ -209,30 +206,24 @@ static const char *intercon[][3] = {
209 */ 206 */
210static int eti_b1_wm8731_init(struct snd_soc_codec *codec) 207static int eti_b1_wm8731_init(struct snd_soc_codec *codec)
211{ 208{
212 int i;
213
214 DBG("eti_b1_wm8731_init() called\n"); 209 DBG("eti_b1_wm8731_init() called\n");
215 210
216 /* Add specific widgets */ 211 /* Add specific widgets */
217 for(i = 0; i < ARRAY_SIZE(eti_b1_dapm_widgets); i++) { 212 snd_soc_dapm_new_controls(codec, eti_b1_dapm_widgets,
218 snd_soc_dapm_new_control(codec, &eti_b1_dapm_widgets[i]); 213 ARRAY_SIZE(eti_b1_dapm_widgets));
219 }
220 214
221 /* Set up specific audio path interconnects */ 215 /* Set up specific audio path interconnects */
222 for(i = 0; intercon[i][0] != NULL; i++) { 216 snd_soc_dapm_add_route(codec, intercon, ARRAY_SIZE(intercon));
223 snd_soc_dapm_connect_input(codec, intercon[i][0],
224 intercon[i][1], intercon[i][2]);
225 }
226 217
227 /* not connected */ 218 /* not connected */
228 snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0); 219 snd_soc_dapm_disable_pin(codec, "RLINEIN");
229 snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0); 220 snd_soc_dapm_disable_pin(codec, "LLINEIN");
230 221
231 /* always connected */ 222 /* always connected */
232 snd_soc_dapm_set_endpoint(codec, "Int Mic", 1); 223 snd_soc_dapm_enable_pin(codec, "Int Mic");
233 snd_soc_dapm_set_endpoint(codec, "Ext Spk", 1); 224 snd_soc_dapm_enable_pin(codec, "Ext Spk");
234 225
235 snd_soc_dapm_sync_endpoints(codec); 226 snd_soc_dapm_sync(codec);
236 227
237 return 0; 228 return 0;
238} 229}
diff --git a/sound/soc/au1x/Kconfig b/sound/soc/au1x/Kconfig
new file mode 100644
index 000000000000..410a893aa66b
--- /dev/null
+++ b/sound/soc/au1x/Kconfig
@@ -0,0 +1,32 @@
1##
2## Au1200/Au1550 PSC + DBDMA
3##
4config SND_SOC_AU1XPSC
5 tristate "SoC Audio for Au1200/Au1250/Au1550"
6 depends on SOC_AU1200 || SOC_AU1550
7 help
8 This option enables support for the Programmable Serial
9 Controllers in AC97 and I2S mode, and the Descriptor-Based DMA
10 Controller (DBDMA) as found on the Au1200/Au1250/Au1550 SoC.
11
12config SND_SOC_AU1XPSC_I2S
13 tristate
14
15config SND_SOC_AU1XPSC_AC97
16 tristate
17 select AC97_BUS
18 select SND_AC97_CODEC
19 select SND_SOC_AC97_BUS
20
21
22##
23## Boards
24##
25config SND_SOC_SAMPLE_PSC_AC97
26 tristate "Sample Au12x0/Au1550 PSC AC97 sound machine"
27 depends on SND_SOC_AU1XPSC
28 select SND_SOC_AU1XPSC_AC97
29 select SND_SOC_AC97_CODEC
30 help
31 This is a sample AC97 sound machine for use in Au12x0/Au1550
32 based systems which have audio on PSC1 (e.g. Db1200 demoboard).
diff --git a/sound/soc/au1x/Makefile b/sound/soc/au1x/Makefile
new file mode 100644
index 000000000000..6c6950b8003a
--- /dev/null
+++ b/sound/soc/au1x/Makefile
@@ -0,0 +1,13 @@
1# Au1200/Au1550 PSC audio
2snd-soc-au1xpsc-dbdma-objs := dbdma2.o
3snd-soc-au1xpsc-i2s-objs := psc-i2s.o
4snd-soc-au1xpsc-ac97-objs := psc-ac97.o
5
6obj-$(CONFIG_SND_SOC_AU1XPSC) += snd-soc-au1xpsc-dbdma.o
7obj-$(CONFIG_SND_SOC_AU1XPSC_I2S) += snd-soc-au1xpsc-i2s.o
8obj-$(CONFIG_SND_SOC_AU1XPSC_AC97) += snd-soc-au1xpsc-ac97.o
9
10# Boards
11snd-soc-sample-ac97-objs := sample-ac97.o
12
13obj-$(CONFIG_SND_SOC_SAMPLE_PSC_AC97) += snd-soc-sample-ac97.o
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
new file mode 100644
index 000000000000..1466d9328800
--- /dev/null
+++ b/sound/soc/au1x/dbdma2.c
@@ -0,0 +1,421 @@
1/*
2 * Au12x0/Au1550 PSC ALSA ASoC audio support.
3 *
4 * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
5 * Manuel Lauss <mano@roarinelk.homelinux.net>
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 * DMA glue for Au1x-PSC audio.
12 *
13 * NOTE: all of these drivers can only work with a SINGLE instance
14 * of a PSC. Multiple independent audio devices are impossible
15 * with ASoC v1.
16 */
17
18
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <linux/dma-mapping.h>
24
25#include <sound/core.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/soc.h>
29
30#include <asm/mach-au1x00/au1000.h>
31#include <asm/mach-au1x00/au1xxx_dbdma.h>
32#include <asm/mach-au1x00/au1xxx_psc.h>
33
34#include "psc.h"
35
36/*#define PCM_DEBUG*/
37
38#define MSG(x...) printk(KERN_INFO "au1xpsc_pcm: " x)
39#ifdef PCM_DEBUG
40#define DBG MSG
41#else
42#define DBG(x...) do {} while (0)
43#endif
44
45struct au1xpsc_audio_dmadata {
46 /* DDMA control data */
47 unsigned int ddma_id; /* DDMA direction ID for this PSC */
48 u32 ddma_chan; /* DDMA context */
49
50 /* PCM context (for irq handlers) */
51 struct snd_pcm_substream *substream;
52 unsigned long curr_period; /* current segment DDMA is working on */
53 unsigned long q_period; /* queue period(s) */
54 unsigned long dma_area; /* address of queued DMA area */
55 unsigned long dma_area_s; /* start address of DMA area */
56 unsigned long pos; /* current byte position being played */
57 unsigned long periods; /* number of SG segments in total */
58 unsigned long period_bytes; /* size in bytes of one SG segment */
59
60 /* runtime data */
61 int msbits;
62};
63
64/* instance data. There can be only one, MacLeod!!!! */
65static struct au1xpsc_audio_dmadata *au1xpsc_audio_pcmdma[2];
66
67/*
68 * These settings are somewhat okay, at least on my machine audio plays
69 * almost skip-free. Especially the 64kB buffer seems to help a LOT.
70 */
71#define AU1XPSC_PERIOD_MIN_BYTES 1024
72#define AU1XPSC_BUFFER_MIN_BYTES 65536
73
74#define AU1XPSC_PCM_FMTS \
75 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \
76 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
77 SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE | \
78 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | \
79 SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE | \
80 0)
81
82/* PCM hardware DMA capabilities - platform specific */
83static const struct snd_pcm_hardware au1xpsc_pcm_hardware = {
84 .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
85 SNDRV_PCM_INFO_INTERLEAVED,
86 .formats = AU1XPSC_PCM_FMTS,
87 .period_bytes_min = AU1XPSC_PERIOD_MIN_BYTES,
88 .period_bytes_max = 4096 * 1024 - 1,
89 .periods_min = 2,
90 .periods_max = 4096, /* 2 to as-much-as-you-like */
91 .buffer_bytes_max = 4096 * 1024 - 1,
92 .fifo_size = 16, /* fifo entries of AC97/I2S PSC */
93};
94
95static void au1x_pcm_queue_tx(struct au1xpsc_audio_dmadata *cd)
96{
97 au1xxx_dbdma_put_source_flags(cd->ddma_chan,
98 (void *)phys_to_virt(cd->dma_area),
99 cd->period_bytes, DDMA_FLAGS_IE);
100
101 /* update next-to-queue period */
102 ++cd->q_period;
103 cd->dma_area += cd->period_bytes;
104 if (cd->q_period >= cd->periods) {
105 cd->q_period = 0;
106 cd->dma_area = cd->dma_area_s;
107 }
108}
109
110static void au1x_pcm_queue_rx(struct au1xpsc_audio_dmadata *cd)
111{
112 au1xxx_dbdma_put_dest_flags(cd->ddma_chan,
113 (void *)phys_to_virt(cd->dma_area),
114 cd->period_bytes, DDMA_FLAGS_IE);
115
116 /* update next-to-queue period */
117 ++cd->q_period;
118 cd->dma_area += cd->period_bytes;
119 if (cd->q_period >= cd->periods) {
120 cd->q_period = 0;
121 cd->dma_area = cd->dma_area_s;
122 }
123}
124
125static void au1x_pcm_dmatx_cb(int irq, void *dev_id)
126{
127 struct au1xpsc_audio_dmadata *cd = dev_id;
128
129 cd->pos += cd->period_bytes;
130 if (++cd->curr_period >= cd->periods) {
131 cd->pos = 0;
132 cd->curr_period = 0;
133 }
134 snd_pcm_period_elapsed(cd->substream);
135 au1x_pcm_queue_tx(cd);
136}
137
138static void au1x_pcm_dmarx_cb(int irq, void *dev_id)
139{
140 struct au1xpsc_audio_dmadata *cd = dev_id;
141
142 cd->pos += cd->period_bytes;
143 if (++cd->curr_period >= cd->periods) {
144 cd->pos = 0;
145 cd->curr_period = 0;
146 }
147 snd_pcm_period_elapsed(cd->substream);
148 au1x_pcm_queue_rx(cd);
149}
150
151static void au1x_pcm_dbdma_free(struct au1xpsc_audio_dmadata *pcd)
152{
153 if (pcd->ddma_chan) {
154 au1xxx_dbdma_stop(pcd->ddma_chan);
155 au1xxx_dbdma_reset(pcd->ddma_chan);
156 au1xxx_dbdma_chan_free(pcd->ddma_chan);
157 pcd->ddma_chan = 0;
158 pcd->msbits = 0;
159 }
160}
161
162/* in case of missing DMA ring or changed TX-source / RX-dest bit widths,
163 * allocate (or reallocate) a 2-descriptor DMA ring with bit depth according
164 * to ALSA-supplied sample depth. This is due to limitations in the dbdma api
165 * (cannot adjust source/dest widths of already allocated descriptor ring).
166 */
167static int au1x_pcm_dbdma_realloc(struct au1xpsc_audio_dmadata *pcd,
168 int stype, int msbits)
169{
170 /* DMA only in 8/16/32 bit widths */
171 if (msbits == 24)
172 msbits = 32;
173
174 /* check current config: correct bits and descriptors allocated? */
175 if ((pcd->ddma_chan) && (msbits == pcd->msbits))
176 goto out; /* all ok! */
177
178 au1x_pcm_dbdma_free(pcd);
179
180 if (stype == PCM_RX)
181 pcd->ddma_chan = au1xxx_dbdma_chan_alloc(pcd->ddma_id,
182 DSCR_CMD0_ALWAYS,
183 au1x_pcm_dmarx_cb, (void *)pcd);
184 else
185 pcd->ddma_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS,
186 pcd->ddma_id,
187 au1x_pcm_dmatx_cb, (void *)pcd);
188
189 if (!pcd->ddma_chan)
190 return -ENOMEM;;
191
192 au1xxx_dbdma_set_devwidth(pcd->ddma_chan, msbits);
193 au1xxx_dbdma_ring_alloc(pcd->ddma_chan, 2);
194
195 pcd->msbits = msbits;
196
197 au1xxx_dbdma_stop(pcd->ddma_chan);
198 au1xxx_dbdma_reset(pcd->ddma_chan);
199
200out:
201 return 0;
202}
203
204static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
205 struct snd_pcm_hw_params *params)
206{
207 struct snd_pcm_runtime *runtime = substream->runtime;
208 struct au1xpsc_audio_dmadata *pcd;
209 int stype, ret;
210
211 ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
212 if (ret < 0)
213 goto out;
214
215 stype = SUBSTREAM_TYPE(substream);
216 pcd = au1xpsc_audio_pcmdma[stype];
217
218 DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d "
219 "runtime->min_align %d\n",
220 (unsigned long)runtime->dma_area,
221 (unsigned long)runtime->dma_addr, runtime->dma_bytes,
222 runtime->min_align);
223
224 DBG("bits %d frags %d frag_bytes %d is_rx %d\n", params->msbits,
225 params_periods(params), params_period_bytes(params), stype);
226
227 ret = au1x_pcm_dbdma_realloc(pcd, stype, params->msbits);
228 if (ret) {
229 MSG("DDMA channel (re)alloc failed!\n");
230 goto out;
231 }
232
233 pcd->substream = substream;
234 pcd->period_bytes = params_period_bytes(params);
235 pcd->periods = params_periods(params);
236 pcd->dma_area_s = pcd->dma_area = (unsigned long)runtime->dma_addr;
237 pcd->q_period = 0;
238 pcd->curr_period = 0;
239 pcd->pos = 0;
240
241 ret = 0;
242out:
243 return ret;
244}
245
246static int au1xpsc_pcm_hw_free(struct snd_pcm_substream *substream)
247{
248 snd_pcm_lib_free_pages(substream);
249 return 0;
250}
251
252static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream)
253{
254 struct au1xpsc_audio_dmadata *pcd =
255 au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)];
256
257 au1xxx_dbdma_reset(pcd->ddma_chan);
258
259 if (SUBSTREAM_TYPE(substream) == PCM_RX) {
260 au1x_pcm_queue_rx(pcd);
261 au1x_pcm_queue_rx(pcd);
262 } else {
263 au1x_pcm_queue_tx(pcd);
264 au1x_pcm_queue_tx(pcd);
265 }
266
267 return 0;
268}
269
270static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
271{
272 u32 c = au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->ddma_chan;
273
274 switch (cmd) {
275 case SNDRV_PCM_TRIGGER_START:
276 case SNDRV_PCM_TRIGGER_RESUME:
277 au1xxx_dbdma_start(c);
278 break;
279 case SNDRV_PCM_TRIGGER_STOP:
280 case SNDRV_PCM_TRIGGER_SUSPEND:
281 au1xxx_dbdma_stop(c);
282 break;
283 default:
284 return -EINVAL;
285 }
286 return 0;
287}
288
289static snd_pcm_uframes_t
290au1xpsc_pcm_pointer(struct snd_pcm_substream *substream)
291{
292 return bytes_to_frames(substream->runtime,
293 au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->pos);
294}
295
296static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
297{
298 snd_soc_set_runtime_hwparams(substream, &au1xpsc_pcm_hardware);
299 return 0;
300}
301
302static int au1xpsc_pcm_close(struct snd_pcm_substream *substream)
303{
304 au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]);
305 return 0;
306}
307
308struct snd_pcm_ops au1xpsc_pcm_ops = {
309 .open = au1xpsc_pcm_open,
310 .close = au1xpsc_pcm_close,
311 .ioctl = snd_pcm_lib_ioctl,
312 .hw_params = au1xpsc_pcm_hw_params,
313 .hw_free = au1xpsc_pcm_hw_free,
314 .prepare = au1xpsc_pcm_prepare,
315 .trigger = au1xpsc_pcm_trigger,
316 .pointer = au1xpsc_pcm_pointer,
317};
318
319static void au1xpsc_pcm_free_dma_buffers(struct snd_pcm *pcm)
320{
321 snd_pcm_lib_preallocate_free_for_all(pcm);
322}
323
324static int au1xpsc_pcm_new(struct snd_card *card,
325 struct snd_soc_dai *dai,
326 struct snd_pcm *pcm)
327{
328 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
329 card->dev, AU1XPSC_BUFFER_MIN_BYTES, (4096 * 1024) - 1);
330
331 return 0;
332}
333
334static int au1xpsc_pcm_probe(struct platform_device *pdev)
335{
336 struct resource *r;
337 int ret;
338
339 if (au1xpsc_audio_pcmdma[PCM_TX] || au1xpsc_audio_pcmdma[PCM_RX])
340 return -EBUSY;
341
342 /* TX DMA */
343 au1xpsc_audio_pcmdma[PCM_TX]
344 = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
345 if (!au1xpsc_audio_pcmdma[PCM_TX])
346 return -ENOMEM;
347
348 r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
349 if (!r) {
350 ret = -ENODEV;
351 goto out1;
352 }
353 (au1xpsc_audio_pcmdma[PCM_TX])->ddma_id = r->start;
354
355 /* RX DMA */
356 au1xpsc_audio_pcmdma[PCM_RX]
357 = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
358 if (!au1xpsc_audio_pcmdma[PCM_RX])
359 return -ENOMEM;
360
361 r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
362 if (!r) {
363 ret = -ENODEV;
364 goto out2;
365 }
366 (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start;
367
368 return 0;
369
370out2:
371 kfree(au1xpsc_audio_pcmdma[PCM_RX]);
372 au1xpsc_audio_pcmdma[PCM_RX] = NULL;
373out1:
374 kfree(au1xpsc_audio_pcmdma[PCM_TX]);
375 au1xpsc_audio_pcmdma[PCM_TX] = NULL;
376 return ret;
377}
378
379static int au1xpsc_pcm_remove(struct platform_device *pdev)
380{
381 int i;
382
383 for (i = 0; i < 2; i++) {
384 if (au1xpsc_audio_pcmdma[i]) {
385 au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]);
386 kfree(au1xpsc_audio_pcmdma[i]);
387 au1xpsc_audio_pcmdma[i] = NULL;
388 }
389 }
390
391 return 0;
392}
393
394/* au1xpsc audio platform */
395struct snd_soc_platform au1xpsc_soc_platform = {
396 .name = "au1xpsc-pcm-dbdma",
397 .probe = au1xpsc_pcm_probe,
398 .remove = au1xpsc_pcm_remove,
399 .pcm_ops = &au1xpsc_pcm_ops,
400 .pcm_new = au1xpsc_pcm_new,
401 .pcm_free = au1xpsc_pcm_free_dma_buffers,
402};
403EXPORT_SYMBOL_GPL(au1xpsc_soc_platform);
404
405static int __init au1xpsc_audio_dbdma_init(void)
406{
407 au1xpsc_audio_pcmdma[PCM_TX] = NULL;
408 au1xpsc_audio_pcmdma[PCM_RX] = NULL;
409 return 0;
410}
411
412static void __exit au1xpsc_audio_dbdma_exit(void)
413{
414}
415
416module_init(au1xpsc_audio_dbdma_init);
417module_exit(au1xpsc_audio_dbdma_exit);
418
419MODULE_LICENSE("GPL");
420MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver");
421MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
new file mode 100644
index 000000000000..57facbad6825
--- /dev/null
+++ b/sound/soc/au1x/psc-ac97.c
@@ -0,0 +1,387 @@
1/*
2 * Au12x0/Au1550 PSC ALSA ASoC audio support.
3 *
4 * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
5 * Manuel Lauss <mano@roarinelk.homelinux.net>
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 * Au1xxx-PSC AC97 glue.
12 *
13 * NOTE: all of these drivers can only work with a SINGLE instance
14 * of a PSC. Multiple independent audio devices are impossible
15 * with ASoC v1.
16 */
17
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/device.h>
21#include <linux/delay.h>
22#include <linux/suspend.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/initval.h>
26#include <sound/soc.h>
27#include <asm/mach-au1x00/au1000.h>
28#include <asm/mach-au1x00/au1xxx_psc.h>
29
30#include "psc.h"
31
32#define AC97_DIR \
33 (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
34
35#define AC97_RATES \
36 SNDRV_PCM_RATE_8000_48000
37
38#define AC97_FMTS \
39 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3BE)
40
41#define AC97PCR_START(stype) \
42 ((stype) == PCM_TX ? PSC_AC97PCR_TS : PSC_AC97PCR_RS)
43#define AC97PCR_STOP(stype) \
44 ((stype) == PCM_TX ? PSC_AC97PCR_TP : PSC_AC97PCR_RP)
45#define AC97PCR_CLRFIFO(stype) \
46 ((stype) == PCM_TX ? PSC_AC97PCR_TC : PSC_AC97PCR_RC)
47
48/* instance data. There can be only one, MacLeod!!!! */
49static struct au1xpsc_audio_data *au1xpsc_ac97_workdata;
50
51/* AC97 controller reads codec register */
52static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
53 unsigned short reg)
54{
55 /* FIXME */
56 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
57 unsigned short data, tmo;
58
59 au_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg), AC97_CDC(pscdata));
60 au_sync();
61
62 tmo = 1000;
63 while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) && --tmo)
64 udelay(2);
65
66 if (!tmo)
67 data = 0xffff;
68 else
69 data = au_readl(AC97_CDC(pscdata)) & 0xffff;
70
71 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
72 au_sync();
73
74 return data;
75}
76
77/* AC97 controller writes to codec register */
78static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
79 unsigned short val)
80{
81 /* FIXME */
82 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
83 unsigned int tmo;
84
85 au_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff), AC97_CDC(pscdata));
86 au_sync();
87 tmo = 1000;
88 while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) && --tmo)
89 au_sync();
90
91 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
92 au_sync();
93}
94
95/* AC97 controller asserts a warm reset */
96static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97)
97{
98 /* FIXME */
99 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
100
101 au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata));
102 au_sync();
103 msleep(10);
104 au_writel(0, AC97_RST(pscdata));
105 au_sync();
106}
107
108static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
109{
110 /* FIXME */
111 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
112 int i;
113
114 /* disable PSC during cold reset */
115 au_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
116 au_sync();
117 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(pscdata));
118 au_sync();
119
120 /* issue cold reset */
121 au_writel(PSC_AC97RST_RST, AC97_RST(pscdata));
122 au_sync();
123 msleep(500);
124 au_writel(0, AC97_RST(pscdata));
125 au_sync();
126
127 /* enable PSC */
128 au_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
129 au_sync();
130
131 /* wait for PSC to indicate it's ready */
132 i = 100000;
133 while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i))
134 au_sync();
135
136 if (i == 0) {
137 printk(KERN_ERR "au1xpsc-ac97: PSC not ready!\n");
138 return;
139 }
140
141 /* enable the ac97 function */
142 au_writel(pscdata->cfg | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
143 au_sync();
144
145 /* wait for AC97 core to become ready */
146 i = 100000;
147 while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i))
148 au_sync();
149 if (i == 0)
150 printk(KERN_ERR "au1xpsc-ac97: AC97 ctrl not ready\n");
151}
152
153/* AC97 controller operations */
154struct snd_ac97_bus_ops soc_ac97_ops = {
155 .read = au1xpsc_ac97_read,
156 .write = au1xpsc_ac97_write,
157 .reset = au1xpsc_ac97_cold_reset,
158 .warm_reset = au1xpsc_ac97_warm_reset,
159};
160EXPORT_SYMBOL_GPL(soc_ac97_ops);
161
162static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
163 struct snd_pcm_hw_params *params)
164{
165 /* FIXME */
166 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
167 unsigned long r, stat;
168 int chans, stype = SUBSTREAM_TYPE(substream);
169
170 chans = params_channels(params);
171
172 r = au_readl(AC97_CFG(pscdata));
173 stat = au_readl(AC97_STAT(pscdata));
174
175 /* already active? */
176 if (stat & (PSC_AC97STAT_TB | PSC_AC97STAT_RB)) {
177 /* reject parameters not currently set up */
178 if ((PSC_AC97CFG_GET_LEN(r) != params->msbits) ||
179 (pscdata->rate != params_rate(params)))
180 return -EINVAL;
181 } else {
182 /* disable AC97 device controller first */
183 au_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
184 au_sync();
185
186 /* set sample bitdepth: REG[24:21]=(BITS-2)/2 */
187 r &= ~PSC_AC97CFG_LEN_MASK;
188 r |= PSC_AC97CFG_SET_LEN(params->msbits);
189
190 /* channels: enable slots for front L/R channel */
191 if (stype == PCM_TX) {
192 r &= ~PSC_AC97CFG_TXSLOT_MASK;
193 r |= PSC_AC97CFG_TXSLOT_ENA(3);
194 r |= PSC_AC97CFG_TXSLOT_ENA(4);
195 } else {
196 r &= ~PSC_AC97CFG_RXSLOT_MASK;
197 r |= PSC_AC97CFG_RXSLOT_ENA(3);
198 r |= PSC_AC97CFG_RXSLOT_ENA(4);
199 }
200
201 /* finally enable the AC97 controller again */
202 au_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
203 au_sync();
204
205 pscdata->cfg = r;
206 pscdata->rate = params_rate(params);
207 }
208
209 return 0;
210}
211
212static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
213 int cmd)
214{
215 /* FIXME */
216 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
217 int ret, stype = SUBSTREAM_TYPE(substream);
218
219 ret = 0;
220
221 switch (cmd) {
222 case SNDRV_PCM_TRIGGER_START:
223 case SNDRV_PCM_TRIGGER_RESUME:
224 au_writel(AC97PCR_START(stype), AC97_PCR(pscdata));
225 au_sync();
226 break;
227 case SNDRV_PCM_TRIGGER_STOP:
228 case SNDRV_PCM_TRIGGER_SUSPEND:
229 au_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata));
230 au_sync();
231 break;
232 default:
233 ret = -EINVAL;
234 }
235 return ret;
236}
237
238static int au1xpsc_ac97_probe(struct platform_device *pdev,
239 struct snd_soc_dai *dai)
240{
241 int ret;
242 struct resource *r;
243 unsigned long sel;
244
245 if (au1xpsc_ac97_workdata)
246 return -EBUSY;
247
248 au1xpsc_ac97_workdata =
249 kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
250 if (!au1xpsc_ac97_workdata)
251 return -ENOMEM;
252
253 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
254 if (!r) {
255 ret = -ENODEV;
256 goto out0;
257 }
258
259 ret = -EBUSY;
260 au1xpsc_ac97_workdata->ioarea =
261 request_mem_region(r->start, r->end - r->start + 1,
262 "au1xpsc_ac97");
263 if (!au1xpsc_ac97_workdata->ioarea)
264 goto out0;
265
266 au1xpsc_ac97_workdata->mmio = ioremap(r->start, 0xffff);
267 if (!au1xpsc_ac97_workdata->mmio)
268 goto out1;
269
270 /* configuration: max dma trigger threshold, enable ac97 */
271 au1xpsc_ac97_workdata->cfg = PSC_AC97CFG_RT_FIFO8 |
272 PSC_AC97CFG_TT_FIFO8 |
273 PSC_AC97CFG_DE_ENABLE;
274
275 /* preserve PSC clock source set up by platform (dev.platform_data
276 * is already occupied by soc layer)
277 */
278 sel = au_readl(PSC_SEL(au1xpsc_ac97_workdata)) & PSC_SEL_CLK_MASK;
279 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata));
280 au_sync();
281 au_writel(0, PSC_SEL(au1xpsc_ac97_workdata));
282 au_sync();
283 au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(au1xpsc_ac97_workdata));
284 au_sync();
285 /* next up: cold reset. Dont check for PSC-ready now since
286 * there may not be any codec clock yet.
287 */
288
289 return 0;
290
291out1:
292 release_resource(au1xpsc_ac97_workdata->ioarea);
293 kfree(au1xpsc_ac97_workdata->ioarea);
294out0:
295 kfree(au1xpsc_ac97_workdata);
296 au1xpsc_ac97_workdata = NULL;
297 return ret;
298}
299
300static void au1xpsc_ac97_remove(struct platform_device *pdev,
301 struct snd_soc_dai *dai)
302{
303 /* disable PSC completely */
304 au_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
305 au_sync();
306 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata));
307 au_sync();
308
309 iounmap(au1xpsc_ac97_workdata->mmio);
310 release_resource(au1xpsc_ac97_workdata->ioarea);
311 kfree(au1xpsc_ac97_workdata->ioarea);
312 kfree(au1xpsc_ac97_workdata);
313 au1xpsc_ac97_workdata = NULL;
314}
315
316static int au1xpsc_ac97_suspend(struct platform_device *pdev,
317 struct snd_soc_dai *dai)
318{
319 /* save interesting registers and disable PSC */
320 au1xpsc_ac97_workdata->pm[0] =
321 au_readl(PSC_SEL(au1xpsc_ac97_workdata));
322
323 au_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
324 au_sync();
325 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata));
326 au_sync();
327
328 return 0;
329}
330
331static int au1xpsc_ac97_resume(struct platform_device *pdev,
332 struct snd_soc_dai *dai)
333{
334 /* restore PSC clock config */
335 au_writel(au1xpsc_ac97_workdata->pm[0] | PSC_SEL_PS_AC97MODE,
336 PSC_SEL(au1xpsc_ac97_workdata));
337 au_sync();
338
339 /* after this point the ac97 core will cold-reset the codec.
340 * During cold-reset the PSC is reinitialized and the last
341 * configuration set up in hw_params() is restored.
342 */
343 return 0;
344}
345
346struct snd_soc_dai au1xpsc_ac97_dai = {
347 .name = "au1xpsc_ac97",
348 .type = SND_SOC_DAI_AC97,
349 .probe = au1xpsc_ac97_probe,
350 .remove = au1xpsc_ac97_remove,
351 .suspend = au1xpsc_ac97_suspend,
352 .resume = au1xpsc_ac97_resume,
353 .playback = {
354 .rates = AC97_RATES,
355 .formats = AC97_FMTS,
356 .channels_min = 2,
357 .channels_max = 2,
358 },
359 .capture = {
360 .rates = AC97_RATES,
361 .formats = AC97_FMTS,
362 .channels_min = 2,
363 .channels_max = 2,
364 },
365 .ops = {
366 .trigger = au1xpsc_ac97_trigger,
367 .hw_params = au1xpsc_ac97_hw_params,
368 },
369};
370EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
371
372static int __init au1xpsc_ac97_init(void)
373{
374 au1xpsc_ac97_workdata = NULL;
375 return 0;
376}
377
378static void __exit au1xpsc_ac97_exit(void)
379{
380}
381
382module_init(au1xpsc_ac97_init);
383module_exit(au1xpsc_ac97_exit);
384
385MODULE_LICENSE("GPL");
386MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver");
387MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
new file mode 100644
index 000000000000..ba4b5c199f21
--- /dev/null
+++ b/sound/soc/au1x/psc-i2s.c
@@ -0,0 +1,414 @@
1/*
2 * Au12x0/Au1550 PSC ALSA ASoC audio support.
3 *
4 * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
5 * Manuel Lauss <mano@roarinelk.homelinux.net>
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 * Au1xxx-PSC I2S glue.
12 *
13 * NOTE: all of these drivers can only work with a SINGLE instance
14 * of a PSC. Multiple independent audio devices are impossible
15 * with ASoC v1.
16 * NOTE: so far only PSC slave mode (bit- and frameclock) is supported.
17 */
18
19#include <linux/init.h>
20#include <linux/module.h>
21#include <linux/suspend.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/initval.h>
25#include <sound/soc.h>
26#include <asm/mach-au1x00/au1000.h>
27#include <asm/mach-au1x00/au1xxx_psc.h>
28
29#include "psc.h"
30
31/* supported I2S DAI hardware formats */
32#define AU1XPSC_I2S_DAIFMT \
33 (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | \
34 SND_SOC_DAIFMT_NB_NF)
35
36/* supported I2S direction */
37#define AU1XPSC_I2S_DIR \
38 (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
39
40#define AU1XPSC_I2S_RATES \
41 SNDRV_PCM_RATE_8000_192000
42
43#define AU1XPSC_I2S_FMTS \
44 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
45
46#define I2SSTAT_BUSY(stype) \
47 ((stype) == PCM_TX ? PSC_I2SSTAT_TB : PSC_I2SSTAT_RB)
48#define I2SPCR_START(stype) \
49 ((stype) == PCM_TX ? PSC_I2SPCR_TS : PSC_I2SPCR_RS)
50#define I2SPCR_STOP(stype) \
51 ((stype) == PCM_TX ? PSC_I2SPCR_TP : PSC_I2SPCR_RP)
52#define I2SPCR_CLRFIFO(stype) \
53 ((stype) == PCM_TX ? PSC_I2SPCR_TC : PSC_I2SPCR_RC)
54
55
56/* instance data. There can be only one, MacLeod!!!! */
57static struct au1xpsc_audio_data *au1xpsc_i2s_workdata;
58
59static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
60 unsigned int fmt)
61{
62 struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
63 unsigned long ct;
64 int ret;
65
66 ret = -EINVAL;
67
68 ct = pscdata->cfg;
69
70 ct &= ~(PSC_I2SCFG_XM | PSC_I2SCFG_MLJ); /* left-justified */
71 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
72 case SND_SOC_DAIFMT_I2S:
73 ct |= PSC_I2SCFG_XM; /* enable I2S mode */
74 break;
75 case SND_SOC_DAIFMT_MSB:
76 break;
77 case SND_SOC_DAIFMT_LSB:
78 ct |= PSC_I2SCFG_MLJ; /* LSB (right-) justified */
79 break;
80 default:
81 goto out;
82 }
83
84 ct &= ~(PSC_I2SCFG_BI | PSC_I2SCFG_WI); /* IB-IF */
85 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
86 case SND_SOC_DAIFMT_NB_NF:
87 ct |= PSC_I2SCFG_BI | PSC_I2SCFG_WI;
88 break;
89 case SND_SOC_DAIFMT_NB_IF:
90 ct |= PSC_I2SCFG_BI;
91 break;
92 case SND_SOC_DAIFMT_IB_NF:
93 ct |= PSC_I2SCFG_WI;
94 break;
95 case SND_SOC_DAIFMT_IB_IF:
96 break;
97 default:
98 goto out;
99 }
100
101 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
102 case SND_SOC_DAIFMT_CBM_CFM: /* CODEC master */
103 ct |= PSC_I2SCFG_MS; /* PSC I2S slave mode */
104 break;
105 case SND_SOC_DAIFMT_CBS_CFS: /* CODEC slave */
106 ct &= ~PSC_I2SCFG_MS; /* PSC I2S Master mode */
107 break;
108 default:
109 goto out;
110 }
111
112 pscdata->cfg = ct;
113 ret = 0;
114out:
115 return ret;
116}
117
118static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream,
119 struct snd_pcm_hw_params *params)
120{
121 struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
122
123 int cfgbits;
124 unsigned long stat;
125
126 /* check if the PSC is already streaming data */
127 stat = au_readl(I2S_STAT(pscdata));
128 if (stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB)) {
129 /* reject parameters not currently set up in hardware */
130 cfgbits = au_readl(I2S_CFG(pscdata));
131 if ((PSC_I2SCFG_GET_LEN(cfgbits) != params->msbits) ||
132 (params_rate(params) != pscdata->rate))
133 return -EINVAL;
134 } else {
135 /* set sample bitdepth */
136 pscdata->cfg &= ~(0x1f << 4);
137 pscdata->cfg |= PSC_I2SCFG_SET_LEN(params->msbits);
138 /* remember current rate for other stream */
139 pscdata->rate = params_rate(params);
140 }
141 return 0;
142}
143
144/* Configure PSC late: on my devel systems the codec is I2S master and
145 * supplies the i2sbitclock __AND__ i2sMclk (!) to the PSC unit. ASoC
146 * uses aggressive PM and switches the codec off when it is not in use
147 * which also means the PSC unit doesn't get any clocks and is therefore
148 * dead. That's why this chunk here gets called from the trigger callback
149 * because I can be reasonably certain the codec is driving the clocks.
150 */
151static int au1xpsc_i2s_configure(struct au1xpsc_audio_data *pscdata)
152{
153 unsigned long tmo;
154
155 /* bring PSC out of sleep, and configure I2S unit */
156 au_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
157 au_sync();
158
159 tmo = 1000000;
160 while (!(au_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_SR) && tmo)
161 tmo--;
162
163 if (!tmo)
164 goto psc_err;
165
166 au_writel(0, I2S_CFG(pscdata));
167 au_sync();
168 au_writel(pscdata->cfg | PSC_I2SCFG_DE_ENABLE, I2S_CFG(pscdata));
169 au_sync();
170
171 /* wait for I2S controller to become ready */
172 tmo = 1000000;
173 while (!(au_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_DR) && tmo)
174 tmo--;
175
176 if (tmo)
177 return 0;
178
179psc_err:
180 au_writel(0, I2S_CFG(pscdata));
181 au_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
182 au_sync();
183 return -ETIMEDOUT;
184}
185
186static int au1xpsc_i2s_start(struct au1xpsc_audio_data *pscdata, int stype)
187{
188 unsigned long tmo, stat;
189 int ret;
190
191 ret = 0;
192
193 /* if both TX and RX are idle, configure the PSC */
194 stat = au_readl(I2S_STAT(pscdata));
195 if (!(stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB))) {
196 ret = au1xpsc_i2s_configure(pscdata);
197 if (ret)
198 goto out;
199 }
200
201 au_writel(I2SPCR_CLRFIFO(stype), I2S_PCR(pscdata));
202 au_sync();
203 au_writel(I2SPCR_START(stype), I2S_PCR(pscdata));
204 au_sync();
205
206 /* wait for start confirmation */
207 tmo = 1000000;
208 while (!(au_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
209 tmo--;
210
211 if (!tmo) {
212 au_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
213 au_sync();
214 ret = -ETIMEDOUT;
215 }
216out:
217 return ret;
218}
219
220static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype)
221{
222 unsigned long tmo, stat;
223
224 au_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
225 au_sync();
226
227 /* wait for stop confirmation */
228 tmo = 1000000;
229 while ((au_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
230 tmo--;
231
232 /* if both TX and RX are idle, disable PSC */
233 stat = au_readl(I2S_STAT(pscdata));
234 if (!(stat & (PSC_I2SSTAT_RB | PSC_I2SSTAT_RB))) {
235 au_writel(0, I2S_CFG(pscdata));
236 au_sync();
237 au_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
238 au_sync();
239 }
240 return 0;
241}
242
243static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
244{
245 struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
246 int ret, stype = SUBSTREAM_TYPE(substream);
247
248 switch (cmd) {
249 case SNDRV_PCM_TRIGGER_START:
250 case SNDRV_PCM_TRIGGER_RESUME:
251 ret = au1xpsc_i2s_start(pscdata, stype);
252 break;
253 case SNDRV_PCM_TRIGGER_STOP:
254 case SNDRV_PCM_TRIGGER_SUSPEND:
255 ret = au1xpsc_i2s_stop(pscdata, stype);
256 break;
257 default:
258 ret = -EINVAL;
259 }
260 return ret;
261}
262
263static int au1xpsc_i2s_probe(struct platform_device *pdev,
264 struct snd_soc_dai *dai)
265{
266 struct resource *r;
267 unsigned long sel;
268 int ret;
269
270 if (au1xpsc_i2s_workdata)
271 return -EBUSY;
272
273 au1xpsc_i2s_workdata =
274 kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
275 if (!au1xpsc_i2s_workdata)
276 return -ENOMEM;
277
278 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
279 if (!r) {
280 ret = -ENODEV;
281 goto out0;
282 }
283
284 ret = -EBUSY;
285 au1xpsc_i2s_workdata->ioarea =
286 request_mem_region(r->start, r->end - r->start + 1,
287 "au1xpsc_i2s");
288 if (!au1xpsc_i2s_workdata->ioarea)
289 goto out0;
290
291 au1xpsc_i2s_workdata->mmio = ioremap(r->start, 0xffff);
292 if (!au1xpsc_i2s_workdata->mmio)
293 goto out1;
294
295 /* preserve PSC clock source set up by platform (dev.platform_data
296 * is already occupied by soc layer)
297 */
298 sel = au_readl(PSC_SEL(au1xpsc_i2s_workdata)) & PSC_SEL_CLK_MASK;
299 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata));
300 au_sync();
301 au_writel(PSC_SEL_PS_I2SMODE | sel, PSC_SEL(au1xpsc_i2s_workdata));
302 au_writel(0, I2S_CFG(au1xpsc_i2s_workdata));
303 au_sync();
304
305 /* preconfigure: set max rx/tx fifo depths */
306 au1xpsc_i2s_workdata->cfg |=
307 PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8;
308
309 /* don't wait for I2S core to become ready now; clocks may not
310 * be running yet; depending on clock input for PSC a wait might
311 * time out.
312 */
313
314 return 0;
315
316out1:
317 release_resource(au1xpsc_i2s_workdata->ioarea);
318 kfree(au1xpsc_i2s_workdata->ioarea);
319out0:
320 kfree(au1xpsc_i2s_workdata);
321 au1xpsc_i2s_workdata = NULL;
322 return ret;
323}
324
325static void au1xpsc_i2s_remove(struct platform_device *pdev,
326 struct snd_soc_dai *dai)
327{
328 au_writel(0, I2S_CFG(au1xpsc_i2s_workdata));
329 au_sync();
330 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata));
331 au_sync();
332
333 iounmap(au1xpsc_i2s_workdata->mmio);
334 release_resource(au1xpsc_i2s_workdata->ioarea);
335 kfree(au1xpsc_i2s_workdata->ioarea);
336 kfree(au1xpsc_i2s_workdata);
337 au1xpsc_i2s_workdata = NULL;
338}
339
340static int au1xpsc_i2s_suspend(struct platform_device *pdev,
341 struct snd_soc_dai *cpu_dai)
342{
343 /* save interesting register and disable PSC */
344 au1xpsc_i2s_workdata->pm[0] =
345 au_readl(PSC_SEL(au1xpsc_i2s_workdata));
346
347 au_writel(0, I2S_CFG(au1xpsc_i2s_workdata));
348 au_sync();
349 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata));
350 au_sync();
351
352 return 0;
353}
354
355static int au1xpsc_i2s_resume(struct platform_device *pdev,
356 struct snd_soc_dai *cpu_dai)
357{
358 /* select I2S mode and PSC clock */
359 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata));
360 au_sync();
361 au_writel(0, PSC_SEL(au1xpsc_i2s_workdata));
362 au_sync();
363 au_writel(au1xpsc_i2s_workdata->pm[0],
364 PSC_SEL(au1xpsc_i2s_workdata));
365 au_sync();
366
367 return 0;
368}
369
370struct snd_soc_dai au1xpsc_i2s_dai = {
371 .name = "au1xpsc_i2s",
372 .type = SND_SOC_DAI_I2S,
373 .probe = au1xpsc_i2s_probe,
374 .remove = au1xpsc_i2s_remove,
375 .suspend = au1xpsc_i2s_suspend,
376 .resume = au1xpsc_i2s_resume,
377 .playback = {
378 .rates = AU1XPSC_I2S_RATES,
379 .formats = AU1XPSC_I2S_FMTS,
380 .channels_min = 2,
381 .channels_max = 8, /* 2 without external help */
382 },
383 .capture = {
384 .rates = AU1XPSC_I2S_RATES,
385 .formats = AU1XPSC_I2S_FMTS,
386 .channels_min = 2,
387 .channels_max = 8, /* 2 without external help */
388 },
389 .ops = {
390 .trigger = au1xpsc_i2s_trigger,
391 .hw_params = au1xpsc_i2s_hw_params,
392 },
393 .dai_ops = {
394 .set_fmt = au1xpsc_i2s_set_fmt,
395 },
396};
397EXPORT_SYMBOL(au1xpsc_i2s_dai);
398
399static int __init au1xpsc_i2s_init(void)
400{
401 au1xpsc_i2s_workdata = NULL;
402 return 0;
403}
404
405static void __exit au1xpsc_i2s_exit(void)
406{
407}
408
409module_init(au1xpsc_i2s_init);
410module_exit(au1xpsc_i2s_exit);
411
412MODULE_LICENSE("GPL");
413MODULE_DESCRIPTION("Au12x0/Au1550 PSC I2S ALSA ASoC audio driver");
414MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h
new file mode 100644
index 000000000000..8fdb1a04a07b
--- /dev/null
+++ b/sound/soc/au1x/psc.h
@@ -0,0 +1,53 @@
1/*
2 * Au12x0/Au1550 PSC ALSA ASoC audio support.
3 *
4 * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
5 * Manuel Lauss <mano@roarinelk.homelinux.net>
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 * NOTE: all of these drivers can only work with a SINGLE instance
12 * of a PSC. Multiple independent audio devices are impossible
13 * with ASoC v1.
14 */
15
16#ifndef _AU1X_PCM_H
17#define _AU1X_PCM_H
18
19extern struct snd_soc_dai au1xpsc_ac97_dai;
20extern struct snd_soc_dai au1xpsc_i2s_dai;
21extern struct snd_soc_platform au1xpsc_soc_platform;
22extern struct snd_ac97_bus_ops soc_ac97_ops;
23
24struct au1xpsc_audio_data {
25 void __iomem *mmio;
26
27 unsigned long cfg;
28 unsigned long rate;
29
30 unsigned long pm[2];
31 struct resource *ioarea;
32};
33
34#define PCM_TX 0
35#define PCM_RX 1
36
37#define SUBSTREAM_TYPE(substream) \
38 ((substream)->stream == SNDRV_PCM_STREAM_PLAYBACK ? PCM_TX : PCM_RX)
39
40/* easy access macros */
41#define PSC_CTRL(x) ((unsigned long)((x)->mmio) + PSC_CTRL_OFFSET)
42#define PSC_SEL(x) ((unsigned long)((x)->mmio) + PSC_SEL_OFFSET)
43#define I2S_STAT(x) ((unsigned long)((x)->mmio) + PSC_I2SSTAT_OFFSET)
44#define I2S_CFG(x) ((unsigned long)((x)->mmio) + PSC_I2SCFG_OFFSET)
45#define I2S_PCR(x) ((unsigned long)((x)->mmio) + PSC_I2SPCR_OFFSET)
46#define AC97_CFG(x) ((unsigned long)((x)->mmio) + PSC_AC97CFG_OFFSET)
47#define AC97_CDC(x) ((unsigned long)((x)->mmio) + PSC_AC97CDC_OFFSET)
48#define AC97_EVNT(x) ((unsigned long)((x)->mmio) + PSC_AC97EVNT_OFFSET)
49#define AC97_PCR(x) ((unsigned long)((x)->mmio) + PSC_AC97PCR_OFFSET)
50#define AC97_RST(x) ((unsigned long)((x)->mmio) + PSC_AC97RST_OFFSET)
51#define AC97_STAT(x) ((unsigned long)((x)->mmio) + PSC_AC97STAT_OFFSET)
52
53#endif
diff --git a/sound/soc/au1x/sample-ac97.c b/sound/soc/au1x/sample-ac97.c
new file mode 100644
index 000000000000..f75ae7f62c3d
--- /dev/null
+++ b/sound/soc/au1x/sample-ac97.c
@@ -0,0 +1,144 @@
1/*
2 * Sample Au12x0/Au1550 PSC AC97 sound machine.
3 *
4 * Copyright (c) 2007-2008 Manuel Lauss <mano@roarinelk.homelinux.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms outlined in the file COPYING at the root of this
8 * source archive.
9 *
10 * This is a very generic AC97 sound machine driver for boards which
11 * have (AC97) audio at PSC1 (e.g. DB1200 demoboards).
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/timer.h>
17#include <linux/interrupt.h>
18#include <linux/platform_device.h>
19#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
23#include <asm/mach-au1x00/au1000.h>
24#include <asm/mach-au1x00/au1xxx_psc.h>
25#include <asm/mach-au1x00/au1xxx_dbdma.h>
26
27#include "../codecs/ac97.h"
28#include "psc.h"
29
30static int au1xpsc_sample_ac97_init(struct snd_soc_codec *codec)
31{
32 snd_soc_dapm_sync(codec);
33 return 0;
34}
35
36static struct snd_soc_dai_link au1xpsc_sample_ac97_dai = {
37 .name = "AC97",
38 .stream_name = "AC97 HiFi",
39 .cpu_dai = &au1xpsc_ac97_dai, /* see psc-ac97.c */
40 .codec_dai = &ac97_dai, /* see codecs/ac97.c */
41 .init = au1xpsc_sample_ac97_init,
42 .ops = NULL,
43};
44
45static struct snd_soc_machine au1xpsc_sample_ac97_machine = {
46 .name = "Au1xxx PSC AC97 Audio",
47 .dai_link = &au1xpsc_sample_ac97_dai,
48 .num_links = 1,
49};
50
51static struct snd_soc_device au1xpsc_sample_ac97_devdata = {
52 .machine = &au1xpsc_sample_ac97_machine,
53 .platform = &au1xpsc_soc_platform, /* see dbdma2.c */
54 .codec_dev = &soc_codec_dev_ac97,
55};
56
57static struct resource au1xpsc_psc1_res[] = {
58 [0] = {
59 .start = CPHYSADDR(PSC1_BASE_ADDR),
60 .end = CPHYSADDR(PSC1_BASE_ADDR) + 0x000fffff,
61 .flags = IORESOURCE_MEM,
62 },
63 [1] = {
64#ifdef CONFIG_SOC_AU1200
65 .start = AU1200_PSC1_INT,
66 .end = AU1200_PSC1_INT,
67#elif defined(CONFIG_SOC_AU1550)
68 .start = AU1550_PSC1_INT,
69 .end = AU1550_PSC1_INT,
70#endif
71 .flags = IORESOURCE_IRQ,
72 },
73 [2] = {
74 .start = DSCR_CMD0_PSC1_TX,
75 .end = DSCR_CMD0_PSC1_TX,
76 .flags = IORESOURCE_DMA,
77 },
78 [3] = {
79 .start = DSCR_CMD0_PSC1_RX,
80 .end = DSCR_CMD0_PSC1_RX,
81 .flags = IORESOURCE_DMA,
82 },
83};
84
85static struct platform_device *au1xpsc_sample_ac97_dev;
86
87static int __init au1xpsc_sample_ac97_load(void)
88{
89 int ret;
90
91#ifdef CONFIG_SOC_AU1200
92 unsigned long io;
93
94 /* modify sys_pinfunc for AC97 on PSC1 */
95 io = au_readl(SYS_PINFUNC);
96 io |= SYS_PINFUNC_P1C;
97 io &= ~(SYS_PINFUNC_P1A | SYS_PINFUNC_P1B);
98 au_writel(io, SYS_PINFUNC);
99 au_sync();
100#endif
101
102 ret = -ENOMEM;
103
104 /* setup PSC clock source for AC97 part: external clock provided
105 * by codec. The psc-ac97.c driver depends on this setting!
106 */
107 au_writel(PSC_SEL_CLK_SERCLK, PSC1_BASE_ADDR + PSC_SEL_OFFSET);
108 au_sync();
109
110 au1xpsc_sample_ac97_dev = platform_device_alloc("soc-audio", -1);
111 if (!au1xpsc_sample_ac97_dev)
112 goto out;
113
114 au1xpsc_sample_ac97_dev->resource =
115 kmemdup(au1xpsc_psc1_res, sizeof(struct resource) *
116 ARRAY_SIZE(au1xpsc_psc1_res), GFP_KERNEL);
117 au1xpsc_sample_ac97_dev->num_resources = ARRAY_SIZE(au1xpsc_psc1_res);
118 au1xpsc_sample_ac97_dev->id = 1;
119
120 platform_set_drvdata(au1xpsc_sample_ac97_dev,
121 &au1xpsc_sample_ac97_devdata);
122 au1xpsc_sample_ac97_devdata.dev = &au1xpsc_sample_ac97_dev->dev;
123 ret = platform_device_add(au1xpsc_sample_ac97_dev);
124
125 if (ret) {
126 platform_device_put(au1xpsc_sample_ac97_dev);
127 au1xpsc_sample_ac97_dev = NULL;
128 }
129
130out:
131 return ret;
132}
133
134static void __exit au1xpsc_sample_ac97_exit(void)
135{
136 platform_device_unregister(au1xpsc_sample_ac97_dev);
137}
138
139module_init(au1xpsc_sample_ac97_load);
140module_exit(au1xpsc_sample_ac97_exit);
141
142MODULE_LICENSE("GPL");
143MODULE_DESCRIPTION("Au1xxx PSC sample AC97 machine");
144MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 3903ab7dfa4a..1db04a28a53d 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1,31 +1,37 @@
1config SND_SOC_AC97_CODEC 1config SND_SOC_AC97_CODEC
2 tristate 2 tristate
3 depends on SND_SOC 3 select SND_AC97_CODEC
4
5config SND_SOC_AK4535
6 tristate
7
8config SND_SOC_UDA1380
9 tristate
10
11config SND_SOC_WM8510
12 tristate
4 13
5config SND_SOC_WM8731 14config SND_SOC_WM8731
6 tristate 15 tristate
7 depends on SND_SOC
8 16
9config SND_SOC_WM8750 17config SND_SOC_WM8750
10 tristate 18 tristate
11 depends on SND_SOC
12 19
13config SND_SOC_WM8753 20config SND_SOC_WM8753
14 tristate 21 tristate
15 depends on SND_SOC 22
23config SND_SOC_WM8990
24 tristate
16 25
17config SND_SOC_WM9712 26config SND_SOC_WM9712
18 tristate 27 tristate
19 depends on SND_SOC
20 28
21config SND_SOC_WM9713 29config SND_SOC_WM9713
22 tristate 30 tristate
23 depends on SND_SOC
24 31
25# Cirrus Logic CS4270 Codec 32# Cirrus Logic CS4270 Codec
26config SND_SOC_CS4270 33config SND_SOC_CS4270
27 tristate 34 tristate
28 depends on SND_SOC
29 35
30# Cirrus Logic CS4270 Codec Hardware Mute Support 36# Cirrus Logic CS4270 Codec Hardware Mute Support
31# Select if you have external muting circuitry attached to your CS4270. 37# Select if you have external muting circuitry attached to your CS4270.
@@ -43,4 +49,4 @@ config SND_SOC_CS4270_VD33_ERRATA
43 49
44config SND_SOC_TLV320AIC3X 50config SND_SOC_TLV320AIC3X
45 tristate 51 tristate
46 depends on SND_SOC && I2C 52 depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 4e1314c9d3ec..d7b97abcf729 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,16 +1,24 @@
1snd-soc-ac97-objs := ac97.o 1snd-soc-ac97-objs := ac97.o
2snd-soc-ak4535-objs := ak4535.o
3snd-soc-uda1380-objs := uda1380.o
4snd-soc-wm8510-objs := wm8510.o
2snd-soc-wm8731-objs := wm8731.o 5snd-soc-wm8731-objs := wm8731.o
3snd-soc-wm8750-objs := wm8750.o 6snd-soc-wm8750-objs := wm8750.o
4snd-soc-wm8753-objs := wm8753.o 7snd-soc-wm8753-objs := wm8753.o
8snd-soc-wm8990-objs := wm8990.o
5snd-soc-wm9712-objs := wm9712.o 9snd-soc-wm9712-objs := wm9712.o
6snd-soc-wm9713-objs := wm9713.o 10snd-soc-wm9713-objs := wm9713.o
7snd-soc-cs4270-objs := cs4270.o 11snd-soc-cs4270-objs := cs4270.o
8snd-soc-tlv320aic3x-objs := tlv320aic3x.o 12snd-soc-tlv320aic3x-objs := tlv320aic3x.o
9 13
10obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o 14obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
15obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
16obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
17obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
11obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o 18obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
12obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o 19obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
13obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o 20obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
21obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
14obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o 22obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
15obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o 23obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
16obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 24obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 2a1ffe396908..61fd96ca7bc7 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -10,9 +10,6 @@
10 * Free Software Foundation; either version 2 of the License, or (at your 10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
12 * 12 *
13 * Revision history
14 * 17th Oct 2005 Initial version.
15 *
16 * Generic AC97 support. 13 * Generic AC97 support.
17 */ 14 */
18 15
@@ -24,6 +21,7 @@
24#include <sound/ac97_codec.h> 21#include <sound/ac97_codec.h>
25#include <sound/initval.h> 22#include <sound/initval.h>
26#include <sound/soc.h> 23#include <sound/soc.h>
24#include "ac97.h"
27 25
28#define AC97_VERSION "0.6" 26#define AC97_VERSION "0.6"
29 27
@@ -43,7 +41,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream)
43 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\ 41 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
44 SNDRV_PCM_RATE_48000) 42 SNDRV_PCM_RATE_48000)
45 43
46struct snd_soc_codec_dai ac97_dai = { 44struct snd_soc_dai ac97_dai = {
47 .name = "AC97 HiFi", 45 .name = "AC97 HiFi",
48 .type = SND_SOC_DAI_AC97, 46 .type = SND_SOC_DAI_AC97,
49 .playback = { 47 .playback = {
@@ -146,9 +144,34 @@ static int ac97_soc_remove(struct platform_device *pdev)
146 return 0; 144 return 0;
147} 145}
148 146
147#ifdef CONFIG_PM
148static int ac97_soc_suspend(struct platform_device *pdev, pm_message_t msg)
149{
150 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
151
152 snd_ac97_suspend(socdev->codec->ac97);
153
154 return 0;
155}
156
157static int ac97_soc_resume(struct platform_device *pdev)
158{
159 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
160
161 snd_ac97_resume(socdev->codec->ac97);
162
163 return 0;
164}
165#else
166#define ac97_soc_suspend NULL
167#define ac97_soc_resume NULL
168#endif
169
149struct snd_soc_codec_device soc_codec_dev_ac97 = { 170struct snd_soc_codec_device soc_codec_dev_ac97 = {
150 .probe = ac97_soc_probe, 171 .probe = ac97_soc_probe,
151 .remove = ac97_soc_remove, 172 .remove = ac97_soc_remove,
173 .suspend = ac97_soc_suspend,
174 .resume = ac97_soc_resume,
152}; 175};
153EXPORT_SYMBOL_GPL(soc_codec_dev_ac97); 176EXPORT_SYMBOL_GPL(soc_codec_dev_ac97);
154 177
diff --git a/sound/soc/codecs/ac97.h b/sound/soc/codecs/ac97.h
index 2bf6d69fd069..281aa42e2bbb 100644
--- a/sound/soc/codecs/ac97.h
+++ b/sound/soc/codecs/ac97.h
@@ -14,6 +14,6 @@
14#define __LINUX_SND_SOC_AC97_H 14#define __LINUX_SND_SOC_AC97_H
15 15
16extern struct snd_soc_codec_device soc_codec_dev_ac97; 16extern struct snd_soc_codec_device soc_codec_dev_ac97;
17extern struct snd_soc_codec_dai ac97_dai; 17extern struct snd_soc_dai ac97_dai;
18 18
19#endif 19#endif
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
new file mode 100644
index 000000000000..b26003c4f3e8
--- /dev/null
+++ b/sound/soc/codecs/ak4535.c
@@ -0,0 +1,696 @@
1/*
2 * ak4535.c -- AK4535 ALSA Soc Audio driver
3 *
4 * Copyright 2005 Openedhand Ltd.
5 *
6 * Author: Richard Purdie <richard@openedhand.com>
7 *
8 * Based on wm8753.c by Liam Girdwood
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pm.h>
20#include <linux/i2c.h>
21#include <linux/platform_device.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26#include <sound/soc-dapm.h>
27#include <sound/initval.h>
28
29#include "ak4535.h"
30
31#define AUDIO_NAME "ak4535"
32#define AK4535_VERSION "0.3"
33
34struct snd_soc_codec_device soc_codec_dev_ak4535;
35
36/* codec private data */
37struct ak4535_priv {
38 unsigned int sysclk;
39};
40
41/*
42 * ak4535 register cache
43 */
44static const u16 ak4535_reg[AK4535_CACHEREGNUM] = {
45 0x0000, 0x0080, 0x0000, 0x0003,
46 0x0002, 0x0000, 0x0011, 0x0001,
47 0x0000, 0x0040, 0x0036, 0x0010,
48 0x0000, 0x0000, 0x0057, 0x0000,
49};
50
51/*
52 * read ak4535 register cache
53 */
54static inline unsigned int ak4535_read_reg_cache(struct snd_soc_codec *codec,
55 unsigned int reg)
56{
57 u16 *cache = codec->reg_cache;
58 if (reg >= AK4535_CACHEREGNUM)
59 return -1;
60 return cache[reg];
61}
62
63static inline unsigned int ak4535_read(struct snd_soc_codec *codec,
64 unsigned int reg)
65{
66 u8 data;
67 data = reg;
68
69 if (codec->hw_write(codec->control_data, &data, 1) != 1)
70 return -EIO;
71
72 if (codec->hw_read(codec->control_data, &data, 1) != 1)
73 return -EIO;
74
75 return data;
76};
77
78/*
79 * write ak4535 register cache
80 */
81static inline void ak4535_write_reg_cache(struct snd_soc_codec *codec,
82 u16 reg, unsigned int value)
83{
84 u16 *cache = codec->reg_cache;
85 if (reg >= AK4535_CACHEREGNUM)
86 return;
87 cache[reg] = value;
88}
89
90/*
91 * write to the AK4535 register space
92 */
93static int ak4535_write(struct snd_soc_codec *codec, unsigned int reg,
94 unsigned int value)
95{
96 u8 data[2];
97
98 /* data is
99 * D15..D8 AK4535 register offset
100 * D7...D0 register data
101 */
102 data[0] = reg & 0xff;
103 data[1] = value & 0xff;
104
105 ak4535_write_reg_cache(codec, reg, value);
106 if (codec->hw_write(codec->control_data, data, 2) == 2)
107 return 0;
108 else
109 return -EIO;
110}
111
112static int ak4535_sync(struct snd_soc_codec *codec)
113{
114 u16 *cache = codec->reg_cache;
115 int i, r = 0;
116
117 for (i = 0; i < AK4535_CACHEREGNUM; i++)
118 r |= ak4535_write(codec, i, cache[i]);
119
120 return r;
121};
122
123static const char *ak4535_mono_gain[] = {"+6dB", "-17dB"};
124static const char *ak4535_mono_out[] = {"(L + R)/2", "Hi-Z"};
125static const char *ak4535_hp_out[] = {"Stereo", "Mono"};
126static const char *ak4535_deemp[] = {"44.1kHz", "Off", "48kHz", "32kHz"};
127static const char *ak4535_mic_select[] = {"Internal", "External"};
128
129static const struct soc_enum ak4535_enum[] = {
130 SOC_ENUM_SINGLE(AK4535_SIG1, 7, 2, ak4535_mono_gain),
131 SOC_ENUM_SINGLE(AK4535_SIG1, 6, 2, ak4535_mono_out),
132 SOC_ENUM_SINGLE(AK4535_MODE2, 2, 2, ak4535_hp_out),
133 SOC_ENUM_SINGLE(AK4535_DAC, 0, 4, ak4535_deemp),
134 SOC_ENUM_SINGLE(AK4535_MIC, 1, 2, ak4535_mic_select),
135};
136
137static const struct snd_kcontrol_new ak4535_snd_controls[] = {
138 SOC_SINGLE("ALC2 Switch", AK4535_SIG1, 1, 1, 0),
139 SOC_ENUM("Mono 1 Output", ak4535_enum[1]),
140 SOC_ENUM("Mono 1 Gain", ak4535_enum[0]),
141 SOC_ENUM("Headphone Output", ak4535_enum[2]),
142 SOC_ENUM("Playback Deemphasis", ak4535_enum[3]),
143 SOC_SINGLE("Bass Volume", AK4535_DAC, 2, 3, 0),
144 SOC_SINGLE("Mic Boost (+20dB) Switch", AK4535_MIC, 0, 1, 0),
145 SOC_ENUM("Mic Select", ak4535_enum[4]),
146 SOC_SINGLE("ALC Operation Time", AK4535_TIMER, 0, 3, 0),
147 SOC_SINGLE("ALC Recovery Time", AK4535_TIMER, 2, 3, 0),
148 SOC_SINGLE("ALC ZC Time", AK4535_TIMER, 4, 3, 0),
149 SOC_SINGLE("ALC 1 Switch", AK4535_ALC1, 5, 1, 0),
150 SOC_SINGLE("ALC 2 Switch", AK4535_ALC1, 6, 1, 0),
151 SOC_SINGLE("ALC Volume", AK4535_ALC2, 0, 127, 0),
152 SOC_SINGLE("Capture Volume", AK4535_PGA, 0, 127, 0),
153 SOC_SINGLE("Left Playback Volume", AK4535_LATT, 0, 127, 1),
154 SOC_SINGLE("Right Playback Volume", AK4535_RATT, 0, 127, 1),
155 SOC_SINGLE("AUX Bypass Volume", AK4535_VOL, 0, 15, 0),
156 SOC_SINGLE("Mic Sidetone Volume", AK4535_VOL, 4, 7, 0),
157};
158
159/* add non dapm controls */
160static int ak4535_add_controls(struct snd_soc_codec *codec)
161{
162 int err, i;
163
164 for (i = 0; i < ARRAY_SIZE(ak4535_snd_controls); i++) {
165 err = snd_ctl_add(codec->card,
166 snd_soc_cnew(&ak4535_snd_controls[i], codec, NULL));
167 if (err < 0)
168 return err;
169 }
170
171 return 0;
172}
173
174/* Mono 1 Mixer */
175static const struct snd_kcontrol_new ak4535_mono1_mixer_controls[] = {
176 SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG1, 4, 1, 0),
177 SOC_DAPM_SINGLE("Mono Playback Switch", AK4535_SIG1, 5, 1, 0),
178};
179
180/* Stereo Mixer */
181static const struct snd_kcontrol_new ak4535_stereo_mixer_controls[] = {
182 SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG2, 4, 1, 0),
183 SOC_DAPM_SINGLE("Playback Switch", AK4535_SIG2, 7, 1, 0),
184 SOC_DAPM_SINGLE("Aux Bypass Switch", AK4535_SIG2, 5, 1, 0),
185};
186
187/* Input Mixer */
188static const struct snd_kcontrol_new ak4535_input_mixer_controls[] = {
189 SOC_DAPM_SINGLE("Mic Capture Switch", AK4535_MIC, 2, 1, 0),
190 SOC_DAPM_SINGLE("Aux Capture Switch", AK4535_MIC, 5, 1, 0),
191};
192
193/* Input mux */
194static const struct snd_kcontrol_new ak4535_input_mux_control =
195 SOC_DAPM_ENUM("Input Select", ak4535_enum[4]);
196
197/* HP L switch */
198static const struct snd_kcontrol_new ak4535_hpl_control =
199 SOC_DAPM_SINGLE("Switch", AK4535_SIG2, 1, 1, 1);
200
201/* HP R switch */
202static const struct snd_kcontrol_new ak4535_hpr_control =
203 SOC_DAPM_SINGLE("Switch", AK4535_SIG2, 0, 1, 1);
204
205/* mono 2 switch */
206static const struct snd_kcontrol_new ak4535_mono2_control =
207 SOC_DAPM_SINGLE("Switch", AK4535_SIG1, 0, 1, 0);
208
209/* Line out switch */
210static const struct snd_kcontrol_new ak4535_line_control =
211 SOC_DAPM_SINGLE("Switch", AK4535_SIG2, 6, 1, 0);
212
213/* ak4535 dapm widgets */
214static const struct snd_soc_dapm_widget ak4535_dapm_widgets[] = {
215 SND_SOC_DAPM_MIXER("Stereo Mixer", SND_SOC_NOPM, 0, 0,
216 &ak4535_stereo_mixer_controls[0],
217 ARRAY_SIZE(ak4535_stereo_mixer_controls)),
218 SND_SOC_DAPM_MIXER("Mono1 Mixer", SND_SOC_NOPM, 0, 0,
219 &ak4535_mono1_mixer_controls[0],
220 ARRAY_SIZE(ak4535_mono1_mixer_controls)),
221 SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0,
222 &ak4535_input_mixer_controls[0],
223 ARRAY_SIZE(ak4535_input_mixer_controls)),
224 SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0,
225 &ak4535_input_mux_control),
226 SND_SOC_DAPM_DAC("DAC", "Playback", AK4535_PM2, 0, 0),
227 SND_SOC_DAPM_SWITCH("Mono 2 Enable", SND_SOC_NOPM, 0, 0,
228 &ak4535_mono2_control),
229 /* speaker powersave bit */
230 SND_SOC_DAPM_PGA("Speaker Enable", AK4535_MODE2, 0, 0, NULL, 0),
231 SND_SOC_DAPM_SWITCH("Line Out Enable", SND_SOC_NOPM, 0, 0,
232 &ak4535_line_control),
233 SND_SOC_DAPM_SWITCH("Left HP Enable", SND_SOC_NOPM, 0, 0,
234 &ak4535_hpl_control),
235 SND_SOC_DAPM_SWITCH("Right HP Enable", SND_SOC_NOPM, 0, 0,
236 &ak4535_hpr_control),
237 SND_SOC_DAPM_OUTPUT("LOUT"),
238 SND_SOC_DAPM_OUTPUT("HPL"),
239 SND_SOC_DAPM_OUTPUT("ROUT"),
240 SND_SOC_DAPM_OUTPUT("HPR"),
241 SND_SOC_DAPM_OUTPUT("SPP"),
242 SND_SOC_DAPM_OUTPUT("SPN"),
243 SND_SOC_DAPM_OUTPUT("MOUT1"),
244 SND_SOC_DAPM_OUTPUT("MOUT2"),
245 SND_SOC_DAPM_OUTPUT("MICOUT"),
246 SND_SOC_DAPM_ADC("ADC", "Capture", AK4535_PM1, 0, 0),
247 SND_SOC_DAPM_PGA("Spk Amp", AK4535_PM2, 3, 0, NULL, 0),
248 SND_SOC_DAPM_PGA("HP R Amp", AK4535_PM2, 1, 0, NULL, 0),
249 SND_SOC_DAPM_PGA("HP L Amp", AK4535_PM2, 2, 0, NULL, 0),
250 SND_SOC_DAPM_PGA("Mic", AK4535_PM1, 1, 0, NULL, 0),
251 SND_SOC_DAPM_PGA("Line Out", AK4535_PM1, 4, 0, NULL, 0),
252 SND_SOC_DAPM_PGA("Mono Out", AK4535_PM1, 3, 0, NULL, 0),
253 SND_SOC_DAPM_PGA("AUX In", AK4535_PM1, 2, 0, NULL, 0),
254
255 SND_SOC_DAPM_MICBIAS("Mic Int Bias", AK4535_MIC, 3, 0),
256 SND_SOC_DAPM_MICBIAS("Mic Ext Bias", AK4535_MIC, 4, 0),
257 SND_SOC_DAPM_INPUT("MICIN"),
258 SND_SOC_DAPM_INPUT("MICEXT"),
259 SND_SOC_DAPM_INPUT("AUX"),
260 SND_SOC_DAPM_INPUT("MIN"),
261 SND_SOC_DAPM_INPUT("AIN"),
262};
263
264static const struct snd_soc_dapm_route audio_map[] = {
265 /*stereo mixer */
266 {"Stereo Mixer", "Playback Switch", "DAC"},
267 {"Stereo Mixer", "Mic Sidetone Switch", "Mic"},
268 {"Stereo Mixer", "Aux Bypass Switch", "AUX In"},
269
270 /* mono1 mixer */
271 {"Mono1 Mixer", "Mic Sidetone Switch", "Mic"},
272 {"Mono1 Mixer", "Mono Playback Switch", "DAC"},
273
274 /* Mic */
275 {"Mic", NULL, "AIN"},
276 {"Input Mux", "Internal", "Mic Int Bias"},
277 {"Input Mux", "External", "Mic Ext Bias"},
278 {"Mic Int Bias", NULL, "MICIN"},
279 {"Mic Ext Bias", NULL, "MICEXT"},
280 {"MICOUT", NULL, "Input Mux"},
281
282 /* line out */
283 {"LOUT", NULL, "Line Out Enable"},
284 {"ROUT", NULL, "Line Out Enable"},
285 {"Line Out Enable", "Switch", "Line Out"},
286 {"Line Out", NULL, "Stereo Mixer"},
287
288 /* mono1 out */
289 {"MOUT1", NULL, "Mono Out"},
290 {"Mono Out", NULL, "Mono1 Mixer"},
291
292 /* left HP */
293 {"HPL", NULL, "Left HP Enable"},
294 {"Left HP Enable", "Switch", "HP L Amp"},
295 {"HP L Amp", NULL, "Stereo Mixer"},
296
297 /* right HP */
298 {"HPR", NULL, "Right HP Enable"},
299 {"Right HP Enable", "Switch", "HP R Amp"},
300 {"HP R Amp", NULL, "Stereo Mixer"},
301
302 /* speaker */
303 {"SPP", NULL, "Speaker Enable"},
304 {"SPN", NULL, "Speaker Enable"},
305 {"Speaker Enable", "Switch", "Spk Amp"},
306 {"Spk Amp", NULL, "MIN"},
307
308 /* mono 2 */
309 {"MOUT2", NULL, "Mono 2 Enable"},
310 {"Mono 2 Enable", "Switch", "Stereo Mixer"},
311
312 /* Aux In */
313 {"Aux In", NULL, "AUX"},
314
315 /* ADC */
316 {"ADC", NULL, "Input Mixer"},
317 {"Input Mixer", "Mic Capture Switch", "Mic"},
318 {"Input Mixer", "Aux Capture Switch", "Aux In"},
319};
320
321static int ak4535_add_widgets(struct snd_soc_codec *codec)
322{
323 snd_soc_dapm_new_controls(codec, ak4535_dapm_widgets,
324 ARRAY_SIZE(ak4535_dapm_widgets));
325
326 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
327
328 snd_soc_dapm_new_widgets(codec);
329 return 0;
330}
331
332static int ak4535_set_dai_sysclk(struct snd_soc_dai *codec_dai,
333 int clk_id, unsigned int freq, int dir)
334{
335 struct snd_soc_codec *codec = codec_dai->codec;
336 struct ak4535_priv *ak4535 = codec->private_data;
337
338 ak4535->sysclk = freq;
339 return 0;
340}
341
342static int ak4535_hw_params(struct snd_pcm_substream *substream,
343 struct snd_pcm_hw_params *params)
344{
345 struct snd_soc_pcm_runtime *rtd = substream->private_data;
346 struct snd_soc_device *socdev = rtd->socdev;
347 struct snd_soc_codec *codec = socdev->codec;
348 struct ak4535_priv *ak4535 = codec->private_data;
349 u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);
350 int rate = params_rate(params), fs = 256;
351
352 if (rate)
353 fs = ak4535->sysclk / rate;
354
355 /* set fs */
356 switch (fs) {
357 case 1024:
358 mode2 |= (0x2 << 5);
359 break;
360 case 512:
361 mode2 |= (0x1 << 5);
362 break;
363 case 256:
364 break;
365 }
366
367 /* set rate */
368 ak4535_write(codec, AK4535_MODE2, mode2);
369 return 0;
370}
371
372static int ak4535_set_dai_fmt(struct snd_soc_dai *codec_dai,
373 unsigned int fmt)
374{
375 struct snd_soc_codec *codec = codec_dai->codec;
376 u8 mode1 = 0;
377
378 /* interface format */
379 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
380 case SND_SOC_DAIFMT_I2S:
381 mode1 = 0x0002;
382 break;
383 case SND_SOC_DAIFMT_LEFT_J:
384 mode1 = 0x0001;
385 break;
386 default:
387 return -EINVAL;
388 }
389
390 /* use 32 fs for BCLK to save power */
391 mode1 |= 0x4;
392
393 ak4535_write(codec, AK4535_MODE1, mode1);
394 return 0;
395}
396
397static int ak4535_mute(struct snd_soc_dai *dai, int mute)
398{
399 struct snd_soc_codec *codec = dai->codec;
400 u16 mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
401 if (!mute)
402 ak4535_write(codec, AK4535_DAC, mute_reg);
403 else
404 ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
405 return 0;
406}
407
408static int ak4535_set_bias_level(struct snd_soc_codec *codec,
409 enum snd_soc_bias_level level)
410{
411 u16 i;
412
413 switch (level) {
414 case SND_SOC_BIAS_ON:
415 ak4535_mute(codec->dai, 0);
416 break;
417 case SND_SOC_BIAS_PREPARE:
418 ak4535_mute(codec->dai, 1);
419 break;
420 case SND_SOC_BIAS_STANDBY:
421 i = ak4535_read_reg_cache(codec, AK4535_PM1);
422 ak4535_write(codec, AK4535_PM1, i | 0x80);
423 i = ak4535_read_reg_cache(codec, AK4535_PM2);
424 ak4535_write(codec, AK4535_PM2, i & (~0x80));
425 break;
426 case SND_SOC_BIAS_OFF:
427 i = ak4535_read_reg_cache(codec, AK4535_PM1);
428 ak4535_write(codec, AK4535_PM1, i & (~0x80));
429 break;
430 }
431 codec->bias_level = level;
432 return 0;
433}
434
435#define AK4535_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
436 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
437 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
438
439struct snd_soc_dai ak4535_dai = {
440 .name = "AK4535",
441 .playback = {
442 .stream_name = "Playback",
443 .channels_min = 1,
444 .channels_max = 2,
445 .rates = AK4535_RATES,
446 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
447 .capture = {
448 .stream_name = "Capture",
449 .channels_min = 1,
450 .channels_max = 2,
451 .rates = AK4535_RATES,
452 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
453 .ops = {
454 .hw_params = ak4535_hw_params,
455 },
456 .dai_ops = {
457 .set_fmt = ak4535_set_dai_fmt,
458 .digital_mute = ak4535_mute,
459 .set_sysclk = ak4535_set_dai_sysclk,
460 },
461};
462EXPORT_SYMBOL_GPL(ak4535_dai);
463
464static int ak4535_suspend(struct platform_device *pdev, pm_message_t state)
465{
466 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
467 struct snd_soc_codec *codec = socdev->codec;
468
469 ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
470 return 0;
471}
472
473static int ak4535_resume(struct platform_device *pdev)
474{
475 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
476 struct snd_soc_codec *codec = socdev->codec;
477 ak4535_sync(codec);
478 ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
479 ak4535_set_bias_level(codec, codec->suspend_bias_level);
480 return 0;
481}
482
483/*
484 * initialise the AK4535 driver
485 * register the mixer and dsp interfaces with the kernel
486 */
487static int ak4535_init(struct snd_soc_device *socdev)
488{
489 struct snd_soc_codec *codec = socdev->codec;
490 int ret = 0;
491
492 codec->name = "AK4535";
493 codec->owner = THIS_MODULE;
494 codec->read = ak4535_read_reg_cache;
495 codec->write = ak4535_write;
496 codec->set_bias_level = ak4535_set_bias_level;
497 codec->dai = &ak4535_dai;
498 codec->num_dai = 1;
499 codec->reg_cache_size = ARRAY_SIZE(ak4535_reg);
500 codec->reg_cache = kmemdup(ak4535_reg, sizeof(ak4535_reg), GFP_KERNEL);
501
502 if (codec->reg_cache == NULL)
503 return -ENOMEM;
504
505 /* register pcms */
506 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
507 if (ret < 0) {
508 printk(KERN_ERR "ak4535: failed to create pcms\n");
509 goto pcm_err;
510 }
511
512 /* power on device */
513 ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
514
515 ak4535_add_controls(codec);
516 ak4535_add_widgets(codec);
517 ret = snd_soc_register_card(socdev);
518 if (ret < 0) {
519 printk(KERN_ERR "ak4535: failed to register card\n");
520 goto card_err;
521 }
522
523 return ret;
524
525card_err:
526 snd_soc_free_pcms(socdev);
527 snd_soc_dapm_free(socdev);
528pcm_err:
529 kfree(codec->reg_cache);
530
531 return ret;
532}
533
534static struct snd_soc_device *ak4535_socdev;
535
536#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
537
538#define I2C_DRIVERID_AK4535 0xfefe /* liam - need a proper id */
539
540static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
541
542/* Magic definition of all other variables and things */
543I2C_CLIENT_INSMOD;
544
545static struct i2c_driver ak4535_i2c_driver;
546static struct i2c_client client_template;
547
548/* If the i2c layer weren't so broken, we could pass this kind of data
549 around */
550static int ak4535_codec_probe(struct i2c_adapter *adap, int addr, int kind)
551{
552 struct snd_soc_device *socdev = ak4535_socdev;
553 struct ak4535_setup_data *setup = socdev->codec_data;
554 struct snd_soc_codec *codec = socdev->codec;
555 struct i2c_client *i2c;
556 int ret;
557
558 if (addr != setup->i2c_address)
559 return -ENODEV;
560
561 client_template.adapter = adap;
562 client_template.addr = addr;
563
564 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
565 if (i2c == NULL) {
566 kfree(codec);
567 return -ENOMEM;
568 }
569 i2c_set_clientdata(i2c, codec);
570 codec->control_data = i2c;
571
572 ret = i2c_attach_client(i2c);
573 if (ret < 0) {
574 printk(KERN_ERR "failed to attach codec at addr %x\n", addr);
575 goto err;
576 }
577
578 ret = ak4535_init(socdev);
579 if (ret < 0) {
580 printk(KERN_ERR "failed to initialise AK4535\n");
581 goto err;
582 }
583 return ret;
584
585err:
586 kfree(codec);
587 kfree(i2c);
588 return ret;
589}
590
591static int ak4535_i2c_detach(struct i2c_client *client)
592{
593 struct snd_soc_codec *codec = i2c_get_clientdata(client);
594 i2c_detach_client(client);
595 kfree(codec->reg_cache);
596 kfree(client);
597 return 0;
598}
599
600static int ak4535_i2c_attach(struct i2c_adapter *adap)
601{
602 return i2c_probe(adap, &addr_data, ak4535_codec_probe);
603}
604
605/* corgi i2c codec control layer */
606static struct i2c_driver ak4535_i2c_driver = {
607 .driver = {
608 .name = "AK4535 I2C Codec",
609 .owner = THIS_MODULE,
610 },
611 .id = I2C_DRIVERID_AK4535,
612 .attach_adapter = ak4535_i2c_attach,
613 .detach_client = ak4535_i2c_detach,
614 .command = NULL,
615};
616
617static struct i2c_client client_template = {
618 .name = "AK4535",
619 .driver = &ak4535_i2c_driver,
620};
621#endif
622
623static int ak4535_probe(struct platform_device *pdev)
624{
625 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
626 struct ak4535_setup_data *setup;
627 struct snd_soc_codec *codec;
628 struct ak4535_priv *ak4535;
629 int ret = 0;
630
631 printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
632
633 setup = socdev->codec_data;
634 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
635 if (codec == NULL)
636 return -ENOMEM;
637
638 ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL);
639 if (ak4535 == NULL) {
640 kfree(codec);
641 return -ENOMEM;
642 }
643
644 codec->private_data = ak4535;
645 socdev->codec = codec;
646 mutex_init(&codec->mutex);
647 INIT_LIST_HEAD(&codec->dapm_widgets);
648 INIT_LIST_HEAD(&codec->dapm_paths);
649
650 ak4535_socdev = socdev;
651#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
652 if (setup->i2c_address) {
653 normal_i2c[0] = setup->i2c_address;
654 codec->hw_write = (hw_write_t)i2c_master_send;
655 codec->hw_read = (hw_read_t)i2c_master_recv;
656 ret = i2c_add_driver(&ak4535_i2c_driver);
657 if (ret != 0)
658 printk(KERN_ERR "can't add i2c driver");
659 }
660#else
661 /* Add other interfaces here */
662#endif
663 return ret;
664}
665
666/* power down chip */
667static int ak4535_remove(struct platform_device *pdev)
668{
669 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
670 struct snd_soc_codec *codec = socdev->codec;
671
672 if (codec->control_data)
673 ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
674
675 snd_soc_free_pcms(socdev);
676 snd_soc_dapm_free(socdev);
677#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
678 i2c_del_driver(&ak4535_i2c_driver);
679#endif
680 kfree(codec->private_data);
681 kfree(codec);
682
683 return 0;
684}
685
686struct snd_soc_codec_device soc_codec_dev_ak4535 = {
687 .probe = ak4535_probe,
688 .remove = ak4535_remove,
689 .suspend = ak4535_suspend,
690 .resume = ak4535_resume,
691};
692EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535);
693
694MODULE_DESCRIPTION("Soc AK4535 driver");
695MODULE_AUTHOR("Richard Purdie");
696MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h
new file mode 100644
index 000000000000..e9fe30e2c056
--- /dev/null
+++ b/sound/soc/codecs/ak4535.h
@@ -0,0 +1,46 @@
1/*
2 * ak4535.h -- AK4535 Soc Audio driver
3 *
4 * Copyright 2005 Openedhand Ltd.
5 *
6 * Author: Richard Purdie <richard@openedhand.com>
7 *
8 * Based on wm8753.h
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef _AK4535_H
16#define _AK4535_H
17
18/* AK4535 register space */
19
20#define AK4535_PM1 0x0
21#define AK4535_PM2 0x1
22#define AK4535_SIG1 0x2
23#define AK4535_SIG2 0x3
24#define AK4535_MODE1 0x4
25#define AK4535_MODE2 0x5
26#define AK4535_DAC 0x6
27#define AK4535_MIC 0x7
28#define AK4535_TIMER 0x8
29#define AK4535_ALC1 0x9
30#define AK4535_ALC2 0xa
31#define AK4535_PGA 0xb
32#define AK4535_LATT 0xc
33#define AK4535_RATT 0xd
34#define AK4535_VOL 0xe
35#define AK4535_STATUS 0xf
36
37#define AK4535_CACHEREGNUM 0x10
38
39struct ak4535_setup_data {
40 unsigned short i2c_address;
41};
42
43extern struct snd_soc_dai ak4535_dai;
44extern struct snd_soc_codec_device soc_codec_dev_ak4535;
45
46#endif
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index e73fcfd9f5cd..9deb8c74fdfd 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -201,7 +201,7 @@ static struct {
201 * driver what the input settings can be. This would need to be implemented 201 * driver what the input settings can be. This would need to be implemented
202 * for stand-alone mode to work. 202 * for stand-alone mode to work.
203 */ 203 */
204static int cs4270_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai, 204static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai,
205 int clk_id, unsigned int freq, int dir) 205 int clk_id, unsigned int freq, int dir)
206{ 206{
207 struct snd_soc_codec *codec = codec_dai->codec; 207 struct snd_soc_codec *codec = codec_dai->codec;
@@ -251,7 +251,7 @@ static int cs4270_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
251 * data for playback only, but ASoC currently does not support different 251 * data for playback only, but ASoC currently does not support different
252 * formats for playback vs. record. 252 * formats for playback vs. record.
253 */ 253 */
254static int cs4270_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 254static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
255 unsigned int format) 255 unsigned int format)
256{ 256{
257 struct snd_soc_codec *codec = codec_dai->codec; 257 struct snd_soc_codec *codec = codec_dai->codec;
@@ -471,7 +471,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
471 * board does not have the MUTEA or MUTEB pins connected to such circuitry, 471 * board does not have the MUTEA or MUTEB pins connected to such circuitry,
472 * then this function will do nothing. 472 * then this function will do nothing.
473 */ 473 */
474static int cs4270_mute(struct snd_soc_codec_dai *dai, int mute) 474static int cs4270_mute(struct snd_soc_dai *dai, int mute)
475{ 475{
476 struct snd_soc_codec *codec = dai->codec; 476 struct snd_soc_codec *codec = dai->codec;
477 int reg6; 477 int reg6;
@@ -667,7 +667,7 @@ error:
667 667
668#endif /* USE_I2C*/ 668#endif /* USE_I2C*/
669 669
670struct snd_soc_codec_dai cs4270_dai = { 670struct snd_soc_dai cs4270_dai = {
671 .name = "CS4270", 671 .name = "CS4270",
672 .playback = { 672 .playback = {
673 .stream_name = "Playback", 673 .stream_name = "Playback",
diff --git a/sound/soc/codecs/cs4270.h b/sound/soc/codecs/cs4270.h
index 0ced49b7804d..adc6cd9667d4 100644
--- a/sound/soc/codecs/cs4270.h
+++ b/sound/soc/codecs/cs4270.h
@@ -16,7 +16,7 @@
16 * The ASoC codec DAI structure for the CS4270. Assign this structure to 16 * The ASoC codec DAI structure for the CS4270. Assign this structure to
17 * the .codec_dai field of your machine driver's snd_soc_dai_link structure. 17 * the .codec_dai field of your machine driver's snd_soc_dai_link structure.
18 */ 18 */
19extern struct snd_soc_codec_dai cs4270_dai; 19extern struct snd_soc_dai cs4270_dai;
20 20
21/* 21/*
22 * The ASoC codec device structure for the CS4270. Assign this structure 22 * The ASoC codec device structure for the CS4270. Assign this structure
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 09b1661b8a3a..b1dce5f459db 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -29,7 +29,7 @@
29 * --------------------------------------- 29 * ---------------------------------------
30 * 30 *
31 * Hence the machine layer should disable unsupported inputs/outputs by 31 * Hence the machine layer should disable unsupported inputs/outputs by
32 * snd_soc_dapm_set_endpoint(codec, "MONO_LOUT", 0), etc. 32 * snd_soc_dapm_disable_pin(codec, "MONO_LOUT"), etc.
33 */ 33 */
34 34
35#include <linux/module.h> 35#include <linux/module.h>
@@ -49,7 +49,7 @@
49#include "tlv320aic3x.h" 49#include "tlv320aic3x.h"
50 50
51#define AUDIO_NAME "aic3x" 51#define AUDIO_NAME "aic3x"
52#define AIC3X_VERSION "0.1" 52#define AIC3X_VERSION "0.2"
53 53
54/* codec private data */ 54/* codec private data */
55struct aic3x_priv { 55struct aic3x_priv {
@@ -138,6 +138,20 @@ static int aic3x_write(struct snd_soc_codec *codec, unsigned int reg,
138 return -EIO; 138 return -EIO;
139} 139}
140 140
141/*
142 * read from the aic3x register space
143 */
144static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
145 u8 *value)
146{
147 *value = reg & 0xff;
148 if (codec->hw_read(codec->control_data, value, 1) != 1)
149 return -EIO;
150
151 aic3x_write_reg_cache(codec, reg, *value);
152 return 0;
153}
154
141#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ 155#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
142{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 156{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
143 .info = snd_soc_info_volsw, \ 157 .info = snd_soc_info_volsw, \
@@ -192,7 +206,7 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
192 } 206 }
193 207
194 if (found) 208 if (found)
195 snd_soc_dapm_sync_endpoints(widget->codec); 209 snd_soc_dapm_sync(widget->codec);
196 } 210 }
197 211
198 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); 212 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
@@ -209,6 +223,8 @@ static const char *aic3x_right_hpcom_mux[] =
209 { "differential of HPROUT", "constant VCM", "single-ended", 223 { "differential of HPROUT", "constant VCM", "single-ended",
210 "differential of HPLCOM", "external feedback" }; 224 "differential of HPLCOM", "external feedback" };
211static const char *aic3x_linein_mode_mux[] = { "single-ended", "differential" }; 225static const char *aic3x_linein_mode_mux[] = { "single-ended", "differential" };
226static const char *aic3x_adc_hpf[] =
227 { "Disabled", "0.0045xFs", "0.0125xFs", "0.025xFs" };
212 228
213#define LDAC_ENUM 0 229#define LDAC_ENUM 0
214#define RDAC_ENUM 1 230#define RDAC_ENUM 1
@@ -218,6 +234,7 @@ static const char *aic3x_linein_mode_mux[] = { "single-ended", "differential" };
218#define LINE1R_ENUM 5 234#define LINE1R_ENUM 5
219#define LINE2L_ENUM 6 235#define LINE2L_ENUM 6
220#define LINE2R_ENUM 7 236#define LINE2R_ENUM 7
237#define ADC_HPF_ENUM 8
221 238
222static const struct soc_enum aic3x_enum[] = { 239static const struct soc_enum aic3x_enum[] = {
223 SOC_ENUM_SINGLE(DAC_LINE_MUX, 6, 3, aic3x_left_dac_mux), 240 SOC_ENUM_SINGLE(DAC_LINE_MUX, 6, 3, aic3x_left_dac_mux),
@@ -228,6 +245,7 @@ static const struct soc_enum aic3x_enum[] = {
228 SOC_ENUM_SINGLE(LINE1R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), 245 SOC_ENUM_SINGLE(LINE1R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux),
229 SOC_ENUM_SINGLE(LINE2L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), 246 SOC_ENUM_SINGLE(LINE2L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux),
230 SOC_ENUM_SINGLE(LINE2R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), 247 SOC_ENUM_SINGLE(LINE2R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux),
248 SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf),
231}; 249};
232 250
233static const struct snd_kcontrol_new aic3x_snd_controls[] = { 251static const struct snd_kcontrol_new aic3x_snd_controls[] = {
@@ -278,6 +296,8 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
278 /* Input */ 296 /* Input */
279 SOC_DOUBLE_R("PGA Capture Volume", LADC_VOL, RADC_VOL, 0, 0x7f, 0), 297 SOC_DOUBLE_R("PGA Capture Volume", LADC_VOL, RADC_VOL, 0, 0x7f, 0),
280 SOC_DOUBLE_R("PGA Capture Switch", LADC_VOL, RADC_VOL, 7, 0x01, 1), 298 SOC_DOUBLE_R("PGA Capture Switch", LADC_VOL, RADC_VOL, 7, 0x01, 1),
299
300 SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]),
281}; 301};
282 302
283/* add non dapm controls */ 303/* add non dapm controls */
@@ -441,11 +461,34 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
441 SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0, 461 SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0,
442 &aic3x_right_line2_mux_controls), 462 &aic3x_right_line2_mux_controls),
443 463
464 /*
465 * Not a real mic bias widget but similar function. This is for dynamic
466 * control of GPIO1 digital mic modulator clock output function when
467 * using digital mic.
468 */
469 SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "GPIO1 dmic modclk",
470 AIC3X_GPIO1_REG, 4, 0xf,
471 AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK,
472 AIC3X_GPIO1_FUNC_DISABLED),
473
474 /*
475 * Also similar function like mic bias. Selects digital mic with
476 * configurable oversampling rate instead of ADC converter.
477 */
478 SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 128",
479 AIC3X_ASD_INTF_CTRLA, 0, 3, 1, 0),
480 SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 64",
481 AIC3X_ASD_INTF_CTRLA, 0, 3, 2, 0),
482 SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 32",
483 AIC3X_ASD_INTF_CTRLA, 0, 3, 3, 0),
484
444 /* Mic Bias */ 485 /* Mic Bias */
445 SND_SOC_DAPM_MICBIAS("Mic Bias 2V", MICBIAS_CTRL, 6, 0), 486 SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias 2V",
446 SND_SOC_DAPM_MICBIAS("Mic Bias 2.5V", MICBIAS_CTRL, 7, 0), 487 MICBIAS_CTRL, 6, 3, 1, 0),
447 SND_SOC_DAPM_MICBIAS("Mic Bias AVDD", MICBIAS_CTRL, 6, 0), 488 SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias 2.5V",
448 SND_SOC_DAPM_MICBIAS("Mic Bias AVDD", MICBIAS_CTRL, 7, 0), 489 MICBIAS_CTRL, 6, 3, 2, 0),
490 SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias AVDD",
491 MICBIAS_CTRL, 6, 3, 3, 0),
449 492
450 /* Left PGA to Left Output bypass */ 493 /* Left PGA to Left Output bypass */
451 SND_SOC_DAPM_MIXER("Left PGA Bypass Mixer", SND_SOC_NOPM, 0, 0, 494 SND_SOC_DAPM_MIXER("Left PGA Bypass Mixer", SND_SOC_NOPM, 0, 0,
@@ -483,7 +526,7 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
483 SND_SOC_DAPM_INPUT("LINE2R"), 526 SND_SOC_DAPM_INPUT("LINE2R"),
484}; 527};
485 528
486static const char *intercon[][3] = { 529static const struct snd_soc_dapm_route intercon[] = {
487 /* Left Output */ 530 /* Left Output */
488 {"Left DAC Mux", "DAC_L1", "Left DAC"}, 531 {"Left DAC Mux", "DAC_L1", "Left DAC"},
489 {"Left DAC Mux", "DAC_L2", "Left DAC"}, 532 {"Left DAC Mux", "DAC_L2", "Left DAC"},
@@ -554,6 +597,7 @@ static const char *intercon[][3] = {
554 {"Left PGA Mixer", "Mic3L Switch", "MIC3L"}, 597 {"Left PGA Mixer", "Mic3L Switch", "MIC3L"},
555 598
556 {"Left ADC", NULL, "Left PGA Mixer"}, 599 {"Left ADC", NULL, "Left PGA Mixer"},
600 {"Left ADC", NULL, "GPIO1 dmic modclk"},
557 601
558 /* Right Input */ 602 /* Right Input */
559 {"Right Line1R Mux", "single-ended", "LINE1R"}, 603 {"Right Line1R Mux", "single-ended", "LINE1R"},
@@ -567,6 +611,7 @@ static const char *intercon[][3] = {
567 {"Right PGA Mixer", "Mic3R Switch", "MIC3R"}, 611 {"Right PGA Mixer", "Mic3R Switch", "MIC3R"},
568 612
569 {"Right ADC", NULL, "Right PGA Mixer"}, 613 {"Right ADC", NULL, "Right PGA Mixer"},
614 {"Right ADC", NULL, "GPIO1 dmic modclk"},
570 615
571 /* Left PGA Bypass */ 616 /* Left PGA Bypass */
572 {"Left PGA Bypass Mixer", "Line Switch", "Left PGA Mixer"}, 617 {"Left PGA Bypass Mixer", "Line Switch", "Left PGA Mixer"},
@@ -628,101 +673,27 @@ static const char *intercon[][3] = {
628 {"Mono Out", NULL, "Right Line2 Bypass Mixer"}, 673 {"Mono Out", NULL, "Right Line2 Bypass Mixer"},
629 {"Right HP Out", NULL, "Right Line2 Bypass Mixer"}, 674 {"Right HP Out", NULL, "Right Line2 Bypass Mixer"},
630 675
631 /* terminator */ 676 /*
632 {NULL, NULL, NULL}, 677 * Logical path between digital mic enable and GPIO1 modulator clock
678 * output function
679 */
680 {"GPIO1 dmic modclk", NULL, "DMic Rate 128"},
681 {"GPIO1 dmic modclk", NULL, "DMic Rate 64"},
682 {"GPIO1 dmic modclk", NULL, "DMic Rate 32"},
633}; 683};
634 684
635static int aic3x_add_widgets(struct snd_soc_codec *codec) 685static int aic3x_add_widgets(struct snd_soc_codec *codec)
636{ 686{
637 int i; 687 snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
638 688 ARRAY_SIZE(aic3x_dapm_widgets));
639 for (i = 0; i < ARRAY_SIZE(aic3x_dapm_widgets); i++)
640 snd_soc_dapm_new_control(codec, &aic3x_dapm_widgets[i]);
641 689
642 /* set up audio path interconnects */ 690 /* set up audio path interconnects */
643 for (i = 0; intercon[i][0] != NULL; i++) 691 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
644 snd_soc_dapm_connect_input(codec, intercon[i][0],
645 intercon[i][1], intercon[i][2]);
646 692
647 snd_soc_dapm_new_widgets(codec); 693 snd_soc_dapm_new_widgets(codec);
648 return 0; 694 return 0;
649} 695}
650 696
651struct aic3x_rate_divs {
652 u32 mclk;
653 u32 rate;
654 u32 fsref_reg;
655 u8 sr_reg:4;
656 u8 pllj_reg;
657 u16 plld_reg;
658};
659
660/* AIC3X codec mclk clock divider coefficients */
661static const struct aic3x_rate_divs aic3x_divs[] = {
662 /* 8k */
663 {12000000, 8000, 48000, 0xa, 16, 3840},
664 {19200000, 8000, 48000, 0xa, 10, 2400},
665 {22579200, 8000, 48000, 0xa, 8, 7075},
666 {33868800, 8000, 48000, 0xa, 5, 8049},
667 /* 11.025k */
668 {12000000, 11025, 44100, 0x6, 15, 528},
669 {19200000, 11025, 44100, 0x6, 9, 4080},
670 {22579200, 11025, 44100, 0x6, 8, 0},
671 {33868800, 11025, 44100, 0x6, 5, 3333},
672 /* 16k */
673 {12000000, 16000, 48000, 0x4, 16, 3840},
674 {19200000, 16000, 48000, 0x4, 10, 2400},
675 {22579200, 16000, 48000, 0x4, 8, 7075},
676 {33868800, 16000, 48000, 0x4, 5, 8049},
677 /* 22.05k */
678 {12000000, 22050, 44100, 0x2, 15, 528},
679 {19200000, 22050, 44100, 0x2, 9, 4080},
680 {22579200, 22050, 44100, 0x2, 8, 0},
681 {33868800, 22050, 44100, 0x2, 5, 3333},
682 /* 32k */
683 {12000000, 32000, 48000, 0x1, 16, 3840},
684 {19200000, 32000, 48000, 0x1, 10, 2400},
685 {22579200, 32000, 48000, 0x1, 8, 7075},
686 {33868800, 32000, 48000, 0x1, 5, 8049},
687 /* 44.1k */
688 {12000000, 44100, 44100, 0x0, 15, 528},
689 {19200000, 44100, 44100, 0x0, 9, 4080},
690 {22579200, 44100, 44100, 0x0, 8, 0},
691 {33868800, 44100, 44100, 0x0, 5, 3333},
692 /* 48k */
693 {12000000, 48000, 48000, 0x0, 16, 3840},
694 {19200000, 48000, 48000, 0x0, 10, 2400},
695 {22579200, 48000, 48000, 0x0, 8, 7075},
696 {33868800, 48000, 48000, 0x0, 5, 8049},
697 /* 64k */
698 {12000000, 64000, 96000, 0x1, 16, 3840},
699 {19200000, 64000, 96000, 0x1, 10, 2400},
700 {22579200, 64000, 96000, 0x1, 8, 7075},
701 {33868800, 64000, 96000, 0x1, 5, 8049},
702 /* 88.2k */
703 {12000000, 88200, 88200, 0x0, 15, 528},
704 {19200000, 88200, 88200, 0x0, 9, 4080},
705 {22579200, 88200, 88200, 0x0, 8, 0},
706 {33868800, 88200, 88200, 0x0, 5, 3333},
707 /* 96k */
708 {12000000, 96000, 96000, 0x0, 16, 3840},
709 {19200000, 96000, 96000, 0x0, 10, 2400},
710 {22579200, 96000, 96000, 0x0, 8, 7075},
711 {33868800, 96000, 96000, 0x0, 5, 8049},
712};
713
714static inline int aic3x_get_divs(int mclk, int rate)
715{
716 int i;
717
718 for (i = 0; i < ARRAY_SIZE(aic3x_divs); i++) {
719 if (aic3x_divs[i].rate == rate && aic3x_divs[i].mclk == mclk)
720 return i;
721 }
722
723 return 0;
724}
725
726static int aic3x_hw_params(struct snd_pcm_substream *substream, 697static int aic3x_hw_params(struct snd_pcm_substream *substream,
727 struct snd_pcm_hw_params *params) 698 struct snd_pcm_hw_params *params)
728{ 699{
@@ -730,49 +701,107 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
730 struct snd_soc_device *socdev = rtd->socdev; 701 struct snd_soc_device *socdev = rtd->socdev;
731 struct snd_soc_codec *codec = socdev->codec; 702 struct snd_soc_codec *codec = socdev->codec;
732 struct aic3x_priv *aic3x = codec->private_data; 703 struct aic3x_priv *aic3x = codec->private_data;
733 int i; 704 int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
734 u8 data, pll_p, pll_r, pll_j; 705 u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
735 u16 pll_d; 706 u16 pll_d = 1;
736
737 i = aic3x_get_divs(aic3x->sysclk, params_rate(params));
738 707
739 /* Route Left DAC to left channel input and 708 /* select data word length */
740 * right DAC to right channel input */ 709 data =
741 data = (LDAC2LCH | RDAC2RCH); 710 aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4));
742 switch (aic3x_divs[i].fsref_reg) { 711 switch (params_format(params)) {
743 case 44100: 712 case SNDRV_PCM_FORMAT_S16_LE:
744 data |= FSREF_44100;
745 break; 713 break;
746 case 48000: 714 case SNDRV_PCM_FORMAT_S20_3LE:
747 data |= FSREF_48000; 715 data |= (0x01 << 4);
748 break; 716 break;
749 case 88200: 717 case SNDRV_PCM_FORMAT_S24_LE:
750 data |= FSREF_44100 | DUAL_RATE_MODE; 718 data |= (0x02 << 4);
751 break; 719 break;
752 case 96000: 720 case SNDRV_PCM_FORMAT_S32_LE:
753 data |= FSREF_48000 | DUAL_RATE_MODE; 721 data |= (0x03 << 4);
754 break; 722 break;
755 } 723 }
724 aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, data);
725
726 /* Fsref can be 44100 or 48000 */
727 fsref = (params_rate(params) % 11025 == 0) ? 44100 : 48000;
728
729 /* Try to find a value for Q which allows us to bypass the PLL and
730 * generate CODEC_CLK directly. */
731 for (pll_q = 2; pll_q < 18; pll_q++)
732 if (aic3x->sysclk / (128 * pll_q) == fsref) {
733 bypass_pll = 1;
734 break;
735 }
736
737 if (bypass_pll) {
738 pll_q &= 0xf;
739 aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
740 aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
741 } else
742 aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
743
744 /* Route Left DAC to left channel input and
745 * right DAC to right channel input */
746 data = (LDAC2LCH | RDAC2RCH);
747 data |= (fsref == 44100) ? FSREF_44100 : FSREF_48000;
748 if (params_rate(params) >= 64000)
749 data |= DUAL_RATE_MODE;
756 aic3x_write(codec, AIC3X_CODEC_DATAPATH_REG, data); 750 aic3x_write(codec, AIC3X_CODEC_DATAPATH_REG, data);
757 751
758 /* codec sample rate select */ 752 /* codec sample rate select */
759 data = aic3x_divs[i].sr_reg; 753 data = (fsref * 20) / params_rate(params);
754 if (params_rate(params) < 64000)
755 data /= 2;
756 data /= 5;
757 data -= 2;
760 data |= (data << 4); 758 data |= (data << 4);
761 aic3x_write(codec, AIC3X_SAMPLE_RATE_SEL_REG, data); 759 aic3x_write(codec, AIC3X_SAMPLE_RATE_SEL_REG, data);
762 760
763 /* Use PLL for generation Fsref by equation: 761 if (bypass_pll)
764 * Fsref = (MCLK * K * R)/(2048 * P); 762 return 0;
765 * Fix P = 2 and R = 1 and calculate K, if 763
766 * K = J.D, i.e. J - an interger portion of K and D is the fractional 764 /* Use PLL
767 * one with 4 digits of precision; 765 * find an apropriate setup for j, d, r and p by iterating over
768 * Example: 766 * p and r - j and d are calculated for each fraction.
769 * For MCLK = 22.5792 MHz and Fsref = 48kHz: 767 * Up to 128 values are probed, the closest one wins the game.
770 * Select P = 2, R= 1, K = 8.7074, which results in J = 8, D = 7074 768 * The sysclk is divided by 1000 to prevent integer overflows.
771 */ 769 */
772 pll_p = 2; 770 codec_clk = (2048 * fsref) / (aic3x->sysclk / 1000);
773 pll_r = 1; 771
774 pll_j = aic3x_divs[i].pllj_reg; 772 for (r = 1; r <= 16; r++)
775 pll_d = aic3x_divs[i].plld_reg; 773 for (p = 1; p <= 8; p++) {
774 int clk, tmp = (codec_clk * pll_r * 10) / pll_p;
775 u8 j = tmp / 10000;
776 u16 d = tmp % 10000;
777
778 if (j > 63)
779 continue;
780
781 if (d != 0 && aic3x->sysclk < 10000000)
782 continue;
783
784 /* This is actually 1000 * ((j + (d/10000)) * r) / p
785 * The term had to be converted to get rid of the
786 * division by 10000 */
787 clk = ((10000 * j * r) + (d * r)) / (10 * p);
788
789 /* check whether this values get closer than the best
790 * ones we had before */
791 if (abs(codec_clk - clk) < abs(codec_clk - last_clk)) {
792 pll_j = j; pll_d = d; pll_r = r; pll_p = p;
793 last_clk = clk;
794 }
795
796 /* Early exit for exact matches */
797 if (clk == codec_clk)
798 break;
799 }
800
801 if (last_clk == 0) {
802 printk(KERN_ERR "%s(): unable to setup PLL\n", __func__);
803 return -EINVAL;
804 }
776 805
777 data = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); 806 data = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
778 aic3x_write(codec, AIC3X_PLL_PROGA_REG, data | (pll_p << PLLP_SHIFT)); 807 aic3x_write(codec, AIC3X_PLL_PROGA_REG, data | (pll_p << PLLP_SHIFT));
@@ -782,28 +811,10 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
782 aic3x_write(codec, AIC3X_PLL_PROGD_REG, 811 aic3x_write(codec, AIC3X_PLL_PROGD_REG,
783 (pll_d & 0x3F) << PLLD_LSB_SHIFT); 812 (pll_d & 0x3F) << PLLD_LSB_SHIFT);
784 813
785 /* select data word length */
786 data =
787 aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4));
788 switch (params_format(params)) {
789 case SNDRV_PCM_FORMAT_S16_LE:
790 break;
791 case SNDRV_PCM_FORMAT_S20_3LE:
792 data |= (0x01 << 4);
793 break;
794 case SNDRV_PCM_FORMAT_S24_LE:
795 data |= (0x02 << 4);
796 break;
797 case SNDRV_PCM_FORMAT_S32_LE:
798 data |= (0x03 << 4);
799 break;
800 }
801 aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, data);
802
803 return 0; 814 return 0;
804} 815}
805 816
806static int aic3x_mute(struct snd_soc_codec_dai *dai, int mute) 817static int aic3x_mute(struct snd_soc_dai *dai, int mute)
807{ 818{
808 struct snd_soc_codec *codec = dai->codec; 819 struct snd_soc_codec *codec = dai->codec;
809 u8 ldac_reg = aic3x_read_reg_cache(codec, LDAC_VOL) & ~MUTE_ON; 820 u8 ldac_reg = aic3x_read_reg_cache(codec, LDAC_VOL) & ~MUTE_ON;
@@ -820,31 +831,25 @@ static int aic3x_mute(struct snd_soc_codec_dai *dai, int mute)
820 return 0; 831 return 0;
821} 832}
822 833
823static int aic3x_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai, 834static int aic3x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
824 int clk_id, unsigned int freq, int dir) 835 int clk_id, unsigned int freq, int dir)
825{ 836{
826 struct snd_soc_codec *codec = codec_dai->codec; 837 struct snd_soc_codec *codec = codec_dai->codec;
827 struct aic3x_priv *aic3x = codec->private_data; 838 struct aic3x_priv *aic3x = codec->private_data;
828 839
829 switch (freq) { 840 aic3x->sysclk = freq;
830 case 12000000: 841 return 0;
831 case 19200000:
832 case 22579200:
833 case 33868800:
834 aic3x->sysclk = freq;
835 return 0;
836 }
837
838 return -EINVAL;
839} 842}
840 843
841static int aic3x_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 844static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
842 unsigned int fmt) 845 unsigned int fmt)
843{ 846{
844 struct snd_soc_codec *codec = codec_dai->codec; 847 struct snd_soc_codec *codec = codec_dai->codec;
845 struct aic3x_priv *aic3x = codec->private_data; 848 struct aic3x_priv *aic3x = codec->private_data;
846 u8 iface_areg = 0; 849 u8 iface_areg, iface_breg;
847 u8 iface_breg = 0; 850
851 iface_areg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f;
852 iface_breg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f;
848 853
849 /* set master/slave audio interface */ 854 /* set master/slave audio interface */
850 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 855 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -883,13 +888,14 @@ static int aic3x_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
883 return 0; 888 return 0;
884} 889}
885 890
886static int aic3x_dapm_event(struct snd_soc_codec *codec, int event) 891static int aic3x_set_bias_level(struct snd_soc_codec *codec,
892 enum snd_soc_bias_level level)
887{ 893{
888 struct aic3x_priv *aic3x = codec->private_data; 894 struct aic3x_priv *aic3x = codec->private_data;
889 u8 reg; 895 u8 reg;
890 896
891 switch (event) { 897 switch (level) {
892 case SNDRV_CTL_POWER_D0: 898 case SND_SOC_BIAS_ON:
893 /* all power is driven by DAPM system */ 899 /* all power is driven by DAPM system */
894 if (aic3x->master) { 900 if (aic3x->master) {
895 /* enable pll */ 901 /* enable pll */
@@ -898,10 +904,9 @@ static int aic3x_dapm_event(struct snd_soc_codec *codec, int event)
898 reg | PLL_ENABLE); 904 reg | PLL_ENABLE);
899 } 905 }
900 break; 906 break;
901 case SNDRV_CTL_POWER_D1: 907 case SND_SOC_BIAS_PREPARE:
902 case SNDRV_CTL_POWER_D2:
903 break; 908 break;
904 case SNDRV_CTL_POWER_D3hot: 909 case SND_SOC_BIAS_STANDBY:
905 /* 910 /*
906 * all power is driven by DAPM system, 911 * all power is driven by DAPM system,
907 * so output power is safe if bypass was set 912 * so output power is safe if bypass was set
@@ -913,7 +918,7 @@ static int aic3x_dapm_event(struct snd_soc_codec *codec, int event)
913 reg & ~PLL_ENABLE); 918 reg & ~PLL_ENABLE);
914 } 919 }
915 break; 920 break;
916 case SNDRV_CTL_POWER_D3cold: 921 case SND_SOC_BIAS_OFF:
917 /* force all power off */ 922 /* force all power off */
918 reg = aic3x_read_reg_cache(codec, LINE1L_2_LADC_CTRL); 923 reg = aic3x_read_reg_cache(codec, LINE1L_2_LADC_CTRL);
919 aic3x_write(codec, LINE1L_2_LADC_CTRL, reg & ~LADC_PWR_ON); 924 aic3x_write(codec, LINE1L_2_LADC_CTRL, reg & ~LADC_PWR_ON);
@@ -949,16 +954,43 @@ static int aic3x_dapm_event(struct snd_soc_codec *codec, int event)
949 } 954 }
950 break; 955 break;
951 } 956 }
952 codec->dapm_state = event; 957 codec->bias_level = level;
953 958
954 return 0; 959 return 0;
955} 960}
956 961
962void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state)
963{
964 u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
965 u8 bit = gpio ? 3: 0;
966 u8 val = aic3x_read_reg_cache(codec, reg) & ~(1 << bit);
967 aic3x_write(codec, reg, val | (!!state << bit));
968}
969EXPORT_SYMBOL_GPL(aic3x_set_gpio);
970
971int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
972{
973 u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
974 u8 val, bit = gpio ? 2: 1;
975
976 aic3x_read(codec, reg, &val);
977 return (val >> bit) & 1;
978}
979EXPORT_SYMBOL_GPL(aic3x_get_gpio);
980
981int aic3x_headset_detected(struct snd_soc_codec *codec)
982{
983 u8 val;
984 aic3x_read(codec, AIC3X_RT_IRQ_FLAGS_REG, &val);
985 return (val >> 2) & 1;
986}
987EXPORT_SYMBOL_GPL(aic3x_headset_detected);
988
957#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000 989#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
958#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 990#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
959 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) 991 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
960 992
961struct snd_soc_codec_dai aic3x_dai = { 993struct snd_soc_dai aic3x_dai = {
962 .name = "aic3x", 994 .name = "aic3x",
963 .playback = { 995 .playback = {
964 .stream_name = "Playback", 996 .stream_name = "Playback",
@@ -988,7 +1020,7 @@ static int aic3x_suspend(struct platform_device *pdev, pm_message_t state)
988 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1020 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
989 struct snd_soc_codec *codec = socdev->codec; 1021 struct snd_soc_codec *codec = socdev->codec;
990 1022
991 aic3x_dapm_event(codec, SNDRV_CTL_POWER_D3cold); 1023 aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
992 1024
993 return 0; 1025 return 0;
994} 1026}
@@ -1008,7 +1040,7 @@ static int aic3x_resume(struct platform_device *pdev)
1008 codec->hw_write(codec->control_data, data, 2); 1040 codec->hw_write(codec->control_data, data, 2);
1009 } 1041 }
1010 1042
1011 aic3x_dapm_event(codec, codec->suspend_dapm_state); 1043 aic3x_set_bias_level(codec, codec->suspend_bias_level);
1012 1044
1013 return 0; 1045 return 0;
1014} 1046}
@@ -1020,16 +1052,17 @@ static int aic3x_resume(struct platform_device *pdev)
1020static int aic3x_init(struct snd_soc_device *socdev) 1052static int aic3x_init(struct snd_soc_device *socdev)
1021{ 1053{
1022 struct snd_soc_codec *codec = socdev->codec; 1054 struct snd_soc_codec *codec = socdev->codec;
1055 struct aic3x_setup_data *setup = socdev->codec_data;
1023 int reg, ret = 0; 1056 int reg, ret = 0;
1024 1057
1025 codec->name = "aic3x"; 1058 codec->name = "aic3x";
1026 codec->owner = THIS_MODULE; 1059 codec->owner = THIS_MODULE;
1027 codec->read = aic3x_read_reg_cache; 1060 codec->read = aic3x_read_reg_cache;
1028 codec->write = aic3x_write; 1061 codec->write = aic3x_write;
1029 codec->dapm_event = aic3x_dapm_event; 1062 codec->set_bias_level = aic3x_set_bias_level;
1030 codec->dai = &aic3x_dai; 1063 codec->dai = &aic3x_dai;
1031 codec->num_dai = 1; 1064 codec->num_dai = 1;
1032 codec->reg_cache_size = sizeof(aic3x_reg); 1065 codec->reg_cache_size = ARRAY_SIZE(aic3x_reg);
1033 codec->reg_cache = kmemdup(aic3x_reg, sizeof(aic3x_reg), GFP_KERNEL); 1066 codec->reg_cache = kmemdup(aic3x_reg, sizeof(aic3x_reg), GFP_KERNEL);
1034 if (codec->reg_cache == NULL) 1067 if (codec->reg_cache == NULL)
1035 return -ENOMEM; 1068 return -ENOMEM;
@@ -1108,7 +1141,11 @@ static int aic3x_init(struct snd_soc_device *socdev)
1108 aic3x_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL); 1141 aic3x_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
1109 1142
1110 /* off, with power on */ 1143 /* off, with power on */
1111 aic3x_dapm_event(codec, SNDRV_CTL_POWER_D3hot); 1144 aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1145
1146 /* setup GPIO functions */
1147 aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4);
1148 aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4);
1112 1149
1113 aic3x_add_controls(codec); 1150 aic3x_add_controls(codec);
1114 aic3x_add_widgets(codec); 1151 aic3x_add_widgets(codec);
@@ -1217,6 +1254,12 @@ static struct i2c_client client_template = {
1217 .name = "AIC3X", 1254 .name = "AIC3X",
1218 .driver = &aic3x_i2c_driver, 1255 .driver = &aic3x_i2c_driver,
1219}; 1256};
1257
1258static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len)
1259{
1260 value[0] = i2c_smbus_read_byte_data(client, value[0]);
1261 return (len == 1);
1262}
1220#endif 1263#endif
1221 1264
1222static int aic3x_probe(struct platform_device *pdev) 1265static int aic3x_probe(struct platform_device *pdev)
@@ -1251,6 +1294,7 @@ static int aic3x_probe(struct platform_device *pdev)
1251 if (setup->i2c_address) { 1294 if (setup->i2c_address) {
1252 normal_i2c[0] = setup->i2c_address; 1295 normal_i2c[0] = setup->i2c_address;
1253 codec->hw_write = (hw_write_t) i2c_master_send; 1296 codec->hw_write = (hw_write_t) i2c_master_send;
1297 codec->hw_read = (hw_read_t) aic3x_i2c_read;
1254 ret = i2c_add_driver(&aic3x_i2c_driver); 1298 ret = i2c_add_driver(&aic3x_i2c_driver);
1255 if (ret != 0) 1299 if (ret != 0)
1256 printk(KERN_ERR "can't add i2c driver"); 1300 printk(KERN_ERR "can't add i2c driver");
@@ -1268,7 +1312,7 @@ static int aic3x_remove(struct platform_device *pdev)
1268 1312
1269 /* power down chip */ 1313 /* power down chip */
1270 if (codec->control_data) 1314 if (codec->control_data)
1271 aic3x_dapm_event(codec, SNDRV_CTL_POWER_D3); 1315 aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
1272 1316
1273 snd_soc_free_pcms(socdev); 1317 snd_soc_free_pcms(socdev);
1274 snd_soc_dapm_free(socdev); 1318 snd_soc_dapm_free(socdev);
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index d0cdeeb629de..d76c079b86e7 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -37,6 +37,8 @@
37#define AIC3X_ASD_INTF_CTRLB 9 37#define AIC3X_ASD_INTF_CTRLB 9
38/* Audio overflow status and PLL R value programming register */ 38/* Audio overflow status and PLL R value programming register */
39#define AIC3X_OVRF_STATUS_AND_PLLR_REG 11 39#define AIC3X_OVRF_STATUS_AND_PLLR_REG 11
40/* Audio codec digital filter control register */
41#define AIC3X_CODEC_DFILT_CTRL 12
40 42
41/* ADC PGA Gain control registers */ 43/* ADC PGA Gain control registers */
42#define LADC_VOL 15 44#define LADC_VOL 15
@@ -108,6 +110,13 @@
108#define DACR1_2_RLOPM_VOL 92 110#define DACR1_2_RLOPM_VOL 92
109#define LLOPM_CTRL 86 111#define LLOPM_CTRL 86
110#define RLOPM_CTRL 93 112#define RLOPM_CTRL 93
113/* GPIO/IRQ registers */
114#define AIC3X_STICKY_IRQ_FLAGS_REG 96
115#define AIC3X_RT_IRQ_FLAGS_REG 97
116#define AIC3X_GPIO1_REG 98
117#define AIC3X_GPIO2_REG 99
118#define AIC3X_GPIOA_REG 100
119#define AIC3X_GPIOB_REG 101
111/* Clock generation control register */ 120/* Clock generation control register */
112#define AIC3X_CLKGEN_CTRL_REG 102 121#define AIC3X_CLKGEN_CTRL_REG 102
113 122
@@ -128,12 +137,15 @@
128 137
129/* PLL registers bitfields */ 138/* PLL registers bitfields */
130#define PLLP_SHIFT 0 139#define PLLP_SHIFT 0
140#define PLLQ_SHIFT 3
131#define PLLR_SHIFT 0 141#define PLLR_SHIFT 0
132#define PLLJ_SHIFT 2 142#define PLLJ_SHIFT 2
133#define PLLD_MSB_SHIFT 0 143#define PLLD_MSB_SHIFT 0
134#define PLLD_LSB_SHIFT 2 144#define PLLD_LSB_SHIFT 2
135 145
136/* Clock generation register bits */ 146/* Clock generation register bits */
147#define CODEC_CLKIN_PLLDIV 0
148#define CODEC_CLKIN_CLKDIV 1
137#define PLL_CLKIN_SHIFT 4 149#define PLL_CLKIN_SHIFT 4
138#define MCLK_SOURCE 0x0 150#define MCLK_SOURCE 0x0
139#define PLL_CLKDIV_SHIFT 0 151#define PLL_CLKDIV_SHIFT 0
@@ -171,11 +183,52 @@
171/* Default input volume */ 183/* Default input volume */
172#define DEFAULT_GAIN 0x20 184#define DEFAULT_GAIN 0x20
173 185
186/* GPIO API */
187enum {
188 AIC3X_GPIO1_FUNC_DISABLED = 0,
189 AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC = 1,
190 AIC3X_GPIO1_FUNC_CLOCK_MUX = 2,
191 AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2 = 3,
192 AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4 = 4,
193 AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8 = 5,
194 AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ = 6,
195 AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ = 7,
196 AIC3X_GPIO1_FUNC_INPUT = 8,
197 AIC3X_GPIO1_FUNC_OUTPUT = 9,
198 AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK = 10,
199 AIC3X_GPIO1_FUNC_AUDIO_WORDCLK = 11,
200 AIC3X_GPIO1_FUNC_BUTTON_IRQ = 12,
201 AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ = 13,
202 AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 14,
203 AIC3X_GPIO1_FUNC_ALL_IRQ = 16
204};
205
206enum {
207 AIC3X_GPIO2_FUNC_DISABLED = 0,
208 AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ = 2,
209 AIC3X_GPIO2_FUNC_INPUT = 3,
210 AIC3X_GPIO2_FUNC_OUTPUT = 4,
211 AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT = 5,
212 AIC3X_GPIO2_FUNC_AUDIO_BITCLK = 8,
213 AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9,
214 AIC3X_GPIO2_FUNC_ALL_IRQ = 10,
215 AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11,
216 AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12,
217 AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ = 13,
218 AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ = 14,
219 AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ = 15
220};
221
222void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
223int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
224int aic3x_headset_detected(struct snd_soc_codec *codec);
225
174struct aic3x_setup_data { 226struct aic3x_setup_data {
175 unsigned short i2c_address; 227 unsigned short i2c_address;
228 unsigned int gpio_func[2];
176}; 229};
177 230
178extern struct snd_soc_codec_dai aic3x_dai; 231extern struct snd_soc_dai aic3x_dai;
179extern struct snd_soc_codec_device soc_codec_dev_aic3x; 232extern struct snd_soc_codec_device soc_codec_dev_aic3x;
180 233
181#endif /* _AIC3X_H */ 234#endif /* _AIC3X_H */
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
new file mode 100644
index 000000000000..a52d6d9e007a
--- /dev/null
+++ b/sound/soc/codecs/uda1380.c
@@ -0,0 +1,852 @@
1/*
2 * uda1380.c - Philips UDA1380 ALSA SoC audio driver
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Copyright (c) 2007 Philipp Zabel <philipp.zabel@gmail.com>
9 * Improved support for DAPM and audio routing/mixing capabilities,
10 * added TLV support.
11 *
12 * Modified by Richard Purdie <richard@openedhand.com> to fit into SoC
13 * codec model.
14 *
15 * Copyright (c) 2005 Giorgio Padrin <giorgio@mandarinlogiq.org>
16 * Copyright 2005 Openedhand Ltd.
17 */
18
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/types.h>
22#include <linux/string.h>
23#include <linux/slab.h>
24#include <linux/errno.h>
25#include <linux/ioctl.h>
26#include <linux/delay.h>
27#include <linux/i2c.h>
28#include <sound/core.h>
29#include <sound/control.h>
30#include <sound/initval.h>
31#include <sound/info.h>
32#include <sound/soc.h>
33#include <sound/soc-dapm.h>
34#include <sound/tlv.h>
35
36#include "uda1380.h"
37
38#define UDA1380_VERSION "0.6"
39#define AUDIO_NAME "uda1380"
40
41/*
42 * uda1380 register cache
43 */
44static const u16 uda1380_reg[UDA1380_CACHEREGNUM] = {
45 0x0502, 0x0000, 0x0000, 0x3f3f,
46 0x0202, 0x0000, 0x0000, 0x0000,
47 0x0000, 0x0000, 0x0000, 0x0000,
48 0x0000, 0x0000, 0x0000, 0x0000,
49 0x0000, 0xff00, 0x0000, 0x4800,
50 0x0000, 0x0000, 0x0000, 0x0000,
51 0x0000, 0x0000, 0x0000, 0x0000,
52 0x0000, 0x0000, 0x0000, 0x0000,
53 0x0000, 0x8000, 0x0002, 0x0000,
54};
55
56/*
57 * read uda1380 register cache
58 */
59static inline unsigned int uda1380_read_reg_cache(struct snd_soc_codec *codec,
60 unsigned int reg)
61{
62 u16 *cache = codec->reg_cache;
63 if (reg == UDA1380_RESET)
64 return 0;
65 if (reg >= UDA1380_CACHEREGNUM)
66 return -1;
67 return cache[reg];
68}
69
70/*
71 * write uda1380 register cache
72 */
73static inline void uda1380_write_reg_cache(struct snd_soc_codec *codec,
74 u16 reg, unsigned int value)
75{
76 u16 *cache = codec->reg_cache;
77 if (reg >= UDA1380_CACHEREGNUM)
78 return;
79 cache[reg] = value;
80}
81
82/*
83 * write to the UDA1380 register space
84 */
85static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
86 unsigned int value)
87{
88 u8 data[3];
89
90 /* data is
91 * data[0] is register offset
92 * data[1] is MS byte
93 * data[2] is LS byte
94 */
95 data[0] = reg;
96 data[1] = (value & 0xff00) >> 8;
97 data[2] = value & 0x00ff;
98
99 uda1380_write_reg_cache(codec, reg, value);
100
101 /* the interpolator & decimator regs must only be written when the
102 * codec DAI is active.
103 */
104 if (!codec->active && (reg >= UDA1380_MVOL))
105 return 0;
106 pr_debug("uda1380: hw write %x val %x\n", reg, value);
107 if (codec->hw_write(codec->control_data, data, 3) == 3) {
108 unsigned int val;
109 i2c_master_send(codec->control_data, data, 1);
110 i2c_master_recv(codec->control_data, data, 2);
111 val = (data[0]<<8) | data[1];
112 if (val != value) {
113 pr_debug("uda1380: READ BACK VAL %x\n",
114 (data[0]<<8) | data[1]);
115 return -EIO;
116 }
117 return 0;
118 } else
119 return -EIO;
120}
121
122#define uda1380_reset(c) uda1380_write(c, UDA1380_RESET, 0)
123
124/* declarations of ALSA reg_elem_REAL controls */
125static const char *uda1380_deemp[] = {
126 "None",
127 "32kHz",
128 "44.1kHz",
129 "48kHz",
130 "96kHz",
131};
132static const char *uda1380_input_sel[] = {
133 "Line",
134 "Mic + Line R",
135 "Line L",
136 "Mic",
137};
138static const char *uda1380_output_sel[] = {
139 "DAC",
140 "Analog Mixer",
141};
142static const char *uda1380_spf_mode[] = {
143 "Flat",
144 "Minimum1",
145 "Minimum2",
146 "Maximum"
147};
148static const char *uda1380_capture_sel[] = {
149 "ADC",
150 "Digital Mixer"
151};
152static const char *uda1380_sel_ns[] = {
153 "3rd-order",
154 "5th-order"
155};
156static const char *uda1380_mix_control[] = {
157 "off",
158 "PCM only",
159 "before sound processing",
160 "after sound processing"
161};
162static const char *uda1380_sdet_setting[] = {
163 "3200",
164 "4800",
165 "9600",
166 "19200"
167};
168static const char *uda1380_os_setting[] = {
169 "single-speed",
170 "double-speed (no mixing)",
171 "quad-speed (no mixing)"
172};
173
174static const struct soc_enum uda1380_deemp_enum[] = {
175 SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, 5, uda1380_deemp),
176 SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, 5, uda1380_deemp),
177};
178static const struct soc_enum uda1380_input_sel_enum =
179 SOC_ENUM_SINGLE(UDA1380_ADC, 2, 4, uda1380_input_sel); /* SEL_MIC, SEL_LNA */
180static const struct soc_enum uda1380_output_sel_enum =
181 SOC_ENUM_SINGLE(UDA1380_PM, 7, 2, uda1380_output_sel); /* R02_EN_AVC */
182static const struct soc_enum uda1380_spf_enum =
183 SOC_ENUM_SINGLE(UDA1380_MODE, 14, 4, uda1380_spf_mode); /* M */
184static const struct soc_enum uda1380_capture_sel_enum =
185 SOC_ENUM_SINGLE(UDA1380_IFACE, 6, 2, uda1380_capture_sel); /* SEL_SOURCE */
186static const struct soc_enum uda1380_sel_ns_enum =
187 SOC_ENUM_SINGLE(UDA1380_MIXER, 14, 2, uda1380_sel_ns); /* SEL_NS */
188static const struct soc_enum uda1380_mix_enum =
189 SOC_ENUM_SINGLE(UDA1380_MIXER, 12, 4, uda1380_mix_control); /* MIX, MIX_POS */
190static const struct soc_enum uda1380_sdet_enum =
191 SOC_ENUM_SINGLE(UDA1380_MIXER, 4, 4, uda1380_sdet_setting); /* SD_VALUE */
192static const struct soc_enum uda1380_os_enum =
193 SOC_ENUM_SINGLE(UDA1380_MIXER, 0, 3, uda1380_os_setting); /* OS */
194
195/*
196 * from -48 dB in 1.5 dB steps (mute instead of -49.5 dB)
197 */
198static DECLARE_TLV_DB_SCALE(amix_tlv, -4950, 150, 1);
199
200/*
201 * from -78 dB in 1 dB steps (3 dB steps, really. LSB are ignored),
202 * from -66 dB in 0.5 dB steps (2 dB steps, really) and
203 * from -52 dB in 0.25 dB steps
204 */
205static const unsigned int mvol_tlv[] = {
206 TLV_DB_RANGE_HEAD(3),
207 0, 15, TLV_DB_SCALE_ITEM(-8200, 100, 1),
208 16, 43, TLV_DB_SCALE_ITEM(-6600, 50, 0),
209 44, 252, TLV_DB_SCALE_ITEM(-5200, 25, 0),
210};
211
212/*
213 * from -72 dB in 1.5 dB steps (6 dB steps really),
214 * from -66 dB in 0.75 dB steps (3 dB steps really),
215 * from -60 dB in 0.5 dB steps (2 dB steps really) and
216 * from -46 dB in 0.25 dB steps
217 */
218static const unsigned int vc_tlv[] = {
219 TLV_DB_RANGE_HEAD(4),
220 0, 7, TLV_DB_SCALE_ITEM(-7800, 150, 1),
221 8, 15, TLV_DB_SCALE_ITEM(-6600, 75, 0),
222 16, 43, TLV_DB_SCALE_ITEM(-6000, 50, 0),
223 44, 228, TLV_DB_SCALE_ITEM(-4600, 25, 0),
224};
225
226/* from 0 to 6 dB in 2 dB steps if SPF mode != flat */
227static DECLARE_TLV_DB_SCALE(tr_tlv, 0, 200, 0);
228
229/* from 0 to 24 dB in 2 dB steps, if SPF mode == maximum, otherwise cuts
230 * off at 18 dB max) */
231static DECLARE_TLV_DB_SCALE(bb_tlv, 0, 200, 0);
232
233/* from -63 to 24 dB in 0.5 dB steps (-128...48) */
234static DECLARE_TLV_DB_SCALE(dec_tlv, -6400, 50, 1);
235
236/* from 0 to 24 dB in 3 dB steps */
237static DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0);
238
239/* from 0 to 30 dB in 2 dB steps */
240static DECLARE_TLV_DB_SCALE(vga_tlv, 0, 200, 0);
241
242static const struct snd_kcontrol_new uda1380_snd_controls[] = {
243 SOC_DOUBLE_TLV("Analog Mixer Volume", UDA1380_AMIX, 0, 8, 44, 1, amix_tlv), /* AVCR, AVCL */
244 SOC_DOUBLE_TLV("Master Playback Volume", UDA1380_MVOL, 0, 8, 252, 1, mvol_tlv), /* MVCL, MVCR */
245 SOC_SINGLE_TLV("ADC Playback Volume", UDA1380_MIXVOL, 8, 228, 1, vc_tlv), /* VC2 */
246 SOC_SINGLE_TLV("PCM Playback Volume", UDA1380_MIXVOL, 0, 228, 1, vc_tlv), /* VC1 */
247 SOC_ENUM("Sound Processing Filter", uda1380_spf_enum), /* M */
248 SOC_DOUBLE_TLV("Tone Control - Treble", UDA1380_MODE, 4, 12, 3, 0, tr_tlv), /* TRL, TRR */
249 SOC_DOUBLE_TLV("Tone Control - Bass", UDA1380_MODE, 0, 8, 15, 0, bb_tlv), /* BBL, BBR */
250/**/ SOC_SINGLE("Master Playback Switch", UDA1380_DEEMP, 14, 1, 1), /* MTM */
251 SOC_SINGLE("ADC Playback Switch", UDA1380_DEEMP, 11, 1, 1), /* MT2 from decimation filter */
252 SOC_ENUM("ADC Playback De-emphasis", uda1380_deemp_enum[0]), /* DE2 */
253 SOC_SINGLE("PCM Playback Switch", UDA1380_DEEMP, 3, 1, 1), /* MT1, from digital data input */
254 SOC_ENUM("PCM Playback De-emphasis", uda1380_deemp_enum[1]), /* DE1 */
255 SOC_SINGLE("DAC Polarity inverting Switch", UDA1380_MIXER, 15, 1, 0), /* DA_POL_INV */
256 SOC_ENUM("Noise Shaper", uda1380_sel_ns_enum), /* SEL_NS */
257 SOC_ENUM("Digital Mixer Signal Control", uda1380_mix_enum), /* MIX_POS, MIX */
258 SOC_SINGLE("Silence Switch", UDA1380_MIXER, 7, 1, 0), /* SILENCE, force DAC output to silence */
259 SOC_SINGLE("Silence Detector Switch", UDA1380_MIXER, 6, 1, 0), /* SDET_ON */
260 SOC_ENUM("Silence Detector Setting", uda1380_sdet_enum), /* SD_VALUE */
261 SOC_ENUM("Oversampling Input", uda1380_os_enum), /* OS */
262 SOC_DOUBLE_S8_TLV("ADC Capture Volume", UDA1380_DEC, -128, 48, dec_tlv), /* ML_DEC, MR_DEC */
263/**/ SOC_SINGLE("ADC Capture Switch", UDA1380_PGA, 15, 1, 1), /* MT_ADC */
264 SOC_DOUBLE_TLV("Line Capture Volume", UDA1380_PGA, 0, 8, 8, 0, pga_tlv), /* PGA_GAINCTRLL, PGA_GAINCTRLR */
265 SOC_SINGLE("ADC Polarity inverting Switch", UDA1380_ADC, 12, 1, 0), /* ADCPOL_INV */
266 SOC_SINGLE_TLV("Mic Capture Volume", UDA1380_ADC, 8, 15, 0, vga_tlv), /* VGA_CTRL */
267 SOC_SINGLE("DC Filter Bypass Switch", UDA1380_ADC, 1, 1, 0), /* SKIP_DCFIL (before decimator) */
268 SOC_SINGLE("DC Filter Enable Switch", UDA1380_ADC, 0, 1, 0), /* EN_DCFIL (at output of decimator) */
269 SOC_SINGLE("AGC Timing", UDA1380_AGC, 8, 7, 0), /* TODO: enum, see table 62 */
270 SOC_SINGLE("AGC Target level", UDA1380_AGC, 2, 3, 1), /* AGC_LEVEL */
271 /* -5.5, -8, -11.5, -14 dBFS */
272 SOC_SINGLE("AGC Switch", UDA1380_AGC, 0, 1, 0),
273};
274
275/* add non dapm controls */
276static int uda1380_add_controls(struct snd_soc_codec *codec)
277{
278 int err, i;
279
280 for (i = 0; i < ARRAY_SIZE(uda1380_snd_controls); i++) {
281 err = snd_ctl_add(codec->card,
282 snd_soc_cnew(&uda1380_snd_controls[i], codec, NULL));
283 if (err < 0)
284 return err;
285 }
286
287 return 0;
288}
289
290/* Input mux */
291static const struct snd_kcontrol_new uda1380_input_mux_control =
292 SOC_DAPM_ENUM("Route", uda1380_input_sel_enum);
293
294/* Output mux */
295static const struct snd_kcontrol_new uda1380_output_mux_control =
296 SOC_DAPM_ENUM("Route", uda1380_output_sel_enum);
297
298/* Capture mux */
299static const struct snd_kcontrol_new uda1380_capture_mux_control =
300 SOC_DAPM_ENUM("Route", uda1380_capture_sel_enum);
301
302
303static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
304 SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0,
305 &uda1380_input_mux_control),
306 SND_SOC_DAPM_MUX("Output Mux", SND_SOC_NOPM, 0, 0,
307 &uda1380_output_mux_control),
308 SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0,
309 &uda1380_capture_mux_control),
310 SND_SOC_DAPM_PGA("Left PGA", UDA1380_PM, 3, 0, NULL, 0),
311 SND_SOC_DAPM_PGA("Right PGA", UDA1380_PM, 1, 0, NULL, 0),
312 SND_SOC_DAPM_PGA("Mic LNA", UDA1380_PM, 4, 0, NULL, 0),
313 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", UDA1380_PM, 2, 0),
314 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", UDA1380_PM, 0, 0),
315 SND_SOC_DAPM_INPUT("VINM"),
316 SND_SOC_DAPM_INPUT("VINL"),
317 SND_SOC_DAPM_INPUT("VINR"),
318 SND_SOC_DAPM_MIXER("Analog Mixer", UDA1380_PM, 6, 0, NULL, 0),
319 SND_SOC_DAPM_OUTPUT("VOUTLHP"),
320 SND_SOC_DAPM_OUTPUT("VOUTRHP"),
321 SND_SOC_DAPM_OUTPUT("VOUTL"),
322 SND_SOC_DAPM_OUTPUT("VOUTR"),
323 SND_SOC_DAPM_DAC("DAC", "Playback", UDA1380_PM, 10, 0),
324 SND_SOC_DAPM_PGA("HeadPhone Driver", UDA1380_PM, 13, 0, NULL, 0),
325};
326
327static const struct snd_soc_dapm_route audio_map[] = {
328
329 /* output mux */
330 {"HeadPhone Driver", NULL, "Output Mux"},
331 {"VOUTR", NULL, "Output Mux"},
332 {"VOUTL", NULL, "Output Mux"},
333
334 {"Analog Mixer", NULL, "VINR"},
335 {"Analog Mixer", NULL, "VINL"},
336 {"Analog Mixer", NULL, "DAC"},
337
338 {"Output Mux", "DAC", "DAC"},
339 {"Output Mux", "Analog Mixer", "Analog Mixer"},
340
341 /* {"DAC", "Digital Mixer", "I2S" } */
342
343 /* headphone driver */
344 {"VOUTLHP", NULL, "HeadPhone Driver"},
345 {"VOUTRHP", NULL, "HeadPhone Driver"},
346
347 /* input mux */
348 {"Left ADC", NULL, "Input Mux"},
349 {"Input Mux", "Mic", "Mic LNA"},
350 {"Input Mux", "Mic + Line R", "Mic LNA"},
351 {"Input Mux", "Line L", "Left PGA"},
352 {"Input Mux", "Line", "Left PGA"},
353
354 /* right input */
355 {"Right ADC", "Mic + Line R", "Right PGA"},
356 {"Right ADC", "Line", "Right PGA"},
357
358 /* inputs */
359 {"Mic LNA", NULL, "VINM"},
360 {"Left PGA", NULL, "VINL"},
361 {"Right PGA", NULL, "VINR"},
362};
363
364static int uda1380_add_widgets(struct snd_soc_codec *codec)
365{
366 snd_soc_dapm_new_controls(codec, uda1380_dapm_widgets,
367 ARRAY_SIZE(uda1380_dapm_widgets));
368
369 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
370
371 snd_soc_dapm_new_widgets(codec);
372 return 0;
373}
374
375static int uda1380_set_dai_fmt(struct snd_soc_dai *codec_dai,
376 unsigned int fmt)
377{
378 struct snd_soc_codec *codec = codec_dai->codec;
379 int iface;
380
381 /* set up DAI based upon fmt */
382 iface = uda1380_read_reg_cache(codec, UDA1380_IFACE);
383 iface &= ~(R01_SFORI_MASK | R01_SIM | R01_SFORO_MASK);
384
385 /* FIXME: how to select I2S for DATAO and MSB for DATAI correctly? */
386 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
387 case SND_SOC_DAIFMT_I2S:
388 iface |= R01_SFORI_I2S | R01_SFORO_I2S;
389 break;
390 case SND_SOC_DAIFMT_LSB:
391 iface |= R01_SFORI_LSB16 | R01_SFORO_I2S;
392 break;
393 case SND_SOC_DAIFMT_MSB:
394 iface |= R01_SFORI_MSB | R01_SFORO_I2S;
395 }
396
397 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM)
398 iface |= R01_SIM;
399
400 uda1380_write(codec, UDA1380_IFACE, iface);
401
402 return 0;
403}
404
405/*
406 * Flush reg cache
407 * We can only write the interpolator and decimator registers
408 * when the DAI is being clocked by the CPU DAI. It's up to the
409 * machine and cpu DAI driver to do this before we are called.
410 */
411static int uda1380_pcm_prepare(struct snd_pcm_substream *substream)
412{
413 struct snd_soc_pcm_runtime *rtd = substream->private_data;
414 struct snd_soc_device *socdev = rtd->socdev;
415 struct snd_soc_codec *codec = socdev->codec;
416 int reg, reg_start, reg_end, clk;
417
418 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
419 reg_start = UDA1380_MVOL;
420 reg_end = UDA1380_MIXER;
421 } else {
422 reg_start = UDA1380_DEC;
423 reg_end = UDA1380_AGC;
424 }
425
426 /* FIXME disable DAC_CLK */
427 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
428 uda1380_write(codec, UDA1380_CLK, clk & ~R00_DAC_CLK);
429
430 for (reg = reg_start; reg <= reg_end; reg++) {
431 pr_debug("uda1380: flush reg %x val %x:", reg,
432 uda1380_read_reg_cache(codec, reg));
433 uda1380_write(codec, reg, uda1380_read_reg_cache(codec, reg));
434 }
435
436 /* FIXME enable DAC_CLK */
437 uda1380_write(codec, UDA1380_CLK, clk | R00_DAC_CLK);
438
439 return 0;
440}
441
442static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
443 struct snd_pcm_hw_params *params)
444{
445 struct snd_soc_pcm_runtime *rtd = substream->private_data;
446 struct snd_soc_device *socdev = rtd->socdev;
447 struct snd_soc_codec *codec = socdev->codec;
448 u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
449
450 /* set WSPLL power and divider if running from this clock */
451 if (clk & R00_DAC_CLK) {
452 int rate = params_rate(params);
453 u16 pm = uda1380_read_reg_cache(codec, UDA1380_PM);
454 clk &= ~0x3; /* clear SEL_LOOP_DIV */
455 switch (rate) {
456 case 6250 ... 12500:
457 clk |= 0x0;
458 break;
459 case 12501 ... 25000:
460 clk |= 0x1;
461 break;
462 case 25001 ... 50000:
463 clk |= 0x2;
464 break;
465 case 50001 ... 100000:
466 clk |= 0x3;
467 break;
468 }
469 uda1380_write(codec, UDA1380_PM, R02_PON_PLL | pm);
470 }
471
472 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
473 clk |= R00_EN_DAC | R00_EN_INT;
474 else
475 clk |= R00_EN_ADC | R00_EN_DEC;
476
477 uda1380_write(codec, UDA1380_CLK, clk);
478 return 0;
479}
480
481static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream)
482{
483 struct snd_soc_pcm_runtime *rtd = substream->private_data;
484 struct snd_soc_device *socdev = rtd->socdev;
485 struct snd_soc_codec *codec = socdev->codec;
486 u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
487
488 /* shut down WSPLL power if running from this clock */
489 if (clk & R00_DAC_CLK) {
490 u16 pm = uda1380_read_reg_cache(codec, UDA1380_PM);
491 uda1380_write(codec, UDA1380_PM, ~R02_PON_PLL & pm);
492 }
493
494 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
495 clk &= ~(R00_EN_DAC | R00_EN_INT);
496 else
497 clk &= ~(R00_EN_ADC | R00_EN_DEC);
498
499 uda1380_write(codec, UDA1380_CLK, clk);
500}
501
502static int uda1380_mute(struct snd_soc_dai *codec_dai, int mute)
503{
504 struct snd_soc_codec *codec = codec_dai->codec;
505 u16 mute_reg = uda1380_read_reg_cache(codec, UDA1380_DEEMP) & ~R13_MTM;
506
507 /* FIXME: mute(codec,0) is called when the magician clock is already
508 * set to WSPLL, but for some unknown reason writing to interpolator
509 * registers works only when clocked by SYSCLK */
510 u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
511 uda1380_write(codec, UDA1380_CLK, ~R00_DAC_CLK & clk);
512 if (mute)
513 uda1380_write(codec, UDA1380_DEEMP, mute_reg | R13_MTM);
514 else
515 uda1380_write(codec, UDA1380_DEEMP, mute_reg);
516 uda1380_write(codec, UDA1380_CLK, clk);
517 return 0;
518}
519
520static int uda1380_set_bias_level(struct snd_soc_codec *codec,
521 enum snd_soc_bias_level level)
522{
523 int pm = uda1380_read_reg_cache(codec, UDA1380_PM);
524
525 switch (level) {
526 case SND_SOC_BIAS_ON:
527 case SND_SOC_BIAS_PREPARE:
528 uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm);
529 break;
530 case SND_SOC_BIAS_STANDBY:
531 uda1380_write(codec, UDA1380_PM, R02_PON_BIAS);
532 break;
533 case SND_SOC_BIAS_OFF:
534 uda1380_write(codec, UDA1380_PM, 0x0);
535 break;
536 }
537 codec->bias_level = level;
538 return 0;
539}
540
541#define UDA1380_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
542 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
543 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
544
545struct snd_soc_dai uda1380_dai[] = {
546{
547 .name = "UDA1380",
548 .playback = {
549 .stream_name = "Playback",
550 .channels_min = 1,
551 .channels_max = 2,
552 .rates = UDA1380_RATES,
553 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
554 .capture = {
555 .stream_name = "Capture",
556 .channels_min = 1,
557 .channels_max = 2,
558 .rates = UDA1380_RATES,
559 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
560 .ops = {
561 .hw_params = uda1380_pcm_hw_params,
562 .shutdown = uda1380_pcm_shutdown,
563 .prepare = uda1380_pcm_prepare,
564 },
565 .dai_ops = {
566 .digital_mute = uda1380_mute,
567 .set_fmt = uda1380_set_dai_fmt,
568 },
569},
570{ /* playback only - dual interface */
571 .name = "UDA1380",
572 .playback = {
573 .stream_name = "Playback",
574 .channels_min = 1,
575 .channels_max = 2,
576 .rates = UDA1380_RATES,
577 .formats = SNDRV_PCM_FMTBIT_S16_LE,
578 },
579 .ops = {
580 .hw_params = uda1380_pcm_hw_params,
581 .shutdown = uda1380_pcm_shutdown,
582 .prepare = uda1380_pcm_prepare,
583 },
584 .dai_ops = {
585 .digital_mute = uda1380_mute,
586 .set_fmt = uda1380_set_dai_fmt,
587 },
588},
589{ /* capture only - dual interface*/
590 .name = "UDA1380",
591 .capture = {
592 .stream_name = "Capture",
593 .channels_min = 1,
594 .channels_max = 2,
595 .rates = UDA1380_RATES,
596 .formats = SNDRV_PCM_FMTBIT_S16_LE,
597 },
598 .ops = {
599 .hw_params = uda1380_pcm_hw_params,
600 .shutdown = uda1380_pcm_shutdown,
601 .prepare = uda1380_pcm_prepare,
602 },
603 .dai_ops = {
604 .set_fmt = uda1380_set_dai_fmt,
605 },
606},
607};
608EXPORT_SYMBOL_GPL(uda1380_dai);
609
610static int uda1380_suspend(struct platform_device *pdev, pm_message_t state)
611{
612 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
613 struct snd_soc_codec *codec = socdev->codec;
614
615 uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
616 return 0;
617}
618
619static int uda1380_resume(struct platform_device *pdev)
620{
621 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
622 struct snd_soc_codec *codec = socdev->codec;
623 int i;
624 u8 data[2];
625 u16 *cache = codec->reg_cache;
626
627 /* Sync reg_cache with the hardware */
628 for (i = 0; i < ARRAY_SIZE(uda1380_reg); i++) {
629 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
630 data[1] = cache[i] & 0x00ff;
631 codec->hw_write(codec->control_data, data, 2);
632 }
633 uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
634 uda1380_set_bias_level(codec, codec->suspend_bias_level);
635 return 0;
636}
637
638/*
639 * initialise the UDA1380 driver
640 * register mixer and dsp interfaces with the kernel
641 */
642static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
643{
644 struct snd_soc_codec *codec = socdev->codec;
645 int ret = 0;
646
647 codec->name = "UDA1380";
648 codec->owner = THIS_MODULE;
649 codec->read = uda1380_read_reg_cache;
650 codec->write = uda1380_write;
651 codec->set_bias_level = uda1380_set_bias_level;
652 codec->dai = uda1380_dai;
653 codec->num_dai = ARRAY_SIZE(uda1380_dai);
654 codec->reg_cache = kmemdup(uda1380_reg, sizeof(uda1380_reg),
655 GFP_KERNEL);
656 if (codec->reg_cache == NULL)
657 return -ENOMEM;
658 codec->reg_cache_size = ARRAY_SIZE(uda1380_reg);
659 codec->reg_cache_step = 1;
660 uda1380_reset(codec);
661
662 /* register pcms */
663 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
664 if (ret < 0) {
665 pr_err("uda1380: failed to create pcms\n");
666 goto pcm_err;
667 }
668
669 /* power on device */
670 uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
671 /* set clock input */
672 switch (dac_clk) {
673 case UDA1380_DAC_CLK_SYSCLK:
674 uda1380_write(codec, UDA1380_CLK, 0);
675 break;
676 case UDA1380_DAC_CLK_WSPLL:
677 uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK);
678 break;
679 }
680
681 /* uda1380 init */
682 uda1380_add_controls(codec);
683 uda1380_add_widgets(codec);
684 ret = snd_soc_register_card(socdev);
685 if (ret < 0) {
686 pr_err("uda1380: failed to register card\n");
687 goto card_err;
688 }
689
690 return ret;
691
692card_err:
693 snd_soc_free_pcms(socdev);
694 snd_soc_dapm_free(socdev);
695pcm_err:
696 kfree(codec->reg_cache);
697 return ret;
698}
699
700static struct snd_soc_device *uda1380_socdev;
701
702#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
703
704#define I2C_DRIVERID_UDA1380 0xfefe /* liam - need a proper id */
705
706static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
707
708/* Magic definition of all other variables and things */
709I2C_CLIENT_INSMOD;
710
711static struct i2c_driver uda1380_i2c_driver;
712static struct i2c_client client_template;
713
714/* If the i2c layer weren't so broken, we could pass this kind of data
715 around */
716
717static int uda1380_codec_probe(struct i2c_adapter *adap, int addr, int kind)
718{
719 struct snd_soc_device *socdev = uda1380_socdev;
720 struct uda1380_setup_data *setup = socdev->codec_data;
721 struct snd_soc_codec *codec = socdev->codec;
722 struct i2c_client *i2c;
723 int ret;
724
725 if (addr != setup->i2c_address)
726 return -ENODEV;
727
728 client_template.adapter = adap;
729 client_template.addr = addr;
730
731 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
732 if (i2c == NULL) {
733 kfree(codec);
734 return -ENOMEM;
735 }
736 i2c_set_clientdata(i2c, codec);
737 codec->control_data = i2c;
738
739 ret = i2c_attach_client(i2c);
740 if (ret < 0) {
741 pr_err("uda1380: failed to attach codec at addr %x\n", addr);
742 goto err;
743 }
744
745 ret = uda1380_init(socdev, setup->dac_clk);
746 if (ret < 0) {
747 pr_err("uda1380: failed to initialise UDA1380\n");
748 goto err;
749 }
750 return ret;
751
752err:
753 kfree(codec);
754 kfree(i2c);
755 return ret;
756}
757
758static int uda1380_i2c_detach(struct i2c_client *client)
759{
760 struct snd_soc_codec *codec = i2c_get_clientdata(client);
761 i2c_detach_client(client);
762 kfree(codec->reg_cache);
763 kfree(client);
764 return 0;
765}
766
767static int uda1380_i2c_attach(struct i2c_adapter *adap)
768{
769 return i2c_probe(adap, &addr_data, uda1380_codec_probe);
770}
771
772static struct i2c_driver uda1380_i2c_driver = {
773 .driver = {
774 .name = "UDA1380 I2C Codec",
775 .owner = THIS_MODULE,
776 },
777 .id = I2C_DRIVERID_UDA1380,
778 .attach_adapter = uda1380_i2c_attach,
779 .detach_client = uda1380_i2c_detach,
780 .command = NULL,
781};
782
783static struct i2c_client client_template = {
784 .name = "UDA1380",
785 .driver = &uda1380_i2c_driver,
786};
787#endif
788
789static int uda1380_probe(struct platform_device *pdev)
790{
791 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
792 struct uda1380_setup_data *setup;
793 struct snd_soc_codec *codec;
794 int ret = 0;
795
796 pr_info("UDA1380 Audio Codec %s", UDA1380_VERSION);
797
798 setup = socdev->codec_data;
799 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
800 if (codec == NULL)
801 return -ENOMEM;
802
803 socdev->codec = codec;
804 mutex_init(&codec->mutex);
805 INIT_LIST_HEAD(&codec->dapm_widgets);
806 INIT_LIST_HEAD(&codec->dapm_paths);
807
808 uda1380_socdev = socdev;
809#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
810 if (setup->i2c_address) {
811 normal_i2c[0] = setup->i2c_address;
812 codec->hw_write = (hw_write_t)i2c_master_send;
813 ret = i2c_add_driver(&uda1380_i2c_driver);
814 if (ret != 0)
815 printk(KERN_ERR "can't add i2c driver");
816 }
817#else
818 /* Add other interfaces here */
819#endif
820 return ret;
821}
822
823/* power down chip */
824static int uda1380_remove(struct platform_device *pdev)
825{
826 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
827 struct snd_soc_codec *codec = socdev->codec;
828
829 if (codec->control_data)
830 uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
831
832 snd_soc_free_pcms(socdev);
833 snd_soc_dapm_free(socdev);
834#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
835 i2c_del_driver(&uda1380_i2c_driver);
836#endif
837 kfree(codec);
838
839 return 0;
840}
841
842struct snd_soc_codec_device soc_codec_dev_uda1380 = {
843 .probe = uda1380_probe,
844 .remove = uda1380_remove,
845 .suspend = uda1380_suspend,
846 .resume = uda1380_resume,
847};
848EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
849
850MODULE_AUTHOR("Giorgio Padrin");
851MODULE_DESCRIPTION("Audio support for codec Philips UDA1380");
852MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/uda1380.h b/sound/soc/codecs/uda1380.h
new file mode 100644
index 000000000000..50c603e2c9f2
--- /dev/null
+++ b/sound/soc/codecs/uda1380.h
@@ -0,0 +1,89 @@
1/*
2 * Audio support for Philips UDA1380
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Copyright (c) 2005 Giorgio Padrin <giorgio@mandarinlogiq.org>
9 */
10
11#ifndef _UDA1380_H
12#define _UDA1380_H
13
14#define UDA1380_CLK 0x00
15#define UDA1380_IFACE 0x01
16#define UDA1380_PM 0x02
17#define UDA1380_AMIX 0x03
18#define UDA1380_HP 0x04
19#define UDA1380_MVOL 0x10
20#define UDA1380_MIXVOL 0x11
21#define UDA1380_MODE 0x12
22#define UDA1380_DEEMP 0x13
23#define UDA1380_MIXER 0x14
24#define UDA1380_INTSTAT 0x18
25#define UDA1380_DEC 0x20
26#define UDA1380_PGA 0x21
27#define UDA1380_ADC 0x22
28#define UDA1380_AGC 0x23
29#define UDA1380_DECSTAT 0x28
30#define UDA1380_RESET 0x7f
31
32#define UDA1380_CACHEREGNUM 0x24
33
34/* Register flags */
35#define R00_EN_ADC 0x0800
36#define R00_EN_DEC 0x0400
37#define R00_EN_DAC 0x0200
38#define R00_EN_INT 0x0100
39#define R00_DAC_CLK 0x0010
40#define R01_SFORI_I2S 0x0000
41#define R01_SFORI_LSB16 0x0100
42#define R01_SFORI_LSB18 0x0200
43#define R01_SFORI_LSB20 0x0300
44#define R01_SFORI_MSB 0x0500
45#define R01_SFORI_MASK 0x0700
46#define R01_SFORO_I2S 0x0000
47#define R01_SFORO_LSB16 0x0001
48#define R01_SFORO_LSB18 0x0002
49#define R01_SFORO_LSB20 0x0003
50#define R01_SFORO_LSB24 0x0004
51#define R01_SFORO_MSB 0x0005
52#define R01_SFORO_MASK 0x0007
53#define R01_SEL_SOURCE 0x0040
54#define R01_SIM 0x0010
55#define R02_PON_PLL 0x8000
56#define R02_PON_HP 0x2000
57#define R02_PON_DAC 0x0400
58#define R02_PON_BIAS 0x0100
59#define R02_EN_AVC 0x0080
60#define R02_PON_AVC 0x0040
61#define R02_PON_LNA 0x0010
62#define R02_PON_PGAL 0x0008
63#define R02_PON_ADCL 0x0004
64#define R02_PON_PGAR 0x0002
65#define R02_PON_ADCR 0x0001
66#define R13_MTM 0x4000
67#define R14_SILENCE 0x0080
68#define R14_SDET_ON 0x0040
69#define R21_MT_ADC 0x8000
70#define R22_SEL_LNA 0x0008
71#define R22_SEL_MIC 0x0004
72#define R22_SKIP_DCFIL 0x0002
73#define R23_AGC_EN 0x0001
74
75struct uda1380_setup_data {
76 unsigned short i2c_address;
77 int dac_clk;
78#define UDA1380_DAC_CLK_SYSCLK 0
79#define UDA1380_DAC_CLK_WSPLL 1
80};
81
82#define UDA1380_DAI_DUPLEX 0 /* playback and capture on single DAI */
83#define UDA1380_DAI_PLAYBACK 1 /* playback DAI */
84#define UDA1380_DAI_CAPTURE 2 /* capture DAI */
85
86extern struct snd_soc_dai uda1380_dai[3];
87extern struct snd_soc_codec_device soc_codec_dev_uda1380;
88
89#endif /* _UDA1380_H */
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
new file mode 100644
index 000000000000..67325fd95447
--- /dev/null
+++ b/sound/soc/codecs/wm8510.c
@@ -0,0 +1,817 @@
1/*
2 * wm8510.c -- WM8510 ALSA Soc Audio driver
3 *
4 * Copyright 2006 Wolfson Microelectronics PLC.
5 *
6 * Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
7 *
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
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/pm.h>
19#include <linux/i2c.h>
20#include <linux/platform_device.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26#include <sound/initval.h>
27
28#include "wm8510.h"
29
30#define AUDIO_NAME "wm8510"
31#define WM8510_VERSION "0.6"
32
33struct snd_soc_codec_device soc_codec_dev_wm8510;
34
35/*
36 * wm8510 register cache
37 * We can't read the WM8510 register space when we are
38 * using 2 wire for device control, so we cache them instead.
39 */
40static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
41 0x0000, 0x0000, 0x0000, 0x0000,
42 0x0050, 0x0000, 0x0140, 0x0000,
43 0x0000, 0x0000, 0x0000, 0x00ff,
44 0x0000, 0x0000, 0x0100, 0x00ff,
45 0x0000, 0x0000, 0x012c, 0x002c,
46 0x002c, 0x002c, 0x002c, 0x0000,
47 0x0032, 0x0000, 0x0000, 0x0000,
48 0x0000, 0x0000, 0x0000, 0x0000,
49 0x0038, 0x000b, 0x0032, 0x0000,
50 0x0008, 0x000c, 0x0093, 0x00e9,
51 0x0000, 0x0000, 0x0000, 0x0000,
52 0x0003, 0x0010, 0x0000, 0x0000,
53 0x0000, 0x0002, 0x0001, 0x0000,
54 0x0000, 0x0000, 0x0039, 0x0000,
55 0x0001,
56};
57
58/*
59 * read wm8510 register cache
60 */
61static inline unsigned int wm8510_read_reg_cache(struct snd_soc_codec *codec,
62 unsigned int reg)
63{
64 u16 *cache = codec->reg_cache;
65 if (reg == WM8510_RESET)
66 return 0;
67 if (reg >= WM8510_CACHEREGNUM)
68 return -1;
69 return cache[reg];
70}
71
72/*
73 * write wm8510 register cache
74 */
75static inline void wm8510_write_reg_cache(struct snd_soc_codec *codec,
76 u16 reg, unsigned int value)
77{
78 u16 *cache = codec->reg_cache;
79 if (reg >= WM8510_CACHEREGNUM)
80 return;
81 cache[reg] = value;
82}
83
84/*
85 * write to the WM8510 register space
86 */
87static int wm8510_write(struct snd_soc_codec *codec, unsigned int reg,
88 unsigned int value)
89{
90 u8 data[2];
91
92 /* data is
93 * D15..D9 WM8510 register offset
94 * D8...D0 register data
95 */
96 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
97 data[1] = value & 0x00ff;
98
99 wm8510_write_reg_cache(codec, reg, value);
100 if (codec->hw_write(codec->control_data, data, 2) == 2)
101 return 0;
102 else
103 return -EIO;
104}
105
106#define wm8510_reset(c) wm8510_write(c, WM8510_RESET, 0)
107
108static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" };
109static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
110static const char *wm8510_alc[] = { "ALC", "Limiter" };
111
112static const struct soc_enum wm8510_enum[] = {
113 SOC_ENUM_SINGLE(WM8510_COMP, 1, 4, wm8510_companding), /* adc */
114 SOC_ENUM_SINGLE(WM8510_COMP, 3, 4, wm8510_companding), /* dac */
115 SOC_ENUM_SINGLE(WM8510_DAC, 4, 4, wm8510_deemp),
116 SOC_ENUM_SINGLE(WM8510_ALC3, 8, 2, wm8510_alc),
117};
118
119static const struct snd_kcontrol_new wm8510_snd_controls[] = {
120
121SOC_SINGLE("Digital Loopback Switch", WM8510_COMP, 0, 1, 0),
122
123SOC_ENUM("DAC Companding", wm8510_enum[1]),
124SOC_ENUM("ADC Companding", wm8510_enum[0]),
125
126SOC_ENUM("Playback De-emphasis", wm8510_enum[2]),
127SOC_SINGLE("DAC Inversion Switch", WM8510_DAC, 0, 1, 0),
128
129SOC_SINGLE("Master Playback Volume", WM8510_DACVOL, 0, 127, 0),
130
131SOC_SINGLE("High Pass Filter Switch", WM8510_ADC, 8, 1, 0),
132SOC_SINGLE("High Pass Cut Off", WM8510_ADC, 4, 7, 0),
133SOC_SINGLE("ADC Inversion Switch", WM8510_COMP, 0, 1, 0),
134
135SOC_SINGLE("Capture Volume", WM8510_ADCVOL, 0, 127, 0),
136
137SOC_SINGLE("DAC Playback Limiter Switch", WM8510_DACLIM1, 8, 1, 0),
138SOC_SINGLE("DAC Playback Limiter Decay", WM8510_DACLIM1, 4, 15, 0),
139SOC_SINGLE("DAC Playback Limiter Attack", WM8510_DACLIM1, 0, 15, 0),
140
141SOC_SINGLE("DAC Playback Limiter Threshold", WM8510_DACLIM2, 4, 7, 0),
142SOC_SINGLE("DAC Playback Limiter Boost", WM8510_DACLIM2, 0, 15, 0),
143
144SOC_SINGLE("ALC Enable Switch", WM8510_ALC1, 8, 1, 0),
145SOC_SINGLE("ALC Capture Max Gain", WM8510_ALC1, 3, 7, 0),
146SOC_SINGLE("ALC Capture Min Gain", WM8510_ALC1, 0, 7, 0),
147
148SOC_SINGLE("ALC Capture ZC Switch", WM8510_ALC2, 8, 1, 0),
149SOC_SINGLE("ALC Capture Hold", WM8510_ALC2, 4, 7, 0),
150SOC_SINGLE("ALC Capture Target", WM8510_ALC2, 0, 15, 0),
151
152SOC_ENUM("ALC Capture Mode", wm8510_enum[3]),
153SOC_SINGLE("ALC Capture Decay", WM8510_ALC3, 4, 15, 0),
154SOC_SINGLE("ALC Capture Attack", WM8510_ALC3, 0, 15, 0),
155
156SOC_SINGLE("ALC Capture Noise Gate Switch", WM8510_NGATE, 3, 1, 0),
157SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8510_NGATE, 0, 7, 0),
158
159SOC_SINGLE("Capture PGA ZC Switch", WM8510_INPPGA, 7, 1, 0),
160SOC_SINGLE("Capture PGA Volume", WM8510_INPPGA, 0, 63, 0),
161
162SOC_SINGLE("Speaker Playback ZC Switch", WM8510_SPKVOL, 7, 1, 0),
163SOC_SINGLE("Speaker Playback Switch", WM8510_SPKVOL, 6, 1, 1),
164SOC_SINGLE("Speaker Playback Volume", WM8510_SPKVOL, 0, 63, 0),
165SOC_SINGLE("Speaker Boost", WM8510_OUTPUT, 2, 1, 0),
166
167SOC_SINGLE("Capture Boost(+20dB)", WM8510_ADCBOOST, 8, 1, 0),
168SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 1),
169};
170
171/* add non dapm controls */
172static int wm8510_add_controls(struct snd_soc_codec *codec)
173{
174 int err, i;
175
176 for (i = 0; i < ARRAY_SIZE(wm8510_snd_controls); i++) {
177 err = snd_ctl_add(codec->card,
178 snd_soc_cnew(&wm8510_snd_controls[i], codec,
179 NULL));
180 if (err < 0)
181 return err;
182 }
183
184 return 0;
185}
186
187/* Speaker Output Mixer */
188static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = {
189SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_SPKMIX, 1, 1, 0),
190SOC_DAPM_SINGLE("Aux Playback Switch", WM8510_SPKMIX, 5, 1, 0),
191SOC_DAPM_SINGLE("PCM Playback Switch", WM8510_SPKMIX, 0, 1, 0),
192};
193
194/* Mono Output Mixer */
195static const struct snd_kcontrol_new wm8510_mono_mixer_controls[] = {
196SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_MONOMIX, 1, 1, 0),
197SOC_DAPM_SINGLE("Aux Playback Switch", WM8510_MONOMIX, 2, 1, 0),
198SOC_DAPM_SINGLE("PCM Playback Switch", WM8510_MONOMIX, 0, 1, 0),
199};
200
201static const struct snd_kcontrol_new wm8510_boost_controls[] = {
202SOC_DAPM_SINGLE("Mic PGA Switch", WM8510_INPPGA, 6, 1, 0),
203SOC_DAPM_SINGLE("Aux Volume", WM8510_ADCBOOST, 0, 7, 0),
204SOC_DAPM_SINGLE("Mic Volume", WM8510_ADCBOOST, 4, 7, 0),
205};
206
207static const struct snd_kcontrol_new wm8510_micpga_controls[] = {
208SOC_DAPM_SINGLE("MICP Switch", WM8510_INPUT, 0, 1, 0),
209SOC_DAPM_SINGLE("MICN Switch", WM8510_INPUT, 1, 1, 0),
210SOC_DAPM_SINGLE("AUX Switch", WM8510_INPUT, 2, 1, 0),
211};
212
213static const struct snd_soc_dapm_widget wm8510_dapm_widgets[] = {
214SND_SOC_DAPM_MIXER("Speaker Mixer", WM8510_POWER3, 2, 0,
215 &wm8510_speaker_mixer_controls[0],
216 ARRAY_SIZE(wm8510_speaker_mixer_controls)),
217SND_SOC_DAPM_MIXER("Mono Mixer", WM8510_POWER3, 3, 0,
218 &wm8510_mono_mixer_controls[0],
219 ARRAY_SIZE(wm8510_mono_mixer_controls)),
220SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8510_POWER3, 0, 0),
221SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8510_POWER2, 0, 0),
222SND_SOC_DAPM_PGA("Aux Input", WM8510_POWER1, 6, 0, NULL, 0),
223SND_SOC_DAPM_PGA("SpkN Out", WM8510_POWER3, 5, 0, NULL, 0),
224SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0),
225SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0),
226
227SND_SOC_DAPM_PGA("Mic PGA", WM8510_POWER2, 2, 0,
228 &wm8510_micpga_controls[0],
229 ARRAY_SIZE(wm8510_micpga_controls)),
230SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0,
231 &wm8510_boost_controls[0],
232 ARRAY_SIZE(wm8510_boost_controls)),
233
234SND_SOC_DAPM_MICBIAS("Mic Bias", WM8510_POWER1, 4, 0),
235
236SND_SOC_DAPM_INPUT("MICN"),
237SND_SOC_DAPM_INPUT("MICP"),
238SND_SOC_DAPM_INPUT("AUX"),
239SND_SOC_DAPM_OUTPUT("MONOOUT"),
240SND_SOC_DAPM_OUTPUT("SPKOUTP"),
241SND_SOC_DAPM_OUTPUT("SPKOUTN"),
242};
243
244static const struct snd_soc_dapm_route audio_map[] = {
245 /* Mono output mixer */
246 {"Mono Mixer", "PCM Playback Switch", "DAC"},
247 {"Mono Mixer", "Aux Playback Switch", "Aux Input"},
248 {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"},
249
250 /* Speaker output mixer */
251 {"Speaker Mixer", "PCM Playback Switch", "DAC"},
252 {"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
253 {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"},
254
255 /* Outputs */
256 {"Mono Out", NULL, "Mono Mixer"},
257 {"MONOOUT", NULL, "Mono Out"},
258 {"SpkN Out", NULL, "Speaker Mixer"},
259 {"SpkP Out", NULL, "Speaker Mixer"},
260 {"SPKOUTN", NULL, "SpkN Out"},
261 {"SPKOUTP", NULL, "SpkP Out"},
262
263 /* Microphone PGA */
264 {"Mic PGA", "MICN Switch", "MICN"},
265 {"Mic PGA", "MICP Switch", "MICP"},
266 { "Mic PGA", "AUX Switch", "Aux Input" },
267
268 /* Boost Mixer */
269 {"Boost Mixer", "Mic PGA Switch", "Mic PGA"},
270 {"Boost Mixer", "Mic Volume", "MICP"},
271 {"Boost Mixer", "Aux Volume", "Aux Input"},
272
273 {"ADC", NULL, "Boost Mixer"},
274};
275
276static int wm8510_add_widgets(struct snd_soc_codec *codec)
277{
278 snd_soc_dapm_new_controls(codec, wm8510_dapm_widgets,
279 ARRAY_SIZE(wm8510_dapm_widgets));
280
281 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
282
283 snd_soc_dapm_new_widgets(codec);
284 return 0;
285}
286
287struct pll_ {
288 unsigned int pre_div:4; /* prescale - 1 */
289 unsigned int n:4;
290 unsigned int k;
291};
292
293static struct pll_ pll_div;
294
295/* The size in bits of the pll divide multiplied by 10
296 * to allow rounding later */
297#define FIXED_PLL_SIZE ((1 << 24) * 10)
298
299static void pll_factors(unsigned int target, unsigned int source)
300{
301 unsigned long long Kpart;
302 unsigned int K, Ndiv, Nmod;
303
304 Ndiv = target / source;
305 if (Ndiv < 6) {
306 source >>= 1;
307 pll_div.pre_div = 1;
308 Ndiv = target / source;
309 } else
310 pll_div.pre_div = 0;
311
312 if ((Ndiv < 6) || (Ndiv > 12))
313 printk(KERN_WARNING
314 "WM8510 N value %d outwith recommended range!d\n",
315 Ndiv);
316
317 pll_div.n = Ndiv;
318 Nmod = target % source;
319 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
320
321 do_div(Kpart, source);
322
323 K = Kpart & 0xFFFFFFFF;
324
325 /* Check if we need to round */
326 if ((K % 10) >= 5)
327 K += 5;
328
329 /* Move down to proper range now rounding is done */
330 K /= 10;
331
332 pll_div.k = K;
333}
334
335static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai,
336 int pll_id, unsigned int freq_in, unsigned int freq_out)
337{
338 struct snd_soc_codec *codec = codec_dai->codec;
339 u16 reg;
340
341 if (freq_in == 0 || freq_out == 0) {
342 /* Clock CODEC directly from MCLK */
343 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK);
344 wm8510_write(codec, WM8510_CLOCK, reg & 0x0ff);
345
346 /* Turn off PLL */
347 reg = wm8510_read_reg_cache(codec, WM8510_POWER1);
348 wm8510_write(codec, WM8510_POWER1, reg & 0x1df);
349 return 0;
350 }
351
352 pll_factors(freq_out*8, freq_in);
353
354 wm8510_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n);
355 wm8510_write(codec, WM8510_PLLK1, pll_div.k >> 18);
356 wm8510_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff);
357 wm8510_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff);
358 reg = wm8510_read_reg_cache(codec, WM8510_POWER1);
359 wm8510_write(codec, WM8510_POWER1, reg | 0x020);
360
361 /* Run CODEC from PLL instead of MCLK */
362 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK);
363 wm8510_write(codec, WM8510_CLOCK, reg | 0x100);
364
365 return 0;
366}
367
368/*
369 * Configure WM8510 clock dividers.
370 */
371static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
372 int div_id, int div)
373{
374 struct snd_soc_codec *codec = codec_dai->codec;
375 u16 reg;
376
377 switch (div_id) {
378 case WM8510_OPCLKDIV:
379 reg = wm8510_read_reg_cache(codec, WM8510_GPIO) & 0x1cf;
380 wm8510_write(codec, WM8510_GPIO, reg | div);
381 break;
382 case WM8510_MCLKDIV:
383 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1f;
384 wm8510_write(codec, WM8510_CLOCK, reg | div);
385 break;
386 case WM8510_ADCCLK:
387 reg = wm8510_read_reg_cache(codec, WM8510_ADC) & 0x1f7;
388 wm8510_write(codec, WM8510_ADC, reg | div);
389 break;
390 case WM8510_DACCLK:
391 reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0x1f7;
392 wm8510_write(codec, WM8510_DAC, reg | div);
393 break;
394 case WM8510_BCLKDIV:
395 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1e3;
396 wm8510_write(codec, WM8510_CLOCK, reg | div);
397 break;
398 default:
399 return -EINVAL;
400 }
401
402 return 0;
403}
404
405static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
406 unsigned int fmt)
407{
408 struct snd_soc_codec *codec = codec_dai->codec;
409 u16 iface = 0;
410 u16 clk = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1fe;
411
412 /* set master/slave audio interface */
413 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
414 case SND_SOC_DAIFMT_CBM_CFM:
415 clk |= 0x0001;
416 break;
417 case SND_SOC_DAIFMT_CBS_CFS:
418 break;
419 default:
420 return -EINVAL;
421 }
422
423 /* interface format */
424 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
425 case SND_SOC_DAIFMT_I2S:
426 iface |= 0x0010;
427 break;
428 case SND_SOC_DAIFMT_RIGHT_J:
429 break;
430 case SND_SOC_DAIFMT_LEFT_J:
431 iface |= 0x0008;
432 break;
433 case SND_SOC_DAIFMT_DSP_A:
434 iface |= 0x00018;
435 break;
436 default:
437 return -EINVAL;
438 }
439
440 /* clock inversion */
441 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
442 case SND_SOC_DAIFMT_NB_NF:
443 break;
444 case SND_SOC_DAIFMT_IB_IF:
445 iface |= 0x0180;
446 break;
447 case SND_SOC_DAIFMT_IB_NF:
448 iface |= 0x0100;
449 break;
450 case SND_SOC_DAIFMT_NB_IF:
451 iface |= 0x0080;
452 break;
453 default:
454 return -EINVAL;
455 }
456
457 wm8510_write(codec, WM8510_IFACE, iface);
458 wm8510_write(codec, WM8510_CLOCK, clk);
459 return 0;
460}
461
462static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
463 struct snd_pcm_hw_params *params)
464{
465 struct snd_soc_pcm_runtime *rtd = substream->private_data;
466 struct snd_soc_device *socdev = rtd->socdev;
467 struct snd_soc_codec *codec = socdev->codec;
468 u16 iface = wm8510_read_reg_cache(codec, WM8510_IFACE) & 0x19f;
469 u16 adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1;
470
471 /* bit size */
472 switch (params_format(params)) {
473 case SNDRV_PCM_FORMAT_S16_LE:
474 break;
475 case SNDRV_PCM_FORMAT_S20_3LE:
476 iface |= 0x0020;
477 break;
478 case SNDRV_PCM_FORMAT_S24_LE:
479 iface |= 0x0040;
480 break;
481 case SNDRV_PCM_FORMAT_S32_LE:
482 iface |= 0x0060;
483 break;
484 }
485
486 /* filter coefficient */
487 switch (params_rate(params)) {
488 case SNDRV_PCM_RATE_8000:
489 adn |= 0x5 << 1;
490 break;
491 case SNDRV_PCM_RATE_11025:
492 adn |= 0x4 << 1;
493 break;
494 case SNDRV_PCM_RATE_16000:
495 adn |= 0x3 << 1;
496 break;
497 case SNDRV_PCM_RATE_22050:
498 adn |= 0x2 << 1;
499 break;
500 case SNDRV_PCM_RATE_32000:
501 adn |= 0x1 << 1;
502 break;
503 case SNDRV_PCM_RATE_44100:
504 case SNDRV_PCM_RATE_48000:
505 break;
506 }
507
508 wm8510_write(codec, WM8510_IFACE, iface);
509 wm8510_write(codec, WM8510_ADD, adn);
510 return 0;
511}
512
513static int wm8510_mute(struct snd_soc_dai *dai, int mute)
514{
515 struct snd_soc_codec *codec = dai->codec;
516 u16 mute_reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0xffbf;
517
518 if (mute)
519 wm8510_write(codec, WM8510_DAC, mute_reg | 0x40);
520 else
521 wm8510_write(codec, WM8510_DAC, mute_reg);
522 return 0;
523}
524
525/* liam need to make this lower power with dapm */
526static int wm8510_set_bias_level(struct snd_soc_codec *codec,
527 enum snd_soc_bias_level level)
528{
529
530 switch (level) {
531 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:
537 case SND_SOC_BIAS_STANDBY:
538 break;
539 case SND_SOC_BIAS_OFF:
540 /* everything off, dac mute, inactive */
541 wm8510_write(codec, WM8510_POWER1, 0x0);
542 wm8510_write(codec, WM8510_POWER2, 0x0);
543 wm8510_write(codec, WM8510_POWER3, 0x0);
544 break;
545 }
546 codec->bias_level = level;
547 return 0;
548}
549
550#define WM8510_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
551 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
552 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
553
554#define WM8510_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
555 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
556
557struct snd_soc_dai wm8510_dai = {
558 .name = "WM8510 HiFi",
559 .playback = {
560 .stream_name = "Playback",
561 .channels_min = 2,
562 .channels_max = 2,
563 .rates = WM8510_RATES,
564 .formats = WM8510_FORMATS,},
565 .capture = {
566 .stream_name = "Capture",
567 .channels_min = 2,
568 .channels_max = 2,
569 .rates = WM8510_RATES,
570 .formats = WM8510_FORMATS,},
571 .ops = {
572 .hw_params = wm8510_pcm_hw_params,
573 },
574 .dai_ops = {
575 .digital_mute = wm8510_mute,
576 .set_fmt = wm8510_set_dai_fmt,
577 .set_clkdiv = wm8510_set_dai_clkdiv,
578 .set_pll = wm8510_set_dai_pll,
579 },
580};
581EXPORT_SYMBOL_GPL(wm8510_dai);
582
583static int wm8510_suspend(struct platform_device *pdev, pm_message_t state)
584{
585 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
586 struct snd_soc_codec *codec = socdev->codec;
587
588 wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
589 return 0;
590}
591
592static int wm8510_resume(struct platform_device *pdev)
593{
594 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
595 struct snd_soc_codec *codec = socdev->codec;
596 int i;
597 u8 data[2];
598 u16 *cache = codec->reg_cache;
599
600 /* Sync reg_cache with the hardware */
601 for (i = 0; i < ARRAY_SIZE(wm8510_reg); i++) {
602 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
603 data[1] = cache[i] & 0x00ff;
604 codec->hw_write(codec->control_data, data, 2);
605 }
606 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
607 wm8510_set_bias_level(codec, codec->suspend_bias_level);
608 return 0;
609}
610
611/*
612 * initialise the WM8510 driver
613 * register the mixer and dsp interfaces with the kernel
614 */
615static int wm8510_init(struct snd_soc_device *socdev)
616{
617 struct snd_soc_codec *codec = socdev->codec;
618 int ret = 0;
619
620 codec->name = "WM8510";
621 codec->owner = THIS_MODULE;
622 codec->read = wm8510_read_reg_cache;
623 codec->write = wm8510_write;
624 codec->set_bias_level = wm8510_set_bias_level;
625 codec->dai = &wm8510_dai;
626 codec->num_dai = 1;
627 codec->reg_cache_size = ARRAY_SIZE(wm8510_reg);
628 codec->reg_cache = kmemdup(wm8510_reg, sizeof(wm8510_reg), GFP_KERNEL);
629
630 if (codec->reg_cache == NULL)
631 return -ENOMEM;
632
633 wm8510_reset(codec);
634
635 /* register pcms */
636 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
637 if (ret < 0) {
638 printk(KERN_ERR "wm8510: failed to create pcms\n");
639 goto pcm_err;
640 }
641
642 /* power on device */
643 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
644 wm8510_add_controls(codec);
645 wm8510_add_widgets(codec);
646 ret = snd_soc_register_card(socdev);
647 if (ret < 0) {
648 printk(KERN_ERR "wm8510: failed to register card\n");
649 goto card_err;
650 }
651 return ret;
652
653card_err:
654 snd_soc_free_pcms(socdev);
655 snd_soc_dapm_free(socdev);
656pcm_err:
657 kfree(codec->reg_cache);
658 return ret;
659}
660
661static struct snd_soc_device *wm8510_socdev;
662
663#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
664
665/*
666 * WM8510 2 wire address is 0x1a
667 */
668#define I2C_DRIVERID_WM8510 0xfefe /* liam - need a proper id */
669
670static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
671
672/* Magic definition of all other variables and things */
673I2C_CLIENT_INSMOD;
674
675static struct i2c_driver wm8510_i2c_driver;
676static struct i2c_client client_template;
677
678/* If the i2c layer weren't so broken, we could pass this kind of data
679 around */
680
681static int wm8510_codec_probe(struct i2c_adapter *adap, int addr, int kind)
682{
683 struct snd_soc_device *socdev = wm8510_socdev;
684 struct wm8510_setup_data *setup = socdev->codec_data;
685 struct snd_soc_codec *codec = socdev->codec;
686 struct i2c_client *i2c;
687 int ret;
688
689 if (addr != setup->i2c_address)
690 return -ENODEV;
691
692 client_template.adapter = adap;
693 client_template.addr = addr;
694
695 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
696 if (i2c == NULL) {
697 kfree(codec);
698 return -ENOMEM;
699 }
700 i2c_set_clientdata(i2c, codec);
701 codec->control_data = i2c;
702
703 ret = i2c_attach_client(i2c);
704 if (ret < 0) {
705 pr_err("failed to attach codec at addr %x\n", addr);
706 goto err;
707 }
708
709 ret = wm8510_init(socdev);
710 if (ret < 0) {
711 pr_err("failed to initialise WM8510\n");
712 goto err;
713 }
714 return ret;
715
716err:
717 kfree(codec);
718 kfree(i2c);
719 return ret;
720}
721
722static int wm8510_i2c_detach(struct i2c_client *client)
723{
724 struct snd_soc_codec *codec = i2c_get_clientdata(client);
725 i2c_detach_client(client);
726 kfree(codec->reg_cache);
727 kfree(client);
728 return 0;
729}
730
731static int wm8510_i2c_attach(struct i2c_adapter *adap)
732{
733 return i2c_probe(adap, &addr_data, wm8510_codec_probe);
734}
735
736/* corgi i2c codec control layer */
737static struct i2c_driver wm8510_i2c_driver = {
738 .driver = {
739 .name = "WM8510 I2C Codec",
740 .owner = THIS_MODULE,
741 },
742 .id = I2C_DRIVERID_WM8510,
743 .attach_adapter = wm8510_i2c_attach,
744 .detach_client = wm8510_i2c_detach,
745 .command = NULL,
746};
747
748static struct i2c_client client_template = {
749 .name = "WM8510",
750 .driver = &wm8510_i2c_driver,
751};
752#endif
753
754static int wm8510_probe(struct platform_device *pdev)
755{
756 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
757 struct wm8510_setup_data *setup;
758 struct snd_soc_codec *codec;
759 int ret = 0;
760
761 pr_info("WM8510 Audio Codec %s", WM8510_VERSION);
762
763 setup = socdev->codec_data;
764 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
765 if (codec == NULL)
766 return -ENOMEM;
767
768 socdev->codec = codec;
769 mutex_init(&codec->mutex);
770 INIT_LIST_HEAD(&codec->dapm_widgets);
771 INIT_LIST_HEAD(&codec->dapm_paths);
772
773 wm8510_socdev = socdev;
774#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
775 if (setup->i2c_address) {
776 normal_i2c[0] = setup->i2c_address;
777 codec->hw_write = (hw_write_t)i2c_master_send;
778 ret = i2c_add_driver(&wm8510_i2c_driver);
779 if (ret != 0)
780 printk(KERN_ERR "can't add i2c driver");
781 }
782#else
783 /* Add other interfaces here */
784#endif
785 return ret;
786}
787
788/* power down chip */
789static int wm8510_remove(struct platform_device *pdev)
790{
791 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
792 struct snd_soc_codec *codec = socdev->codec;
793
794 if (codec->control_data)
795 wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
796
797 snd_soc_free_pcms(socdev);
798 snd_soc_dapm_free(socdev);
799#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
800 i2c_del_driver(&wm8510_i2c_driver);
801#endif
802 kfree(codec);
803
804 return 0;
805}
806
807struct snd_soc_codec_device soc_codec_dev_wm8510 = {
808 .probe = wm8510_probe,
809 .remove = wm8510_remove,
810 .suspend = wm8510_suspend,
811 .resume = wm8510_resume,
812};
813EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510);
814
815MODULE_DESCRIPTION("ASoC WM8510 driver");
816MODULE_AUTHOR("Liam Girdwood");
817MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8510.h b/sound/soc/codecs/wm8510.h
new file mode 100644
index 000000000000..f5d2e42eb3f4
--- /dev/null
+++ b/sound/soc/codecs/wm8510.h
@@ -0,0 +1,103 @@
1/*
2 * wm8510.h -- WM8510 Soc Audio driver
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _WM8510_H
10#define _WM8510_H
11
12/* WM8510 register space */
13
14#define WM8510_RESET 0x0
15#define WM8510_POWER1 0x1
16#define WM8510_POWER2 0x2
17#define WM8510_POWER3 0x3
18#define WM8510_IFACE 0x4
19#define WM8510_COMP 0x5
20#define WM8510_CLOCK 0x6
21#define WM8510_ADD 0x7
22#define WM8510_GPIO 0x8
23#define WM8510_DAC 0xa
24#define WM8510_DACVOL 0xb
25#define WM8510_ADC 0xe
26#define WM8510_ADCVOL 0xf
27#define WM8510_EQ1 0x12
28#define WM8510_EQ2 0x13
29#define WM8510_EQ3 0x14
30#define WM8510_EQ4 0x15
31#define WM8510_EQ5 0x16
32#define WM8510_DACLIM1 0x18
33#define WM8510_DACLIM2 0x19
34#define WM8510_NOTCH1 0x1b
35#define WM8510_NOTCH2 0x1c
36#define WM8510_NOTCH3 0x1d
37#define WM8510_NOTCH4 0x1e
38#define WM8510_ALC1 0x20
39#define WM8510_ALC2 0x21
40#define WM8510_ALC3 0x22
41#define WM8510_NGATE 0x23
42#define WM8510_PLLN 0x24
43#define WM8510_PLLK1 0x25
44#define WM8510_PLLK2 0x26
45#define WM8510_PLLK3 0x27
46#define WM8510_ATTEN 0x28
47#define WM8510_INPUT 0x2c
48#define WM8510_INPPGA 0x2d
49#define WM8510_ADCBOOST 0x2f
50#define WM8510_OUTPUT 0x31
51#define WM8510_SPKMIX 0x32
52#define WM8510_SPKVOL 0x36
53#define WM8510_MONOMIX 0x38
54
55#define WM8510_CACHEREGNUM 57
56
57/* Clock divider Id's */
58#define WM8510_OPCLKDIV 0
59#define WM8510_MCLKDIV 1
60#define WM8510_ADCCLK 2
61#define WM8510_DACCLK 3
62#define WM8510_BCLKDIV 4
63
64/* DAC clock dividers */
65#define WM8510_DACCLK_F2 (1 << 3)
66#define WM8510_DACCLK_F4 (0 << 3)
67
68/* ADC clock dividers */
69#define WM8510_ADCCLK_F2 (1 << 3)
70#define WM8510_ADCCLK_F4 (0 << 3)
71
72/* PLL Out dividers */
73#define WM8510_OPCLKDIV_1 (0 << 4)
74#define WM8510_OPCLKDIV_2 (1 << 4)
75#define WM8510_OPCLKDIV_3 (2 << 4)
76#define WM8510_OPCLKDIV_4 (3 << 4)
77
78/* BCLK clock dividers */
79#define WM8510_BCLKDIV_1 (0 << 2)
80#define WM8510_BCLKDIV_2 (1 << 2)
81#define WM8510_BCLKDIV_4 (2 << 2)
82#define WM8510_BCLKDIV_8 (3 << 2)
83#define WM8510_BCLKDIV_16 (4 << 2)
84#define WM8510_BCLKDIV_32 (5 << 2)
85
86/* MCLK clock dividers */
87#define WM8510_MCLKDIV_1 (0 << 5)
88#define WM8510_MCLKDIV_1_5 (1 << 5)
89#define WM8510_MCLKDIV_2 (2 << 5)
90#define WM8510_MCLKDIV_3 (3 << 5)
91#define WM8510_MCLKDIV_4 (4 << 5)
92#define WM8510_MCLKDIV_6 (5 << 5)
93#define WM8510_MCLKDIV_8 (6 << 5)
94#define WM8510_MCLKDIV_12 (7 << 5)
95
96struct wm8510_setup_data {
97 unsigned short i2c_address;
98};
99
100extern struct snd_soc_dai wm8510_dai;
101extern struct snd_soc_codec_device soc_codec_dev_wm8510;
102
103#endif
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 0cf9265fca8f..369d39c3f745 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -31,25 +31,6 @@
31#define AUDIO_NAME "wm8731" 31#define AUDIO_NAME "wm8731"
32#define WM8731_VERSION "0.13" 32#define WM8731_VERSION "0.13"
33 33
34/*
35 * Debug
36 */
37
38#define WM8731_DEBUG 0
39
40#ifdef WM8731_DEBUG
41#define dbg(format, arg...) \
42 printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
43#else
44#define dbg(format, arg...) do {} while (0)
45#endif
46#define err(format, arg...) \
47 printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
48#define info(format, arg...) \
49 printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
50#define warn(format, arg...) \
51 printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
52
53struct snd_soc_codec_device soc_codec_dev_wm8731; 34struct snd_soc_codec_device soc_codec_dev_wm8731;
54 35
55/* codec private data */ 36/* codec private data */
@@ -193,7 +174,7 @@ SND_SOC_DAPM_INPUT("RLINEIN"),
193SND_SOC_DAPM_INPUT("LLINEIN"), 174SND_SOC_DAPM_INPUT("LLINEIN"),
194}; 175};
195 176
196static const char *intercon[][3] = { 177static const struct snd_soc_dapm_route intercon[] = {
197 /* output mixer */ 178 /* output mixer */
198 {"Output Mixer", "Line Bypass Switch", "Line Input"}, 179 {"Output Mixer", "Line Bypass Switch", "Line Input"},
199 {"Output Mixer", "HiFi Playback Switch", "DAC"}, 180 {"Output Mixer", "HiFi Playback Switch", "DAC"},
@@ -214,22 +195,14 @@ static const char *intercon[][3] = {
214 {"Line Input", NULL, "LLINEIN"}, 195 {"Line Input", NULL, "LLINEIN"},
215 {"Line Input", NULL, "RLINEIN"}, 196 {"Line Input", NULL, "RLINEIN"},
216 {"Mic Bias", NULL, "MICIN"}, 197 {"Mic Bias", NULL, "MICIN"},
217
218 /* terminator */
219 {NULL, NULL, NULL},
220}; 198};
221 199
222static int wm8731_add_widgets(struct snd_soc_codec *codec) 200static int wm8731_add_widgets(struct snd_soc_codec *codec)
223{ 201{
224 int i; 202 snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
225 203 ARRAY_SIZE(wm8731_dapm_widgets));
226 for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
227 snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
228 204
229 /* set up audio path interconnects */ 205 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
230 for (i = 0; intercon[i][0] != NULL; i++)
231 snd_soc_dapm_connect_input(codec, intercon[i][0],
232 intercon[i][1], intercon[i][2]);
233 206
234 snd_soc_dapm_new_widgets(codec); 207 snd_soc_dapm_new_widgets(codec);
235 return 0; 208 return 0;
@@ -345,7 +318,7 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream)
345 } 318 }
346} 319}
347 320
348static int wm8731_mute(struct snd_soc_codec_dai *dai, int mute) 321static int wm8731_mute(struct snd_soc_dai *dai, int mute)
349{ 322{
350 struct snd_soc_codec *codec = dai->codec; 323 struct snd_soc_codec *codec = dai->codec;
351 u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7; 324 u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7;
@@ -357,7 +330,7 @@ static int wm8731_mute(struct snd_soc_codec_dai *dai, int mute)
357 return 0; 330 return 0;
358} 331}
359 332
360static int wm8731_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai, 333static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
361 int clk_id, unsigned int freq, int dir) 334 int clk_id, unsigned int freq, int dir)
362{ 335{
363 struct snd_soc_codec *codec = codec_dai->codec; 336 struct snd_soc_codec *codec = codec_dai->codec;
@@ -376,7 +349,7 @@ static int wm8731_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
376} 349}
377 350
378 351
379static int wm8731_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 352static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai,
380 unsigned int fmt) 353 unsigned int fmt)
381{ 354{
382 struct snd_soc_codec *codec = codec_dai->codec; 355 struct snd_soc_codec *codec = codec_dai->codec;
@@ -435,29 +408,29 @@ static int wm8731_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
435 return 0; 408 return 0;
436} 409}
437 410
438static int wm8731_dapm_event(struct snd_soc_codec *codec, int event) 411static int wm8731_set_bias_level(struct snd_soc_codec *codec,
412 enum snd_soc_bias_level level)
439{ 413{
440 u16 reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f; 414 u16 reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f;
441 415
442 switch (event) { 416 switch (level) {
443 case SNDRV_CTL_POWER_D0: /* full On */ 417 case SND_SOC_BIAS_ON:
444 /* vref/mid, osc on, dac unmute */ 418 /* vref/mid, osc on, dac unmute */
445 wm8731_write(codec, WM8731_PWR, reg); 419 wm8731_write(codec, WM8731_PWR, reg);
446 break; 420 break;
447 case SNDRV_CTL_POWER_D1: /* partial On */ 421 case SND_SOC_BIAS_PREPARE:
448 case SNDRV_CTL_POWER_D2: /* partial On */
449 break; 422 break;
450 case SNDRV_CTL_POWER_D3hot: /* Off, with power */ 423 case SND_SOC_BIAS_STANDBY:
451 /* everything off except vref/vmid, */ 424 /* everything off except vref/vmid, */
452 wm8731_write(codec, WM8731_PWR, reg | 0x0040); 425 wm8731_write(codec, WM8731_PWR, reg | 0x0040);
453 break; 426 break;
454 case SNDRV_CTL_POWER_D3cold: /* Off, without power */ 427 case SND_SOC_BIAS_OFF:
455 /* everything off, dac mute, inactive */ 428 /* everything off, dac mute, inactive */
456 wm8731_write(codec, WM8731_ACTIVE, 0x0); 429 wm8731_write(codec, WM8731_ACTIVE, 0x0);
457 wm8731_write(codec, WM8731_PWR, 0xffff); 430 wm8731_write(codec, WM8731_PWR, 0xffff);
458 break; 431 break;
459 } 432 }
460 codec->dapm_state = event; 433 codec->bias_level = level;
461 return 0; 434 return 0;
462} 435}
463 436
@@ -470,7 +443,7 @@ static int wm8731_dapm_event(struct snd_soc_codec *codec, int event)
470#define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 443#define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
471 SNDRV_PCM_FMTBIT_S24_LE) 444 SNDRV_PCM_FMTBIT_S24_LE)
472 445
473struct snd_soc_codec_dai wm8731_dai = { 446struct snd_soc_dai wm8731_dai = {
474 .name = "WM8731", 447 .name = "WM8731",
475 .playback = { 448 .playback = {
476 .stream_name = "Playback", 449 .stream_name = "Playback",
@@ -503,7 +476,7 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
503 struct snd_soc_codec *codec = socdev->codec; 476 struct snd_soc_codec *codec = socdev->codec;
504 477
505 wm8731_write(codec, WM8731_ACTIVE, 0x0); 478 wm8731_write(codec, WM8731_ACTIVE, 0x0);
506 wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3cold); 479 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
507 return 0; 480 return 0;
508} 481}
509 482
@@ -521,8 +494,8 @@ static int wm8731_resume(struct platform_device *pdev)
521 data[1] = cache[i] & 0x00ff; 494 data[1] = cache[i] & 0x00ff;
522 codec->hw_write(codec->control_data, data, 2); 495 codec->hw_write(codec->control_data, data, 2);
523 } 496 }
524 wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3hot); 497 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
525 wm8731_dapm_event(codec, codec->suspend_dapm_state); 498 wm8731_set_bias_level(codec, codec->suspend_bias_level);
526 return 0; 499 return 0;
527} 500}
528 501
@@ -539,10 +512,10 @@ static int wm8731_init(struct snd_soc_device *socdev)
539 codec->owner = THIS_MODULE; 512 codec->owner = THIS_MODULE;
540 codec->read = wm8731_read_reg_cache; 513 codec->read = wm8731_read_reg_cache;
541 codec->write = wm8731_write; 514 codec->write = wm8731_write;
542 codec->dapm_event = wm8731_dapm_event; 515 codec->set_bias_level = wm8731_set_bias_level;
543 codec->dai = &wm8731_dai; 516 codec->dai = &wm8731_dai;
544 codec->num_dai = 1; 517 codec->num_dai = 1;
545 codec->reg_cache_size = sizeof(wm8731_reg); 518 codec->reg_cache_size = ARRAY_SIZE(wm8731_reg);
546 codec->reg_cache = kmemdup(wm8731_reg, sizeof(wm8731_reg), GFP_KERNEL); 519 codec->reg_cache = kmemdup(wm8731_reg, sizeof(wm8731_reg), GFP_KERNEL);
547 if (codec->reg_cache == NULL) 520 if (codec->reg_cache == NULL)
548 return -ENOMEM; 521 return -ENOMEM;
@@ -557,7 +530,7 @@ static int wm8731_init(struct snd_soc_device *socdev)
557 } 530 }
558 531
559 /* power on device */ 532 /* power on device */
560 wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3hot); 533 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
561 534
562 /* set the update bits */ 535 /* set the update bits */
563 reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V); 536 reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V);
@@ -632,13 +605,13 @@ static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind)
632 605
633 ret = i2c_attach_client(i2c); 606 ret = i2c_attach_client(i2c);
634 if (ret < 0) { 607 if (ret < 0) {
635 err("failed to attach codec at addr %x\n", addr); 608 pr_err("failed to attach codec at addr %x\n", addr);
636 goto err; 609 goto err;
637 } 610 }
638 611
639 ret = wm8731_init(socdev); 612 ret = wm8731_init(socdev);
640 if (ret < 0) { 613 if (ret < 0) {
641 err("failed to initialise WM8731\n"); 614 pr_err("failed to initialise WM8731\n");
642 goto err; 615 goto err;
643 } 616 }
644 return ret; 617 return ret;
@@ -689,7 +662,7 @@ static int wm8731_probe(struct platform_device *pdev)
689 struct wm8731_priv *wm8731; 662 struct wm8731_priv *wm8731;
690 int ret = 0; 663 int ret = 0;
691 664
692 info("WM8731 Audio Codec %s", WM8731_VERSION); 665 pr_info("WM8731 Audio Codec %s", WM8731_VERSION);
693 666
694 setup = socdev->codec_data; 667 setup = socdev->codec_data;
695 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 668 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
@@ -730,7 +703,7 @@ static int wm8731_remove(struct platform_device *pdev)
730 struct snd_soc_codec *codec = socdev->codec; 703 struct snd_soc_codec *codec = socdev->codec;
731 704
732 if (codec->control_data) 705 if (codec->control_data)
733 wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3cold); 706 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
734 707
735 snd_soc_free_pcms(socdev); 708 snd_soc_free_pcms(socdev);
736 snd_soc_dapm_free(socdev); 709 snd_soc_dapm_free(socdev);
diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h
index 5bcab6a7afb4..99f2e3c60e33 100644
--- a/sound/soc/codecs/wm8731.h
+++ b/sound/soc/codecs/wm8731.h
@@ -38,7 +38,7 @@ struct wm8731_setup_data {
38 unsigned short i2c_address; 38 unsigned short i2c_address;
39}; 39};
40 40
41extern struct snd_soc_codec_dai wm8731_dai; 41extern struct snd_soc_dai wm8731_dai;
42extern struct snd_soc_codec_device soc_codec_dev_wm8731; 42extern struct snd_soc_codec_device soc_codec_dev_wm8731;
43 43
44#endif 44#endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 16cd5d4d5ad9..e23cb09f0d14 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -31,25 +31,6 @@
31#define AUDIO_NAME "WM8750" 31#define AUDIO_NAME "WM8750"
32#define WM8750_VERSION "0.12" 32#define WM8750_VERSION "0.12"
33 33
34/*
35 * Debug
36 */
37
38#define WM8750_DEBUG 0
39
40#ifdef WM8750_DEBUG
41#define dbg(format, arg...) \
42 printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
43#else
44#define dbg(format, arg...) do {} while (0)
45#endif
46#define err(format, arg...) \
47 printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
48#define info(format, arg...) \
49 printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
50#define warn(format, arg...) \
51 printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
52
53/* codec private data */ 34/* codec private data */
54struct wm8750_priv { 35struct wm8750_priv {
55 unsigned int sysclk; 36 unsigned int sysclk;
@@ -378,7 +359,7 @@ static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
378 SND_SOC_DAPM_INPUT("RINPUT3"), 359 SND_SOC_DAPM_INPUT("RINPUT3"),
379}; 360};
380 361
381static const char *audio_map[][3] = { 362static const struct snd_soc_dapm_route audio_map[] = {
382 /* left mixer */ 363 /* left mixer */
383 {"Left Mixer", "Playback Switch", "Left DAC"}, 364 {"Left Mixer", "Playback Switch", "Left DAC"},
384 {"Left Mixer", "Left Bypass Switch", "Left Line Mux"}, 365 {"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
@@ -470,22 +451,14 @@ static const char *audio_map[][3] = {
470 /* ADC */ 451 /* ADC */
471 {"Left ADC", NULL, "Left ADC Mux"}, 452 {"Left ADC", NULL, "Left ADC Mux"},
472 {"Right ADC", NULL, "Right ADC Mux"}, 453 {"Right ADC", NULL, "Right ADC Mux"},
473
474 /* terminator */
475 {NULL, NULL, NULL},
476}; 454};
477 455
478static int wm8750_add_widgets(struct snd_soc_codec *codec) 456static int wm8750_add_widgets(struct snd_soc_codec *codec)
479{ 457{
480 int i; 458 snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets,
481 459 ARRAY_SIZE(wm8750_dapm_widgets));
482 for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++)
483 snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
484 460
485 /* set up audio path audio_mapnects */ 461 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
486 for (i = 0; audio_map[i][0] != NULL; i++)
487 snd_soc_dapm_connect_input(codec, audio_map[i][0],
488 audio_map[i][1], audio_map[i][2]);
489 462
490 snd_soc_dapm_new_widgets(codec); 463 snd_soc_dapm_new_widgets(codec);
491 return 0; 464 return 0;
@@ -563,7 +536,7 @@ static inline int get_coeff(int mclk, int rate)
563 return -EINVAL; 536 return -EINVAL;
564} 537}
565 538
566static int wm8750_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai, 539static int wm8750_set_dai_sysclk(struct snd_soc_dai *codec_dai,
567 int clk_id, unsigned int freq, int dir) 540 int clk_id, unsigned int freq, int dir)
568{ 541{
569 struct snd_soc_codec *codec = codec_dai->codec; 542 struct snd_soc_codec *codec = codec_dai->codec;
@@ -581,7 +554,7 @@ static int wm8750_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
581 return -EINVAL; 554 return -EINVAL;
582} 555}
583 556
584static int wm8750_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 557static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai,
585 unsigned int fmt) 558 unsigned int fmt)
586{ 559{
587 struct snd_soc_codec *codec = codec_dai->codec; 560 struct snd_soc_codec *codec = codec_dai->codec;
@@ -674,7 +647,7 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
674 return 0; 647 return 0;
675} 648}
676 649
677static int wm8750_mute(struct snd_soc_codec_dai *dai, int mute) 650static int wm8750_mute(struct snd_soc_dai *dai, int mute)
678{ 651{
679 struct snd_soc_codec *codec = dai->codec; 652 struct snd_soc_codec *codec = dai->codec;
680 u16 mute_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7; 653 u16 mute_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7;
@@ -686,29 +659,29 @@ static int wm8750_mute(struct snd_soc_codec_dai *dai, int mute)
686 return 0; 659 return 0;
687} 660}
688 661
689static int wm8750_dapm_event(struct snd_soc_codec *codec, int event) 662static int wm8750_set_bias_level(struct snd_soc_codec *codec,
663 enum snd_soc_bias_level level)
690{ 664{
691 u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3e; 665 u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3e;
692 666
693 switch (event) { 667 switch (level) {
694 case SNDRV_CTL_POWER_D0: /* full On */ 668 case SND_SOC_BIAS_ON:
695 /* set vmid to 50k and unmute dac */ 669 /* set vmid to 50k and unmute dac */
696 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); 670 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
697 break; 671 break;
698 case SNDRV_CTL_POWER_D1: /* partial On */ 672 case SND_SOC_BIAS_PREPARE:
699 case SNDRV_CTL_POWER_D2: /* partial On */
700 /* set vmid to 5k for quick power up */ 673 /* set vmid to 5k for quick power up */
701 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c1); 674 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
702 break; 675 break;
703 case SNDRV_CTL_POWER_D3hot: /* Off, with power */ 676 case SND_SOC_BIAS_STANDBY:
704 /* mute dac and set vmid to 500k, enable VREF */ 677 /* mute dac and set vmid to 500k, enable VREF */
705 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0141); 678 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
706 break; 679 break;
707 case SNDRV_CTL_POWER_D3cold: /* Off, without power */ 680 case SND_SOC_BIAS_OFF:
708 wm8750_write(codec, WM8750_PWR1, 0x0001); 681 wm8750_write(codec, WM8750_PWR1, 0x0001);
709 break; 682 break;
710 } 683 }
711 codec->dapm_state = event; 684 codec->bias_level = level;
712 return 0; 685 return 0;
713} 686}
714 687
@@ -719,7 +692,7 @@ static int wm8750_dapm_event(struct snd_soc_codec *codec, int event)
719#define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 692#define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
720 SNDRV_PCM_FMTBIT_S24_LE) 693 SNDRV_PCM_FMTBIT_S24_LE)
721 694
722struct snd_soc_codec_dai wm8750_dai = { 695struct snd_soc_dai wm8750_dai = {
723 .name = "WM8750", 696 .name = "WM8750",
724 .playback = { 697 .playback = {
725 .stream_name = "Playback", 698 .stream_name = "Playback",
@@ -748,7 +721,7 @@ static void wm8750_work(struct work_struct *work)
748{ 721{
749 struct snd_soc_codec *codec = 722 struct snd_soc_codec *codec =
750 container_of(work, struct snd_soc_codec, delayed_work.work); 723 container_of(work, struct snd_soc_codec, delayed_work.work);
751 wm8750_dapm_event(codec, codec->dapm_state); 724 wm8750_set_bias_level(codec, codec->bias_level);
752} 725}
753 726
754static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) 727static int wm8750_suspend(struct platform_device *pdev, pm_message_t state)
@@ -756,7 +729,7 @@ static int wm8750_suspend(struct platform_device *pdev, pm_message_t state)
756 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 729 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
757 struct snd_soc_codec *codec = socdev->codec; 730 struct snd_soc_codec *codec = socdev->codec;
758 731
759 wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3cold); 732 wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
760 return 0; 733 return 0;
761} 734}
762 735
@@ -777,12 +750,12 @@ static int wm8750_resume(struct platform_device *pdev)
777 codec->hw_write(codec->control_data, data, 2); 750 codec->hw_write(codec->control_data, data, 2);
778 } 751 }
779 752
780 wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3hot); 753 wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
781 754
782 /* charge wm8750 caps */ 755 /* charge wm8750 caps */
783 if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) { 756 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
784 wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2); 757 wm8750_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
785 codec->dapm_state = SNDRV_CTL_POWER_D0; 758 codec->bias_level = SND_SOC_BIAS_ON;
786 schedule_delayed_work(&codec->delayed_work, 759 schedule_delayed_work(&codec->delayed_work,
787 msecs_to_jiffies(1000)); 760 msecs_to_jiffies(1000));
788 } 761 }
@@ -803,10 +776,10 @@ static int wm8750_init(struct snd_soc_device *socdev)
803 codec->owner = THIS_MODULE; 776 codec->owner = THIS_MODULE;
804 codec->read = wm8750_read_reg_cache; 777 codec->read = wm8750_read_reg_cache;
805 codec->write = wm8750_write; 778 codec->write = wm8750_write;
806 codec->dapm_event = wm8750_dapm_event; 779 codec->set_bias_level = wm8750_set_bias_level;
807 codec->dai = &wm8750_dai; 780 codec->dai = &wm8750_dai;
808 codec->num_dai = 1; 781 codec->num_dai = 1;
809 codec->reg_cache_size = sizeof(wm8750_reg); 782 codec->reg_cache_size = ARRAY_SIZE(wm8750_reg);
810 codec->reg_cache = kmemdup(wm8750_reg, sizeof(wm8750_reg), GFP_KERNEL); 783 codec->reg_cache = kmemdup(wm8750_reg, sizeof(wm8750_reg), GFP_KERNEL);
811 if (codec->reg_cache == NULL) 784 if (codec->reg_cache == NULL)
812 return -ENOMEM; 785 return -ENOMEM;
@@ -821,8 +794,8 @@ static int wm8750_init(struct snd_soc_device *socdev)
821 } 794 }
822 795
823 /* charge output caps */ 796 /* charge output caps */
824 wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2); 797 wm8750_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
825 codec->dapm_state = SNDRV_CTL_POWER_D3hot; 798 codec->bias_level = SND_SOC_BIAS_STANDBY;
826 schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000)); 799 schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
827 800
828 /* set the update bits */ 801 /* set the update bits */
@@ -904,13 +877,13 @@ static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind)
904 877
905 ret = i2c_attach_client(i2c); 878 ret = i2c_attach_client(i2c);
906 if (ret < 0) { 879 if (ret < 0) {
907 err("failed to attach codec at addr %x\n", addr); 880 pr_err("failed to attach codec at addr %x\n", addr);
908 goto err; 881 goto err;
909 } 882 }
910 883
911 ret = wm8750_init(socdev); 884 ret = wm8750_init(socdev);
912 if (ret < 0) { 885 if (ret < 0) {
913 err("failed to initialise WM8750\n"); 886 pr_err("failed to initialise WM8750\n");
914 goto err; 887 goto err;
915 } 888 }
916 return ret; 889 return ret;
@@ -961,7 +934,7 @@ static int wm8750_probe(struct platform_device *pdev)
961 struct wm8750_priv *wm8750; 934 struct wm8750_priv *wm8750;
962 int ret = 0; 935 int ret = 0;
963 936
964 info("WM8750 Audio Codec %s", WM8750_VERSION); 937 pr_info("WM8750 Audio Codec %s", WM8750_VERSION);
965 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 938 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
966 if (codec == NULL) 939 if (codec == NULL)
967 return -ENOMEM; 940 return -ENOMEM;
@@ -1021,7 +994,7 @@ static int wm8750_remove(struct platform_device *pdev)
1021 struct snd_soc_codec *codec = socdev->codec; 994 struct snd_soc_codec *codec = socdev->codec;
1022 995
1023 if (codec->control_data) 996 if (codec->control_data)
1024 wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3cold); 997 wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
1025 run_delayed_work(&codec->delayed_work); 998 run_delayed_work(&codec->delayed_work);
1026 snd_soc_free_pcms(socdev); 999 snd_soc_free_pcms(socdev);
1027 snd_soc_dapm_free(socdev); 1000 snd_soc_dapm_free(socdev);
diff --git a/sound/soc/codecs/wm8750.h b/sound/soc/codecs/wm8750.h
index a97a54a6348e..8ef30e628b21 100644
--- a/sound/soc/codecs/wm8750.h
+++ b/sound/soc/codecs/wm8750.h
@@ -61,7 +61,7 @@ struct wm8750_setup_data {
61 unsigned short i2c_address; 61 unsigned short i2c_address;
62}; 62};
63 63
64extern struct snd_soc_codec_dai wm8750_dai; 64extern struct snd_soc_dai wm8750_dai;
65extern struct snd_soc_codec_device soc_codec_dev_wm8750; 65extern struct snd_soc_codec_device soc_codec_dev_wm8750;
66 66
67#endif 67#endif
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index fb41826c4c4c..8604809f0c36 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -55,25 +55,6 @@
55#define AUDIO_NAME "wm8753" 55#define AUDIO_NAME "wm8753"
56#define WM8753_VERSION "0.16" 56#define WM8753_VERSION "0.16"
57 57
58/*
59 * Debug
60 */
61
62#define WM8753_DEBUG 0
63
64#ifdef WM8753_DEBUG
65#define dbg(format, arg...) \
66 printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
67#else
68#define dbg(format, arg...) do {} while (0)
69#endif
70#define err(format, arg...) \
71 printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
72#define info(format, arg...) \
73 printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
74#define warn(format, arg...) \
75 printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
76
77static int caps_charge = 2000; 58static int caps_charge = 2000;
78module_param(caps_charge, int, 0); 59module_param(caps_charge, int, 0);
79MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); 60MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");
@@ -260,28 +241,50 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
260 return 1; 241 return 1;
261} 242}
262 243
263static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); 244static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 300, 0);
245static const DECLARE_TLV_DB_SCALE(mic_preamp_tlv, 1200, 600, 0);
246static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);
247static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
248static const unsigned int out_tlv[] = {
249 TLV_DB_RANGE_HEAD(2),
250 /* 0000000 - 0101111 = "Analogue mute" */
251 0, 48, TLV_DB_SCALE_ITEM(-25500, 0, 0),
252 48, 127, TLV_DB_SCALE_ITEM(-7300, 100, 0),
253};
254static const DECLARE_TLV_DB_SCALE(mix_tlv, -1500, 300, 0);
255static const DECLARE_TLV_DB_SCALE(voice_mix_tlv, -1200, 300, 0);
256static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0);
264 257
265static const struct snd_kcontrol_new wm8753_snd_controls[] = { 258static const struct snd_kcontrol_new wm8753_snd_controls[] = {
266SOC_DOUBLE_R("PCM Volume", WM8753_LDAC, WM8753_RDAC, 0, 255, 0), 259SOC_DOUBLE_R_TLV("PCM Volume", WM8753_LDAC, WM8753_RDAC, 0, 255, 0, dac_tlv),
267 260
268SOC_DOUBLE_R("ADC Capture Volume", WM8753_LADC, WM8753_RADC, 0, 255, 0), 261SOC_DOUBLE_R_TLV("ADC Capture Volume", WM8753_LADC, WM8753_RADC, 0, 255, 0,
269 262 adc_tlv),
270SOC_DOUBLE_R("Headphone Playback Volume", WM8753_LOUT1V, WM8753_ROUT1V, 0, 127, 0), 263
271SOC_DOUBLE_R("Speaker Playback Volume", WM8753_LOUT2V, WM8753_ROUT2V, 0, 127, 0), 264SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8753_LOUT1V, WM8753_ROUT1V,
272 265 0, 127, 0, out_tlv),
273SOC_SINGLE("Mono Playback Volume", WM8753_MOUTV, 0, 127, 0), 266SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8753_LOUT2V, WM8753_ROUT2V, 0,
274 267 127, 0, out_tlv),
275SOC_DOUBLE_R("Bypass Playback Volume", WM8753_LOUTM1, WM8753_ROUTM1, 4, 7, 1), 268
276SOC_DOUBLE_R("Sidetone Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 4, 7, 1), 269SOC_SINGLE_TLV("Mono Playback Volume", WM8753_MOUTV, 0, 127, 0, out_tlv),
277SOC_DOUBLE_R("Voice Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 0, 7, 1), 270
278 271SOC_DOUBLE_R_TLV("Bypass Playback Volume", WM8753_LOUTM1, WM8753_ROUTM1, 4, 7,
279SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8753_LOUT1V, WM8753_ROUT1V, 7, 1, 0), 272 1, mix_tlv),
280SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7, 1, 0), 273SOC_DOUBLE_R_TLV("Sidetone Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 4,
281 274 7, 1, mix_tlv),
282SOC_SINGLE("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1), 275SOC_DOUBLE_R_TLV("Voice Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 0, 7,
283SOC_SINGLE("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1), 276 1, voice_mix_tlv),
284SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 0, 7, 1), 277
278SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8753_LOUT1V, WM8753_ROUT1V, 7,
279 1, 0),
280SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7,
281 1, 0),
282
283SOC_SINGLE_TLV("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1, mix_tlv),
284SOC_SINGLE_TLV("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1,
285 mix_tlv),
286SOC_SINGLE_TLV("Mono Voice Playback Volume", WM8753_MOUTM2, 0, 7, 1,
287 voice_mix_tlv),
285SOC_SINGLE("Mono Playback ZC Switch", WM8753_MOUTV, 7, 1, 0), 288SOC_SINGLE("Mono Playback ZC Switch", WM8753_MOUTV, 7, 1, 0),
286 289
287SOC_ENUM("Bass Boost", wm8753_enum[0]), 290SOC_ENUM("Bass Boost", wm8753_enum[0]),
@@ -291,10 +294,13 @@ SOC_SINGLE("Bass Volume", WM8753_BASS, 0, 15, 1),
291SOC_SINGLE("Treble Volume", WM8753_TREBLE, 0, 15, 1), 294SOC_SINGLE("Treble Volume", WM8753_TREBLE, 0, 15, 1),
292SOC_ENUM("Treble Cut-off", wm8753_enum[2]), 295SOC_ENUM("Treble Cut-off", wm8753_enum[2]),
293 296
294SOC_DOUBLE_TLV("Sidetone Capture Volume", WM8753_RECMIX1, 0, 4, 7, 1, rec_mix_tlv), 297SOC_DOUBLE_TLV("Sidetone Capture Volume", WM8753_RECMIX1, 0, 4, 7, 1,
295SOC_SINGLE_TLV("Voice Sidetone Capture Volume", WM8753_RECMIX2, 0, 7, 1, rec_mix_tlv), 298 rec_mix_tlv),
299SOC_SINGLE_TLV("Voice Sidetone Capture Volume", WM8753_RECMIX2, 0, 7, 1,
300 rec_mix_tlv),
296 301
297SOC_DOUBLE_R("Capture Volume", WM8753_LINVOL, WM8753_RINVOL, 0, 63, 0), 302SOC_DOUBLE_R_TLV("Capture Volume", WM8753_LINVOL, WM8753_RINVOL, 0, 63, 0,
303 pga_tlv),
298SOC_DOUBLE_R("Capture ZC Switch", WM8753_LINVOL, WM8753_RINVOL, 6, 1, 0), 304SOC_DOUBLE_R("Capture ZC Switch", WM8753_LINVOL, WM8753_RINVOL, 6, 1, 0),
299SOC_DOUBLE_R("Capture Switch", WM8753_LINVOL, WM8753_RINVOL, 7, 1, 1), 305SOC_DOUBLE_R("Capture Switch", WM8753_LINVOL, WM8753_RINVOL, 7, 1, 1),
300 306
@@ -326,8 +332,8 @@ SOC_ENUM("De-emphasis", wm8753_enum[8]),
326SOC_ENUM("Playback Mono Mix", wm8753_enum[9]), 332SOC_ENUM("Playback Mono Mix", wm8753_enum[9]),
327SOC_ENUM("Playback Phase", wm8753_enum[10]), 333SOC_ENUM("Playback Phase", wm8753_enum[10]),
328 334
329SOC_SINGLE("Mic2 Capture Volume", WM8753_INCTL1, 7, 3, 0), 335SOC_SINGLE_TLV("Mic2 Capture Volume", WM8753_INCTL1, 7, 3, 0, mic_preamp_tlv),
330SOC_SINGLE("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0), 336SOC_SINGLE_TLV("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0, mic_preamp_tlv),
331 337
332SOC_ENUM_EXT("DAI Mode", wm8753_enum[26], wm8753_get_dai, wm8753_set_dai), 338SOC_ENUM_EXT("DAI Mode", wm8753_enum[26], wm8753_get_dai, wm8753_set_dai),
333 339
@@ -523,7 +529,7 @@ SND_SOC_DAPM_INPUT("MIC2"),
523SND_SOC_DAPM_VMID("VREF"), 529SND_SOC_DAPM_VMID("VREF"),
524}; 530};
525 531
526static const char *audio_map[][3] = { 532static const struct snd_soc_dapm_route audio_map[] = {
527 /* left mixer */ 533 /* left mixer */
528 {"Left Mixer", "Left Playback Switch", "Left DAC"}, 534 {"Left Mixer", "Left Playback Switch", "Left DAC"},
529 {"Left Mixer", "Voice Playback Switch", "Voice DAC"}, 535 {"Left Mixer", "Voice Playback Switch", "Voice DAC"},
@@ -674,23 +680,14 @@ static const char *audio_map[][3] = {
674 680
675 /* ACOP */ 681 /* ACOP */
676 {"ACOP", NULL, "ALC Mixer"}, 682 {"ACOP", NULL, "ALC Mixer"},
677
678 /* terminator */
679 {NULL, NULL, NULL},
680}; 683};
681 684
682static int wm8753_add_widgets(struct snd_soc_codec *codec) 685static int wm8753_add_widgets(struct snd_soc_codec *codec)
683{ 686{
684 int i; 687 snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
688 ARRAY_SIZE(wm8753_dapm_widgets));
685 689
686 for (i = 0; i < ARRAY_SIZE(wm8753_dapm_widgets); i++) 690 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
687 snd_soc_dapm_new_control(codec, &wm8753_dapm_widgets[i]);
688
689 /* set up the WM8753 audio map */
690 for (i = 0; audio_map[i][0] != NULL; i++) {
691 snd_soc_dapm_connect_input(codec, audio_map[i][0],
692 audio_map[i][1], audio_map[i][2]);
693 }
694 691
695 snd_soc_dapm_new_widgets(codec); 692 snd_soc_dapm_new_widgets(codec);
696 return 0; 693 return 0;
@@ -743,7 +740,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
743 pll_div->k = K; 740 pll_div->k = K;
744} 741}
745 742
746static int wm8753_set_dai_pll(struct snd_soc_codec_dai *codec_dai, 743static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai,
747 int pll_id, unsigned int freq_in, unsigned int freq_out) 744 int pll_id, unsigned int freq_in, unsigned int freq_out)
748{ 745{
749 u16 reg, enable; 746 u16 reg, enable;
@@ -866,7 +863,7 @@ static int get_coeff(int mclk, int rate)
866/* 863/*
867 * Clock after PLL and dividers 864 * Clock after PLL and dividers
868 */ 865 */
869static int wm8753_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai, 866static int wm8753_set_dai_sysclk(struct snd_soc_dai *codec_dai,
870 int clk_id, unsigned int freq, int dir) 867 int clk_id, unsigned int freq, int dir)
871{ 868{
872 struct snd_soc_codec *codec = codec_dai->codec; 869 struct snd_soc_codec *codec = codec_dai->codec;
@@ -893,7 +890,7 @@ static int wm8753_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
893/* 890/*
894 * Set's ADC and Voice DAC format. 891 * Set's ADC and Voice DAC format.
895 */ 892 */
896static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 893static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
897 unsigned int fmt) 894 unsigned int fmt)
898{ 895{
899 struct snd_soc_codec *codec = codec_dai->codec; 896 struct snd_soc_codec *codec = codec_dai->codec;
@@ -963,7 +960,7 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
963/* 960/*
964 * Set's PCM dai fmt and BCLK. 961 * Set's PCM dai fmt and BCLK.
965 */ 962 */
966static int wm8753_pcm_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 963static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
967 unsigned int fmt) 964 unsigned int fmt)
968{ 965{
969 struct snd_soc_codec *codec = codec_dai->codec; 966 struct snd_soc_codec *codec = codec_dai->codec;
@@ -1029,7 +1026,7 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
1029 return 0; 1026 return 0;
1030} 1027}
1031 1028
1032static int wm8753_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai, 1029static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
1033 int div_id, int div) 1030 int div_id, int div)
1034{ 1031{
1035 struct snd_soc_codec *codec = codec_dai->codec; 1032 struct snd_soc_codec *codec = codec_dai->codec;
@@ -1057,7 +1054,7 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
1057/* 1054/*
1058 * Set's HiFi DAC format. 1055 * Set's HiFi DAC format.
1059 */ 1056 */
1060static int wm8753_hdac_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 1057static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,
1061 unsigned int fmt) 1058 unsigned int fmt)
1062{ 1059{
1063 struct snd_soc_codec *codec = codec_dai->codec; 1060 struct snd_soc_codec *codec = codec_dai->codec;
@@ -1090,7 +1087,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
1090/* 1087/*
1091 * Set's I2S DAI format. 1088 * Set's I2S DAI format.
1092 */ 1089 */
1093static int wm8753_i2s_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 1090static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
1094 unsigned int fmt) 1091 unsigned int fmt)
1095{ 1092{
1096 struct snd_soc_codec *codec = codec_dai->codec; 1093 struct snd_soc_codec *codec = codec_dai->codec;
@@ -1198,7 +1195,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
1198 return 0; 1195 return 0;
1199} 1196}
1200 1197
1201static int wm8753_mode1v_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 1198static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai,
1202 unsigned int fmt) 1199 unsigned int fmt)
1203{ 1200{
1204 struct snd_soc_codec *codec = codec_dai->codec; 1201 struct snd_soc_codec *codec = codec_dai->codec;
@@ -1213,7 +1210,7 @@ static int wm8753_mode1v_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
1213 return wm8753_pcm_set_dai_fmt(codec_dai, fmt); 1210 return wm8753_pcm_set_dai_fmt(codec_dai, fmt);
1214} 1211}
1215 1212
1216static int wm8753_mode1h_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 1213static int wm8753_mode1h_set_dai_fmt(struct snd_soc_dai *codec_dai,
1217 unsigned int fmt) 1214 unsigned int fmt)
1218{ 1215{
1219 if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0) 1216 if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)
@@ -1221,7 +1218,7 @@ static int wm8753_mode1h_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
1221 return wm8753_i2s_set_dai_fmt(codec_dai, fmt); 1218 return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
1222} 1219}
1223 1220
1224static int wm8753_mode2_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 1221static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai,
1225 unsigned int fmt) 1222 unsigned int fmt)
1226{ 1223{
1227 struct snd_soc_codec *codec = codec_dai->codec; 1224 struct snd_soc_codec *codec = codec_dai->codec;
@@ -1236,7 +1233,7 @@ static int wm8753_mode2_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
1236 return wm8753_i2s_set_dai_fmt(codec_dai, fmt); 1233 return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
1237} 1234}
1238 1235
1239static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 1236static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai,
1240 unsigned int fmt) 1237 unsigned int fmt)
1241{ 1238{
1242 struct snd_soc_codec *codec = codec_dai->codec; 1239 struct snd_soc_codec *codec = codec_dai->codec;
@@ -1253,7 +1250,7 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
1253 return wm8753_i2s_set_dai_fmt(codec_dai, fmt); 1250 return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
1254} 1251}
1255 1252
1256static int wm8753_mute(struct snd_soc_codec_dai *dai, int mute) 1253static int wm8753_mute(struct snd_soc_dai *dai, int mute)
1257{ 1254{
1258 struct snd_soc_codec *codec = dai->codec; 1255 struct snd_soc_codec *codec = dai->codec;
1259 u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; 1256 u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7;
@@ -1274,29 +1271,29 @@ static int wm8753_mute(struct snd_soc_codec_dai *dai, int mute)
1274 return 0; 1271 return 0;
1275} 1272}
1276 1273
1277static int wm8753_dapm_event(struct snd_soc_codec *codec, int event) 1274static int wm8753_set_bias_level(struct snd_soc_codec *codec,
1275 enum snd_soc_bias_level level)
1278{ 1276{
1279 u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e; 1277 u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e;
1280 1278
1281 switch (event) { 1279 switch (level) {
1282 case SNDRV_CTL_POWER_D0: /* full On */ 1280 case SND_SOC_BIAS_ON:
1283 /* set vmid to 50k and unmute dac */ 1281 /* set vmid to 50k and unmute dac */
1284 wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); 1282 wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
1285 break; 1283 break;
1286 case SNDRV_CTL_POWER_D1: /* partial On */ 1284 case SND_SOC_BIAS_PREPARE:
1287 case SNDRV_CTL_POWER_D2: /* partial On */
1288 /* set vmid to 5k for quick power up */ 1285 /* set vmid to 5k for quick power up */
1289 wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); 1286 wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
1290 break; 1287 break;
1291 case SNDRV_CTL_POWER_D3hot: /* Off, with power */ 1288 case SND_SOC_BIAS_STANDBY:
1292 /* mute dac and set vmid to 500k, enable VREF */ 1289 /* mute dac and set vmid to 500k, enable VREF */
1293 wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141); 1290 wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
1294 break; 1291 break;
1295 case SNDRV_CTL_POWER_D3cold: /* Off, without power */ 1292 case SND_SOC_BIAS_OFF:
1296 wm8753_write(codec, WM8753_PWR1, 0x0001); 1293 wm8753_write(codec, WM8753_PWR1, 0x0001);
1297 break; 1294 break;
1298 } 1295 }
1299 codec->dapm_state = event; 1296 codec->bias_level = level;
1300 return 0; 1297 return 0;
1301} 1298}
1302 1299
@@ -1319,7 +1316,7 @@ static int wm8753_dapm_event(struct snd_soc_codec *codec, int event)
1319 * 3. Voice disabled - HIFI over HIFI 1316 * 3. Voice disabled - HIFI over HIFI
1320 * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture 1317 * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
1321 */ 1318 */
1322static const struct snd_soc_codec_dai wm8753_all_dai[] = { 1319static const struct snd_soc_dai wm8753_all_dai[] = {
1323/* DAI HiFi mode 1 */ 1320/* DAI HiFi mode 1 */
1324{ .name = "WM8753 HiFi", 1321{ .name = "WM8753 HiFi",
1325 .id = 1, 1322 .id = 1,
@@ -1459,7 +1456,7 @@ static const struct snd_soc_codec_dai wm8753_all_dai[] = {
1459}, 1456},
1460}; 1457};
1461 1458
1462struct snd_soc_codec_dai wm8753_dai[2]; 1459struct snd_soc_dai wm8753_dai[2];
1463EXPORT_SYMBOL_GPL(wm8753_dai); 1460EXPORT_SYMBOL_GPL(wm8753_dai);
1464 1461
1465static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode) 1462static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode)
@@ -1500,7 +1497,7 @@ static void wm8753_work(struct work_struct *work)
1500{ 1497{
1501 struct snd_soc_codec *codec = 1498 struct snd_soc_codec *codec =
1502 container_of(work, struct snd_soc_codec, delayed_work.work); 1499 container_of(work, struct snd_soc_codec, delayed_work.work);
1503 wm8753_dapm_event(codec, codec->dapm_state); 1500 wm8753_set_bias_level(codec, codec->bias_level);
1504} 1501}
1505 1502
1506static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) 1503static int wm8753_suspend(struct platform_device *pdev, pm_message_t state)
@@ -1512,7 +1509,7 @@ static int wm8753_suspend(struct platform_device *pdev, pm_message_t state)
1512 if (!codec->card) 1509 if (!codec->card)
1513 return 0; 1510 return 0;
1514 1511
1515 wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3cold); 1512 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
1516 return 0; 1513 return 0;
1517} 1514}
1518 1515
@@ -1537,12 +1534,12 @@ static int wm8753_resume(struct platform_device *pdev)
1537 codec->hw_write(codec->control_data, data, 2); 1534 codec->hw_write(codec->control_data, data, 2);
1538 } 1535 }
1539 1536
1540 wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3hot); 1537 wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1541 1538
1542 /* charge wm8753 caps */ 1539 /* charge wm8753 caps */
1543 if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) { 1540 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
1544 wm8753_dapm_event(codec, SNDRV_CTL_POWER_D2); 1541 wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
1545 codec->dapm_state = SNDRV_CTL_POWER_D0; 1542 codec->bias_level = SND_SOC_BIAS_ON;
1546 schedule_delayed_work(&codec->delayed_work, 1543 schedule_delayed_work(&codec->delayed_work,
1547 msecs_to_jiffies(caps_charge)); 1544 msecs_to_jiffies(caps_charge));
1548 } 1545 }
@@ -1563,10 +1560,10 @@ static int wm8753_init(struct snd_soc_device *socdev)
1563 codec->owner = THIS_MODULE; 1560 codec->owner = THIS_MODULE;
1564 codec->read = wm8753_read_reg_cache; 1561 codec->read = wm8753_read_reg_cache;
1565 codec->write = wm8753_write; 1562 codec->write = wm8753_write;
1566 codec->dapm_event = wm8753_dapm_event; 1563 codec->set_bias_level = wm8753_set_bias_level;
1567 codec->dai = wm8753_dai; 1564 codec->dai = wm8753_dai;
1568 codec->num_dai = 2; 1565 codec->num_dai = 2;
1569 codec->reg_cache_size = sizeof(wm8753_reg); 1566 codec->reg_cache_size = ARRAY_SIZE(wm8753_reg);
1570 codec->reg_cache = kmemdup(wm8753_reg, sizeof(wm8753_reg), GFP_KERNEL); 1567 codec->reg_cache = kmemdup(wm8753_reg, sizeof(wm8753_reg), GFP_KERNEL);
1571 1568
1572 if (codec->reg_cache == NULL) 1569 if (codec->reg_cache == NULL)
@@ -1584,8 +1581,8 @@ static int wm8753_init(struct snd_soc_device *socdev)
1584 } 1581 }
1585 1582
1586 /* charge output caps */ 1583 /* charge output caps */
1587 wm8753_dapm_event(codec, SNDRV_CTL_POWER_D2); 1584 wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
1588 codec->dapm_state = SNDRV_CTL_POWER_D3hot; 1585 codec->bias_level = SND_SOC_BIAS_STANDBY;
1589 schedule_delayed_work(&codec->delayed_work, 1586 schedule_delayed_work(&codec->delayed_work,
1590 msecs_to_jiffies(caps_charge)); 1587 msecs_to_jiffies(caps_charge));
1591 1588
@@ -1673,13 +1670,13 @@ static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind)
1673 1670
1674 ret = i2c_attach_client(i2c); 1671 ret = i2c_attach_client(i2c);
1675 if (ret < 0) { 1672 if (ret < 0) {
1676 err("failed to attach codec at addr %x\n", addr); 1673 pr_err("failed to attach codec at addr %x\n", addr);
1677 goto err; 1674 goto err;
1678 } 1675 }
1679 1676
1680 ret = wm8753_init(socdev); 1677 ret = wm8753_init(socdev);
1681 if (ret < 0) { 1678 if (ret < 0) {
1682 err("failed to initialise WM8753\n"); 1679 pr_err("failed to initialise WM8753\n");
1683 goto err; 1680 goto err;
1684 } 1681 }
1685 1682
@@ -1731,7 +1728,7 @@ static int wm8753_probe(struct platform_device *pdev)
1731 struct wm8753_priv *wm8753; 1728 struct wm8753_priv *wm8753;
1732 int ret = 0; 1729 int ret = 0;
1733 1730
1734 info("WM8753 Audio Codec %s", WM8753_VERSION); 1731 pr_info("WM8753 Audio Codec %s", WM8753_VERSION);
1735 1732
1736 setup = socdev->codec_data; 1733 setup = socdev->codec_data;
1737 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 1734 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
@@ -1792,7 +1789,7 @@ static int wm8753_remove(struct platform_device *pdev)
1792 struct snd_soc_codec *codec = socdev->codec; 1789 struct snd_soc_codec *codec = socdev->codec;
1793 1790
1794 if (codec->control_data) 1791 if (codec->control_data)
1795 wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3cold); 1792 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
1796 run_delayed_work(&codec->delayed_work); 1793 run_delayed_work(&codec->delayed_work);
1797 snd_soc_free_pcms(socdev); 1794 snd_soc_free_pcms(socdev);
1798 snd_soc_dapm_free(socdev); 1795 snd_soc_dapm_free(socdev);
diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h
index 95e2a1f53169..44f5f1ff0cc7 100644
--- a/sound/soc/codecs/wm8753.h
+++ b/sound/soc/codecs/wm8753.h
@@ -120,7 +120,7 @@ struct wm8753_setup_data {
120#define WM8753_DAI_HIFI 0 120#define WM8753_DAI_HIFI 0
121#define WM8753_DAI_VOICE 1 121#define WM8753_DAI_VOICE 1
122 122
123extern struct snd_soc_codec_dai wm8753_dai[2]; 123extern struct snd_soc_dai wm8753_dai[2];
124extern struct snd_soc_codec_device soc_codec_dev_wm8753; 124extern struct snd_soc_codec_device soc_codec_dev_wm8753;
125 125
126#endif 126#endif
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
new file mode 100644
index 000000000000..3ecce5168e94
--- /dev/null
+++ b/sound/soc/codecs/wm8990.c
@@ -0,0 +1,1626 @@
1/*
2 * wm8990.c -- WM8990 ALSA Soc Audio driver
3 *
4 * Copyright 2008 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood
6 * lg@opensource.wolfsonmicro.com or linux@wolfsonmicro.com
7 *
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
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pm.h>
20#include <linux/i2c.h>
21#include <linux/platform_device.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26#include <sound/soc-dapm.h>
27#include <sound/initval.h>
28#include <sound/tlv.h>
29#include <asm/div64.h>
30
31#include "wm8990.h"
32
33#define AUDIO_NAME "wm8990"
34#define WM8990_VERSION "0.2"
35
36/* codec private data */
37struct wm8990_priv {
38 unsigned int sysclk;
39 unsigned int pcmclk;
40};
41
42/*
43 * wm8990 register cache. Note that register 0 is not included in the
44 * cache.
45 */
46static const u16 wm8990_reg[] = {
47 0x8990, /* R0 - Reset */
48 0x0000, /* R1 - Power Management (1) */
49 0x6000, /* R2 - Power Management (2) */
50 0x0000, /* R3 - Power Management (3) */
51 0x4050, /* R4 - Audio Interface (1) */
52 0x4000, /* R5 - Audio Interface (2) */
53 0x01C8, /* R6 - Clocking (1) */
54 0x0000, /* R7 - Clocking (2) */
55 0x0040, /* R8 - Audio Interface (3) */
56 0x0040, /* R9 - Audio Interface (4) */
57 0x0004, /* R10 - DAC CTRL */
58 0x00C0, /* R11 - Left DAC Digital Volume */
59 0x00C0, /* R12 - Right DAC Digital Volume */
60 0x0000, /* R13 - Digital Side Tone */
61 0x0100, /* R14 - ADC CTRL */
62 0x00C0, /* R15 - Left ADC Digital Volume */
63 0x00C0, /* R16 - Right ADC Digital Volume */
64 0x0000, /* R17 */
65 0x0000, /* R18 - GPIO CTRL 1 */
66 0x1000, /* R19 - GPIO1 & GPIO2 */
67 0x1010, /* R20 - GPIO3 & GPIO4 */
68 0x1010, /* R21 - GPIO5 & GPIO6 */
69 0x8000, /* R22 - GPIOCTRL 2 */
70 0x0800, /* R23 - GPIO_POL */
71 0x008B, /* R24 - Left Line Input 1&2 Volume */
72 0x008B, /* R25 - Left Line Input 3&4 Volume */
73 0x008B, /* R26 - Right Line Input 1&2 Volume */
74 0x008B, /* R27 - Right Line Input 3&4 Volume */
75 0x0000, /* R28 - Left Output Volume */
76 0x0000, /* R29 - Right Output Volume */
77 0x0066, /* R30 - Line Outputs Volume */
78 0x0022, /* R31 - Out3/4 Volume */
79 0x0079, /* R32 - Left OPGA Volume */
80 0x0079, /* R33 - Right OPGA Volume */
81 0x0003, /* R34 - Speaker Volume */
82 0x0003, /* R35 - ClassD1 */
83 0x0000, /* R36 */
84 0x0100, /* R37 - ClassD3 */
85 0x0000, /* R38 */
86 0x0000, /* R39 - Input Mixer1 */
87 0x0000, /* R40 - Input Mixer2 */
88 0x0000, /* R41 - Input Mixer3 */
89 0x0000, /* R42 - Input Mixer4 */
90 0x0000, /* R43 - Input Mixer5 */
91 0x0000, /* R44 - Input Mixer6 */
92 0x0000, /* R45 - Output Mixer1 */
93 0x0000, /* R46 - Output Mixer2 */
94 0x0000, /* R47 - Output Mixer3 */
95 0x0000, /* R48 - Output Mixer4 */
96 0x0000, /* R49 - Output Mixer5 */
97 0x0000, /* R50 - Output Mixer6 */
98 0x0180, /* R51 - Out3/4 Mixer */
99 0x0000, /* R52 - Line Mixer1 */
100 0x0000, /* R53 - Line Mixer2 */
101 0x0000, /* R54 - Speaker Mixer */
102 0x0000, /* R55 - Additional Control */
103 0x0000, /* R56 - AntiPOP1 */
104 0x0000, /* R57 - AntiPOP2 */
105 0x0000, /* R58 - MICBIAS */
106 0x0000, /* R59 */
107 0x0008, /* R60 - PLL1 */
108 0x0031, /* R61 - PLL2 */
109 0x0026, /* R62 - PLL3 */
110};
111
112/*
113 * read wm8990 register cache
114 */
115static inline unsigned int wm8990_read_reg_cache(struct snd_soc_codec *codec,
116 unsigned int reg)
117{
118 u16 *cache = codec->reg_cache;
119 BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1);
120 return cache[reg];
121}
122
123/*
124 * write wm8990 register cache
125 */
126static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec,
127 unsigned int reg, unsigned int value)
128{
129 u16 *cache = codec->reg_cache;
130 BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1);
131
132 /* Reset register is uncached */
133 if (reg == 0)
134 return;
135
136 cache[reg] = value;
137}
138
139/*
140 * write to the wm8990 register space
141 */
142static int wm8990_write(struct snd_soc_codec *codec, unsigned int reg,
143 unsigned int value)
144{
145 u8 data[3];
146
147 data[0] = reg & 0xFF;
148 data[1] = (value >> 8) & 0xFF;
149 data[2] = value & 0xFF;
150
151 wm8990_write_reg_cache(codec, reg, value);
152
153 if (codec->hw_write(codec->control_data, data, 3) == 2)
154 return 0;
155 else
156 return -EIO;
157}
158
159#define wm8990_reset(c) wm8990_write(c, WM8990_RESET, 0)
160
161static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600);
162
163static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000);
164
165static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, 0, -2100);
166
167static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600);
168
169static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0);
170
171static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0);
172
173static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763);
174
175static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0);
176
177static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
178 struct snd_ctl_elem_value *ucontrol)
179{
180 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
181 int reg = kcontrol->private_value & 0xff;
182 int ret;
183 u16 val;
184
185 ret = snd_soc_put_volsw(kcontrol, ucontrol);
186 if (ret < 0)
187 return ret;
188
189 /* now hit the volume update bits (always bit 8) */
190 val = wm8990_read_reg_cache(codec, reg);
191 return wm8990_write(codec, reg, val | 0x0100);
192}
193
194#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
195 tlv_array) {\
196 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
197 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
198 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
199 .tlv.p = (tlv_array), \
200 .info = snd_soc_info_volsw, \
201 .get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \
202 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
203
204
205static const char *wm8990_digital_sidetone[] =
206 {"None", "Left ADC", "Right ADC", "Reserved"};
207
208static const struct soc_enum wm8990_left_digital_sidetone_enum =
209SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE,
210 WM8990_ADC_TO_DACL_SHIFT,
211 WM8990_ADC_TO_DACL_MASK,
212 wm8990_digital_sidetone);
213
214static const struct soc_enum wm8990_right_digital_sidetone_enum =
215SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE,
216 WM8990_ADC_TO_DACR_SHIFT,
217 WM8990_ADC_TO_DACR_MASK,
218 wm8990_digital_sidetone);
219
220static const char *wm8990_adcmode[] =
221 {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
222
223static const struct soc_enum wm8990_right_adcmode_enum =
224SOC_ENUM_SINGLE(WM8990_ADC_CTRL,
225 WM8990_ADC_HPF_CUT_SHIFT,
226 WM8990_ADC_HPF_CUT_MASK,
227 wm8990_adcmode);
228
229static const struct snd_kcontrol_new wm8990_snd_controls[] = {
230/* INMIXL */
231SOC_SINGLE("LIN12 PGA Boost", WM8990_INPUT_MIXER3, WM8990_L12MNBST_BIT, 1, 0),
232SOC_SINGLE("LIN34 PGA Boost", WM8990_INPUT_MIXER3, WM8990_L34MNBST_BIT, 1, 0),
233/* INMIXR */
234SOC_SINGLE("RIN12 PGA Boost", WM8990_INPUT_MIXER3, WM8990_R12MNBST_BIT, 1, 0),
235SOC_SINGLE("RIN34 PGA Boost", WM8990_INPUT_MIXER3, WM8990_R34MNBST_BIT, 1, 0),
236
237/* LOMIX */
238SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8990_OUTPUT_MIXER3,
239 WM8990_LLI3LOVOL_SHIFT, WM8990_LLI3LOVOL_MASK, 1, out_mix_tlv),
240SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER3,
241 WM8990_LR12LOVOL_SHIFT, WM8990_LR12LOVOL_MASK, 1, out_mix_tlv),
242SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER3,
243 WM8990_LL12LOVOL_SHIFT, WM8990_LL12LOVOL_MASK, 1, out_mix_tlv),
244SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8990_OUTPUT_MIXER5,
245 WM8990_LRI3LOVOL_SHIFT, WM8990_LRI3LOVOL_MASK, 1, out_mix_tlv),
246SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8990_OUTPUT_MIXER5,
247 WM8990_LRBLOVOL_SHIFT, WM8990_LRBLOVOL_MASK, 1, out_mix_tlv),
248SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8990_OUTPUT_MIXER5,
249 WM8990_LRBLOVOL_SHIFT, WM8990_LRBLOVOL_MASK, 1, out_mix_tlv),
250
251/* ROMIX */
252SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8990_OUTPUT_MIXER4,
253 WM8990_RRI3ROVOL_SHIFT, WM8990_RRI3ROVOL_MASK, 1, out_mix_tlv),
254SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER4,
255 WM8990_RL12ROVOL_SHIFT, WM8990_RL12ROVOL_MASK, 1, out_mix_tlv),
256SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER4,
257 WM8990_RR12ROVOL_SHIFT, WM8990_RR12ROVOL_MASK, 1, out_mix_tlv),
258SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8990_OUTPUT_MIXER6,
259 WM8990_RLI3ROVOL_SHIFT, WM8990_RLI3ROVOL_MASK, 1, out_mix_tlv),
260SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8990_OUTPUT_MIXER6,
261 WM8990_RLBROVOL_SHIFT, WM8990_RLBROVOL_MASK, 1, out_mix_tlv),
262SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8990_OUTPUT_MIXER6,
263 WM8990_RRBROVOL_SHIFT, WM8990_RRBROVOL_MASK, 1, out_mix_tlv),
264
265/* LOUT */
266SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8990_LEFT_OUTPUT_VOLUME,
267 WM8990_LOUTVOL_SHIFT, WM8990_LOUTVOL_MASK, 0, out_pga_tlv),
268SOC_SINGLE("LOUT ZC", WM8990_LEFT_OUTPUT_VOLUME, WM8990_LOZC_BIT, 1, 0),
269
270/* ROUT */
271SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8990_RIGHT_OUTPUT_VOLUME,
272 WM8990_ROUTVOL_SHIFT, WM8990_ROUTVOL_MASK, 0, out_pga_tlv),
273SOC_SINGLE("ROUT ZC", WM8990_RIGHT_OUTPUT_VOLUME, WM8990_ROZC_BIT, 1, 0),
274
275/* LOPGA */
276SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8990_LEFT_OPGA_VOLUME,
277 WM8990_LOPGAVOL_SHIFT, WM8990_LOPGAVOL_MASK, 0, out_pga_tlv),
278SOC_SINGLE("LOPGA ZC Switch", WM8990_LEFT_OPGA_VOLUME,
279 WM8990_LOPGAZC_BIT, 1, 0),
280
281/* ROPGA */
282SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8990_RIGHT_OPGA_VOLUME,
283 WM8990_ROPGAVOL_SHIFT, WM8990_ROPGAVOL_MASK, 0, out_pga_tlv),
284SOC_SINGLE("ROPGA ZC Switch", WM8990_RIGHT_OPGA_VOLUME,
285 WM8990_ROPGAZC_BIT, 1, 0),
286
287SOC_SINGLE("LON Mute Switch", WM8990_LINE_OUTPUTS_VOLUME,
288 WM8990_LONMUTE_BIT, 1, 0),
289SOC_SINGLE("LOP Mute Switch", WM8990_LINE_OUTPUTS_VOLUME,
290 WM8990_LOPMUTE_BIT, 1, 0),
291SOC_SINGLE("LOP Attenuation Switch", WM8990_LINE_OUTPUTS_VOLUME,
292 WM8990_LOATTN_BIT, 1, 0),
293SOC_SINGLE("RON Mute Switch", WM8990_LINE_OUTPUTS_VOLUME,
294 WM8990_RONMUTE_BIT, 1, 0),
295SOC_SINGLE("ROP Mute Switch", WM8990_LINE_OUTPUTS_VOLUME,
296 WM8990_ROPMUTE_BIT, 1, 0),
297SOC_SINGLE("ROP Attenuation Switch", WM8990_LINE_OUTPUTS_VOLUME,
298 WM8990_ROATTN_BIT, 1, 0),
299
300SOC_SINGLE("OUT3 Mute Switch", WM8990_OUT3_4_VOLUME,
301 WM8990_OUT3MUTE_BIT, 1, 0),
302SOC_SINGLE("OUT3 Attenuation Switch", WM8990_OUT3_4_VOLUME,
303 WM8990_OUT3ATTN_BIT, 1, 0),
304
305SOC_SINGLE("OUT4 Mute Switch", WM8990_OUT3_4_VOLUME,
306 WM8990_OUT4MUTE_BIT, 1, 0),
307SOC_SINGLE("OUT4 Attenuation Switch", WM8990_OUT3_4_VOLUME,
308 WM8990_OUT4ATTN_BIT, 1, 0),
309
310SOC_SINGLE("Speaker Mode Switch", WM8990_CLASSD1,
311 WM8990_CDMODE_BIT, 1, 0),
312
313SOC_SINGLE("Speaker Output Attenuation Volume", WM8990_SPEAKER_VOLUME,
314 WM8990_SPKVOL_SHIFT, WM8990_SPKVOL_MASK, 0),
315SOC_SINGLE("Speaker DC Boost Volume", WM8990_CLASSD3,
316 WM8990_DCGAIN_SHIFT, WM8990_DCGAIN_MASK, 0),
317SOC_SINGLE("Speaker AC Boost Volume", WM8990_CLASSD3,
318 WM8990_ACGAIN_SHIFT, WM8990_ACGAIN_MASK, 0),
319
320SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume",
321 WM8990_LEFT_DAC_DIGITAL_VOLUME,
322 WM8990_DACL_VOL_SHIFT,
323 WM8990_DACL_VOL_MASK,
324 0,
325 out_dac_tlv),
326
327SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume",
328 WM8990_RIGHT_DAC_DIGITAL_VOLUME,
329 WM8990_DACR_VOL_SHIFT,
330 WM8990_DACR_VOL_MASK,
331 0,
332 out_dac_tlv),
333
334SOC_ENUM("Left Digital Sidetone", wm8990_left_digital_sidetone_enum),
335SOC_ENUM("Right Digital Sidetone", wm8990_right_digital_sidetone_enum),
336
337SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8990_DIGITAL_SIDE_TONE,
338 WM8990_ADCL_DAC_SVOL_SHIFT, WM8990_ADCL_DAC_SVOL_MASK, 0,
339 out_sidetone_tlv),
340SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8990_DIGITAL_SIDE_TONE,
341 WM8990_ADCR_DAC_SVOL_SHIFT, WM8990_ADCR_DAC_SVOL_MASK, 0,
342 out_sidetone_tlv),
343
344SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8990_ADC_CTRL,
345 WM8990_ADC_HPF_ENA_BIT, 1, 0),
346
347SOC_ENUM("ADC HPF Mode", wm8990_right_adcmode_enum),
348
349SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume",
350 WM8990_LEFT_ADC_DIGITAL_VOLUME,
351 WM8990_ADCL_VOL_SHIFT,
352 WM8990_ADCL_VOL_MASK,
353 0,
354 in_adc_tlv),
355
356SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume",
357 WM8990_RIGHT_ADC_DIGITAL_VOLUME,
358 WM8990_ADCR_VOL_SHIFT,
359 WM8990_ADCR_VOL_MASK,
360 0,
361 in_adc_tlv),
362
363SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN12 Volume",
364 WM8990_LEFT_LINE_INPUT_1_2_VOLUME,
365 WM8990_LIN12VOL_SHIFT,
366 WM8990_LIN12VOL_MASK,
367 0,
368 in_pga_tlv),
369
370SOC_SINGLE("LIN12 ZC Switch", WM8990_LEFT_LINE_INPUT_1_2_VOLUME,
371 WM8990_LI12ZC_BIT, 1, 0),
372
373SOC_SINGLE("LIN12 Mute Switch", WM8990_LEFT_LINE_INPUT_1_2_VOLUME,
374 WM8990_LI12MUTE_BIT, 1, 0),
375
376SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN34 Volume",
377 WM8990_LEFT_LINE_INPUT_3_4_VOLUME,
378 WM8990_LIN34VOL_SHIFT,
379 WM8990_LIN34VOL_MASK,
380 0,
381 in_pga_tlv),
382
383SOC_SINGLE("LIN34 ZC Switch", WM8990_LEFT_LINE_INPUT_3_4_VOLUME,
384 WM8990_LI34ZC_BIT, 1, 0),
385
386SOC_SINGLE("LIN34 Mute Switch", WM8990_LEFT_LINE_INPUT_3_4_VOLUME,
387 WM8990_LI34MUTE_BIT, 1, 0),
388
389SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN12 Volume",
390 WM8990_RIGHT_LINE_INPUT_1_2_VOLUME,
391 WM8990_RIN12VOL_SHIFT,
392 WM8990_RIN12VOL_MASK,
393 0,
394 in_pga_tlv),
395
396SOC_SINGLE("RIN12 ZC Switch", WM8990_RIGHT_LINE_INPUT_1_2_VOLUME,
397 WM8990_RI12ZC_BIT, 1, 0),
398
399SOC_SINGLE("RIN12 Mute Switch", WM8990_RIGHT_LINE_INPUT_1_2_VOLUME,
400 WM8990_RI12MUTE_BIT, 1, 0),
401
402SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN34 Volume",
403 WM8990_RIGHT_LINE_INPUT_3_4_VOLUME,
404 WM8990_RIN34VOL_SHIFT,
405 WM8990_RIN34VOL_MASK,
406 0,
407 in_pga_tlv),
408
409SOC_SINGLE("RIN34 ZC Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME,
410 WM8990_RI34ZC_BIT, 1, 0),
411
412SOC_SINGLE("RIN34 Mute Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME,
413 WM8990_RI34MUTE_BIT, 1, 0),
414
415};
416
417/* add non dapm controls */
418static int wm8990_add_controls(struct snd_soc_codec *codec)
419{
420 int err, i;
421
422 for (i = 0; i < ARRAY_SIZE(wm8990_snd_controls); i++) {
423 err = snd_ctl_add(codec->card,
424 snd_soc_cnew(&wm8990_snd_controls[i], codec,
425 NULL));
426 if (err < 0)
427 return err;
428 }
429 return 0;
430}
431
432/*
433 * _DAPM_ Controls
434 */
435
436static int inmixer_event(struct snd_soc_dapm_widget *w,
437 struct snd_kcontrol *kcontrol, int event)
438{
439 u16 reg, fakepower;
440
441 reg = wm8990_read_reg_cache(w->codec, WM8990_POWER_MANAGEMENT_2);
442 fakepower = wm8990_read_reg_cache(w->codec, WM8990_INTDRIVBITS);
443
444 if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) |
445 (1 << WM8990_AINLMUX_PWR_BIT))) {
446 reg |= WM8990_AINL_ENA;
447 } else {
448 reg &= ~WM8990_AINL_ENA;
449 }
450
451 if (fakepower & ((1 << WM8990_INMIXR_PWR_BIT) |
452 (1 << WM8990_AINRMUX_PWR_BIT))) {
453 reg |= WM8990_AINR_ENA;
454 } else {
455 reg &= ~WM8990_AINL_ENA;
456 }
457 wm8990_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
458
459 return 0;
460}
461
462static int outmixer_event(struct snd_soc_dapm_widget *w,
463 struct snd_kcontrol *kcontrol, int event)
464{
465 u32 reg_shift = kcontrol->private_value & 0xfff;
466 int ret = 0;
467 u16 reg;
468
469 switch (reg_shift) {
470 case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) :
471 reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER1);
472 if (reg & WM8990_LDLO) {
473 printk(KERN_WARNING
474 "Cannot set as Output Mixer 1 LDLO Set\n");
475 ret = -1;
476 }
477 break;
478 case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8):
479 reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER2);
480 if (reg & WM8990_RDRO) {
481 printk(KERN_WARNING
482 "Cannot set as Output Mixer 2 RDRO Set\n");
483 ret = -1;
484 }
485 break;
486 case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8):
487 reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER);
488 if (reg & WM8990_LDSPK) {
489 printk(KERN_WARNING
490 "Cannot set as Speaker Mixer LDSPK Set\n");
491 ret = -1;
492 }
493 break;
494 case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8):
495 reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER);
496 if (reg & WM8990_RDSPK) {
497 printk(KERN_WARNING
498 "Cannot set as Speaker Mixer RDSPK Set\n");
499 ret = -1;
500 }
501 break;
502 }
503
504 return ret;
505}
506
507/* INMIX dB values */
508static const unsigned int in_mix_tlv[] = {
509 TLV_DB_RANGE_HEAD(1),
510 0, 7, TLV_DB_LINEAR_ITEM(-1200, 600),
511};
512
513/* Left In PGA Connections */
514static const struct snd_kcontrol_new wm8990_dapm_lin12_pga_controls[] = {
515SOC_DAPM_SINGLE("LIN1 Switch", WM8990_INPUT_MIXER2, WM8990_LMN1_BIT, 1, 0),
516SOC_DAPM_SINGLE("LIN2 Switch", WM8990_INPUT_MIXER2, WM8990_LMP2_BIT, 1, 0),
517};
518
519static const struct snd_kcontrol_new wm8990_dapm_lin34_pga_controls[] = {
520SOC_DAPM_SINGLE("LIN3 Switch", WM8990_INPUT_MIXER2, WM8990_LMN3_BIT, 1, 0),
521SOC_DAPM_SINGLE("LIN4 Switch", WM8990_INPUT_MIXER2, WM8990_LMP4_BIT, 1, 0),
522};
523
524/* Right In PGA Connections */
525static const struct snd_kcontrol_new wm8990_dapm_rin12_pga_controls[] = {
526SOC_DAPM_SINGLE("RIN1 Switch", WM8990_INPUT_MIXER2, WM8990_RMN1_BIT, 1, 0),
527SOC_DAPM_SINGLE("RIN2 Switch", WM8990_INPUT_MIXER2, WM8990_RMP2_BIT, 1, 0),
528};
529
530static const struct snd_kcontrol_new wm8990_dapm_rin34_pga_controls[] = {
531SOC_DAPM_SINGLE("RIN3 Switch", WM8990_INPUT_MIXER2, WM8990_RMN3_BIT, 1, 0),
532SOC_DAPM_SINGLE("RIN4 Switch", WM8990_INPUT_MIXER2, WM8990_RMP4_BIT, 1, 0),
533};
534
535/* INMIXL */
536static const struct snd_kcontrol_new wm8990_dapm_inmixl_controls[] = {
537SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8990_INPUT_MIXER3,
538 WM8990_LDBVOL_SHIFT, WM8990_LDBVOL_MASK, 0, in_mix_tlv),
539SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8990_INPUT_MIXER5, WM8990_LI2BVOL_SHIFT,
540 7, 0, in_mix_tlv),
541SOC_DAPM_SINGLE("LINPGA12 Switch", WM8990_INPUT_MIXER3, WM8990_L12MNB_BIT,
542 1, 0),
543SOC_DAPM_SINGLE("LINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT,
544 1, 0),
545};
546
547/* INMIXR */
548static const struct snd_kcontrol_new wm8990_dapm_inmixr_controls[] = {
549SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8990_INPUT_MIXER4,
550 WM8990_RDBVOL_SHIFT, WM8990_RDBVOL_MASK, 0, in_mix_tlv),
551SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8990_INPUT_MIXER6, WM8990_RI2BVOL_SHIFT,
552 7, 0, in_mix_tlv),
553SOC_DAPM_SINGLE("RINPGA12 Switch", WM8990_INPUT_MIXER3, WM8990_L12MNB_BIT,
554 1, 0),
555SOC_DAPM_SINGLE("RINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT,
556 1, 0),
557};
558
559/* AINLMUX */
560static const char *wm8990_ainlmux[] =
561 {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
562
563static const struct soc_enum wm8990_ainlmux_enum =
564SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT,
565 ARRAY_SIZE(wm8990_ainlmux), wm8990_ainlmux);
566
567static const struct snd_kcontrol_new wm8990_dapm_ainlmux_controls =
568SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum);
569
570/* DIFFINL */
571
572/* AINRMUX */
573static const char *wm8990_ainrmux[] =
574 {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
575
576static const struct soc_enum wm8990_ainrmux_enum =
577SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT,
578 ARRAY_SIZE(wm8990_ainrmux), wm8990_ainrmux);
579
580static const struct snd_kcontrol_new wm8990_dapm_ainrmux_controls =
581SOC_DAPM_ENUM("Route", wm8990_ainrmux_enum);
582
583/* RXVOICE */
584static const struct snd_kcontrol_new wm8990_dapm_rxvoice_controls[] = {
585SOC_DAPM_SINGLE_TLV("LIN4/RXN", WM8990_INPUT_MIXER5, WM8990_LR4BVOL_SHIFT,
586 WM8990_LR4BVOL_MASK, 0, in_mix_tlv),
587SOC_DAPM_SINGLE_TLV("RIN4/RXP", WM8990_INPUT_MIXER6, WM8990_RL4BVOL_SHIFT,
588 WM8990_RL4BVOL_MASK, 0, in_mix_tlv),
589};
590
591/* LOMIX */
592static const struct snd_kcontrol_new wm8990_dapm_lomix_controls[] = {
593SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8990_OUTPUT_MIXER1,
594 WM8990_LRBLO_BIT, 1, 0),
595SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8990_OUTPUT_MIXER1,
596 WM8990_LLBLO_BIT, 1, 0),
597SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8990_OUTPUT_MIXER1,
598 WM8990_LRI3LO_BIT, 1, 0),
599SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8990_OUTPUT_MIXER1,
600 WM8990_LLI3LO_BIT, 1, 0),
601SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER1,
602 WM8990_LR12LO_BIT, 1, 0),
603SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER1,
604 WM8990_LL12LO_BIT, 1, 0),
605SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8990_OUTPUT_MIXER1,
606 WM8990_LDLO_BIT, 1, 0),
607};
608
609/* ROMIX */
610static const struct snd_kcontrol_new wm8990_dapm_romix_controls[] = {
611SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8990_OUTPUT_MIXER2,
612 WM8990_RLBRO_BIT, 1, 0),
613SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8990_OUTPUT_MIXER2,
614 WM8990_RRBRO_BIT, 1, 0),
615SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8990_OUTPUT_MIXER2,
616 WM8990_RLI3RO_BIT, 1, 0),
617SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8990_OUTPUT_MIXER2,
618 WM8990_RRI3RO_BIT, 1, 0),
619SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER2,
620 WM8990_RL12RO_BIT, 1, 0),
621SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER2,
622 WM8990_RR12RO_BIT, 1, 0),
623SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8990_OUTPUT_MIXER2,
624 WM8990_RDRO_BIT, 1, 0),
625};
626
627/* LONMIX */
628static const struct snd_kcontrol_new wm8990_dapm_lonmix_controls[] = {
629SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8990_LINE_MIXER1,
630 WM8990_LLOPGALON_BIT, 1, 0),
631SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8990_LINE_MIXER1,
632 WM8990_LROPGALON_BIT, 1, 0),
633SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8990_LINE_MIXER1,
634 WM8990_LOPLON_BIT, 1, 0),
635};
636
637/* LOPMIX */
638static const struct snd_kcontrol_new wm8990_dapm_lopmix_controls[] = {
639SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8990_LINE_MIXER1,
640 WM8990_LR12LOP_BIT, 1, 0),
641SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8990_LINE_MIXER1,
642 WM8990_LL12LOP_BIT, 1, 0),
643SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8990_LINE_MIXER1,
644 WM8990_LLOPGALOP_BIT, 1, 0),
645};
646
647/* RONMIX */
648static const struct snd_kcontrol_new wm8990_dapm_ronmix_controls[] = {
649SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8990_LINE_MIXER2,
650 WM8990_RROPGARON_BIT, 1, 0),
651SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8990_LINE_MIXER2,
652 WM8990_RLOPGARON_BIT, 1, 0),
653SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8990_LINE_MIXER2,
654 WM8990_ROPRON_BIT, 1, 0),
655};
656
657/* ROPMIX */
658static const struct snd_kcontrol_new wm8990_dapm_ropmix_controls[] = {
659SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8990_LINE_MIXER2,
660 WM8990_RL12ROP_BIT, 1, 0),
661SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8990_LINE_MIXER2,
662 WM8990_RR12ROP_BIT, 1, 0),
663SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8990_LINE_MIXER2,
664 WM8990_RROPGAROP_BIT, 1, 0),
665};
666
667/* OUT3MIX */
668static const struct snd_kcontrol_new wm8990_dapm_out3mix_controls[] = {
669SOC_DAPM_SINGLE("OUT3MIX LIN4/RXP Bypass Switch", WM8990_OUT3_4_MIXER,
670 WM8990_LI4O3_BIT, 1, 0),
671SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8990_OUT3_4_MIXER,
672 WM8990_LPGAO3_BIT, 1, 0),
673};
674
675/* OUT4MIX */
676static const struct snd_kcontrol_new wm8990_dapm_out4mix_controls[] = {
677SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8990_OUT3_4_MIXER,
678 WM8990_RPGAO4_BIT, 1, 0),
679SOC_DAPM_SINGLE("OUT4MIX RIN4/RXP Bypass Switch", WM8990_OUT3_4_MIXER,
680 WM8990_RI4O4_BIT, 1, 0),
681};
682
683/* SPKMIX */
684static const struct snd_kcontrol_new wm8990_dapm_spkmix_controls[] = {
685SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8990_SPEAKER_MIXER,
686 WM8990_LI2SPK_BIT, 1, 0),
687SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8990_SPEAKER_MIXER,
688 WM8990_LB2SPK_BIT, 1, 0),
689SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8990_SPEAKER_MIXER,
690 WM8990_LOPGASPK_BIT, 1, 0),
691SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8990_SPEAKER_MIXER,
692 WM8990_LDSPK_BIT, 1, 0),
693SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8990_SPEAKER_MIXER,
694 WM8990_RDSPK_BIT, 1, 0),
695SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8990_SPEAKER_MIXER,
696 WM8990_ROPGASPK_BIT, 1, 0),
697SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8990_SPEAKER_MIXER,
698 WM8990_RL12ROP_BIT, 1, 0),
699SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8990_SPEAKER_MIXER,
700 WM8990_RI2SPK_BIT, 1, 0),
701};
702
703static const struct snd_soc_dapm_widget wm8990_dapm_widgets[] = {
704/* Input Side */
705/* Input Lines */
706SND_SOC_DAPM_INPUT("LIN1"),
707SND_SOC_DAPM_INPUT("LIN2"),
708SND_SOC_DAPM_INPUT("LIN3"),
709SND_SOC_DAPM_INPUT("LIN4/RXN"),
710SND_SOC_DAPM_INPUT("RIN3"),
711SND_SOC_DAPM_INPUT("RIN4/RXP"),
712SND_SOC_DAPM_INPUT("RIN1"),
713SND_SOC_DAPM_INPUT("RIN2"),
714SND_SOC_DAPM_INPUT("Internal ADC Source"),
715
716/* DACs */
717SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8990_POWER_MANAGEMENT_2,
718 WM8990_ADCL_ENA_BIT, 0),
719SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8990_POWER_MANAGEMENT_2,
720 WM8990_ADCR_ENA_BIT, 0),
721
722/* Input PGAs */
723SND_SOC_DAPM_MIXER("LIN12 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_LIN12_ENA_BIT,
724 0, &wm8990_dapm_lin12_pga_controls[0],
725 ARRAY_SIZE(wm8990_dapm_lin12_pga_controls)),
726SND_SOC_DAPM_MIXER("LIN34 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_LIN34_ENA_BIT,
727 0, &wm8990_dapm_lin34_pga_controls[0],
728 ARRAY_SIZE(wm8990_dapm_lin34_pga_controls)),
729SND_SOC_DAPM_MIXER("RIN12 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_RIN12_ENA_BIT,
730 0, &wm8990_dapm_rin12_pga_controls[0],
731 ARRAY_SIZE(wm8990_dapm_rin12_pga_controls)),
732SND_SOC_DAPM_MIXER("RIN34 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_RIN34_ENA_BIT,
733 0, &wm8990_dapm_rin34_pga_controls[0],
734 ARRAY_SIZE(wm8990_dapm_rin34_pga_controls)),
735
736/* INMIXL */
737SND_SOC_DAPM_MIXER_E("INMIXL", WM8990_INTDRIVBITS, WM8990_INMIXL_PWR_BIT, 0,
738 &wm8990_dapm_inmixl_controls[0],
739 ARRAY_SIZE(wm8990_dapm_inmixl_controls),
740 inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
741
742/* AINLMUX */
743SND_SOC_DAPM_MUX_E("AILNMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0,
744 &wm8990_dapm_ainlmux_controls, inmixer_event,
745 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
746
747/* INMIXR */
748SND_SOC_DAPM_MIXER_E("INMIXR", WM8990_INTDRIVBITS, WM8990_INMIXR_PWR_BIT, 0,
749 &wm8990_dapm_inmixr_controls[0],
750 ARRAY_SIZE(wm8990_dapm_inmixr_controls),
751 inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
752
753/* AINRMUX */
754SND_SOC_DAPM_MUX_E("AIRNMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0,
755 &wm8990_dapm_ainrmux_controls, inmixer_event,
756 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
757
758/* Output Side */
759/* DACs */
760SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8990_POWER_MANAGEMENT_3,
761 WM8990_DACL_ENA_BIT, 0),
762SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8990_POWER_MANAGEMENT_3,
763 WM8990_DACR_ENA_BIT, 0),
764
765/* LOMIX */
766SND_SOC_DAPM_MIXER_E("LOMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LOMIX_ENA_BIT,
767 0, &wm8990_dapm_lomix_controls[0],
768 ARRAY_SIZE(wm8990_dapm_lomix_controls),
769 outmixer_event, SND_SOC_DAPM_PRE_REG),
770
771/* LONMIX */
772SND_SOC_DAPM_MIXER("LONMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LON_ENA_BIT, 0,
773 &wm8990_dapm_lonmix_controls[0],
774 ARRAY_SIZE(wm8990_dapm_lonmix_controls)),
775
776/* LOPMIX */
777SND_SOC_DAPM_MIXER("LOPMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LOP_ENA_BIT, 0,
778 &wm8990_dapm_lopmix_controls[0],
779 ARRAY_SIZE(wm8990_dapm_lopmix_controls)),
780
781/* OUT3MIX */
782SND_SOC_DAPM_MIXER("OUT3MIX", WM8990_POWER_MANAGEMENT_1, WM8990_OUT3_ENA_BIT, 0,
783 &wm8990_dapm_out3mix_controls[0],
784 ARRAY_SIZE(wm8990_dapm_out3mix_controls)),
785
786/* SPKMIX */
787SND_SOC_DAPM_MIXER_E("SPKMIX", WM8990_POWER_MANAGEMENT_1, WM8990_SPK_ENA_BIT, 0,
788 &wm8990_dapm_spkmix_controls[0],
789 ARRAY_SIZE(wm8990_dapm_spkmix_controls), outmixer_event,
790 SND_SOC_DAPM_PRE_REG),
791
792/* OUT4MIX */
793SND_SOC_DAPM_MIXER("OUT4MIX", WM8990_POWER_MANAGEMENT_1, WM8990_OUT4_ENA_BIT, 0,
794 &wm8990_dapm_out4mix_controls[0],
795 ARRAY_SIZE(wm8990_dapm_out4mix_controls)),
796
797/* ROPMIX */
798SND_SOC_DAPM_MIXER("ROPMIX", WM8990_POWER_MANAGEMENT_3, WM8990_ROP_ENA_BIT, 0,
799 &wm8990_dapm_ropmix_controls[0],
800 ARRAY_SIZE(wm8990_dapm_ropmix_controls)),
801
802/* RONMIX */
803SND_SOC_DAPM_MIXER("RONMIX", WM8990_POWER_MANAGEMENT_3, WM8990_RON_ENA_BIT, 0,
804 &wm8990_dapm_ronmix_controls[0],
805 ARRAY_SIZE(wm8990_dapm_ronmix_controls)),
806
807/* ROMIX */
808SND_SOC_DAPM_MIXER_E("ROMIX", WM8990_POWER_MANAGEMENT_3, WM8990_ROMIX_ENA_BIT,
809 0, &wm8990_dapm_romix_controls[0],
810 ARRAY_SIZE(wm8990_dapm_romix_controls),
811 outmixer_event, SND_SOC_DAPM_PRE_REG),
812
813/* LOUT PGA */
814SND_SOC_DAPM_PGA("LOUT PGA", WM8990_POWER_MANAGEMENT_1, WM8990_LOUT_ENA_BIT, 0,
815 NULL, 0),
816
817/* ROUT PGA */
818SND_SOC_DAPM_PGA("ROUT PGA", WM8990_POWER_MANAGEMENT_1, WM8990_ROUT_ENA_BIT, 0,
819 NULL, 0),
820
821/* LOPGA */
822SND_SOC_DAPM_PGA("LOPGA", WM8990_POWER_MANAGEMENT_3, WM8990_LOPGA_ENA_BIT, 0,
823 NULL, 0),
824
825/* ROPGA */
826SND_SOC_DAPM_PGA("ROPGA", WM8990_POWER_MANAGEMENT_3, WM8990_ROPGA_ENA_BIT, 0,
827 NULL, 0),
828
829/* MICBIAS */
830SND_SOC_DAPM_MICBIAS("MICBIAS", WM8990_POWER_MANAGEMENT_1,
831 WM8990_MICBIAS_ENA_BIT, 0),
832
833SND_SOC_DAPM_OUTPUT("LON"),
834SND_SOC_DAPM_OUTPUT("LOP"),
835SND_SOC_DAPM_OUTPUT("OUT3"),
836SND_SOC_DAPM_OUTPUT("LOUT"),
837SND_SOC_DAPM_OUTPUT("SPKN"),
838SND_SOC_DAPM_OUTPUT("SPKP"),
839SND_SOC_DAPM_OUTPUT("ROUT"),
840SND_SOC_DAPM_OUTPUT("OUT4"),
841SND_SOC_DAPM_OUTPUT("ROP"),
842SND_SOC_DAPM_OUTPUT("RON"),
843
844SND_SOC_DAPM_OUTPUT("Internal DAC Sink"),
845};
846
847static const struct snd_soc_dapm_route audio_map[] = {
848 /* Make DACs turn on when playing even if not mixed into any outputs */
849 {"Internal DAC Sink", NULL, "Left DAC"},
850 {"Internal DAC Sink", NULL, "Right DAC"},
851
852 /* Make ADCs turn on when recording even if not mixed from any inputs */
853 {"Left ADC", NULL, "Internal ADC Source"},
854 {"Right ADC", NULL, "Internal ADC Source"},
855
856 /* Input Side */
857 /* LIN12 PGA */
858 {"LIN12 PGA", "LIN1 Switch", "LIN1"},
859 {"LIN12 PGA", "LIN2 Switch", "LIN2"},
860 /* LIN34 PGA */
861 {"LIN34 PGA", "LIN3 Switch", "LIN3"},
862 {"LIN34 PGA", "LIN4 Switch", "LIN4"},
863 /* INMIXL */
864 {"INMIXL", "Record Left Volume", "LOMIX"},
865 {"INMIXL", "LIN2 Volume", "LIN2"},
866 {"INMIXL", "LINPGA12 Switch", "LIN12 PGA"},
867 {"INMIXL", "LINPGA34 Switch", "LIN34 PGA"},
868 /* AILNMUX */
869 {"AILNMUX", "INMIXL Mix", "INMIXL"},
870 {"AILNMUX", "DIFFINL Mix", "LIN12PGA"},
871 {"AILNMUX", "DIFFINL Mix", "LIN34PGA"},
872 {"AILNMUX", "RXVOICE Mix", "LIN4/RXN"},
873 {"AILNMUX", "RXVOICE Mix", "RIN4/RXP"},
874 /* ADC */
875 {"Left ADC", NULL, "AILNMUX"},
876
877 /* RIN12 PGA */
878 {"RIN12 PGA", "RIN1 Switch", "RIN1"},
879 {"RIN12 PGA", "RIN2 Switch", "RIN2"},
880 /* RIN34 PGA */
881 {"RIN34 PGA", "RIN3 Switch", "RIN3"},
882 {"RIN34 PGA", "RIN4 Switch", "RIN4"},
883 /* INMIXL */
884 {"INMIXR", "Record Right Volume", "ROMIX"},
885 {"INMIXR", "RIN2 Volume", "RIN2"},
886 {"INMIXR", "RINPGA12 Switch", "RIN12 PGA"},
887 {"INMIXR", "RINPGA34 Switch", "RIN34 PGA"},
888 /* AIRNMUX */
889 {"AIRNMUX", "INMIXR Mix", "INMIXR"},
890 {"AIRNMUX", "DIFFINR Mix", "RIN12PGA"},
891 {"AIRNMUX", "DIFFINR Mix", "RIN34PGA"},
892 {"AIRNMUX", "RXVOICE Mix", "RIN4/RXN"},
893 {"AIRNMUX", "RXVOICE Mix", "RIN4/RXP"},
894 /* ADC */
895 {"Right ADC", NULL, "AIRNMUX"},
896
897 /* LOMIX */
898 {"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"},
899 {"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"},
900 {"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
901 {"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
902 {"LOMIX", "LOMIX Right ADC Bypass Switch", "AINRMUX"},
903 {"LOMIX", "LOMIX Left ADC Bypass Switch", "AINLMUX"},
904 {"LOMIX", "LOMIX Left DAC Switch", "Left DAC"},
905
906 /* ROMIX */
907 {"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"},
908 {"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"},
909 {"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
910 {"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
911 {"ROMIX", "ROMIX Right ADC Bypass Switch", "AINRMUX"},
912 {"ROMIX", "ROMIX Left ADC Bypass Switch", "AINLMUX"},
913 {"ROMIX", "ROMIX Right DAC Switch", "Right DAC"},
914
915 /* SPKMIX */
916 {"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"},
917 {"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"},
918 {"SPKMIX", "SPKMIX LADC Bypass Switch", "AINLMUX"},
919 {"SPKMIX", "SPKMIX RADC Bypass Switch", "AINRMUX"},
920 {"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"},
921 {"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"},
922 {"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"},
923 {"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"},
924
925 /* LONMIX */
926 {"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"},
927 {"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"},
928 {"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"},
929
930 /* LOPMIX */
931 {"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"},
932 {"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"},
933 {"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"},
934
935 /* OUT3MIX */
936 {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXP"},
937 {"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"},
938
939 /* OUT4MIX */
940 {"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"},
941 {"OUT4MIX", "OUT4MIX RIN4/RXP Bypass Switch", "RIN4/RXP"},
942
943 /* RONMIX */
944 {"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"},
945 {"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"},
946 {"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"},
947
948 /* ROPMIX */
949 {"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"},
950 {"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"},
951 {"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"},
952
953 /* Out Mixer PGAs */
954 {"LOPGA", NULL, "LOMIX"},
955 {"ROPGA", NULL, "ROMIX"},
956
957 {"LOUT PGA", NULL, "LOMIX"},
958 {"ROUT PGA", NULL, "ROMIX"},
959
960 /* Output Pins */
961 {"LON", NULL, "LONMIX"},
962 {"LOP", NULL, "LOPMIX"},
963 {"OUT", NULL, "OUT3MIX"},
964 {"LOUT", NULL, "LOUT PGA"},
965 {"SPKN", NULL, "SPKMIX"},
966 {"ROUT", NULL, "ROUT PGA"},
967 {"OUT4", NULL, "OUT4MIX"},
968 {"ROP", NULL, "ROPMIX"},
969 {"RON", NULL, "RONMIX"},
970};
971
972static int wm8990_add_widgets(struct snd_soc_codec *codec)
973{
974 snd_soc_dapm_new_controls(codec, wm8990_dapm_widgets,
975 ARRAY_SIZE(wm8990_dapm_widgets));
976
977 /* set up the WM8990 audio map */
978 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
979
980 snd_soc_dapm_new_widgets(codec);
981 return 0;
982}
983
984/* PLL divisors */
985struct _pll_div {
986 u32 div2;
987 u32 n;
988 u32 k;
989};
990
991/* The size in bits of the pll divide multiplied by 10
992 * to allow rounding later */
993#define FIXED_PLL_SIZE ((1 << 16) * 10)
994
995static void pll_factors(struct _pll_div *pll_div, unsigned int target,
996 unsigned int source)
997{
998 u64 Kpart;
999 unsigned int K, Ndiv, Nmod;
1000
1001
1002 Ndiv = target / source;
1003 if (Ndiv < 6) {
1004 source >>= 1;
1005 pll_div->div2 = 1;
1006 Ndiv = target / source;
1007 } else
1008 pll_div->div2 = 0;
1009
1010 if ((Ndiv < 6) || (Ndiv > 12))
1011 printk(KERN_WARNING
1012 "WM8990 N value outwith recommended range! N = %d\n", Ndiv);
1013
1014 pll_div->n = Ndiv;
1015 Nmod = target % source;
1016 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
1017
1018 do_div(Kpart, source);
1019
1020 K = Kpart & 0xFFFFFFFF;
1021
1022 /* Check if we need to round */
1023 if ((K % 10) >= 5)
1024 K += 5;
1025
1026 /* Move down to proper range now rounding is done */
1027 K /= 10;
1028
1029 pll_div->k = K;
1030}
1031
1032static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai,
1033 int pll_id, unsigned int freq_in, unsigned int freq_out)
1034{
1035 u16 reg;
1036 struct snd_soc_codec *codec = codec_dai->codec;
1037 struct _pll_div pll_div;
1038
1039 if (freq_in && freq_out) {
1040 pll_factors(&pll_div, freq_out * 4, freq_in);
1041
1042 /* Turn on PLL */
1043 reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
1044 reg |= WM8990_PLL_ENA;
1045 wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
1046
1047 /* sysclk comes from PLL */
1048 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2);
1049 wm8990_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
1050
1051 /* set up N , fractional mode and pre-divisor if neccessary */
1052 wm8990_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
1053 (pll_div.div2?WM8990_PRESCALE:0));
1054 wm8990_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
1055 wm8990_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF));
1056 } else {
1057 /* Turn on PLL */
1058 reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
1059 reg &= ~WM8990_PLL_ENA;
1060 wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
1061 }
1062 return 0;
1063}
1064
1065/*
1066 * Clock after PLL and dividers
1067 */
1068static int wm8990_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1069 int clk_id, unsigned int freq, int dir)
1070{
1071 struct snd_soc_codec *codec = codec_dai->codec;
1072 struct wm8990_priv *wm8990 = codec->private_data;
1073
1074 wm8990->sysclk = freq;
1075 return 0;
1076}
1077
1078/*
1079 * Set's ADC and Voice DAC format.
1080 */
1081static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai,
1082 unsigned int fmt)
1083{
1084 struct snd_soc_codec *codec = codec_dai->codec;
1085 u16 audio1, audio3;
1086
1087 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1);
1088 audio3 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_3);
1089
1090 /* set master/slave audio interface */
1091 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1092 case SND_SOC_DAIFMT_CBS_CFS:
1093 audio3 &= ~WM8990_AIF_MSTR1;
1094 break;
1095 case SND_SOC_DAIFMT_CBM_CFM:
1096 audio3 |= WM8990_AIF_MSTR1;
1097 break;
1098 default:
1099 return -EINVAL;
1100 }
1101
1102 audio1 &= ~WM8990_AIF_FMT_MASK;
1103
1104 /* interface format */
1105 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1106 case SND_SOC_DAIFMT_I2S:
1107 audio1 |= WM8990_AIF_TMF_I2S;
1108 audio1 &= ~WM8990_AIF_LRCLK_INV;
1109 break;
1110 case SND_SOC_DAIFMT_RIGHT_J:
1111 audio1 |= WM8990_AIF_TMF_RIGHTJ;
1112 audio1 &= ~WM8990_AIF_LRCLK_INV;
1113 break;
1114 case SND_SOC_DAIFMT_LEFT_J:
1115 audio1 |= WM8990_AIF_TMF_LEFTJ;
1116 audio1 &= ~WM8990_AIF_LRCLK_INV;
1117 break;
1118 case SND_SOC_DAIFMT_DSP_A:
1119 audio1 |= WM8990_AIF_TMF_DSP;
1120 audio1 &= ~WM8990_AIF_LRCLK_INV;
1121 break;
1122 case SND_SOC_DAIFMT_DSP_B:
1123 audio1 |= WM8990_AIF_TMF_DSP | WM8990_AIF_LRCLK_INV;
1124 break;
1125 default:
1126 return -EINVAL;
1127 }
1128
1129 wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
1130 wm8990_write(codec, WM8990_AUDIO_INTERFACE_3, audio3);
1131 return 0;
1132}
1133
1134static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
1135 int div_id, int div)
1136{
1137 struct snd_soc_codec *codec = codec_dai->codec;
1138 u16 reg;
1139
1140 switch (div_id) {
1141 case WM8990_MCLK_DIV:
1142 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
1143 ~WM8990_MCLK_DIV_MASK;
1144 wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
1145 break;
1146 case WM8990_DACCLK_DIV:
1147 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
1148 ~WM8990_DAC_CLKDIV_MASK;
1149 wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
1150 break;
1151 case WM8990_ADCCLK_DIV:
1152 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
1153 ~WM8990_ADC_CLKDIV_MASK;
1154 wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
1155 break;
1156 case WM8990_BCLK_DIV:
1157 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_1) &
1158 ~WM8990_BCLK_DIV_MASK;
1159 wm8990_write(codec, WM8990_CLOCKING_1, reg | div);
1160 break;
1161 default:
1162 return -EINVAL;
1163 }
1164
1165 return 0;
1166}
1167
1168/*
1169 * Set PCM DAI bit size and sample rate.
1170 */
1171static int wm8990_hw_params(struct snd_pcm_substream *substream,
1172 struct snd_pcm_hw_params *params)
1173{
1174 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1175 struct snd_soc_device *socdev = rtd->socdev;
1176 struct snd_soc_codec *codec = socdev->codec;
1177 u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1);
1178
1179 audio1 &= ~WM8990_AIF_WL_MASK;
1180 /* bit size */
1181 switch (params_format(params)) {
1182 case SNDRV_PCM_FORMAT_S16_LE:
1183 break;
1184 case SNDRV_PCM_FORMAT_S20_3LE:
1185 audio1 |= WM8990_AIF_WL_20BITS;
1186 break;
1187 case SNDRV_PCM_FORMAT_S24_LE:
1188 audio1 |= WM8990_AIF_WL_24BITS;
1189 break;
1190 case SNDRV_PCM_FORMAT_S32_LE:
1191 audio1 |= WM8990_AIF_WL_32BITS;
1192 break;
1193 }
1194
1195 wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
1196 return 0;
1197}
1198
1199static int wm8990_mute(struct snd_soc_dai *dai, int mute)
1200{
1201 struct snd_soc_codec *codec = dai->codec;
1202 u16 val;
1203
1204 val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE;
1205
1206 if (mute)
1207 wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
1208 else
1209 wm8990_write(codec, WM8990_DAC_CTRL, val);
1210
1211 return 0;
1212}
1213
1214static int wm8990_set_bias_level(struct snd_soc_codec *codec,
1215 enum snd_soc_bias_level level)
1216{
1217 u16 val;
1218
1219 switch (level) {
1220 case SND_SOC_BIAS_ON:
1221 break;
1222 case SND_SOC_BIAS_PREPARE:
1223 break;
1224 case SND_SOC_BIAS_STANDBY:
1225 if (codec->bias_level == SND_SOC_BIAS_OFF) {
1226 /* Enable all output discharge bits */
1227 wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
1228 WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
1229 WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
1230 WM8990_DIS_ROUT);
1231
1232 /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */
1233 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1234 WM8990_BUFDCOPEN | WM8990_POBCTRL |
1235 WM8990_VMIDTOG);
1236
1237 /* Delay to allow output caps to discharge */
1238 msleep(msecs_to_jiffies(300));
1239
1240 /* Disable VMIDTOG */
1241 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1242 WM8990_BUFDCOPEN | WM8990_POBCTRL);
1243
1244 /* disable all output discharge bits */
1245 wm8990_write(codec, WM8990_ANTIPOP1, 0);
1246
1247 /* Enable outputs */
1248 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00);
1249
1250 msleep(msecs_to_jiffies(50));
1251
1252 /* Enable VMID at 2x50k */
1253 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02);
1254
1255 msleep(msecs_to_jiffies(100));
1256
1257 /* Enable VREF */
1258 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
1259
1260 msleep(msecs_to_jiffies(600));
1261
1262 /* Enable BUFIOEN */
1263 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1264 WM8990_BUFDCOPEN | WM8990_POBCTRL |
1265 WM8990_BUFIOEN);
1266
1267 /* Disable outputs */
1268 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3);
1269
1270 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
1271 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
1272 } else {
1273 /* ON -> standby */
1274
1275 }
1276 break;
1277
1278 case SND_SOC_BIAS_OFF:
1279 /* Enable POBCTRL and SOFT_ST */
1280 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1281 WM8990_POBCTRL | WM8990_BUFIOEN);
1282
1283 /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */
1284 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1285 WM8990_BUFDCOPEN | WM8990_POBCTRL |
1286 WM8990_BUFIOEN);
1287
1288 /* mute DAC */
1289 val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL);
1290 wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
1291
1292 /* Enable any disabled outputs */
1293 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
1294
1295 /* Disable VMID */
1296 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01);
1297
1298 msleep(msecs_to_jiffies(300));
1299
1300 /* Enable all output discharge bits */
1301 wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
1302 WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
1303 WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
1304 WM8990_DIS_ROUT);
1305
1306 /* Disable VREF */
1307 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0);
1308
1309 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
1310 wm8990_write(codec, WM8990_ANTIPOP2, 0x0);
1311 break;
1312 }
1313
1314 codec->bias_level = level;
1315 return 0;
1316}
1317
1318#define WM8990_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
1319 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
1320 SNDRV_PCM_RATE_48000)
1321
1322#define WM8990_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1323 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
1324
1325/*
1326 * The WM8990 supports 2 different and mutually exclusive DAI
1327 * configurations.
1328 *
1329 * 1. ADC/DAC on Primary Interface
1330 * 2. ADC on Primary Interface/DAC on secondary
1331 */
1332struct snd_soc_dai wm8990_dai = {
1333/* ADC/DAC on primary */
1334 .name = "WM8990 ADC/DAC Primary",
1335 .id = 1,
1336 .playback = {
1337 .stream_name = "Playback",
1338 .channels_min = 1,
1339 .channels_max = 2,
1340 .rates = WM8990_RATES,
1341 .formats = WM8990_FORMATS,},
1342 .capture = {
1343 .stream_name = "Capture",
1344 .channels_min = 1,
1345 .channels_max = 2,
1346 .rates = WM8990_RATES,
1347 .formats = WM8990_FORMATS,},
1348 .ops = {
1349 .hw_params = wm8990_hw_params,},
1350 .dai_ops = {
1351 .digital_mute = wm8990_mute,
1352 .set_fmt = wm8990_set_dai_fmt,
1353 .set_clkdiv = wm8990_set_dai_clkdiv,
1354 .set_pll = wm8990_set_dai_pll,
1355 .set_sysclk = wm8990_set_dai_sysclk,
1356 },
1357};
1358EXPORT_SYMBOL_GPL(wm8990_dai);
1359
1360static int wm8990_suspend(struct platform_device *pdev, pm_message_t state)
1361{
1362 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1363 struct snd_soc_codec *codec = socdev->codec;
1364
1365 /* we only need to suspend if we are a valid card */
1366 if (!codec->card)
1367 return 0;
1368
1369 wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
1370 return 0;
1371}
1372
1373static int wm8990_resume(struct platform_device *pdev)
1374{
1375 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1376 struct snd_soc_codec *codec = socdev->codec;
1377 int i;
1378 u8 data[2];
1379 u16 *cache = codec->reg_cache;
1380
1381 /* we only need to resume if we are a valid card */
1382 if (!codec->card)
1383 return 0;
1384
1385 /* Sync reg_cache with the hardware */
1386 for (i = 0; i < ARRAY_SIZE(wm8990_reg); i++) {
1387 if (i + 1 == WM8990_RESET)
1388 continue;
1389 data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
1390 data[1] = cache[i] & 0x00ff;
1391 codec->hw_write(codec->control_data, data, 2);
1392 }
1393
1394 wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1395 return 0;
1396}
1397
1398/*
1399 * initialise the WM8990 driver
1400 * register the mixer and dsp interfaces with the kernel
1401 */
1402static int wm8990_init(struct snd_soc_device *socdev)
1403{
1404 struct snd_soc_codec *codec = socdev->codec;
1405 u16 reg;
1406 int ret = 0;
1407
1408 codec->name = "WM8990";
1409 codec->owner = THIS_MODULE;
1410 codec->read = wm8990_read_reg_cache;
1411 codec->write = wm8990_write;
1412 codec->set_bias_level = wm8990_set_bias_level;
1413 codec->dai = &wm8990_dai;
1414 codec->num_dai = 2;
1415 codec->reg_cache_size = ARRAY_SIZE(wm8990_reg);
1416 codec->reg_cache = kmemdup(wm8990_reg, sizeof(wm8990_reg), GFP_KERNEL);
1417
1418 if (codec->reg_cache == NULL)
1419 return -ENOMEM;
1420
1421 wm8990_reset(codec);
1422
1423 /* register pcms */
1424 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1425 if (ret < 0) {
1426 printk(KERN_ERR "wm8990: failed to create pcms\n");
1427 goto pcm_err;
1428 }
1429
1430 /* charge output caps */
1431 codec->bias_level = SND_SOC_BIAS_OFF;
1432 wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1433
1434 reg = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_4);
1435 wm8990_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1);
1436
1437 reg = wm8990_read_reg_cache(codec, WM8990_GPIO1_GPIO2) &
1438 ~WM8990_GPIO1_SEL_MASK;
1439 wm8990_write(codec, WM8990_GPIO1_GPIO2, reg | 1);
1440
1441 reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
1442 wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA);
1443
1444 wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
1445 wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
1446
1447 wm8990_add_controls(codec);
1448 wm8990_add_widgets(codec);
1449 ret = snd_soc_register_card(socdev);
1450 if (ret < 0) {
1451 printk(KERN_ERR "wm8990: failed to register card\n");
1452 goto card_err;
1453 }
1454 return ret;
1455
1456card_err:
1457 snd_soc_free_pcms(socdev);
1458 snd_soc_dapm_free(socdev);
1459pcm_err:
1460 kfree(codec->reg_cache);
1461 return ret;
1462}
1463
1464/* If the i2c layer weren't so broken, we could pass this kind of data
1465 around */
1466static struct snd_soc_device *wm8990_socdev;
1467
1468#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1469
1470/*
1471 * WM891 2 wire address is determined by GPIO5
1472 * state during powerup.
1473 * low = 0x34
1474 * high = 0x36
1475 */
1476static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
1477
1478/* Magic definition of all other variables and things */
1479I2C_CLIENT_INSMOD;
1480
1481static struct i2c_driver wm8990_i2c_driver;
1482static struct i2c_client client_template;
1483
1484static int wm8990_codec_probe(struct i2c_adapter *adap, int addr, int kind)
1485{
1486 struct snd_soc_device *socdev = wm8990_socdev;
1487 struct wm8990_setup_data *setup = socdev->codec_data;
1488 struct snd_soc_codec *codec = socdev->codec;
1489 struct i2c_client *i2c;
1490 int ret;
1491
1492 if (addr != setup->i2c_address)
1493 return -ENODEV;
1494
1495 client_template.adapter = adap;
1496 client_template.addr = addr;
1497
1498 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
1499 if (i2c == NULL) {
1500 kfree(codec);
1501 return -ENOMEM;
1502 }
1503 i2c_set_clientdata(i2c, codec);
1504 codec->control_data = i2c;
1505
1506 ret = i2c_attach_client(i2c);
1507 if (ret < 0) {
1508 pr_err("failed to attach codec at addr %x\n", addr);
1509 goto err;
1510 }
1511
1512 ret = wm8990_init(socdev);
1513 if (ret < 0) {
1514 pr_err("failed to initialise WM8990\n");
1515 goto err;
1516 }
1517 return ret;
1518
1519err:
1520 kfree(codec);
1521 kfree(i2c);
1522 return ret;
1523}
1524
1525static int wm8990_i2c_detach(struct i2c_client *client)
1526{
1527 struct snd_soc_codec *codec = i2c_get_clientdata(client);
1528 i2c_detach_client(client);
1529 kfree(codec->reg_cache);
1530 kfree(client);
1531 return 0;
1532}
1533
1534static int wm8990_i2c_attach(struct i2c_adapter *adap)
1535{
1536 return i2c_probe(adap, &addr_data, wm8990_codec_probe);
1537}
1538
1539static struct i2c_driver wm8990_i2c_driver = {
1540 .driver = {
1541 .name = "WM8990 I2C Codec",
1542 .owner = THIS_MODULE,
1543 },
1544 .attach_adapter = wm8990_i2c_attach,
1545 .detach_client = wm8990_i2c_detach,
1546 .command = NULL,
1547};
1548
1549static struct i2c_client client_template = {
1550 .name = "WM8990",
1551 .driver = &wm8990_i2c_driver,
1552};
1553#endif
1554
1555static int wm8990_probe(struct platform_device *pdev)
1556{
1557 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1558 struct wm8990_setup_data *setup;
1559 struct snd_soc_codec *codec;
1560 struct wm8990_priv *wm8990;
1561 int ret = 0;
1562
1563 pr_info("WM8990 Audio Codec %s\n", WM8990_VERSION);
1564
1565 setup = socdev->codec_data;
1566 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
1567 if (codec == NULL)
1568 return -ENOMEM;
1569
1570 wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL);
1571 if (wm8990 == NULL) {
1572 kfree(codec);
1573 return -ENOMEM;
1574 }
1575
1576 codec->private_data = wm8990;
1577 socdev->codec = codec;
1578 mutex_init(&codec->mutex);
1579 INIT_LIST_HEAD(&codec->dapm_widgets);
1580 INIT_LIST_HEAD(&codec->dapm_paths);
1581 wm8990_socdev = socdev;
1582
1583#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1584 if (setup->i2c_address) {
1585 normal_i2c[0] = setup->i2c_address;
1586 codec->hw_write = (hw_write_t)i2c_master_send;
1587 ret = i2c_add_driver(&wm8990_i2c_driver);
1588 if (ret != 0)
1589 printk(KERN_ERR "can't add i2c driver");
1590 }
1591#else
1592 /* Add other interfaces here */
1593#endif
1594 return ret;
1595}
1596
1597/* power down chip */
1598static int wm8990_remove(struct platform_device *pdev)
1599{
1600 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1601 struct snd_soc_codec *codec = socdev->codec;
1602
1603 if (codec->control_data)
1604 wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
1605 snd_soc_free_pcms(socdev);
1606 snd_soc_dapm_free(socdev);
1607#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1608 i2c_del_driver(&wm8990_i2c_driver);
1609#endif
1610 kfree(codec->private_data);
1611 kfree(codec);
1612
1613 return 0;
1614}
1615
1616struct snd_soc_codec_device soc_codec_dev_wm8990 = {
1617 .probe = wm8990_probe,
1618 .remove = wm8990_remove,
1619 .suspend = wm8990_suspend,
1620 .resume = wm8990_resume,
1621};
1622EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990);
1623
1624MODULE_DESCRIPTION("ASoC WM8990 driver");
1625MODULE_AUTHOR("Liam Girdwood");
1626MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h
new file mode 100644
index 000000000000..6bea57485283
--- /dev/null
+++ b/sound/soc/codecs/wm8990.h
@@ -0,0 +1,832 @@
1/*
2 * wm8990.h -- audio driver for WM8990
3 *
4 * Copyright 2007 Wolfson Microelectronics PLC.
5 * Author: Graeme Gregory
6 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
7 *
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
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#ifndef __WM8990REGISTERDEFS_H__
16#define __WM8990REGISTERDEFS_H__
17
18/*
19 * Register values.
20 */
21#define WM8990_RESET 0x00
22#define WM8990_POWER_MANAGEMENT_1 0x01
23#define WM8990_POWER_MANAGEMENT_2 0x02
24#define WM8990_POWER_MANAGEMENT_3 0x03
25#define WM8990_AUDIO_INTERFACE_1 0x04
26#define WM8990_AUDIO_INTERFACE_2 0x05
27#define WM8990_CLOCKING_1 0x06
28#define WM8990_CLOCKING_2 0x07
29#define WM8990_AUDIO_INTERFACE_3 0x08
30#define WM8990_AUDIO_INTERFACE_4 0x09
31#define WM8990_DAC_CTRL 0x0A
32#define WM8990_LEFT_DAC_DIGITAL_VOLUME 0x0B
33#define WM8990_RIGHT_DAC_DIGITAL_VOLUME 0x0C
34#define WM8990_DIGITAL_SIDE_TONE 0x0D
35#define WM8990_ADC_CTRL 0x0E
36#define WM8990_LEFT_ADC_DIGITAL_VOLUME 0x0F
37#define WM8990_RIGHT_ADC_DIGITAL_VOLUME 0x10
38#define WM8990_GPIO_CTRL_1 0x12
39#define WM8990_GPIO1_GPIO2 0x13
40#define WM8990_GPIO3_GPIO4 0x14
41#define WM8990_GPIO5_GPIO6 0x15
42#define WM8990_GPIOCTRL_2 0x16
43#define WM8990_GPIO_POL 0x17
44#define WM8990_LEFT_LINE_INPUT_1_2_VOLUME 0x18
45#define WM8990_LEFT_LINE_INPUT_3_4_VOLUME 0x19
46#define WM8990_RIGHT_LINE_INPUT_1_2_VOLUME 0x1A
47#define WM8990_RIGHT_LINE_INPUT_3_4_VOLUME 0x1B
48#define WM8990_LEFT_OUTPUT_VOLUME 0x1C
49#define WM8990_RIGHT_OUTPUT_VOLUME 0x1D
50#define WM8990_LINE_OUTPUTS_VOLUME 0x1E
51#define WM8990_OUT3_4_VOLUME 0x1F
52#define WM8990_LEFT_OPGA_VOLUME 0x20
53#define WM8990_RIGHT_OPGA_VOLUME 0x21
54#define WM8990_SPEAKER_VOLUME 0x22
55#define WM8990_CLASSD1 0x23
56#define WM8990_CLASSD3 0x25
57#define WM8990_INPUT_MIXER1 0x27
58#define WM8990_INPUT_MIXER2 0x28
59#define WM8990_INPUT_MIXER3 0x29
60#define WM8990_INPUT_MIXER4 0x2A
61#define WM8990_INPUT_MIXER5 0x2B
62#define WM8990_INPUT_MIXER6 0x2C
63#define WM8990_OUTPUT_MIXER1 0x2D
64#define WM8990_OUTPUT_MIXER2 0x2E
65#define WM8990_OUTPUT_MIXER3 0x2F
66#define WM8990_OUTPUT_MIXER4 0x30
67#define WM8990_OUTPUT_MIXER5 0x31
68#define WM8990_OUTPUT_MIXER6 0x32
69#define WM8990_OUT3_4_MIXER 0x33
70#define WM8990_LINE_MIXER1 0x34
71#define WM8990_LINE_MIXER2 0x35
72#define WM8990_SPEAKER_MIXER 0x36
73#define WM8990_ADDITIONAL_CONTROL 0x37
74#define WM8990_ANTIPOP1 0x38
75#define WM8990_ANTIPOP2 0x39
76#define WM8990_MICBIAS 0x3A
77#define WM8990_PLL1 0x3C
78#define WM8990_PLL2 0x3D
79#define WM8990_PLL3 0x3E
80#define WM8990_INTDRIVBITS 0x3F
81
82#define WM8990_REGISTER_COUNT 60
83#define WM8990_MAX_REGISTER 0x3F
84
85/*
86 * Field Definitions.
87 */
88
89/*
90 * R0 (0x00) - Reset
91 */
92#define WM8990_SW_RESET_CHIP_ID_MASK 0xFFFF /* SW_RESET_CHIP_ID */
93
94/*
95 * R1 (0x01) - Power Management (1)
96 */
97#define WM8990_SPK_ENA 0x1000 /* SPK_ENA */
98#define WM8990_SPK_ENA_BIT 12
99#define WM8990_OUT3_ENA 0x0800 /* OUT3_ENA */
100#define WM8990_OUT3_ENA_BIT 11
101#define WM8990_OUT4_ENA 0x0400 /* OUT4_ENA */
102#define WM8990_OUT4_ENA_BIT 10
103#define WM8990_LOUT_ENA 0x0200 /* LOUT_ENA */
104#define WM8990_LOUT_ENA_BIT 9
105#define WM8990_ROUT_ENA 0x0100 /* ROUT_ENA */
106#define WM8990_ROUT_ENA_BIT 8
107#define WM8990_MICBIAS_ENA 0x0010 /* MICBIAS_ENA */
108#define WM8990_MICBIAS_ENA_BIT 4
109#define WM8990_VMID_MODE_MASK 0x0006 /* VMID_MODE - [2:1] */
110#define WM8990_VREF_ENA 0x0001 /* VREF_ENA */
111#define WM8990_VREF_ENA_BIT 0
112
113/*
114 * R2 (0x02) - Power Management (2)
115 */
116#define WM8990_PLL_ENA 0x8000 /* PLL_ENA */
117#define WM8990_PLL_ENA_BIT 15
118#define WM8990_TSHUT_ENA 0x4000 /* TSHUT_ENA */
119#define WM8990_TSHUT_ENA_BIT 14
120#define WM8990_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */
121#define WM8990_TSHUT_OPDIS_BIT 13
122#define WM8990_OPCLK_ENA 0x0800 /* OPCLK_ENA */
123#define WM8990_OPCLK_ENA_BIT 11
124#define WM8990_AINL_ENA 0x0200 /* AINL_ENA */
125#define WM8990_AINL_ENA_BIT 9
126#define WM8990_AINR_ENA 0x0100 /* AINR_ENA */
127#define WM8990_AINR_ENA_BIT 8
128#define WM8990_LIN34_ENA 0x0080 /* LIN34_ENA */
129#define WM8990_LIN34_ENA_BIT 7
130#define WM8990_LIN12_ENA 0x0040 /* LIN12_ENA */
131#define WM8990_LIN12_ENA_BIT 6
132#define WM8990_RIN34_ENA 0x0020 /* RIN34_ENA */
133#define WM8990_RIN34_ENA_BIT 5
134#define WM8990_RIN12_ENA 0x0010 /* RIN12_ENA */
135#define WM8990_RIN12_ENA_BIT 4
136#define WM8990_ADCL_ENA 0x0002 /* ADCL_ENA */
137#define WM8990_ADCL_ENA_BIT 1
138#define WM8990_ADCR_ENA 0x0001 /* ADCR_ENA */
139#define WM8990_ADCR_ENA_BIT 0
140
141/*
142 * R3 (0x03) - Power Management (3)
143 */
144#define WM8990_LON_ENA 0x2000 /* LON_ENA */
145#define WM8990_LON_ENA_BIT 13
146#define WM8990_LOP_ENA 0x1000 /* LOP_ENA */
147#define WM8990_LOP_ENA_BIT 12
148#define WM8990_RON_ENA 0x0800 /* RON_ENA */
149#define WM8990_RON_ENA_BIT 11
150#define WM8990_ROP_ENA 0x0400 /* ROP_ENA */
151#define WM8990_ROP_ENA_BIT 10
152#define WM8990_LOPGA_ENA 0x0080 /* LOPGA_ENA */
153#define WM8990_LOPGA_ENA_BIT 7
154#define WM8990_ROPGA_ENA 0x0040 /* ROPGA_ENA */
155#define WM8990_ROPGA_ENA_BIT 6
156#define WM8990_LOMIX_ENA 0x0020 /* LOMIX_ENA */
157#define WM8990_LOMIX_ENA_BIT 5
158#define WM8990_ROMIX_ENA 0x0010 /* ROMIX_ENA */
159#define WM8990_ROMIX_ENA_BIT 4
160#define WM8990_DACL_ENA 0x0002 /* DACL_ENA */
161#define WM8990_DACL_ENA_BIT 1
162#define WM8990_DACR_ENA 0x0001 /* DACR_ENA */
163#define WM8990_DACR_ENA_BIT 0
164
165/*
166 * R4 (0x04) - Audio Interface (1)
167 */
168#define WM8990_AIFADCL_SRC 0x8000 /* AIFADCL_SRC */
169#define WM8990_AIFADCR_SRC 0x4000 /* AIFADCR_SRC */
170#define WM8990_AIFADC_TDM 0x2000 /* AIFADC_TDM */
171#define WM8990_AIFADC_TDM_CHAN 0x1000 /* AIFADC_TDM_CHAN */
172#define WM8990_AIF_BCLK_INV 0x0100 /* AIF_BCLK_INV */
173#define WM8990_AIF_LRCLK_INV 0x0080 /* AIF_LRCLK_INV */
174#define WM8990_AIF_WL_MASK 0x0060 /* AIF_WL - [6:5] */
175#define WM8990_AIF_WL_16BITS (0 << 5)
176#define WM8990_AIF_WL_20BITS (1 << 5)
177#define WM8990_AIF_WL_24BITS (2 << 5)
178#define WM8990_AIF_WL_32BITS (3 << 5)
179#define WM8990_AIF_FMT_MASK 0x0018 /* AIF_FMT - [4:3] */
180#define WM8990_AIF_TMF_RIGHTJ (0 << 3)
181#define WM8990_AIF_TMF_LEFTJ (1 << 3)
182#define WM8990_AIF_TMF_I2S (2 << 3)
183#define WM8990_AIF_TMF_DSP (3 << 3)
184
185/*
186 * R5 (0x05) - Audio Interface (2)
187 */
188#define WM8990_DACL_SRC 0x8000 /* DACL_SRC */
189#define WM8990_DACR_SRC 0x4000 /* DACR_SRC */
190#define WM8990_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */
191#define WM8990_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */
192#define WM8990_DAC_BOOST_MASK 0x0C00 /* DAC_BOOST */
193#define WM8990_DAC_COMP 0x0010 /* DAC_COMP */
194#define WM8990_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */
195#define WM8990_ADC_COMP 0x0004 /* ADC_COMP */
196#define WM8990_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */
197#define WM8990_LOOPBACK 0x0001 /* LOOPBACK */
198
199/*
200 * R6 (0x06) - Clocking (1)
201 */
202#define WM8990_TOCLK_RATE 0x8000 /* TOCLK_RATE */
203#define WM8990_TOCLK_ENA 0x4000 /* TOCLK_ENA */
204#define WM8990_OPCLKDIV_MASK 0x1E00 /* OPCLKDIV - [12:9] */
205#define WM8990_DCLKDIV_MASK 0x01C0 /* DCLKDIV - [8:6] */
206#define WM8990_BCLK_DIV_MASK 0x001E /* BCLK_DIV - [4:1] */
207#define WM8990_BCLK_DIV_1 (0x0 << 1)
208#define WM8990_BCLK_DIV_1_5 (0x1 << 1)
209#define WM8990_BCLK_DIV_2 (0x2 << 1)
210#define WM8990_BCLK_DIV_3 (0x3 << 1)
211#define WM8990_BCLK_DIV_4 (0x4 << 1)
212#define WM8990_BCLK_DIV_5_5 (0x5 << 1)
213#define WM8990_BCLK_DIV_6 (0x6 << 1)
214#define WM8990_BCLK_DIV_8 (0x7 << 1)
215#define WM8990_BCLK_DIV_11 (0x8 << 1)
216#define WM8990_BCLK_DIV_12 (0x9 << 1)
217#define WM8990_BCLK_DIV_16 (0xA << 1)
218#define WM8990_BCLK_DIV_22 (0xB << 1)
219#define WM8990_BCLK_DIV_24 (0xC << 1)
220#define WM8990_BCLK_DIV_32 (0xD << 1)
221#define WM8990_BCLK_DIV_44 (0xE << 1)
222#define WM8990_BCLK_DIV_48 (0xF << 1)
223
224/*
225 * R7 (0x07) - Clocking (2)
226 */
227#define WM8990_MCLK_SRC 0x8000 /* MCLK_SRC */
228#define WM8990_SYSCLK_SRC 0x4000 /* SYSCLK_SRC */
229#define WM8990_CLK_FORCE 0x2000 /* CLK_FORCE */
230#define WM8990_MCLK_DIV_MASK 0x1800 /* MCLK_DIV - [12:11] */
231#define WM8990_MCLK_DIV_1 (0 << 11)
232#define WM8990_MCLK_DIV_2 (2 << 11)
233#define WM8990_MCLK_INV 0x0400 /* MCLK_INV */
234#define WM8990_ADC_CLKDIV_MASK 0x00E0 /* ADC_CLKDIV */
235#define WM8990_ADC_CLKDIV_1 (0 << 5)
236#define WM8990_ADC_CLKDIV_1_5 (1 << 5)
237#define WM8990_ADC_CLKDIV_2 (2 << 5)
238#define WM8990_ADC_CLKDIV_3 (3 << 5)
239#define WM8990_ADC_CLKDIV_4 (4 << 5)
240#define WM8990_ADC_CLKDIV_5_5 (5 << 5)
241#define WM8990_ADC_CLKDIV_6 (6 << 5)
242#define WM8990_DAC_CLKDIV_MASK 0x001C /* DAC_CLKDIV - [4:2] */
243#define WM8990_DAC_CLKDIV_1 (0 << 2)
244#define WM8990_DAC_CLKDIV_1_5 (1 << 2)
245#define WM8990_DAC_CLKDIV_2 (2 << 2)
246#define WM8990_DAC_CLKDIV_3 (3 << 2)
247#define WM8990_DAC_CLKDIV_4 (4 << 2)
248#define WM8990_DAC_CLKDIV_5_5 (5 << 2)
249#define WM8990_DAC_CLKDIV_6 (6 << 2)
250
251/*
252 * R8 (0x08) - Audio Interface (3)
253 */
254#define WM8990_AIF_MSTR1 0x8000 /* AIF_MSTR1 */
255#define WM8990_AIF_MSTR2 0x4000 /* AIF_MSTR2 */
256#define WM8990_AIF_SEL 0x2000 /* AIF_SEL */
257#define WM8990_ADCLRC_DIR 0x0800 /* ADCLRC_DIR */
258#define WM8990_ADCLRC_RATE_MASK 0x07FF /* ADCLRC_RATE */
259
260/*
261 * R9 (0x09) - Audio Interface (4)
262 */
263#define WM8990_ALRCGPIO1 0x8000 /* ALRCGPIO1 */
264#define WM8990_ALRCBGPIO6 0x4000 /* ALRCBGPIO6 */
265#define WM8990_AIF_TRIS 0x2000 /* AIF_TRIS */
266#define WM8990_DACLRC_DIR 0x0800 /* DACLRC_DIR */
267#define WM8990_DACLRC_RATE_MASK 0x07FF /* DACLRC_RATE */
268
269/*
270 * R10 (0x0A) - DAC CTRL
271 */
272#define WM8990_AIF_LRCLKRATE 0x0400 /* AIF_LRCLKRATE */
273#define WM8990_DAC_MONO 0x0200 /* DAC_MONO */
274#define WM8990_DAC_SB_FILT 0x0100 /* DAC_SB_FILT */
275#define WM8990_DAC_MUTERATE 0x0080 /* DAC_MUTERATE */
276#define WM8990_DAC_MUTEMODE 0x0040 /* DAC_MUTEMODE */
277#define WM8990_DEEMP_MASK 0x0030 /* DEEMP - [5:4] */
278#define WM8990_DAC_MUTE 0x0004 /* DAC_MUTE */
279#define WM8990_DACL_DATINV 0x0002 /* DACL_DATINV */
280#define WM8990_DACR_DATINV 0x0001 /* DACR_DATINV */
281
282/*
283 * R11 (0x0B) - Left DAC Digital Volume
284 */
285#define WM8990_DAC_VU 0x0100 /* DAC_VU */
286#define WM8990_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */
287#define WM8990_DACL_VOL_SHIFT 0
288/*
289 * R12 (0x0C) - Right DAC Digital Volume
290 */
291#define WM8990_DAC_VU 0x0100 /* DAC_VU */
292#define WM8990_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */
293#define WM8990_DACR_VOL_SHIFT 0
294/*
295 * R13 (0x0D) - Digital Side Tone
296 */
297#define WM8990_ADCL_DAC_SVOL_MASK 0x0F /* ADCL_DAC_SVOL */
298#define WM8990_ADCL_DAC_SVOL_SHIFT 9
299#define WM8990_ADCR_DAC_SVOL_MASK 0x0F /* ADCR_DAC_SVOL */
300#define WM8990_ADCR_DAC_SVOL_SHIFT 5
301#define WM8990_ADC_TO_DACL_MASK 0x03 /* ADC_TO_DACL - [3:2] */
302#define WM8990_ADC_TO_DACL_SHIFT 2
303#define WM8990_ADC_TO_DACR_MASK 0x03 /* ADC_TO_DACR - [1:0] */
304#define WM8990_ADC_TO_DACR_SHIFT 0
305
306/*
307 * R14 (0x0E) - ADC CTRL
308 */
309#define WM8990_ADC_HPF_ENA 0x0100 /* ADC_HPF_ENA */
310#define WM8990_ADC_HPF_ENA_BIT 8
311#define WM8990_ADC_HPF_CUT_MASK 0x03 /* ADC_HPF_CUT - [6:5] */
312#define WM8990_ADC_HPF_CUT_SHIFT 5
313#define WM8990_ADCL_DATINV 0x0002 /* ADCL_DATINV */
314#define WM8990_ADCL_DATINV_BIT 1
315#define WM8990_ADCR_DATINV 0x0001 /* ADCR_DATINV */
316#define WM8990_ADCR_DATINV_BIT 0
317
318/*
319 * R15 (0x0F) - Left ADC Digital Volume
320 */
321#define WM8990_ADC_VU 0x0100 /* ADC_VU */
322#define WM8990_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */
323#define WM8990_ADCL_VOL_SHIFT 0
324
325/*
326 * R16 (0x10) - Right ADC Digital Volume
327 */
328#define WM8990_ADC_VU 0x0100 /* ADC_VU */
329#define WM8990_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */
330#define WM8990_ADCR_VOL_SHIFT 0
331
332/*
333 * R18 (0x12) - GPIO CTRL 1
334 */
335#define WM8990_IRQ 0x1000 /* IRQ */
336#define WM8990_TEMPOK 0x0800 /* TEMPOK */
337#define WM8990_MICSHRT 0x0400 /* MICSHRT */
338#define WM8990_MICDET 0x0200 /* MICDET */
339#define WM8990_PLL_LCK 0x0100 /* PLL_LCK */
340#define WM8990_GPI8_STATUS 0x0080 /* GPI8_STATUS */
341#define WM8990_GPI7_STATUS 0x0040 /* GPI7_STATUS */
342#define WM8990_GPIO6_STATUS 0x0020 /* GPIO6_STATUS */
343#define WM8990_GPIO5_STATUS 0x0010 /* GPIO5_STATUS */
344#define WM8990_GPIO4_STATUS 0x0008 /* GPIO4_STATUS */
345#define WM8990_GPIO3_STATUS 0x0004 /* GPIO3_STATUS */
346#define WM8990_GPIO2_STATUS 0x0002 /* GPIO2_STATUS */
347#define WM8990_GPIO1_STATUS 0x0001 /* GPIO1_STATUS */
348
349/*
350 * R19 (0x13) - GPIO1 & GPIO2
351 */
352#define WM8990_GPIO2_DEB_ENA 0x8000 /* GPIO2_DEB_ENA */
353#define WM8990_GPIO2_IRQ_ENA 0x4000 /* GPIO2_IRQ_ENA */
354#define WM8990_GPIO2_PU 0x2000 /* GPIO2_PU */
355#define WM8990_GPIO2_PD 0x1000 /* GPIO2_PD */
356#define WM8990_GPIO2_SEL_MASK 0x0F00 /* GPIO2_SEL - [11:8] */
357#define WM8990_GPIO1_DEB_ENA 0x0080 /* GPIO1_DEB_ENA */
358#define WM8990_GPIO1_IRQ_ENA 0x0040 /* GPIO1_IRQ_ENA */
359#define WM8990_GPIO1_PU 0x0020 /* GPIO1_PU */
360#define WM8990_GPIO1_PD 0x0010 /* GPIO1_PD */
361#define WM8990_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */
362
363/*
364 * R20 (0x14) - GPIO3 & GPIO4
365 */
366#define WM8990_GPIO4_DEB_ENA 0x8000 /* GPIO4_DEB_ENA */
367#define WM8990_GPIO4_IRQ_ENA 0x4000 /* GPIO4_IRQ_ENA */
368#define WM8990_GPIO4_PU 0x2000 /* GPIO4_PU */
369#define WM8990_GPIO4_PD 0x1000 /* GPIO4_PD */
370#define WM8990_GPIO4_SEL_MASK 0x0F00 /* GPIO4_SEL - [11:8] */
371#define WM8990_GPIO3_DEB_ENA 0x0080 /* GPIO3_DEB_ENA */
372#define WM8990_GPIO3_IRQ_ENA 0x0040 /* GPIO3_IRQ_ENA */
373#define WM8990_GPIO3_PU 0x0020 /* GPIO3_PU */
374#define WM8990_GPIO3_PD 0x0010 /* GPIO3_PD */
375#define WM8990_GPIO3_SEL_MASK 0x000F /* GPIO3_SEL - [3:0] */
376
377/*
378 * R21 (0x15) - GPIO5 & GPIO6
379 */
380#define WM8990_GPIO6_DEB_ENA 0x8000 /* GPIO6_DEB_ENA */
381#define WM8990_GPIO6_IRQ_ENA 0x4000 /* GPIO6_IRQ_ENA */
382#define WM8990_GPIO6_PU 0x2000 /* GPIO6_PU */
383#define WM8990_GPIO6_PD 0x1000 /* GPIO6_PD */
384#define WM8990_GPIO6_SEL_MASK 0x0F00 /* GPIO6_SEL - [11:8] */
385#define WM8990_GPIO5_DEB_ENA 0x0080 /* GPIO5_DEB_ENA */
386#define WM8990_GPIO5_IRQ_ENA 0x0040 /* GPIO5_IRQ_ENA */
387#define WM8990_GPIO5_PU 0x0020 /* GPIO5_PU */
388#define WM8990_GPIO5_PD 0x0010 /* GPIO5_PD */
389#define WM8990_GPIO5_SEL_MASK 0x000F /* GPIO5_SEL - [3:0] */
390
391/*
392 * R22 (0x16) - GPIOCTRL 2
393 */
394#define WM8990_RD_3W_ENA 0x8000 /* RD_3W_ENA */
395#define WM8990_MODE_3W4W 0x4000 /* MODE_3W4W */
396#define WM8990_TEMPOK_IRQ_ENA 0x0800 /* TEMPOK_IRQ_ENA */
397#define WM8990_MICSHRT_IRQ_ENA 0x0400 /* MICSHRT_IRQ_ENA */
398#define WM8990_MICDET_IRQ_ENA 0x0200 /* MICDET_IRQ_ENA */
399#define WM8990_PLL_LCK_IRQ_ENA 0x0100 /* PLL_LCK_IRQ_ENA */
400#define WM8990_GPI8_DEB_ENA 0x0080 /* GPI8_DEB_ENA */
401#define WM8990_GPI8_IRQ_ENA 0x0040 /* GPI8_IRQ_ENA */
402#define WM8990_GPI8_ENA 0x0010 /* GPI8_ENA */
403#define WM8990_GPI7_DEB_ENA 0x0008 /* GPI7_DEB_ENA */
404#define WM8990_GPI7_IRQ_ENA 0x0004 /* GPI7_IRQ_ENA */
405#define WM8990_GPI7_ENA 0x0001 /* GPI7_ENA */
406
407/*
408 * R23 (0x17) - GPIO_POL
409 */
410#define WM8990_IRQ_INV 0x1000 /* IRQ_INV */
411#define WM8990_TEMPOK_POL 0x0800 /* TEMPOK_POL */
412#define WM8990_MICSHRT_POL 0x0400 /* MICSHRT_POL */
413#define WM8990_MICDET_POL 0x0200 /* MICDET_POL */
414#define WM8990_PLL_LCK_POL 0x0100 /* PLL_LCK_POL */
415#define WM8990_GPI8_POL 0x0080 /* GPI8_POL */
416#define WM8990_GPI7_POL 0x0040 /* GPI7_POL */
417#define WM8990_GPIO6_POL 0x0020 /* GPIO6_POL */
418#define WM8990_GPIO5_POL 0x0010 /* GPIO5_POL */
419#define WM8990_GPIO4_POL 0x0008 /* GPIO4_POL */
420#define WM8990_GPIO3_POL 0x0004 /* GPIO3_POL */
421#define WM8990_GPIO2_POL 0x0002 /* GPIO2_POL */
422#define WM8990_GPIO1_POL 0x0001 /* GPIO1_POL */
423
424/*
425 * R24 (0x18) - Left Line Input 1&2 Volume
426 */
427#define WM8990_IPVU 0x0100 /* IPVU */
428#define WM8990_LI12MUTE 0x0080 /* LI12MUTE */
429#define WM8990_LI12MUTE_BIT 7
430#define WM8990_LI12ZC 0x0040 /* LI12ZC */
431#define WM8990_LI12ZC_BIT 6
432#define WM8990_LIN12VOL_MASK 0x001F /* LIN12VOL - [4:0] */
433#define WM8990_LIN12VOL_SHIFT 0
434/*
435 * R25 (0x19) - Left Line Input 3&4 Volume
436 */
437#define WM8990_IPVU 0x0100 /* IPVU */
438#define WM8990_LI34MUTE 0x0080 /* LI34MUTE */
439#define WM8990_LI34MUTE_BIT 7
440#define WM8990_LI34ZC 0x0040 /* LI34ZC */
441#define WM8990_LI34ZC_BIT 6
442#define WM8990_LIN34VOL_MASK 0x001F /* LIN34VOL - [4:0] */
443#define WM8990_LIN34VOL_SHIFT 0
444
445/*
446 * R26 (0x1A) - Right Line Input 1&2 Volume
447 */
448#define WM8990_IPVU 0x0100 /* IPVU */
449#define WM8990_RI12MUTE 0x0080 /* RI12MUTE */
450#define WM8990_RI12MUTE_BIT 7
451#define WM8990_RI12ZC 0x0040 /* RI12ZC */
452#define WM8990_RI12ZC_BIT 6
453#define WM8990_RIN12VOL_MASK 0x001F /* RIN12VOL - [4:0] */
454#define WM8990_RIN12VOL_SHIFT 0
455
456/*
457 * R27 (0x1B) - Right Line Input 3&4 Volume
458 */
459#define WM8990_IPVU 0x0100 /* IPVU */
460#define WM8990_RI34MUTE 0x0080 /* RI34MUTE */
461#define WM8990_RI34MUTE_BIT 7
462#define WM8990_RI34ZC 0x0040 /* RI34ZC */
463#define WM8990_RI34ZC_BIT 6
464#define WM8990_RIN34VOL_MASK 0x001F /* RIN34VOL - [4:0] */
465#define WM8990_RIN34VOL_SHIFT 0
466
467/*
468 * R28 (0x1C) - Left Output Volume
469 */
470#define WM8990_OPVU 0x0100 /* OPVU */
471#define WM8990_LOZC 0x0080 /* LOZC */
472#define WM8990_LOZC_BIT 7
473#define WM8990_LOUTVOL_MASK 0x007F /* LOUTVOL - [6:0] */
474#define WM8990_LOUTVOL_SHIFT 0
475/*
476 * R29 (0x1D) - Right Output Volume
477 */
478#define WM8990_OPVU 0x0100 /* OPVU */
479#define WM8990_ROZC 0x0080 /* ROZC */
480#define WM8990_ROZC_BIT 7
481#define WM8990_ROUTVOL_MASK 0x007F /* ROUTVOL - [6:0] */
482#define WM8990_ROUTVOL_SHIFT 0
483/*
484 * R30 (0x1E) - Line Outputs Volume
485 */
486#define WM8990_LONMUTE 0x0040 /* LONMUTE */
487#define WM8990_LONMUTE_BIT 6
488#define WM8990_LOPMUTE 0x0020 /* LOPMUTE */
489#define WM8990_LOPMUTE_BIT 5
490#define WM8990_LOATTN 0x0010 /* LOATTN */
491#define WM8990_LOATTN_BIT 4
492#define WM8990_RONMUTE 0x0004 /* RONMUTE */
493#define WM8990_RONMUTE_BIT 2
494#define WM8990_ROPMUTE 0x0002 /* ROPMUTE */
495#define WM8990_ROPMUTE_BIT 1
496#define WM8990_ROATTN 0x0001 /* ROATTN */
497#define WM8990_ROATTN_BIT 0
498
499/*
500 * R31 (0x1F) - Out3/4 Volume
501 */
502#define WM8990_OUT3MUTE 0x0020 /* OUT3MUTE */
503#define WM8990_OUT3MUTE_BIT 5
504#define WM8990_OUT3ATTN 0x0010 /* OUT3ATTN */
505#define WM8990_OUT3ATTN_BIT 4
506#define WM8990_OUT4MUTE 0x0002 /* OUT4MUTE */
507#define WM8990_OUT4MUTE_BIT 1
508#define WM8990_OUT4ATTN 0x0001 /* OUT4ATTN */
509#define WM8990_OUT4ATTN_BIT 0
510
511/*
512 * R32 (0x20) - Left OPGA Volume
513 */
514#define WM8990_OPVU 0x0100 /* OPVU */
515#define WM8990_LOPGAZC 0x0080 /* LOPGAZC */
516#define WM8990_LOPGAZC_BIT 7
517#define WM8990_LOPGAVOL_MASK 0x007F /* LOPGAVOL - [6:0] */
518#define WM8990_LOPGAVOL_SHIFT 0
519
520/*
521 * R33 (0x21) - Right OPGA Volume
522 */
523#define WM8990_OPVU 0x0100 /* OPVU */
524#define WM8990_ROPGAZC 0x0080 /* ROPGAZC */
525#define WM8990_ROPGAZC_BIT 7
526#define WM8990_ROPGAVOL_MASK 0x007F /* ROPGAVOL - [6:0] */
527#define WM8990_ROPGAVOL_SHIFT 0
528/*
529 * R34 (0x22) - Speaker Volume
530 */
531#define WM8990_SPKVOL_MASK 0x0003 /* SPKVOL - [1:0] */
532#define WM8990_SPKVOL_SHIFT 0
533
534/*
535 * R35 (0x23) - ClassD1
536 */
537#define WM8990_CDMODE 0x0100 /* CDMODE */
538#define WM8990_CDMODE_BIT 8
539
540/*
541 * R37 (0x25) - ClassD3
542 */
543#define WM8990_DCGAIN_MASK 0x0007 /* DCGAIN - [5:3] */
544#define WM8990_DCGAIN_SHIFT 3
545#define WM8990_ACGAIN_MASK 0x0007 /* ACGAIN - [2:0] */
546#define WM8990_ACGAIN_SHIFT 0
547/*
548 * R39 (0x27) - Input Mixer1
549 */
550#define WM8990_AINLMODE_MASK 0x000C /* AINLMODE - [3:2] */
551#define WM8990_AINLMODE_SHIFT 2
552#define WM8990_AINRMODE_MASK 0x0003 /* AINRMODE - [1:0] */
553#define WM8990_AINRMODE_SHIFT 0
554
555/*
556 * R40 (0x28) - Input Mixer2
557 */
558#define WM8990_LMP4 0x0080 /* LMP4 */
559#define WM8990_LMP4_BIT 7 /* LMP4 */
560#define WM8990_LMN3 0x0040 /* LMN3 */
561#define WM8990_LMN3_BIT 6 /* LMN3 */
562#define WM8990_LMP2 0x0020 /* LMP2 */
563#define WM8990_LMP2_BIT 5 /* LMP2 */
564#define WM8990_LMN1 0x0010 /* LMN1 */
565#define WM8990_LMN1_BIT 4 /* LMN1 */
566#define WM8990_RMP4 0x0008 /* RMP4 */
567#define WM8990_RMP4_BIT 3 /* RMP4 */
568#define WM8990_RMN3 0x0004 /* RMN3 */
569#define WM8990_RMN3_BIT 2 /* RMN3 */
570#define WM8990_RMP2 0x0002 /* RMP2 */
571#define WM8990_RMP2_BIT 1 /* RMP2 */
572#define WM8990_RMN1 0x0001 /* RMN1 */
573#define WM8990_RMN1_BIT 0 /* RMN1 */
574
575/*
576 * R41 (0x29) - Input Mixer3
577 */
578#define WM8990_L34MNB 0x0100 /* L34MNB */
579#define WM8990_L34MNB_BIT 8
580#define WM8990_L34MNBST 0x0080 /* L34MNBST */
581#define WM8990_L34MNBST_BIT 7
582#define WM8990_L12MNB 0x0020 /* L12MNB */
583#define WM8990_L12MNB_BIT 5
584#define WM8990_L12MNBST 0x0010 /* L12MNBST */
585#define WM8990_L12MNBST_BIT 4
586#define WM8990_LDBVOL_MASK 0x0007 /* LDBVOL - [2:0] */
587#define WM8990_LDBVOL_SHIFT 0
588
589/*
590 * R42 (0x2A) - Input Mixer4
591 */
592#define WM8990_R34MNB 0x0100 /* R34MNB */
593#define WM8990_R34MNB_BIT 8
594#define WM8990_R34MNBST 0x0080 /* R34MNBST */
595#define WM8990_R34MNBST_BIT 7
596#define WM8990_R12MNB 0x0020 /* R12MNB */
597#define WM8990_R12MNB_BIT 5
598#define WM8990_R12MNBST 0x0010 /* R12MNBST */
599#define WM8990_R12MNBST_BIT 4
600#define WM8990_RDBVOL_MASK 0x0007 /* RDBVOL - [2:0] */
601#define WM8990_RDBVOL_SHIFT 0
602
603/*
604 * R43 (0x2B) - Input Mixer5
605 */
606#define WM8990_LI2BVOL_MASK 0x07 /* LI2BVOL - [8:6] */
607#define WM8990_LI2BVOL_SHIFT 6
608#define WM8990_LR4BVOL_MASK 0x07 /* LR4BVOL - [5:3] */
609#define WM8990_LR4BVOL_SHIFT 3
610#define WM8990_LL4BVOL_MASK 0x07 /* LL4BVOL - [2:0] */
611#define WM8990_LL4BVOL_SHIFT 0
612
613/*
614 * R44 (0x2C) - Input Mixer6
615 */
616#define WM8990_RI2BVOL_MASK 0x07 /* RI2BVOL - [8:6] */
617#define WM8990_RI2BVOL_SHIFT 6
618#define WM8990_RL4BVOL_MASK 0x07 /* RL4BVOL - [5:3] */
619#define WM8990_RL4BVOL_SHIFT 3
620#define WM8990_RR4BVOL_MASK 0x07 /* RR4BVOL - [2:0] */
621#define WM8990_RR4BVOL_SHIFT 0
622
623/*
624 * R45 (0x2D) - Output Mixer1
625 */
626#define WM8990_LRBLO 0x0080 /* LRBLO */
627#define WM8990_LRBLO_BIT 7
628#define WM8990_LLBLO 0x0040 /* LLBLO */
629#define WM8990_LLBLO_BIT 6
630#define WM8990_LRI3LO 0x0020 /* LRI3LO */
631#define WM8990_LRI3LO_BIT 5
632#define WM8990_LLI3LO 0x0010 /* LLI3LO */
633#define WM8990_LLI3LO_BIT 4
634#define WM8990_LR12LO 0x0008 /* LR12LO */
635#define WM8990_LR12LO_BIT 3
636#define WM8990_LL12LO 0x0004 /* LL12LO */
637#define WM8990_LL12LO_BIT 2
638#define WM8990_LDLO 0x0001 /* LDLO */
639#define WM8990_LDLO_BIT 0
640
641/*
642 * R46 (0x2E) - Output Mixer2
643 */
644#define WM8990_RLBRO 0x0080 /* RLBRO */
645#define WM8990_RLBRO_BIT 7
646#define WM8990_RRBRO 0x0040 /* RRBRO */
647#define WM8990_RRBRO_BIT 6
648#define WM8990_RLI3RO 0x0020 /* RLI3RO */
649#define WM8990_RLI3RO_BIT 5
650#define WM8990_RRI3RO 0x0010 /* RRI3RO */
651#define WM8990_RRI3RO_BIT 4
652#define WM8990_RL12RO 0x0008 /* RL12RO */
653#define WM8990_RL12RO_BIT 3
654#define WM8990_RR12RO 0x0004 /* RR12RO */
655#define WM8990_RR12RO_BIT 2
656#define WM8990_RDRO 0x0001 /* RDRO */
657#define WM8990_RDRO_BIT 0
658
659/*
660 * R47 (0x2F) - Output Mixer3
661 */
662#define WM8990_LLI3LOVOL_MASK 0x07 /* LLI3LOVOL - [8:6] */
663#define WM8990_LLI3LOVOL_SHIFT 6
664#define WM8990_LR12LOVOL_MASK 0x07 /* LR12LOVOL - [5:3] */
665#define WM8990_LR12LOVOL_SHIFT 3
666#define WM8990_LL12LOVOL_MASK 0x07 /* LL12LOVOL - [2:0] */
667#define WM8990_LL12LOVOL_SHIFT 0
668
669/*
670 * R48 (0x30) - Output Mixer4
671 */
672#define WM8990_RRI3ROVOL_MASK 0x07 /* RRI3ROVOL - [8:6] */
673#define WM8990_RRI3ROVOL_SHIFT 6
674#define WM8990_RL12ROVOL_MASK 0x07 /* RL12ROVOL - [5:3] */
675#define WM8990_RL12ROVOL_SHIFT 3
676#define WM8990_RR12ROVOL_MASK 0x07 /* RR12ROVOL - [2:0] */
677#define WM8990_RR12ROVOL_SHIFT 0
678
679/*
680 * R49 (0x31) - Output Mixer5
681 */
682#define WM8990_LRI3LOVOL_MASK 0x07 /* LRI3LOVOL - [8:6] */
683#define WM8990_LRI3LOVOL_SHIFT 6
684#define WM8990_LRBLOVOL_MASK 0x07 /* LRBLOVOL - [5:3] */
685#define WM8990_LRBLOVOL_SHIFT 3
686#define WM8990_LLBLOVOL_MASK 0x07 /* LLBLOVOL - [2:0] */
687#define WM8990_LLBLOVOL_SHIFT 0
688
689/*
690 * R50 (0x32) - Output Mixer6
691 */
692#define WM8990_RLI3ROVOL_MASK 0x07 /* RLI3ROVOL - [8:6] */
693#define WM8990_RLI3ROVOL_SHIFT 6
694#define WM8990_RLBROVOL_MASK 0x07 /* RLBROVOL - [5:3] */
695#define WM8990_RLBROVOL_SHIFT 3
696#define WM8990_RRBROVOL_MASK 0x07 /* RRBROVOL - [2:0] */
697#define WM8990_RRBROVOL_SHIFT 0
698
699/*
700 * R51 (0x33) - Out3/4 Mixer
701 */
702#define WM8990_VSEL_MASK 0x0180 /* VSEL - [8:7] */
703#define WM8990_LI4O3 0x0020 /* LI4O3 */
704#define WM8990_LI4O3_BIT 5
705#define WM8990_LPGAO3 0x0010 /* LPGAO3 */
706#define WM8990_LPGAO3_BIT 4
707#define WM8990_RI4O4 0x0002 /* RI4O4 */
708#define WM8990_RI4O4_BIT 1
709#define WM8990_RPGAO4 0x0001 /* RPGAO4 */
710#define WM8990_RPGAO4_BIT 0
711/*
712 * R52 (0x34) - Line Mixer1
713 */
714#define WM8990_LLOPGALON 0x0040 /* LLOPGALON */
715#define WM8990_LLOPGALON_BIT 6
716#define WM8990_LROPGALON 0x0020 /* LROPGALON */
717#define WM8990_LROPGALON_BIT 5
718#define WM8990_LOPLON 0x0010 /* LOPLON */
719#define WM8990_LOPLON_BIT 4
720#define WM8990_LR12LOP 0x0004 /* LR12LOP */
721#define WM8990_LR12LOP_BIT 2
722#define WM8990_LL12LOP 0x0002 /* LL12LOP */
723#define WM8990_LL12LOP_BIT 1
724#define WM8990_LLOPGALOP 0x0001 /* LLOPGALOP */
725#define WM8990_LLOPGALOP_BIT 0
726/*
727 * R53 (0x35) - Line Mixer2
728 */
729#define WM8990_RROPGARON 0x0040 /* RROPGARON */
730#define WM8990_RROPGARON_BIT 6
731#define WM8990_RLOPGARON 0x0020 /* RLOPGARON */
732#define WM8990_RLOPGARON_BIT 5
733#define WM8990_ROPRON 0x0010 /* ROPRON */
734#define WM8990_ROPRON_BIT 4
735#define WM8990_RL12ROP 0x0004 /* RL12ROP */
736#define WM8990_RL12ROP_BIT 2
737#define WM8990_RR12ROP 0x0002 /* RR12ROP */
738#define WM8990_RR12ROP_BIT 1
739#define WM8990_RROPGAROP 0x0001 /* RROPGAROP */
740#define WM8990_RROPGAROP_BIT 0
741
742/*
743 * R54 (0x36) - Speaker Mixer
744 */
745#define WM8990_LB2SPK 0x0080 /* LB2SPK */
746#define WM8990_LB2SPK_BIT 7
747#define WM8990_RB2SPK 0x0040 /* RB2SPK */
748#define WM8990_RB2SPK_BIT 6
749#define WM8990_LI2SPK 0x0020 /* LI2SPK */
750#define WM8990_LI2SPK_BIT 5
751#define WM8990_RI2SPK 0x0010 /* RI2SPK */
752#define WM8990_RI2SPK_BIT 4
753#define WM8990_LOPGASPK 0x0008 /* LOPGASPK */
754#define WM8990_LOPGASPK_BIT 3
755#define WM8990_ROPGASPK 0x0004 /* ROPGASPK */
756#define WM8990_ROPGASPK_BIT 2
757#define WM8990_LDSPK 0x0002 /* LDSPK */
758#define WM8990_LDSPK_BIT 1
759#define WM8990_RDSPK 0x0001 /* RDSPK */
760#define WM8990_RDSPK_BIT 0
761
762/*
763 * R55 (0x37) - Additional Control
764 */
765#define WM8990_VROI 0x0001 /* VROI */
766
767/*
768 * R56 (0x38) - AntiPOP1
769 */
770#define WM8990_DIS_LLINE 0x0020 /* DIS_LLINE */
771#define WM8990_DIS_RLINE 0x0010 /* DIS_RLINE */
772#define WM8990_DIS_OUT3 0x0008 /* DIS_OUT3 */
773#define WM8990_DIS_OUT4 0x0004 /* DIS_OUT4 */
774#define WM8990_DIS_LOUT 0x0002 /* DIS_LOUT */
775#define WM8990_DIS_ROUT 0x0001 /* DIS_ROUT */
776
777/*
778 * R57 (0x39) - AntiPOP2
779 */
780#define WM8990_SOFTST 0x0040 /* SOFTST */
781#define WM8990_BUFIOEN 0x0008 /* BUFIOEN */
782#define WM8990_BUFDCOPEN 0x0004 /* BUFDCOPEN */
783#define WM8990_POBCTRL 0x0002 /* POBCTRL */
784#define WM8990_VMIDTOG 0x0001 /* VMIDTOG */
785
786/*
787 * R58 (0x3A) - MICBIAS
788 */
789#define WM8990_MCDSCTH_MASK 0x00C0 /* MCDSCTH - [7:6] */
790#define WM8990_MCDTHR_MASK 0x0038 /* MCDTHR - [5:3] */
791#define WM8990_MCD 0x0004 /* MCD */
792#define WM8990_MBSEL 0x0001 /* MBSEL */
793
794/*
795 * R60 (0x3C) - PLL1
796 */
797#define WM8990_SDM 0x0080 /* SDM */
798#define WM8990_PRESCALE 0x0040 /* PRESCALE */
799#define WM8990_PLLN_MASK 0x000F /* PLLN - [3:0] */
800
801/*
802 * R61 (0x3D) - PLL2
803 */
804#define WM8990_PLLK1_MASK 0x00FF /* PLLK1 - [7:0] */
805
806/*
807 * R62 (0x3E) - PLL3
808 */
809#define WM8990_PLLK2_MASK 0x00FF /* PLLK2 - [7:0] */
810
811/*
812 * R63 (0x3F) - Internal Driver Bits
813 */
814#define WM8990_INMIXL_PWR_BIT 0
815#define WM8990_AINLMUX_PWR_BIT 1
816#define WM8990_INMIXR_PWR_BIT 2
817#define WM8990_AINRMUX_PWR_BIT 3
818
819struct wm8990_setup_data {
820 unsigned short i2c_address;
821};
822
823#define WM8990_MCLK_DIV 0
824#define WM8990_DACCLK_DIV 1
825#define WM8990_ADCCLK_DIV 2
826#define WM8990_BCLK_DIV 3
827
828extern struct snd_soc_dai wm8990_dai;
829extern struct snd_soc_codec_device soc_codec_dev_wm8990;
830
831#endif /* __WM8990REGISTERDEFS_H__ */
832/*------------------------------ END OF FILE ---------------------------------*/
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 76c1e2d33e7d..9fc8edd82225 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -9,9 +9,6 @@
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
10 * Free Software Foundation; either version 2 of the License, or (at your 10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
12 *
13 * Revision history
14 * 4th Feb 2006 Initial version.
15 */ 12 */
16 13
17#include <linux/init.h> 14#include <linux/init.h>
@@ -25,6 +22,7 @@
25#include <sound/initval.h> 22#include <sound/initval.h>
26#include <sound/soc.h> 23#include <sound/soc.h>
27#include <sound/soc-dapm.h> 24#include <sound/soc-dapm.h>
25#include "wm9712.h"
28 26
29#define WM9712_VERSION "0.4" 27#define WM9712_VERSION "0.4"
30 28
@@ -351,7 +349,7 @@ SND_SOC_DAPM_INPUT("MIC1"),
351SND_SOC_DAPM_INPUT("MIC2"), 349SND_SOC_DAPM_INPUT("MIC2"),
352}; 350};
353 351
354static const char *audio_map[][3] = { 352static const struct snd_soc_dapm_route audio_map[] = {
355 /* virtual mixer - mixes left & right channels for spk and mono */ 353 /* virtual mixer - mixes left & right channels for spk and mono */
356 {"AC97 Mixer", NULL, "Left DAC"}, 354 {"AC97 Mixer", NULL, "Left DAC"},
357 {"AC97 Mixer", NULL, "Right DAC"}, 355 {"AC97 Mixer", NULL, "Right DAC"},
@@ -446,21 +444,14 @@ static const char *audio_map[][3] = {
446 {"Speaker PGA", NULL, "Speaker Mux"}, 444 {"Speaker PGA", NULL, "Speaker Mux"},
447 {"LOUT2", NULL, "Speaker PGA"}, 445 {"LOUT2", NULL, "Speaker PGA"},
448 {"ROUT2", NULL, "Speaker PGA"}, 446 {"ROUT2", NULL, "Speaker PGA"},
449
450 {NULL, NULL, NULL},
451}; 447};
452 448
453static int wm9712_add_widgets(struct snd_soc_codec *codec) 449static int wm9712_add_widgets(struct snd_soc_codec *codec)
454{ 450{
455 int i; 451 snd_soc_dapm_new_controls(codec, wm9712_dapm_widgets,
456 452 ARRAY_SIZE(wm9712_dapm_widgets));
457 for (i = 0; i < ARRAY_SIZE(wm9712_dapm_widgets); i++)
458 snd_soc_dapm_new_control(codec, &wm9712_dapm_widgets[i]);
459 453
460 /* set up audio path connects */ 454 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
461 for (i = 0; audio_map[i][0] != NULL; i++)
462 snd_soc_dapm_connect_input(codec, audio_map[i][0],
463 audio_map[i][1], audio_map[i][2]);
464 455
465 snd_soc_dapm_new_widgets(codec); 456 snd_soc_dapm_new_widgets(codec);
466 return 0; 457 return 0;
@@ -541,7 +532,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream)
541 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\ 532 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
542 SNDRV_PCM_RATE_48000) 533 SNDRV_PCM_RATE_48000)
543 534
544struct snd_soc_codec_dai wm9712_dai[] = { 535struct snd_soc_dai wm9712_dai[] = {
545{ 536{
546 .name = "AC97 HiFi", 537 .name = "AC97 HiFi",
547 .type = SND_SOC_DAI_AC97_BUS, 538 .type = SND_SOC_DAI_AC97_BUS,
@@ -574,23 +565,23 @@ struct snd_soc_codec_dai wm9712_dai[] = {
574}; 565};
575EXPORT_SYMBOL_GPL(wm9712_dai); 566EXPORT_SYMBOL_GPL(wm9712_dai);
576 567
577static int wm9712_dapm_event(struct snd_soc_codec *codec, int event) 568static int wm9712_set_bias_level(struct snd_soc_codec *codec,
569 enum snd_soc_bias_level level)
578{ 570{
579 switch (event) { 571 switch (level) {
580 case SNDRV_CTL_POWER_D0: /* full On */ 572 case SND_SOC_BIAS_ON:
581 case SNDRV_CTL_POWER_D1: /* partial On */ 573 case SND_SOC_BIAS_PREPARE:
582 case SNDRV_CTL_POWER_D2: /* partial On */
583 break; 574 break;
584 case SNDRV_CTL_POWER_D3hot: /* Off, with power */ 575 case SND_SOC_BIAS_STANDBY:
585 ac97_write(codec, AC97_POWERDOWN, 0x0000); 576 ac97_write(codec, AC97_POWERDOWN, 0x0000);
586 break; 577 break;
587 case SNDRV_CTL_POWER_D3cold: /* Off, without power */ 578 case SND_SOC_BIAS_OFF:
588 /* disable everything including AC link */ 579 /* disable everything including AC link */
589 ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff); 580 ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
590 ac97_write(codec, AC97_POWERDOWN, 0xffff); 581 ac97_write(codec, AC97_POWERDOWN, 0xffff);
591 break; 582 break;
592 } 583 }
593 codec->dapm_state = event; 584 codec->bias_level = level;
594 return 0; 585 return 0;
595} 586}
596 587
@@ -598,12 +589,12 @@ static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
598{ 589{
599 if (try_warm && soc_ac97_ops.warm_reset) { 590 if (try_warm && soc_ac97_ops.warm_reset) {
600 soc_ac97_ops.warm_reset(codec->ac97); 591 soc_ac97_ops.warm_reset(codec->ac97);
601 if (!(ac97_read(codec, 0) & 0x8000)) 592 if (ac97_read(codec, 0) == wm9712_reg[0])
602 return 1; 593 return 1;
603 } 594 }
604 595
605 soc_ac97_ops.reset(codec->ac97); 596 soc_ac97_ops.reset(codec->ac97);
606 if (ac97_read(codec, 0) & 0x8000) 597 if (ac97_read(codec, 0) != wm9712_reg[0])
607 goto err; 598 goto err;
608 return 0; 599 return 0;
609 600
@@ -618,7 +609,7 @@ static int wm9712_soc_suspend(struct platform_device *pdev,
618 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 609 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
619 struct snd_soc_codec *codec = socdev->codec; 610 struct snd_soc_codec *codec = socdev->codec;
620 611
621 wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3cold); 612 wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF);
622 return 0; 613 return 0;
623} 614}
624 615
@@ -635,7 +626,7 @@ static int wm9712_soc_resume(struct platform_device *pdev)
635 return ret; 626 return ret;
636 } 627 }
637 628
638 wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot); 629 wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
639 630
640 if (ret == 0) { 631 if (ret == 0) {
641 /* Sync reg_cache with the hardware after cold reset */ 632 /* Sync reg_cache with the hardware after cold reset */
@@ -647,8 +638,8 @@ static int wm9712_soc_resume(struct platform_device *pdev)
647 } 638 }
648 } 639 }
649 640
650 if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) 641 if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
651 wm9712_dapm_event(codec, SNDRV_CTL_POWER_D0); 642 wm9712_set_bias_level(codec, SND_SOC_BIAS_ON);
652 643
653 return ret; 644 return ret;
654} 645}
@@ -682,7 +673,7 @@ static int wm9712_soc_probe(struct platform_device *pdev)
682 codec->num_dai = ARRAY_SIZE(wm9712_dai); 673 codec->num_dai = ARRAY_SIZE(wm9712_dai);
683 codec->write = ac97_write; 674 codec->write = ac97_write;
684 codec->read = ac97_read; 675 codec->read = ac97_read;
685 codec->dapm_event = wm9712_dapm_event; 676 codec->set_bias_level = wm9712_set_bias_level;
686 INIT_LIST_HEAD(&codec->dapm_widgets); 677 INIT_LIST_HEAD(&codec->dapm_widgets);
687 INIT_LIST_HEAD(&codec->dapm_paths); 678 INIT_LIST_HEAD(&codec->dapm_paths);
688 679
@@ -706,7 +697,7 @@ static int wm9712_soc_probe(struct platform_device *pdev)
706 /* set alc mux to none */ 697 /* set alc mux to none */
707 ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); 698 ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
708 699
709 wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot); 700 wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
710 wm9712_add_controls(codec); 701 wm9712_add_controls(codec);
711 wm9712_add_widgets(codec); 702 wm9712_add_widgets(codec);
712 ret = snd_soc_register_card(socdev); 703 ret = snd_soc_register_card(socdev);
diff --git a/sound/soc/codecs/wm9712.h b/sound/soc/codecs/wm9712.h
index 719105d61e65..d29e8a18ca6d 100644
--- a/sound/soc/codecs/wm9712.h
+++ b/sound/soc/codecs/wm9712.h
@@ -8,7 +8,7 @@
8#define WM9712_DAI_AC97_HIFI 0 8#define WM9712_DAI_AC97_HIFI 0
9#define WM9712_DAI_AC97_AUX 1 9#define WM9712_DAI_AC97_AUX 1
10 10
11extern struct snd_soc_codec_dai wm9712_dai[2]; 11extern struct snd_soc_dai wm9712_dai[2];
12extern struct snd_soc_codec_device soc_codec_dev_wm9712; 12extern struct snd_soc_codec_device soc_codec_dev_wm9712;
13 13
14#endif 14#endif
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 1f241161445c..38d1fe0971fc 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -10,9 +10,6 @@
10 * Free Software Foundation; either version 2 of the License, or (at your 10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
12 * 12 *
13 * Revision history
14 * 4th Feb 2006 Initial version.
15 *
16 * Features:- 13 * Features:-
17 * 14 *
18 * o Support for AC97 Codec, Voice DAC and Aux DAC 15 * o Support for AC97 Codec, Voice DAC and Aux DAC
@@ -456,7 +453,7 @@ SND_SOC_DAPM_INPUT("MIC2B"),
456SND_SOC_DAPM_VMID("VMID"), 453SND_SOC_DAPM_VMID("VMID"),
457}; 454};
458 455
459static const char *audio_map[][3] = { 456static const struct snd_soc_dapm_route audio_map[] = {
460 /* left HP mixer */ 457 /* left HP mixer */
461 {"Left HP Mixer", "PC Beep Playback Switch", "PCBEEP"}, 458 {"Left HP Mixer", "PC Beep Playback Switch", "PCBEEP"},
462 {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"}, 459 {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"},
@@ -607,21 +604,14 @@ static const char *audio_map[][3] = {
607 {"Capture Mono Mux", "Stereo", "Capture Mixer"}, 604 {"Capture Mono Mux", "Stereo", "Capture Mixer"},
608 {"Capture Mono Mux", "Left", "Left Capture Source"}, 605 {"Capture Mono Mux", "Left", "Left Capture Source"},
609 {"Capture Mono Mux", "Right", "Right Capture Source"}, 606 {"Capture Mono Mux", "Right", "Right Capture Source"},
610
611 {NULL, NULL, NULL},
612}; 607};
613 608
614static int wm9713_add_widgets(struct snd_soc_codec *codec) 609static int wm9713_add_widgets(struct snd_soc_codec *codec)
615{ 610{
616 int i; 611 snd_soc_dapm_new_controls(codec, wm9713_dapm_widgets,
617 612 ARRAY_SIZE(wm9713_dapm_widgets));
618 for (i = 0; i < ARRAY_SIZE(wm9713_dapm_widgets); i++)
619 snd_soc_dapm_new_control(codec, &wm9713_dapm_widgets[i]);
620 613
621 /* set up audio path audio_mapnects */ 614 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
622 for (i = 0; audio_map[i][0] != NULL; i++)
623 snd_soc_dapm_connect_input(codec, audio_map[i][0],
624 audio_map[i][1], audio_map[i][2]);
625 615
626 snd_soc_dapm_new_widgets(codec); 616 snd_soc_dapm_new_widgets(codec);
627 return 0; 617 return 0;
@@ -799,7 +789,7 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
799 return 0; 789 return 0;
800} 790}
801 791
802static int wm9713_set_dai_pll(struct snd_soc_codec_dai *codec_dai, 792static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai,
803 int pll_id, unsigned int freq_in, unsigned int freq_out) 793 int pll_id, unsigned int freq_in, unsigned int freq_out)
804{ 794{
805 struct snd_soc_codec *codec = codec_dai->codec; 795 struct snd_soc_codec *codec = codec_dai->codec;
@@ -810,7 +800,7 @@ static int wm9713_set_dai_pll(struct snd_soc_codec_dai *codec_dai,
810 * Tristate the PCM DAI lines, tristate can be disabled by calling 800 * Tristate the PCM DAI lines, tristate can be disabled by calling
811 * wm9713_set_dai_fmt() 801 * wm9713_set_dai_fmt()
812 */ 802 */
813static int wm9713_set_dai_tristate(struct snd_soc_codec_dai *codec_dai, 803static int wm9713_set_dai_tristate(struct snd_soc_dai *codec_dai,
814 int tristate) 804 int tristate)
815{ 805{
816 struct snd_soc_codec *codec = codec_dai->codec; 806 struct snd_soc_codec *codec = codec_dai->codec;
@@ -826,7 +816,7 @@ static int wm9713_set_dai_tristate(struct snd_soc_codec_dai *codec_dai,
826 * Configure WM9713 clock dividers. 816 * Configure WM9713 clock dividers.
827 * Voice DAC needs 256 FS 817 * Voice DAC needs 256 FS
828 */ 818 */
829static int wm9713_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai, 819static int wm9713_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
830 int div_id, int div) 820 int div_id, int div)
831{ 821{
832 struct snd_soc_codec *codec = codec_dai->codec; 822 struct snd_soc_codec *codec = codec_dai->codec;
@@ -868,7 +858,7 @@ static int wm9713_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
868 return 0; 858 return 0;
869} 859}
870 860
871static int wm9713_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 861static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai,
872 unsigned int fmt) 862 unsigned int fmt)
873{ 863{
874 struct snd_soc_codec *codec = codec_dai->codec; 864 struct snd_soc_codec *codec = codec_dai->codec;
@@ -886,7 +876,7 @@ static int wm9713_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
886 gpio |= 0x0018; 876 gpio |= 0x0018;
887 break; 877 break;
888 case SND_SOC_DAIFMT_CBS_CFS: 878 case SND_SOC_DAIFMT_CBS_CFS:
889 reg |= 0x0200; 879 reg |= 0x2000;
890 gpio |= 0x001a; 880 gpio |= 0x001a;
891 break; 881 break;
892 case SND_SOC_DAIFMT_CBS_CFM: 882 case SND_SOC_DAIFMT_CBS_CFM:
@@ -1011,15 +1001,24 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream)
1011 return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate); 1001 return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
1012} 1002}
1013 1003
1014#define WM9713_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ 1004#define WM9713_RATES (SNDRV_PCM_RATE_8000 | \
1015 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\ 1005 SNDRV_PCM_RATE_11025 | \
1016 SNDRV_PCM_RATE_48000) 1006 SNDRV_PCM_RATE_22050 | \
1007 SNDRV_PCM_RATE_44100 | \
1008 SNDRV_PCM_RATE_48000)
1009
1010#define WM9713_PCM_RATES (SNDRV_PCM_RATE_8000 | \
1011 SNDRV_PCM_RATE_11025 | \
1012 SNDRV_PCM_RATE_16000 | \
1013 SNDRV_PCM_RATE_22050 | \
1014 SNDRV_PCM_RATE_44100 | \
1015 SNDRV_PCM_RATE_48000)
1017 1016
1018#define WM9713_PCM_FORMATS \ 1017#define WM9713_PCM_FORMATS \
1019 (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ 1018 (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
1020 SNDRV_PCM_FORMAT_S24_LE) 1019 SNDRV_PCM_FORMAT_S24_LE)
1021 1020
1022struct snd_soc_codec_dai wm9713_dai[] = { 1021struct snd_soc_dai wm9713_dai[] = {
1023{ 1022{
1024 .name = "AC97 HiFi", 1023 .name = "AC97 HiFi",
1025 .type = SND_SOC_DAI_AC97_BUS, 1024 .type = SND_SOC_DAI_AC97_BUS,
@@ -1061,13 +1060,13 @@ struct snd_soc_codec_dai wm9713_dai[] = {
1061 .stream_name = "Voice Playback", 1060 .stream_name = "Voice Playback",
1062 .channels_min = 1, 1061 .channels_min = 1,
1063 .channels_max = 1, 1062 .channels_max = 1,
1064 .rates = WM9713_RATES, 1063 .rates = WM9713_PCM_RATES,
1065 .formats = WM9713_PCM_FORMATS,}, 1064 .formats = WM9713_PCM_FORMATS,},
1066 .capture = { 1065 .capture = {
1067 .stream_name = "Voice Capture", 1066 .stream_name = "Voice Capture",
1068 .channels_min = 1, 1067 .channels_min = 1,
1069 .channels_max = 2, 1068 .channels_max = 2,
1070 .rates = WM9713_RATES, 1069 .rates = WM9713_PCM_RATES,
1071 .formats = WM9713_PCM_FORMATS,}, 1070 .formats = WM9713_PCM_FORMATS,},
1072 .ops = { 1071 .ops = {
1073 .hw_params = wm9713_pcm_hw_params, 1072 .hw_params = wm9713_pcm_hw_params,
@@ -1086,44 +1085,44 @@ int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
1086{ 1085{
1087 if (try_warm && soc_ac97_ops.warm_reset) { 1086 if (try_warm && soc_ac97_ops.warm_reset) {
1088 soc_ac97_ops.warm_reset(codec->ac97); 1087 soc_ac97_ops.warm_reset(codec->ac97);
1089 if (!(ac97_read(codec, 0) & 0x8000)) 1088 if (ac97_read(codec, 0) == wm9713_reg[0])
1090 return 1; 1089 return 1;
1091 } 1090 }
1092 1091
1093 soc_ac97_ops.reset(codec->ac97); 1092 soc_ac97_ops.reset(codec->ac97);
1094 if (ac97_read(codec, 0) & 0x8000) 1093 if (ac97_read(codec, 0) != wm9713_reg[0])
1095 return -EIO; 1094 return -EIO;
1096 return 0; 1095 return 0;
1097} 1096}
1098EXPORT_SYMBOL_GPL(wm9713_reset); 1097EXPORT_SYMBOL_GPL(wm9713_reset);
1099 1098
1100static int wm9713_dapm_event(struct snd_soc_codec *codec, int event) 1099static int wm9713_set_bias_level(struct snd_soc_codec *codec,
1100 enum snd_soc_bias_level level)
1101{ 1101{
1102 u16 reg; 1102 u16 reg;
1103 1103
1104 switch (event) { 1104 switch (level) {
1105 case SNDRV_CTL_POWER_D0: /* full On */ 1105 case SND_SOC_BIAS_ON:
1106 /* enable thermal shutdown */ 1106 /* enable thermal shutdown */
1107 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x1bff; 1107 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x1bff;
1108 ac97_write(codec, AC97_EXTENDED_MID, reg); 1108 ac97_write(codec, AC97_EXTENDED_MID, reg);
1109 break; 1109 break;
1110 case SNDRV_CTL_POWER_D1: /* partial On */ 1110 case SND_SOC_BIAS_PREPARE:
1111 case SNDRV_CTL_POWER_D2: /* partial On */
1112 break; 1111 break;
1113 case SNDRV_CTL_POWER_D3hot: /* Off, with power */ 1112 case SND_SOC_BIAS_STANDBY:
1114 /* enable master bias and vmid */ 1113 /* enable master bias and vmid */
1115 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x3bff; 1114 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x3bff;
1116 ac97_write(codec, AC97_EXTENDED_MID, reg); 1115 ac97_write(codec, AC97_EXTENDED_MID, reg);
1117 ac97_write(codec, AC97_POWERDOWN, 0x0000); 1116 ac97_write(codec, AC97_POWERDOWN, 0x0000);
1118 break; 1117 break;
1119 case SNDRV_CTL_POWER_D3cold: /* Off, without power */ 1118 case SND_SOC_BIAS_OFF:
1120 /* disable everything including AC link */ 1119 /* disable everything including AC link */
1121 ac97_write(codec, AC97_EXTENDED_MID, 0xffff); 1120 ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
1122 ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff); 1121 ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
1123 ac97_write(codec, AC97_POWERDOWN, 0xffff); 1122 ac97_write(codec, AC97_POWERDOWN, 0xffff);
1124 break; 1123 break;
1125 } 1124 }
1126 codec->dapm_state = event; 1125 codec->bias_level = level;
1127 return 0; 1126 return 0;
1128} 1127}
1129 1128
@@ -1160,7 +1159,7 @@ static int wm9713_soc_resume(struct platform_device *pdev)
1160 return ret; 1159 return ret;
1161 } 1160 }
1162 1161
1163 wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot); 1162 wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1164 1163
1165 /* do we need to re-start the PLL ? */ 1164 /* do we need to re-start the PLL ? */
1166 if (wm9713->pll_out) 1165 if (wm9713->pll_out)
@@ -1176,8 +1175,8 @@ static int wm9713_soc_resume(struct platform_device *pdev)
1176 } 1175 }
1177 } 1176 }
1178 1177
1179 if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) 1178 if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
1180 wm9713_dapm_event(codec, SNDRV_CTL_POWER_D0); 1179 wm9713_set_bias_level(codec, SND_SOC_BIAS_ON);
1181 1180
1182 return ret; 1181 return ret;
1183} 1182}
@@ -1216,7 +1215,7 @@ static int wm9713_soc_probe(struct platform_device *pdev)
1216 codec->num_dai = ARRAY_SIZE(wm9713_dai); 1215 codec->num_dai = ARRAY_SIZE(wm9713_dai);
1217 codec->write = ac97_write; 1216 codec->write = ac97_write;
1218 codec->read = ac97_read; 1217 codec->read = ac97_read;
1219 codec->dapm_event = wm9713_dapm_event; 1218 codec->set_bias_level = wm9713_set_bias_level;
1220 INIT_LIST_HEAD(&codec->dapm_widgets); 1219 INIT_LIST_HEAD(&codec->dapm_widgets);
1221 INIT_LIST_HEAD(&codec->dapm_paths); 1220 INIT_LIST_HEAD(&codec->dapm_paths);
1222 1221
@@ -1238,7 +1237,7 @@ static int wm9713_soc_probe(struct platform_device *pdev)
1238 goto reset_err; 1237 goto reset_err;
1239 } 1238 }
1240 1239
1241 wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot); 1240 wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1242 1241
1243 /* unmute the adc - move to kcontrol */ 1242 /* unmute the adc - move to kcontrol */
1244 reg = ac97_read(codec, AC97_CD) & 0x7fff; 1243 reg = ac97_read(codec, AC97_CD) & 0x7fff;
diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h
index d357b6c8134b..63b8d81756e3 100644
--- a/sound/soc/codecs/wm9713.h
+++ b/sound/soc/codecs/wm9713.h
@@ -46,7 +46,7 @@
46#define WM9713_DAI_PCM_VOICE 2 46#define WM9713_DAI_PCM_VOICE 2
47 47
48extern struct snd_soc_codec_device soc_codec_dev_wm9713; 48extern struct snd_soc_codec_device soc_codec_dev_wm9713;
49extern struct snd_soc_codec_dai wm9713_dai[3]; 49extern struct snd_soc_dai wm9713_dai[3];
50 50
51int wm9713_reset(struct snd_soc_codec *codec, int try_warm); 51int wm9713_reset(struct snd_soc_codec *codec, int try_warm);
52 52
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 20680c551aab..8f7e33834902 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -1,6 +1,6 @@
1config SND_DAVINCI_SOC 1config SND_DAVINCI_SOC
2 tristate "SoC Audio for the TI DAVINCI chip" 2 tristate "SoC Audio for the TI DAVINCI chip"
3 depends on ARCH_DAVINCI && SND_SOC 3 depends on ARCH_DAVINCI
4 help 4 help
5 Say Y or M if you want to add support for codecs attached to 5 Say Y or M if you want to add support for codecs attached to
6 the DAVINCI AC97 or I2S interface. You will also need 6 the DAVINCI AC97 or I2S interface. You will also need
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index fcd165240333..5e2c306399ed 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -33,24 +33,24 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
33 struct snd_pcm_hw_params *params) 33 struct snd_pcm_hw_params *params)
34{ 34{
35 struct snd_soc_pcm_runtime *rtd = substream->private_data; 35 struct snd_soc_pcm_runtime *rtd = substream->private_data;
36 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 36 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
37 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 37 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
38 int ret = 0; 38 int ret = 0;
39 39
40 /* set codec DAI configuration */ 40 /* set codec DAI configuration */
41 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 41 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
42 SND_SOC_DAIFMT_CBM_CFM); 42 SND_SOC_DAIFMT_CBM_CFM);
43 if (ret < 0) 43 if (ret < 0)
44 return ret; 44 return ret;
45 45
46 /* set cpu DAI configuration */ 46 /* set cpu DAI configuration */
47 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM | 47 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM |
48 SND_SOC_DAIFMT_IB_NF); 48 SND_SOC_DAIFMT_IB_NF);
49 if (ret < 0) 49 if (ret < 0)
50 return ret; 50 return ret;
51 51
52 /* set the codec system clock */ 52 /* set the codec system clock */
53 ret = codec_dai->dai_ops.set_sysclk(codec_dai, 0, EVM_CODEC_CLOCK, 53 ret = snd_soc_dai_set_sysclk(codec_dai, 0, EVM_CODEC_CLOCK,
54 SND_SOC_CLOCK_OUT); 54 SND_SOC_CLOCK_OUT);
55 if (ret < 0) 55 if (ret < 0)
56 return ret; 56 return ret;
@@ -71,7 +71,7 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
71}; 71};
72 72
73/* davinci-evm machine audio_mapnections to the codec pins */ 73/* davinci-evm machine audio_mapnections to the codec pins */
74static const char *audio_map[][3] = { 74static const struct snd_soc_dapm_route audio_map[] = {
75 /* Headphone connected to HPLOUT, HPROUT */ 75 /* Headphone connected to HPLOUT, HPROUT */
76 {"Headphone Jack", NULL, "HPLOUT"}, 76 {"Headphone Jack", NULL, "HPLOUT"},
77 {"Headphone Jack", NULL, "HPROUT"}, 77 {"Headphone Jack", NULL, "HPROUT"},
@@ -90,36 +90,30 @@ static const char *audio_map[][3] = {
90 {"LINE2L", NULL, "Line In"}, 90 {"LINE2L", NULL, "Line In"},
91 {"LINE1R", NULL, "Line In"}, 91 {"LINE1R", NULL, "Line In"},
92 {"LINE2R", NULL, "Line In"}, 92 {"LINE2R", NULL, "Line In"},
93
94 {NULL, NULL, NULL},
95}; 93};
96 94
97/* Logic for a aic3x as connected on a davinci-evm */ 95/* Logic for a aic3x as connected on a davinci-evm */
98static int evm_aic3x_init(struct snd_soc_codec *codec) 96static int evm_aic3x_init(struct snd_soc_codec *codec)
99{ 97{
100 int i;
101
102 /* Add davinci-evm specific widgets */ 98 /* Add davinci-evm specific widgets */
103 for (i = 0; i < ARRAY_SIZE(aic3x_dapm_widgets); i++) 99 snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
104 snd_soc_dapm_new_control(codec, &aic3x_dapm_widgets[i]); 100 ARRAY_SIZE(aic3x_dapm_widgets));
105 101
106 /* Set up davinci-evm specific audio path audio_map */ 102 /* Set up davinci-evm specific audio path audio_map */
107 for (i = 0; audio_map[i][0] != NULL; i++) 103 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
108 snd_soc_dapm_connect_input(codec, audio_map[i][0],
109 audio_map[i][1], audio_map[i][2]);
110 104
111 /* not connected */ 105 /* not connected */
112 snd_soc_dapm_set_endpoint(codec, "MONO_LOUT", 0); 106 snd_soc_dapm_disable_pin(codec, "MONO_LOUT");
113 snd_soc_dapm_set_endpoint(codec, "HPLCOM", 0); 107 snd_soc_dapm_disable_pin(codec, "HPLCOM");
114 snd_soc_dapm_set_endpoint(codec, "HPRCOM", 0); 108 snd_soc_dapm_disable_pin(codec, "HPRCOM");
115 109
116 /* always connected */ 110 /* always connected */
117 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1); 111 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
118 snd_soc_dapm_set_endpoint(codec, "Line Out", 1); 112 snd_soc_dapm_enable_pin(codec, "Line Out");
119 snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1); 113 snd_soc_dapm_enable_pin(codec, "Mic Jack");
120 snd_soc_dapm_set_endpoint(codec, "Line In", 1); 114 snd_soc_dapm_enable_pin(codec, "Line In");
121 115
122 snd_soc_dapm_sync_endpoints(codec); 116 snd_soc_dapm_sync(codec);
123 117
124 return 0; 118 return 0;
125} 119}
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index c421774b33ee..5ebf1ff71c4c 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -147,7 +147,7 @@ static void davinci_mcbsp_stop(struct snd_pcm_substream *substream)
147static int davinci_i2s_startup(struct snd_pcm_substream *substream) 147static int davinci_i2s_startup(struct snd_pcm_substream *substream)
148{ 148{
149 struct snd_soc_pcm_runtime *rtd = substream->private_data; 149 struct snd_soc_pcm_runtime *rtd = substream->private_data;
150 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 150 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
151 struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; 151 struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
152 152
153 cpu_dai->dma_data = dev->dma_params[substream->stream]; 153 cpu_dai->dma_data = dev->dma_params[substream->stream];
@@ -155,7 +155,7 @@ static int davinci_i2s_startup(struct snd_pcm_substream *substream)
155 return 0; 155 return 0;
156} 156}
157 157
158static int davinci_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai, 158static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
159 unsigned int fmt) 159 unsigned int fmt)
160{ 160{
161 struct davinci_mcbsp_dev *dev = cpu_dai->private_data; 161 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
@@ -295,11 +295,12 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
295 return ret; 295 return ret;
296} 296}
297 297
298static int davinci_i2s_probe(struct platform_device *pdev) 298static int davinci_i2s_probe(struct platform_device *pdev,
299 struct snd_soc_dai *dai)
299{ 300{
300 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 301 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
301 struct snd_soc_machine *machine = socdev->machine; 302 struct snd_soc_machine *machine = socdev->machine;
302 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai; 303 struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
303 struct davinci_mcbsp_dev *dev; 304 struct davinci_mcbsp_dev *dev;
304 struct resource *mem, *ioarea; 305 struct resource *mem, *ioarea;
305 struct evm_snd_platform_data *pdata; 306 struct evm_snd_platform_data *pdata;
@@ -356,11 +357,12 @@ err_release_region:
356 return ret; 357 return ret;
357} 358}
358 359
359static void davinci_i2s_remove(struct platform_device *pdev) 360static void davinci_i2s_remove(struct platform_device *pdev,
361 struct snd_soc_dai *dai)
360{ 362{
361 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 363 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
362 struct snd_soc_machine *machine = socdev->machine; 364 struct snd_soc_machine *machine = socdev->machine;
363 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai; 365 struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
364 struct davinci_mcbsp_dev *dev = cpu_dai->private_data; 366 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
365 struct resource *mem; 367 struct resource *mem;
366 368
@@ -376,7 +378,7 @@ static void davinci_i2s_remove(struct platform_device *pdev)
376 378
377#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 379#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000
378 380
379struct snd_soc_cpu_dai davinci_i2s_dai = { 381struct snd_soc_dai davinci_i2s_dai = {
380 .name = "davinci-i2s", 382 .name = "davinci-i2s",
381 .id = 0, 383 .id = 0,
382 .type = SND_SOC_DAI_I2S, 384 .type = SND_SOC_DAI_I2S,
diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h
index 9592d17db320..c5b091807eec 100644
--- a/sound/soc/davinci/davinci-i2s.h
+++ b/sound/soc/davinci/davinci-i2s.h
@@ -12,6 +12,6 @@
12#ifndef _DAVINCI_I2S_H 12#ifndef _DAVINCI_I2S_H
13#define _DAVINCI_I2S_H 13#define _DAVINCI_I2S_H
14 14
15extern struct snd_soc_cpu_dai davinci_i2s_dai; 15extern struct snd_soc_dai davinci_i2s_dai;
16 16
17#endif 17#endif
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 6a76927c9971..6a5e56a782bb 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -350,7 +350,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
350static u64 davinci_pcm_dmamask = 0xffffffff; 350static u64 davinci_pcm_dmamask = 0xffffffff;
351 351
352static int davinci_pcm_new(struct snd_card *card, 352static int davinci_pcm_new(struct snd_card *card,
353 struct snd_soc_codec_dai *dai, struct snd_pcm *pcm) 353 struct snd_soc_dai *dai, struct snd_pcm *pcm)
354{ 354{
355 int ret; 355 int ret;
356 356
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 257101f44e9e..3368ace60977 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -1,8 +1,6 @@
1menu "ALSA SoC audio for Freescale SOCs"
2
3config SND_SOC_MPC8610 1config SND_SOC_MPC8610
4 bool "ALSA SoC support for the MPC8610 SOC" 2 bool "ALSA SoC support for the MPC8610 SOC"
5 depends on SND_SOC && MPC8610_HPCD 3 depends on MPC8610_HPCD
6 default y if MPC8610 4 default y if MPC8610
7 help 5 help
8 Say Y if you want to add support for codecs attached to the SSI 6 Say Y if you want to add support for codecs attached to the SSI
@@ -16,5 +14,3 @@ config SND_SOC_MPC8610_HPCD
16 default y if MPC8610_HPCD 14 default y if MPC8610_HPCD
17 help 15 help
18 Say Y if you want to enable audio on the Freescale MPC8610 HPCD. 16 Say Y if you want to enable audio on the Freescale MPC8610 HPCD.
19
20endmenu
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 78de7168d2ba..da2bc5902864 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -282,7 +282,7 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
282 * once for each .dai_link in the machine driver's snd_soc_machine 282 * once for each .dai_link in the machine driver's snd_soc_machine
283 * structure. 283 * structure.
284 */ 284 */
285static int fsl_dma_new(struct snd_card *card, struct snd_soc_codec_dai *dai, 285static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
286 struct snd_pcm *pcm) 286 struct snd_pcm *pcm)
287{ 287{
288 static u64 fsl_dma_dmamask = DMA_BIT_MASK(32); 288 static u64 fsl_dma_dmamask = DMA_BIT_MASK(32);
diff --git a/sound/soc/fsl/fsl_dma.h b/sound/soc/fsl/fsl_dma.h
index 430a6ce8b0d0..385d4a42603c 100644
--- a/sound/soc/fsl/fsl_dma.h
+++ b/sound/soc/fsl/fsl_dma.h
@@ -126,7 +126,7 @@ struct fsl_dma_link_descriptor {
126 u8 res[4]; /* Reserved */ 126 u8 res[4]; /* Reserved */
127} __attribute__ ((aligned(32), packed)); 127} __attribute__ ((aligned(32), packed));
128 128
129/* DMA information needed to create a snd_soc_cpu_dai object 129/* DMA information needed to create a snd_soc_dai object
130 * 130 *
131 * ssi_stx_phys: bus address of SSI STX register to use 131 * ssi_stx_phys: bus address of SSI STX register to use
132 * ssi_srx_phys: bus address of SSI SRX register to use 132 * ssi_srx_phys: bus address of SSI SRX register to use
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index f588545698f3..71bff33f5528 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -82,7 +82,7 @@ struct fsl_ssi_private {
82 struct device *dev; 82 struct device *dev;
83 unsigned int playback; 83 unsigned int playback;
84 unsigned int capture; 84 unsigned int capture;
85 struct snd_soc_cpu_dai cpu_dai; 85 struct snd_soc_dai cpu_dai;
86 struct device_attribute dev_attr; 86 struct device_attribute dev_attr;
87 87
88 struct { 88 struct {
@@ -479,7 +479,7 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream)
479 * @freq: the frequency of the given clock ID, currently ignored 479 * @freq: the frequency of the given clock ID, currently ignored
480 * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master) 480 * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master)
481 */ 481 */
482static int fsl_ssi_set_sysclk(struct snd_soc_cpu_dai *cpu_dai, 482static int fsl_ssi_set_sysclk(struct snd_soc_dai *cpu_dai,
483 int clk_id, unsigned int freq, int dir) 483 int clk_id, unsigned int freq, int dir)
484{ 484{
485 485
@@ -497,7 +497,7 @@ static int fsl_ssi_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
497 * 497 *
498 * @format: one of SND_SOC_DAIFMT_xxx 498 * @format: one of SND_SOC_DAIFMT_xxx
499 */ 499 */
500static int fsl_ssi_set_fmt(struct snd_soc_cpu_dai *cpu_dai, unsigned int format) 500static int fsl_ssi_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
501{ 501{
502 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL; 502 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
503} 503}
@@ -505,7 +505,7 @@ static int fsl_ssi_set_fmt(struct snd_soc_cpu_dai *cpu_dai, unsigned int format)
505/** 505/**
506 * fsl_ssi_dai_template: template CPU DAI for the SSI 506 * fsl_ssi_dai_template: template CPU DAI for the SSI
507 */ 507 */
508static struct snd_soc_cpu_dai fsl_ssi_dai_template = { 508static struct snd_soc_dai fsl_ssi_dai_template = {
509 .playback = { 509 .playback = {
510 /* The SSI does not support monaural audio. */ 510 /* The SSI does not support monaural audio. */
511 .channels_min = 2, 511 .channels_min = 2,
@@ -569,15 +569,15 @@ static ssize_t fsl_sysfs_ssi_show(struct device *dev,
569} 569}
570 570
571/** 571/**
572 * fsl_ssi_create_dai: create a snd_soc_cpu_dai structure 572 * fsl_ssi_create_dai: create a snd_soc_dai structure
573 * 573 *
574 * This function is called by the machine driver to create a snd_soc_cpu_dai 574 * This function is called by the machine driver to create a snd_soc_dai
575 * structure. The function creates an ssi_private object, which contains 575 * structure. The function creates an ssi_private object, which contains
576 * the snd_soc_cpu_dai. It also creates the sysfs statistics device. 576 * the snd_soc_dai. It also creates the sysfs statistics device.
577 */ 577 */
578struct snd_soc_cpu_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info) 578struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
579{ 579{
580 struct snd_soc_cpu_dai *fsl_ssi_dai; 580 struct snd_soc_dai *fsl_ssi_dai;
581 struct fsl_ssi_private *ssi_private; 581 struct fsl_ssi_private *ssi_private;
582 int ret = 0; 582 int ret = 0;
583 struct device_attribute *dev_attr; 583 struct device_attribute *dev_attr;
@@ -588,7 +588,7 @@ struct snd_soc_cpu_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
588 return NULL; 588 return NULL;
589 } 589 }
590 memcpy(&ssi_private->cpu_dai, &fsl_ssi_dai_template, 590 memcpy(&ssi_private->cpu_dai, &fsl_ssi_dai_template,
591 sizeof(struct snd_soc_cpu_dai)); 591 sizeof(struct snd_soc_dai));
592 592
593 fsl_ssi_dai = &ssi_private->cpu_dai; 593 fsl_ssi_dai = &ssi_private->cpu_dai;
594 dev_attr = &ssi_private->dev_attr; 594 dev_attr = &ssi_private->dev_attr;
@@ -623,11 +623,11 @@ struct snd_soc_cpu_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
623EXPORT_SYMBOL_GPL(fsl_ssi_create_dai); 623EXPORT_SYMBOL_GPL(fsl_ssi_create_dai);
624 624
625/** 625/**
626 * fsl_ssi_destroy_dai: destroy the snd_soc_cpu_dai object 626 * fsl_ssi_destroy_dai: destroy the snd_soc_dai object
627 * 627 *
628 * This function undoes the operations of fsl_ssi_create_dai() 628 * This function undoes the operations of fsl_ssi_create_dai()
629 */ 629 */
630void fsl_ssi_destroy_dai(struct snd_soc_cpu_dai *fsl_ssi_dai) 630void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai)
631{ 631{
632 struct fsl_ssi_private *ssi_private = 632 struct fsl_ssi_private *ssi_private =
633 container_of(fsl_ssi_dai, struct fsl_ssi_private, cpu_dai); 633 container_of(fsl_ssi_dai, struct fsl_ssi_private, cpu_dai);
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index c5ce88e15651..83b44d700e33 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -217,8 +217,8 @@ struct fsl_ssi_info {
217 struct device *dev; 217 struct device *dev;
218}; 218};
219 219
220struct snd_soc_cpu_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info); 220struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info);
221void fsl_ssi_destroy_dai(struct snd_soc_cpu_dai *fsl_ssi_dai); 221void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai);
222 222
223#endif 223#endif
224 224
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index a00aac7a71f1..4bdc9d8fc90e 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -58,9 +58,9 @@ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)
58 sound_device->dev.platform_data; 58 sound_device->dev.platform_data;
59 59
60 /* Program the signal routing between the SSI and the DMA */ 60 /* Program the signal routing between the SSI and the DMA */
61 guts_set_dmacr(machine_data->guts, machine_data->dma_id + 1, 61 guts_set_dmacr(machine_data->guts, machine_data->dma_id,
62 machine_data->dma_channel_id[0], CCSR_GUTS_DMACR_DEV_SSI); 62 machine_data->dma_channel_id[0], CCSR_GUTS_DMACR_DEV_SSI);
63 guts_set_dmacr(machine_data->guts, machine_data->dma_id + 1, 63 guts_set_dmacr(machine_data->guts, machine_data->dma_id,
64 machine_data->dma_channel_id[1], CCSR_GUTS_DMACR_DEV_SSI); 64 machine_data->dma_channel_id[1], CCSR_GUTS_DMACR_DEV_SSI);
65 65
66 guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id, 66 guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id,
@@ -96,62 +96,52 @@ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)
96static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) 96static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)
97{ 97{
98 struct snd_soc_pcm_runtime *rtd = substream->private_data; 98 struct snd_soc_pcm_runtime *rtd = substream->private_data;
99 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 99 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
100 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 100 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
101 struct mpc8610_hpcd_data *machine_data = 101 struct mpc8610_hpcd_data *machine_data =
102 rtd->socdev->dev->platform_data; 102 rtd->socdev->dev->platform_data;
103 int ret = 0; 103 int ret = 0;
104 104
105 /* Tell the CPU driver what the serial protocol is. */ 105 /* Tell the CPU driver what the serial protocol is. */
106 if (cpu_dai->dai_ops.set_fmt) { 106 ret = snd_soc_dai_set_fmt(cpu_dai, machine_data->dai_format);
107 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, 107 if (ret < 0) {
108 machine_data->dai_format); 108 dev_err(substream->pcm->card->dev,
109 if (ret < 0) { 109 "could not set CPU driver audio format\n");
110 dev_err(substream->pcm->card->dev, 110 return ret;
111 "could not set CPU driver audio format\n");
112 return ret;
113 }
114 } 111 }
115 112
116 /* Tell the codec driver what the serial protocol is. */ 113 /* Tell the codec driver what the serial protocol is. */
117 if (codec_dai->dai_ops.set_fmt) { 114 ret = snd_soc_dai_set_fmt(codec_dai, machine_data->dai_format);
118 ret = codec_dai->dai_ops.set_fmt(codec_dai, 115 if (ret < 0) {
119 machine_data->dai_format); 116 dev_err(substream->pcm->card->dev,
120 if (ret < 0) { 117 "could not set codec driver audio format\n");
121 dev_err(substream->pcm->card->dev, 118 return ret;
122 "could not set codec driver audio format\n");
123 return ret;
124 }
125 } 119 }
126 120
127 /* 121 /*
128 * Tell the CPU driver what the clock frequency is, and whether it's a 122 * Tell the CPU driver what the clock frequency is, and whether it's a
129 * slave or master. 123 * slave or master.
130 */ 124 */
131 if (cpu_dai->dai_ops.set_sysclk) { 125 ret = snd_soc_dai_set_sysclk(cpu_dai, 0,
132 ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, 0, 126 machine_data->clk_frequency,
133 machine_data->clk_frequency, 127 machine_data->cpu_clk_direction);
134 machine_data->cpu_clk_direction); 128 if (ret < 0) {
135 if (ret < 0) { 129 dev_err(substream->pcm->card->dev,
136 dev_err(substream->pcm->card->dev, 130 "could not set CPU driver clock parameters\n");
137 "could not set CPU driver clock parameters\n"); 131 return ret;
138 return ret;
139 }
140 } 132 }
141 133
142 /* 134 /*
143 * Tell the codec driver what the MCLK frequency is, and whether it's 135 * Tell the codec driver what the MCLK frequency is, and whether it's
144 * a slave or master. 136 * a slave or master.
145 */ 137 */
146 if (codec_dai->dai_ops.set_sysclk) { 138 ret = snd_soc_dai_set_sysclk(codec_dai, 0,
147 ret = codec_dai->dai_ops.set_sysclk(codec_dai, 0, 139 machine_data->clk_frequency,
148 machine_data->clk_frequency, 140 machine_data->codec_clk_direction);
149 machine_data->codec_clk_direction); 141 if (ret < 0) {
150 if (ret < 0) { 142 dev_err(substream->pcm->card->dev,
151 dev_err(substream->pcm->card->dev, 143 "could not set codec driver clock params\n");
152 "could not set codec driver clock params\n"); 144 return ret;
153 return ret;
154 }
155 } 145 }
156 146
157 return 0; 147 return 0;
@@ -170,9 +160,9 @@ int mpc8610_hpcd_machine_remove(struct platform_device *sound_device)
170 160
171 /* Restore the signal routing */ 161 /* Restore the signal routing */
172 162
173 guts_set_dmacr(machine_data->guts, machine_data->dma_id + 1, 163 guts_set_dmacr(machine_data->guts, machine_data->dma_id,
174 machine_data->dma_channel_id[0], 0); 164 machine_data->dma_channel_id[0], 0);
175 guts_set_dmacr(machine_data->guts, machine_data->dma_id + 1, 165 guts_set_dmacr(machine_data->guts, machine_data->dma_id,
176 machine_data->dma_channel_id[1], 0); 166 machine_data->dma_channel_id[1], 0);
177 167
178 switch (machine_data->ssi_id) { 168 switch (machine_data->ssi_id) {
@@ -182,7 +172,7 @@ int mpc8610_hpcd_machine_remove(struct platform_device *sound_device)
182 break; 172 break;
183 case 1: 173 case 1:
184 clrsetbits_be32(&machine_data->guts->pmuxcr, 174 clrsetbits_be32(&machine_data->guts->pmuxcr,
185 CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI1_LA); 175 CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_LA);
186 break; 176 break;
187 } 177 }
188 178
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 0230d83e8e5e..aea27e70043c 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -1,5 +1,3 @@
1menu "SoC Audio for the Texas Instruments OMAP"
2
3config SND_OMAP_SOC 1config SND_OMAP_SOC
4 tristate "SoC Audio for the Texas Instruments OMAP chips" 2 tristate "SoC Audio for the Texas Instruments OMAP chips"
5 depends on ARCH_OMAP && SND_SOC 3 depends on ARCH_OMAP && SND_SOC
@@ -15,5 +13,3 @@ config SND_OMAP_SOC_N810
15 select SND_SOC_TLV320AIC3X 13 select SND_SOC_TLV320AIC3X
16 help 14 help
17 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.
18
19endmenu
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index 6533563a6011..02cec96859b8 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -30,15 +30,15 @@
30 30
31#include <asm/mach-types.h> 31#include <asm/mach-types.h>
32#include <asm/arch/hardware.h> 32#include <asm/arch/hardware.h>
33#include <asm/arch/gpio.h> 33#include <linux/gpio.h>
34#include <asm/arch/mcbsp.h> 34#include <asm/arch/mcbsp.h>
35 35
36#include "omap-mcbsp.h" 36#include "omap-mcbsp.h"
37#include "omap-pcm.h" 37#include "omap-pcm.h"
38#include "../codecs/tlv320aic3x.h" 38#include "../codecs/tlv320aic3x.h"
39 39
40#define RX44_HEADSET_AMP_GPIO 10 40#define N810_HEADSET_AMP_GPIO 10
41#define RX44_SPEAKER_AMP_GPIO 101 41#define N810_SPEAKER_AMP_GPIO 101
42 42
43static struct clk *sys_clkout2; 43static struct clk *sys_clkout2;
44static struct clk *sys_clkout2_src; 44static struct clk *sys_clkout2_src;
@@ -46,13 +46,26 @@ static struct clk *func96m_clk;
46 46
47static int n810_spk_func; 47static int n810_spk_func;
48static int n810_jack_func; 48static int n810_jack_func;
49static int n810_dmic_func;
49 50
50static void n810_ext_control(struct snd_soc_codec *codec) 51static void n810_ext_control(struct snd_soc_codec *codec)
51{ 52{
52 snd_soc_dapm_set_endpoint(codec, "Ext Spk", n810_spk_func); 53 if (n810_spk_func)
53 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", n810_jack_func); 54 snd_soc_dapm_enable_pin(codec, "Ext Spk");
55 else
56 snd_soc_dapm_disable_pin(codec, "Ext Spk");
57
58 if (n810_jack_func)
59 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
60 else
61 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
54 62
55 snd_soc_dapm_sync_endpoints(codec); 63 if (n810_dmic_func)
64 snd_soc_dapm_enable_pin(codec, "DMic");
65 else
66 snd_soc_dapm_disable_pin(codec, "DMic");
67
68 snd_soc_dapm_sync(codec);
56} 69}
57 70
58static int n810_startup(struct snd_pcm_substream *substream) 71static int n810_startup(struct snd_pcm_substream *substream)
@@ -73,12 +86,12 @@ static int n810_hw_params(struct snd_pcm_substream *substream,
73 struct snd_pcm_hw_params *params) 86 struct snd_pcm_hw_params *params)
74{ 87{
75 struct snd_soc_pcm_runtime *rtd = substream->private_data; 88 struct snd_soc_pcm_runtime *rtd = substream->private_data;
76 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 89 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
77 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 90 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
78 int err; 91 int err;
79 92
80 /* Set codec DAI configuration */ 93 /* Set codec DAI configuration */
81 err = codec_dai->dai_ops.set_fmt(codec_dai, 94 err = snd_soc_dai_set_fmt(codec_dai,
82 SND_SOC_DAIFMT_I2S | 95 SND_SOC_DAIFMT_I2S |
83 SND_SOC_DAIFMT_NB_NF | 96 SND_SOC_DAIFMT_NB_NF |
84 SND_SOC_DAIFMT_CBM_CFM); 97 SND_SOC_DAIFMT_CBM_CFM);
@@ -86,7 +99,7 @@ static int n810_hw_params(struct snd_pcm_substream *substream,
86 return err; 99 return err;
87 100
88 /* Set cpu DAI configuration */ 101 /* Set cpu DAI configuration */
89 err = cpu_dai->dai_ops.set_fmt(cpu_dai, 102 err = snd_soc_dai_set_fmt(cpu_dai,
90 SND_SOC_DAIFMT_I2S | 103 SND_SOC_DAIFMT_I2S |
91 SND_SOC_DAIFMT_NB_NF | 104 SND_SOC_DAIFMT_NB_NF |
92 SND_SOC_DAIFMT_CBM_CFM); 105 SND_SOC_DAIFMT_CBM_CFM);
@@ -94,7 +107,7 @@ static int n810_hw_params(struct snd_pcm_substream *substream,
94 return err; 107 return err;
95 108
96 /* Set the codec system clock for DAC and ADC */ 109 /* Set the codec system clock for DAC and ADC */
97 err = codec_dai->dai_ops.set_sysclk(codec_dai, 0, 12000000, 110 err = snd_soc_dai_set_sysclk(codec_dai, 0, 12000000,
98 SND_SOC_CLOCK_IN); 111 SND_SOC_CLOCK_IN);
99 112
100 return err; 113 return err;
@@ -150,13 +163,35 @@ static int n810_set_jack(struct snd_kcontrol *kcontrol,
150 return 1; 163 return 1;
151} 164}
152 165
166static int n810_get_input(struct snd_kcontrol *kcontrol,
167 struct snd_ctl_elem_value *ucontrol)
168{
169 ucontrol->value.integer.value[0] = n810_dmic_func;
170
171 return 0;
172}
173
174static int n810_set_input(struct snd_kcontrol *kcontrol,
175 struct snd_ctl_elem_value *ucontrol)
176{
177 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
178
179 if (n810_dmic_func == ucontrol->value.integer.value[0])
180 return 0;
181
182 n810_dmic_func = ucontrol->value.integer.value[0];
183 n810_ext_control(codec);
184
185 return 1;
186}
187
153static int n810_spk_event(struct snd_soc_dapm_widget *w, 188static int n810_spk_event(struct snd_soc_dapm_widget *w,
154 struct snd_kcontrol *k, int event) 189 struct snd_kcontrol *k, int event)
155{ 190{
156 if (SND_SOC_DAPM_EVENT_ON(event)) 191 if (SND_SOC_DAPM_EVENT_ON(event))
157 omap_set_gpio_dataout(RX44_SPEAKER_AMP_GPIO, 1); 192 gpio_set_value(N810_SPEAKER_AMP_GPIO, 1);
158 else 193 else
159 omap_set_gpio_dataout(RX44_SPEAKER_AMP_GPIO, 0); 194 gpio_set_value(N810_SPEAKER_AMP_GPIO, 0);
160 195
161 return 0; 196 return 0;
162} 197}
@@ -165,9 +200,9 @@ static int n810_jack_event(struct snd_soc_dapm_widget *w,
165 struct snd_kcontrol *k, int event) 200 struct snd_kcontrol *k, int event)
166{ 201{
167 if (SND_SOC_DAPM_EVENT_ON(event)) 202 if (SND_SOC_DAPM_EVENT_ON(event))
168 omap_set_gpio_dataout(RX44_HEADSET_AMP_GPIO, 1); 203 gpio_set_value(N810_HEADSET_AMP_GPIO, 1);
169 else 204 else
170 omap_set_gpio_dataout(RX44_HEADSET_AMP_GPIO, 0); 205 gpio_set_value(N810_HEADSET_AMP_GPIO, 0);
171 206
172 return 0; 207 return 0;
173} 208}
@@ -175,21 +210,27 @@ static int n810_jack_event(struct snd_soc_dapm_widget *w,
175static const struct snd_soc_dapm_widget aic33_dapm_widgets[] = { 210static const struct snd_soc_dapm_widget aic33_dapm_widgets[] = {
176 SND_SOC_DAPM_SPK("Ext Spk", n810_spk_event), 211 SND_SOC_DAPM_SPK("Ext Spk", n810_spk_event),
177 SND_SOC_DAPM_HP("Headphone Jack", n810_jack_event), 212 SND_SOC_DAPM_HP("Headphone Jack", n810_jack_event),
213 SND_SOC_DAPM_MIC("DMic", NULL),
178}; 214};
179 215
180static const char *audio_map[][3] = { 216static const struct snd_soc_dapm_route audio_map[] = {
181 {"Headphone Jack", NULL, "HPLOUT"}, 217 {"Headphone Jack", NULL, "HPLOUT"},
182 {"Headphone Jack", NULL, "HPROUT"}, 218 {"Headphone Jack", NULL, "HPROUT"},
183 219
184 {"Ext Spk", NULL, "LLOUT"}, 220 {"Ext Spk", NULL, "LLOUT"},
185 {"Ext Spk", NULL, "RLOUT"}, 221 {"Ext Spk", NULL, "RLOUT"},
222
223 {"DMic Rate 64", NULL, "Mic Bias 2V"},
224 {"Mic Bias 2V", NULL, "DMic"},
186}; 225};
187 226
188static const char *spk_function[] = {"Off", "On"}; 227static const char *spk_function[] = {"Off", "On"};
189static const char *jack_function[] = {"Off", "Headphone"}; 228static const char *jack_function[] = {"Off", "Headphone"};
229static const char *input_function[] = {"ADC", "Digital Mic"};
190static const struct soc_enum n810_enum[] = { 230static const struct soc_enum n810_enum[] = {
191 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), 231 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
192 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function), 232 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function),
233 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function),
193}; 234};
194 235
195static const struct snd_kcontrol_new aic33_n810_controls[] = { 236static const struct snd_kcontrol_new aic33_n810_controls[] = {
@@ -197,6 +238,8 @@ static const struct snd_kcontrol_new aic33_n810_controls[] = {
197 n810_get_spk, n810_set_spk), 238 n810_get_spk, n810_set_spk),
198 SOC_ENUM_EXT("Jack Function", n810_enum[1], 239 SOC_ENUM_EXT("Jack Function", n810_enum[1],
199 n810_get_jack, n810_set_jack), 240 n810_get_jack, n810_set_jack),
241 SOC_ENUM_EXT("Input Select", n810_enum[2],
242 n810_get_input, n810_set_input),
200}; 243};
201 244
202static int n810_aic33_init(struct snd_soc_codec *codec) 245static int n810_aic33_init(struct snd_soc_codec *codec)
@@ -204,9 +247,9 @@ static int n810_aic33_init(struct snd_soc_codec *codec)
204 int i, err; 247 int i, err;
205 248
206 /* Not connected */ 249 /* Not connected */
207 snd_soc_dapm_set_endpoint(codec, "MONO_LOUT", 0); 250 snd_soc_dapm_disable_pin(codec, "MONO_LOUT");
208 snd_soc_dapm_set_endpoint(codec, "HPLCOM", 0); 251 snd_soc_dapm_disable_pin(codec, "HPLCOM");
209 snd_soc_dapm_set_endpoint(codec, "HPRCOM", 0); 252 snd_soc_dapm_disable_pin(codec, "HPRCOM");
210 253
211 /* Add N810 specific controls */ 254 /* Add N810 specific controls */
212 for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) { 255 for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) {
@@ -217,15 +260,13 @@ static int n810_aic33_init(struct snd_soc_codec *codec)
217 } 260 }
218 261
219 /* Add N810 specific widgets */ 262 /* Add N810 specific widgets */
220 for (i = 0; i < ARRAY_SIZE(aic33_dapm_widgets); i++) 263 snd_soc_dapm_new_controls(codec, aic33_dapm_widgets,
221 snd_soc_dapm_new_control(codec, &aic33_dapm_widgets[i]); 264 ARRAY_SIZE(aic33_dapm_widgets));
222 265
223 /* Set up N810 specific audio path audio_map */ 266 /* Set up N810 specific audio path audio_map */
224 for (i = 0; i < ARRAY_SIZE(audio_map); i++) 267 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
225 snd_soc_dapm_connect_input(codec, audio_map[i][0],
226 audio_map[i][1], audio_map[i][2]);
227 268
228 snd_soc_dapm_sync_endpoints(codec); 269 snd_soc_dapm_sync(codec);
229 270
230 return 0; 271 return 0;
231} 272}
@@ -250,6 +291,8 @@ static struct snd_soc_machine snd_soc_machine_n810 = {
250/* Audio private data */ 291/* Audio private data */
251static struct aic3x_setup_data n810_aic33_setup = { 292static struct aic3x_setup_data n810_aic33_setup = {
252 .i2c_address = 0x18, 293 .i2c_address = 0x18,
294 .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
295 .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
253}; 296};
254 297
255/* Audio subsystem */ 298/* Audio subsystem */
@@ -267,7 +310,7 @@ static int __init n810_soc_init(void)
267 int err; 310 int err;
268 struct device *dev; 311 struct device *dev;
269 312
270 if (!machine_is_nokia_n810()) 313 if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax()))
271 return -ENODEV; 314 return -ENODEV;
272 315
273 n810_snd_device = platform_device_alloc("soc-audio", -1); 316 n810_snd_device = platform_device_alloc("soc-audio", -1);
@@ -305,12 +348,12 @@ static int __init n810_soc_init(void)
305 clk_set_parent(sys_clkout2_src, func96m_clk); 348 clk_set_parent(sys_clkout2_src, func96m_clk);
306 clk_set_rate(sys_clkout2, 12000000); 349 clk_set_rate(sys_clkout2, 12000000);
307 350
308 if (omap_request_gpio(RX44_HEADSET_AMP_GPIO) < 0) 351 if (gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0)
309 BUG(); 352 BUG();
310 if (omap_request_gpio(RX44_SPEAKER_AMP_GPIO) < 0) 353 if (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0)
311 BUG(); 354 BUG();
312 omap_set_gpio_direction(RX44_HEADSET_AMP_GPIO, 0); 355 gpio_direction_output(N810_HEADSET_AMP_GPIO, 0);
313 omap_set_gpio_direction(RX44_SPEAKER_AMP_GPIO, 0); 356 gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0);
314 357
315 return 0; 358 return 0;
316err2: 359err2:
@@ -325,6 +368,9 @@ err1:
325 368
326static void __exit n810_soc_exit(void) 369static void __exit n810_soc_exit(void)
327{ 370{
371 gpio_free(N810_SPEAKER_AMP_GPIO);
372 gpio_free(N810_HEADSET_AMP_GPIO);
373
328 platform_device_unregister(n810_snd_device); 374 platform_device_unregister(n810_snd_device);
329} 375}
330 376
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 40d87e6d0de8..00b0c9d73cd4 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -103,7 +103,7 @@ static const unsigned long omap2420_mcbsp_port[][2] = {};
103static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream) 103static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
104{ 104{
105 struct snd_soc_pcm_runtime *rtd = substream->private_data; 105 struct snd_soc_pcm_runtime *rtd = substream->private_data;
106 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 106 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
107 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 107 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
108 int err = 0; 108 int err = 0;
109 109
@@ -116,7 +116,7 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
116static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream) 116static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream)
117{ 117{
118 struct snd_soc_pcm_runtime *rtd = substream->private_data; 118 struct snd_soc_pcm_runtime *rtd = substream->private_data;
119 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 119 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
120 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 120 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
121 121
122 if (!cpu_dai->active) { 122 if (!cpu_dai->active) {
@@ -128,7 +128,7 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream)
128static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd) 128static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd)
129{ 129{
130 struct snd_soc_pcm_runtime *rtd = substream->private_data; 130 struct snd_soc_pcm_runtime *rtd = substream->private_data;
131 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 131 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
132 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 132 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
133 int err = 0; 133 int err = 0;
134 134
@@ -157,7 +157,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
157 struct snd_pcm_hw_params *params) 157 struct snd_pcm_hw_params *params)
158{ 158{
159 struct snd_soc_pcm_runtime *rtd = substream->private_data; 159 struct snd_soc_pcm_runtime *rtd = substream->private_data;
160 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 160 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
161 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 161 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
162 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 162 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
163 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; 163 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
@@ -223,7 +223,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
223 * This must be called before _set_clkdiv and _set_sysclk since McBSP register 223 * This must be called before _set_clkdiv and _set_sysclk since McBSP register
224 * cache is initialized here 224 * cache is initialized here
225 */ 225 */
226static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai, 226static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
227 unsigned int fmt) 227 unsigned int fmt)
228{ 228{
229 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 229 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
@@ -292,7 +292,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
292 return 0; 292 return 0;
293} 293}
294 294
295static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai, 295static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
296 int div_id, int div) 296 int div_id, int div)
297{ 297{
298 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 298 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
@@ -347,7 +347,7 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
347 return 0; 347 return 0;
348} 348}
349 349
350static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, 350static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
351 int clk_id, unsigned int freq, 351 int clk_id, unsigned int freq,
352 int dir) 352 int dir)
353{ 353{
@@ -376,7 +376,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
376 return err; 376 return err;
377} 377}
378 378
379struct snd_soc_cpu_dai omap_mcbsp_dai[NUM_LINKS] = { 379struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS] = {
380{ 380{
381 .name = "omap-mcbsp-dai", 381 .name = "omap-mcbsp-dai",
382 .id = 0, 382 .id = 0,
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index 9965fd4b0427..ed8afb550671 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -44,6 +44,6 @@ enum omap_mcbsp_div {
44 */ 44 */
45#define NUM_LINKS 1 45#define NUM_LINKS 1
46 46
47extern struct snd_soc_cpu_dai omap_mcbsp_dai[NUM_LINKS]; 47extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS];
48 48
49#endif 49#endif
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 62370202c649..e092f3d836d0 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -316,7 +316,7 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm)
316 } 316 }
317} 317}
318 318
319int omap_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai, 319int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
320 struct snd_pcm *pcm) 320 struct snd_pcm *pcm)
321{ 321{
322 int ret = 0; 322 int ret = 0;
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 484f883459e0..12f6ac99b04c 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -1,6 +1,6 @@
1config SND_PXA2XX_SOC 1config SND_PXA2XX_SOC
2 tristate "SoC Audio for the Intel PXA2xx chip" 2 tristate "SoC Audio for the Intel PXA2xx chip"
3 depends on ARCH_PXA && SND_SOC 3 depends on ARCH_PXA
4 help 4 help
5 Say Y or M if you want to add support for codecs attached to 5 Say Y or M if you want to add support for codecs attached to
6 the PXA2xx AC97, I2S or SSP interface. You will also need 6 the PXA2xx AC97, I2S or SSP interface. You will also need
@@ -62,3 +62,12 @@ config SND_PXA2XX_SOC_E800
62 help 62 help
63 Say Y if you want to add support for SoC audio on the 63 Say Y if you want to add support for SoC audio on the
64 Toshiba e800 PDA 64 Toshiba e800 PDA
65
66config SND_PXA2XX_SOC_EM_X270
67 tristate "SoC Audio support for CompuLab EM-x270"
68 depends on SND_PXA2XX_SOC && MACH_EM_X270
69 select SND_PXA2XX_SOC_AC97
70 select SND_SOC_WM9712
71 help
72 Say Y if you want to add support for SoC audio on
73 CompuLab EM-x270.
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 04e5646f75ba..5bc8edf9dca9 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -13,10 +13,11 @@ snd-soc-poodle-objs := poodle.o
13snd-soc-tosa-objs := tosa.o 13snd-soc-tosa-objs := tosa.o
14snd-soc-e800-objs := e800_wm9712.o 14snd-soc-e800-objs := e800_wm9712.o
15snd-soc-spitz-objs := spitz.o 15snd-soc-spitz-objs := spitz.o
16snd-soc-em-x270-objs := em-x270.o
16 17
17obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o 18obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
18obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o 19obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
19obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o 20obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o
20obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o 21obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o
21obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o 22obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
22 23obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 7f32a1167572..c0294464a23a 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -11,10 +11,6 @@
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
12 * Free Software Foundation; either version 2 of the License, or (at your 12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version. 13 * option) any later version.
14 *
15 * Revision history
16 * 30th Nov 2005 Initial version.
17 *
18 */ 14 */
19 15
20#include <linux/module.h> 16#include <linux/module.h>
@@ -54,47 +50,51 @@ static int corgi_spk_func;
54 50
55static void corgi_ext_control(struct snd_soc_codec *codec) 51static void corgi_ext_control(struct snd_soc_codec *codec)
56{ 52{
57 int spk = 0, mic = 0, line = 0, hp = 0, hs = 0;
58
59 /* set up jack connection */ 53 /* set up jack connection */
60 switch (corgi_jack_func) { 54 switch (corgi_jack_func) {
61 case CORGI_HP: 55 case CORGI_HP:
62 hp = 1;
63 /* set = unmute headphone */ 56 /* set = unmute headphone */
64 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 57 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
65 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 58 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
59 snd_soc_dapm_disable_pin(codec, "Mic Jack");
60 snd_soc_dapm_disable_pin(codec, "Line Jack");
61 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
62 snd_soc_dapm_disable_pin(codec, "Headset Jack");
66 break; 63 break;
67 case CORGI_MIC: 64 case CORGI_MIC:
68 mic = 1;
69 /* reset = mute headphone */ 65 /* reset = mute headphone */
70 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 66 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
71 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 67 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
68 snd_soc_dapm_enable_pin(codec, "Mic Jack");
69 snd_soc_dapm_disable_pin(codec, "Line Jack");
70 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
71 snd_soc_dapm_disable_pin(codec, "Headset Jack");
72 break; 72 break;
73 case CORGI_LINE: 73 case CORGI_LINE:
74 line = 1;
75 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 74 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
76 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 75 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
76 snd_soc_dapm_disable_pin(codec, "Mic Jack");
77 snd_soc_dapm_enable_pin(codec, "Line Jack");
78 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
79 snd_soc_dapm_disable_pin(codec, "Headset Jack");
77 break; 80 break;
78 case CORGI_HEADSET: 81 case CORGI_HEADSET:
79 hs = 1;
80 mic = 1;
81 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 82 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
82 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 83 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
84 snd_soc_dapm_enable_pin(codec, "Mic Jack");
85 snd_soc_dapm_disable_pin(codec, "Line Jack");
86 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
87 snd_soc_dapm_enable_pin(codec, "Headset Jack");
83 break; 88 break;
84 } 89 }
85 90
86 if (corgi_spk_func == CORGI_SPK_ON) 91 if (corgi_spk_func == CORGI_SPK_ON)
87 spk = 1; 92 snd_soc_dapm_enable_pin(codec, "Ext Spk");
88 93 else
89 /* set the enpoints to their new connetion states */ 94 snd_soc_dapm_disable_pin(codec, "Ext Spk");
90 snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk);
91 snd_soc_dapm_set_endpoint(codec, "Mic Jack", mic);
92 snd_soc_dapm_set_endpoint(codec, "Line Jack", line);
93 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp);
94 snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs);
95 95
96 /* signal a DAPM event */ 96 /* signal a DAPM event */
97 snd_soc_dapm_sync_endpoints(codec); 97 snd_soc_dapm_sync(codec);
98} 98}
99 99
100static int corgi_startup(struct snd_pcm_substream *substream) 100static int corgi_startup(struct snd_pcm_substream *substream)
@@ -123,8 +123,8 @@ static int corgi_hw_params(struct snd_pcm_substream *substream,
123 struct snd_pcm_hw_params *params) 123 struct snd_pcm_hw_params *params)
124{ 124{
125 struct snd_soc_pcm_runtime *rtd = substream->private_data; 125 struct snd_soc_pcm_runtime *rtd = substream->private_data;
126 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 126 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
127 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 127 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
128 unsigned int clk = 0; 128 unsigned int clk = 0;
129 int ret = 0; 129 int ret = 0;
130 130
@@ -143,25 +143,25 @@ static int corgi_hw_params(struct snd_pcm_substream *substream,
143 } 143 }
144 144
145 /* set codec DAI configuration */ 145 /* set codec DAI configuration */
146 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 146 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
147 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 147 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
148 if (ret < 0) 148 if (ret < 0)
149 return ret; 149 return ret;
150 150
151 /* set cpu DAI configuration */ 151 /* set cpu DAI configuration */
152 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 152 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
153 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 153 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
154 if (ret < 0) 154 if (ret < 0)
155 return ret; 155 return ret;
156 156
157 /* set the codec system clock for DAC and ADC */ 157 /* set the codec system clock for DAC and ADC */
158 ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK, clk, 158 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk,
159 SND_SOC_CLOCK_IN); 159 SND_SOC_CLOCK_IN);
160 if (ret < 0) 160 if (ret < 0)
161 return ret; 161 return ret;
162 162
163 /* set the I2S system clock as input (unused) */ 163 /* set the I2S system clock as input (unused) */
164 ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0, 164 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
165 SND_SOC_CLOCK_IN); 165 SND_SOC_CLOCK_IN);
166 if (ret < 0) 166 if (ret < 0)
167 return ret; 167 return ret;
@@ -247,7 +247,7 @@ SND_SOC_DAPM_HP("Headset Jack", NULL),
247}; 247};
248 248
249/* Corgi machine audio map (connections to the codec pins) */ 249/* Corgi machine audio map (connections to the codec pins) */
250static const char *audio_map[][3] = { 250static const struct snd_soc_dapm_route audio_map[] = {
251 251
252 /* headset Jack - in = micin, out = LHPOUT*/ 252 /* headset Jack - in = micin, out = LHPOUT*/
253 {"Headset Jack", NULL, "LHPOUT"}, 253 {"Headset Jack", NULL, "LHPOUT"},
@@ -265,8 +265,6 @@ static const char *audio_map[][3] = {
265 265
266 /* Same as the above but no mic bias for line signals */ 266 /* Same as the above but no mic bias for line signals */
267 {"MICIN", NULL, "Line Jack"}, 267 {"MICIN", NULL, "Line Jack"},
268
269 {NULL, NULL, NULL},
270}; 268};
271 269
272static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", 270static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
@@ -291,8 +289,8 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
291{ 289{
292 int i, err; 290 int i, err;
293 291
294 snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0); 292 snd_soc_dapm_disable_pin(codec, "LLINEIN");
295 snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0); 293 snd_soc_dapm_disable_pin(codec, "RLINEIN");
296 294
297 /* Add corgi specific controls */ 295 /* Add corgi specific controls */
298 for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) { 296 for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
@@ -303,15 +301,13 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
303 } 301 }
304 302
305 /* Add corgi specific widgets */ 303 /* Add corgi specific widgets */
306 for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) 304 snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
307 snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]); 305 ARRAY_SIZE(wm8731_dapm_widgets));
308 306
309 /* Set up corgi specific audio path audio_map */ 307 /* Set up corgi specific audio path audio_map */
310 for (i = 0; audio_map[i][0] != NULL; i++) 308 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
311 snd_soc_dapm_connect_input(codec, audio_map[i][0],
312 audio_map[i][1], audio_map[i][2]);
313 309
314 snd_soc_dapm_sync_endpoints(codec); 310 snd_soc_dapm_sync(codec);
315 return 0; 311 return 0;
316} 312}
317 313
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c
new file mode 100644
index 000000000000..02dcac39cdf6
--- /dev/null
+++ b/sound/soc/pxa/em-x270.c
@@ -0,0 +1,102 @@
1/*
2 * em-x270.c -- SoC audio for EM-X270
3 *
4 * Copyright 2007 CompuLab, Ltd.
5 *
6 * Author: Mike Rapoport <mike@compulab.co.il>
7 *
8 * Copied from tosa.c:
9 * Copyright 2005 Wolfson Microelectronics PLC.
10 * Copyright 2005 Openedhand Ltd.
11 *
12 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
13 * Richard Purdie <richard@openedhand.com>
14 *
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 2 of the License, or (at your
18 * option) any later version.
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/moduleparam.h>
24#include <linux/device.h>
25
26#include <sound/driver.h>
27#include <sound/core.h>
28#include <sound/pcm.h>
29#include <sound/soc.h>
30#include <sound/soc-dapm.h>
31
32#include <asm/mach-types.h>
33#include <asm/arch/pxa-regs.h>
34#include <asm/arch/hardware.h>
35#include <asm/arch/audio.h>
36
37#include "../codecs/wm9712.h"
38#include "pxa2xx-pcm.h"
39#include "pxa2xx-ac97.h"
40
41static struct snd_soc_dai_link em_x270_dai[] = {
42 {
43 .name = "AC97",
44 .stream_name = "AC97 HiFi",
45 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
46 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
47 },
48 {
49 .name = "AC97 Aux",
50 .stream_name = "AC97 Aux",
51 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
52 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
53 },
54};
55
56static struct snd_soc_machine em_x270 = {
57 .name = "EM-X270",
58 .dai_link = em_x270_dai,
59 .num_links = ARRAY_SIZE(em_x270_dai),
60};
61
62static struct snd_soc_device em_x270_snd_devdata = {
63 .machine = &em_x270,
64 .platform = &pxa2xx_soc_platform,
65 .codec_dev = &soc_codec_dev_wm9712,
66};
67
68static struct platform_device *em_x270_snd_device;
69
70static int __init em_x270_init(void)
71{
72 int ret;
73
74 if (!machine_is_em_x270())
75 return -ENODEV;
76
77 em_x270_snd_device = platform_device_alloc("soc-audio", -1);
78 if (!em_x270_snd_device)
79 return -ENOMEM;
80
81 platform_set_drvdata(em_x270_snd_device, &em_x270_snd_devdata);
82 em_x270_snd_devdata.dev = &em_x270_snd_device->dev;
83 ret = platform_device_add(em_x270_snd_device);
84
85 if (ret)
86 platform_device_put(em_x270_snd_device);
87
88 return ret;
89}
90
91static void __exit em_x270_exit(void)
92{
93 platform_device_unregister(em_x270_snd_device);
94}
95
96module_init(em_x270_init);
97module_exit(em_x270_exit);
98
99/* Module information */
100MODULE_AUTHOR("Mike Rapoport");
101MODULE_DESCRIPTION("ALSA SoC EM-X270");
102MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index 7e830b218943..65a4e9a8c39e 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -48,8 +48,6 @@ static int poodle_spk_func;
48 48
49static void poodle_ext_control(struct snd_soc_codec *codec) 49static void poodle_ext_control(struct snd_soc_codec *codec)
50{ 50{
51 int spk = 0;
52
53 /* set up jack connection */ 51 /* set up jack connection */
54 if (poodle_jack_func == POODLE_HP) { 52 if (poodle_jack_func == POODLE_HP) {
55 /* set = unmute headphone */ 53 /* set = unmute headphone */
@@ -57,23 +55,23 @@ static void poodle_ext_control(struct snd_soc_codec *codec)
57 POODLE_LOCOMO_GPIO_MUTE_L, 1); 55 POODLE_LOCOMO_GPIO_MUTE_L, 1);
58 locomo_gpio_write(&poodle_locomo_device.dev, 56 locomo_gpio_write(&poodle_locomo_device.dev,
59 POODLE_LOCOMO_GPIO_MUTE_R, 1); 57 POODLE_LOCOMO_GPIO_MUTE_R, 1);
60 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1); 58 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
61 } else { 59 } else {
62 locomo_gpio_write(&poodle_locomo_device.dev, 60 locomo_gpio_write(&poodle_locomo_device.dev,
63 POODLE_LOCOMO_GPIO_MUTE_L, 0); 61 POODLE_LOCOMO_GPIO_MUTE_L, 0);
64 locomo_gpio_write(&poodle_locomo_device.dev, 62 locomo_gpio_write(&poodle_locomo_device.dev,
65 POODLE_LOCOMO_GPIO_MUTE_R, 0); 63 POODLE_LOCOMO_GPIO_MUTE_R, 0);
66 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0); 64 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
67 } 65 }
68 66
69 if (poodle_spk_func == POODLE_SPK_ON)
70 spk = 1;
71
72 /* set the enpoints to their new connetion states */ 67 /* set the enpoints to their new connetion states */
73 snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk); 68 if (poodle_spk_func == POODLE_SPK_ON)
69 snd_soc_dapm_enable_pin(codec, "Ext Spk");
70 else
71 snd_soc_dapm_disable_pin(codec, "Ext Spk");
74 72
75 /* signal a DAPM event */ 73 /* signal a DAPM event */
76 snd_soc_dapm_sync_endpoints(codec); 74 snd_soc_dapm_sync(codec);
77} 75}
78 76
79static int poodle_startup(struct snd_pcm_substream *substream) 77static int poodle_startup(struct snd_pcm_substream *substream)
@@ -104,8 +102,8 @@ static int poodle_hw_params(struct snd_pcm_substream *substream,
104 struct snd_pcm_hw_params *params) 102 struct snd_pcm_hw_params *params)
105{ 103{
106 struct snd_soc_pcm_runtime *rtd = substream->private_data; 104 struct snd_soc_pcm_runtime *rtd = substream->private_data;
107 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 105 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
108 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 106 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
109 unsigned int clk = 0; 107 unsigned int clk = 0;
110 int ret = 0; 108 int ret = 0;
111 109
@@ -124,25 +122,25 @@ static int poodle_hw_params(struct snd_pcm_substream *substream,
124 } 122 }
125 123
126 /* set codec DAI configuration */ 124 /* set codec DAI configuration */
127 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 125 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
128 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 126 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
129 if (ret < 0) 127 if (ret < 0)
130 return ret; 128 return ret;
131 129
132 /* set cpu DAI configuration */ 130 /* set cpu DAI configuration */
133 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 131 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
134 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 132 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
135 if (ret < 0) 133 if (ret < 0)
136 return ret; 134 return ret;
137 135
138 /* set the codec system clock for DAC and ADC */ 136 /* set the codec system clock for DAC and ADC */
139 ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK, clk, 137 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk,
140 SND_SOC_CLOCK_IN); 138 SND_SOC_CLOCK_IN);
141 if (ret < 0) 139 if (ret < 0)
142 return ret; 140 return ret;
143 141
144 /* set the I2S system clock as input (unused) */ 142 /* set the I2S system clock as input (unused) */
145 ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0, 143 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
146 SND_SOC_CLOCK_IN); 144 SND_SOC_CLOCK_IN);
147 if (ret < 0) 145 if (ret < 0)
148 return ret; 146 return ret;
@@ -215,8 +213,8 @@ SND_SOC_DAPM_HP("Headphone Jack", NULL),
215SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event), 213SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event),
216}; 214};
217 215
218/* Corgi machine audio_mapnections to the codec pins */ 216/* Corgi machine connections to the codec pins */
219static const char *audio_map[][3] = { 217static const struct snd_soc_dapm_route audio_map[] = {
220 218
221 /* headphone connected to LHPOUT1, RHPOUT1 */ 219 /* headphone connected to LHPOUT1, RHPOUT1 */
222 {"Headphone Jack", NULL, "LHPOUT"}, 220 {"Headphone Jack", NULL, "LHPOUT"},
@@ -225,8 +223,6 @@ static const char *audio_map[][3] = {
225 /* speaker connected to LOUT, ROUT */ 223 /* speaker connected to LOUT, ROUT */
226 {"Ext Spk", NULL, "ROUT"}, 224 {"Ext Spk", NULL, "ROUT"},
227 {"Ext Spk", NULL, "LOUT"}, 225 {"Ext Spk", NULL, "LOUT"},
228
229 {NULL, NULL, NULL},
230}; 226};
231 227
232static const char *jack_function[] = {"Off", "Headphone"}; 228static const char *jack_function[] = {"Off", "Headphone"};
@@ -250,9 +246,9 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
250{ 246{
251 int i, err; 247 int i, err;
252 248
253 snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0); 249 snd_soc_dapm_disable_pin(codec, "LLINEIN");
254 snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0); 250 snd_soc_dapm_disable_pin(codec, "RLINEIN");
255 snd_soc_dapm_set_endpoint(codec, "MICIN", 1); 251 snd_soc_dapm_enable_pin(codec, "MICIN");
256 252
257 /* Add poodle specific controls */ 253 /* Add poodle specific controls */
258 for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) { 254 for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) {
@@ -263,15 +259,13 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
263 } 259 }
264 260
265 /* Add poodle specific widgets */ 261 /* Add poodle specific widgets */
266 for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) 262 snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
267 snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]); 263 ARRAY_SIZE(wm8731_dapm_widgets));
268 264
269 /* Set up poodle specific audio path audio_map */ 265 /* Set up poodle specific audio path audio_map */
270 for (i = 0; audio_map[i][0] != NULL; i++) 266 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
271 snd_soc_dapm_connect_input(codec, audio_map[i][0],
272 audio_map[i][1], audio_map[i][2]);
273 267
274 snd_soc_dapm_sync_endpoints(codec); 268 snd_soc_dapm_sync(codec);
275 return 0; 269 return 0;
276} 270}
277 271
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 97ec2d90547c..059af815ea0c 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -283,7 +283,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
283 283
284#ifdef CONFIG_PM 284#ifdef CONFIG_PM
285static int pxa2xx_ac97_suspend(struct platform_device *pdev, 285static int pxa2xx_ac97_suspend(struct platform_device *pdev,
286 struct snd_soc_cpu_dai *dai) 286 struct snd_soc_dai *dai)
287{ 287{
288 GCR |= GCR_ACLINK_OFF; 288 GCR |= GCR_ACLINK_OFF;
289 clk_disable(ac97_clk); 289 clk_disable(ac97_clk);
@@ -291,7 +291,7 @@ static int pxa2xx_ac97_suspend(struct platform_device *pdev,
291} 291}
292 292
293static int pxa2xx_ac97_resume(struct platform_device *pdev, 293static int pxa2xx_ac97_resume(struct platform_device *pdev,
294 struct snd_soc_cpu_dai *dai) 294 struct snd_soc_dai *dai)
295{ 295{
296 pxa_gpio_mode(GPIO31_SYNC_AC97_MD); 296 pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
297 pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); 297 pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
@@ -310,7 +310,8 @@ static int pxa2xx_ac97_resume(struct platform_device *pdev,
310#define pxa2xx_ac97_resume NULL 310#define pxa2xx_ac97_resume NULL
311#endif 311#endif
312 312
313static int pxa2xx_ac97_probe(struct platform_device *pdev) 313static int pxa2xx_ac97_probe(struct platform_device *pdev,
314 struct snd_soc_dai *dai)
314{ 315{
315 int ret; 316 int ret;
316 317
@@ -355,7 +356,8 @@ static int pxa2xx_ac97_probe(struct platform_device *pdev)
355 return ret; 356 return ret;
356} 357}
357 358
358static void pxa2xx_ac97_remove(struct platform_device *pdev) 359static void pxa2xx_ac97_remove(struct platform_device *pdev,
360 struct snd_soc_dai *dai)
359{ 361{
360 GCR |= GCR_ACLINK_OFF; 362 GCR |= GCR_ACLINK_OFF;
361 free_irq(IRQ_AC97, NULL); 363 free_irq(IRQ_AC97, NULL);
@@ -372,7 +374,7 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
372 struct snd_pcm_hw_params *params) 374 struct snd_pcm_hw_params *params)
373{ 375{
374 struct snd_soc_pcm_runtime *rtd = substream->private_data; 376 struct snd_soc_pcm_runtime *rtd = substream->private_data;
375 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 377 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
376 378
377 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 379 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
378 cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out; 380 cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out;
@@ -386,7 +388,7 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
386 struct snd_pcm_hw_params *params) 388 struct snd_pcm_hw_params *params)
387{ 389{
388 struct snd_soc_pcm_runtime *rtd = substream->private_data; 390 struct snd_soc_pcm_runtime *rtd = substream->private_data;
389 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 391 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
390 392
391 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 393 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
392 cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out; 394 cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
@@ -400,7 +402,7 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
400 struct snd_pcm_hw_params *params) 402 struct snd_pcm_hw_params *params)
401{ 403{
402 struct snd_soc_pcm_runtime *rtd = substream->private_data; 404 struct snd_soc_pcm_runtime *rtd = substream->private_data;
403 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 405 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
404 406
405 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 407 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
406 return -ENODEV; 408 return -ENODEV;
@@ -418,7 +420,7 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
418 * There is only 1 physical AC97 interface for pxa2xx, but it 420 * There is only 1 physical AC97 interface for pxa2xx, but it
419 * has extra fifo's that can be used for aux DACs and ADCs. 421 * has extra fifo's that can be used for aux DACs and ADCs.
420 */ 422 */
421struct snd_soc_cpu_dai pxa_ac97_dai[] = { 423struct snd_soc_dai pxa_ac97_dai[] = {
422{ 424{
423 .name = "pxa2xx-ac97", 425 .name = "pxa2xx-ac97",
424 .id = 0, 426 .id = 0,
diff --git a/sound/soc/pxa/pxa2xx-ac97.h b/sound/soc/pxa/pxa2xx-ac97.h
index b8ccfee095c4..e390de8edcd4 100644
--- a/sound/soc/pxa/pxa2xx-ac97.h
+++ b/sound/soc/pxa/pxa2xx-ac97.h
@@ -14,7 +14,7 @@
14#define PXA2XX_DAI_AC97_AUX 1 14#define PXA2XX_DAI_AC97_AUX 1
15#define PXA2XX_DAI_AC97_MIC 2 15#define PXA2XX_DAI_AC97_MIC 2
16 16
17extern struct snd_soc_cpu_dai pxa_ac97_dai[3]; 17extern struct snd_soc_dai pxa_ac97_dai[3];
18 18
19/* platform data */ 19/* platform data */
20extern struct snd_ac97_bus_ops pxa2xx_ac97_ops; 20extern struct snd_ac97_bus_ops pxa2xx_ac97_ops;
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 425071030970..9c06553b9267 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -9,9 +9,6 @@
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
10 * Free Software Foundation; either version 2 of the License, or (at your 10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
12 *
13 * Revision history
14 * 12th Aug 2005 Initial version.
15 */ 12 */
16 13
17#include <linux/init.h> 14#include <linux/init.h>
@@ -80,7 +77,7 @@ static struct pxa2xx_gpio gpio_bus[] = {
80static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream) 77static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream)
81{ 78{
82 struct snd_soc_pcm_runtime *rtd = substream->private_data; 79 struct snd_soc_pcm_runtime *rtd = substream->private_data;
83 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 80 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
84 81
85 if (!cpu_dai->active) { 82 if (!cpu_dai->active) {
86 SACR0 |= SACR0_RST; 83 SACR0 |= SACR0_RST;
@@ -101,7 +98,7 @@ static int pxa_i2s_wait(void)
101 return 0; 98 return 0;
102} 99}
103 100
104static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai, 101static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
105 unsigned int fmt) 102 unsigned int fmt)
106{ 103{
107 /* interface format */ 104 /* interface format */
@@ -127,7 +124,7 @@ static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
127 return 0; 124 return 0;
128} 125}
129 126
130static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, 127static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
131 int clk_id, unsigned int freq, int dir) 128 int clk_id, unsigned int freq, int dir)
132{ 129{
133 if (clk_id != PXA2XX_I2S_SYSCLK) 130 if (clk_id != PXA2XX_I2S_SYSCLK)
@@ -143,7 +140,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
143 struct snd_pcm_hw_params *params) 140 struct snd_pcm_hw_params *params)
144{ 141{
145 struct snd_soc_pcm_runtime *rtd = substream->private_data; 142 struct snd_soc_pcm_runtime *rtd = substream->private_data;
146 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 143 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
147 144
148 pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx); 145 pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx);
149 pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx); 146 pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
@@ -240,7 +237,7 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
240 237
241#ifdef CONFIG_PM 238#ifdef CONFIG_PM
242static int pxa2xx_i2s_suspend(struct platform_device *dev, 239static int pxa2xx_i2s_suspend(struct platform_device *dev,
243 struct snd_soc_cpu_dai *dai) 240 struct snd_soc_dai *dai)
244{ 241{
245 if (!dai->active) 242 if (!dai->active)
246 return 0; 243 return 0;
@@ -258,7 +255,7 @@ static int pxa2xx_i2s_suspend(struct platform_device *dev,
258} 255}
259 256
260static int pxa2xx_i2s_resume(struct platform_device *pdev, 257static int pxa2xx_i2s_resume(struct platform_device *pdev,
261 struct snd_soc_cpu_dai *dai) 258 struct snd_soc_dai *dai)
262{ 259{
263 if (!dai->active) 260 if (!dai->active)
264 return 0; 261 return 0;
@@ -283,7 +280,7 @@ static int pxa2xx_i2s_resume(struct platform_device *pdev,
283 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ 280 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
284 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) 281 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
285 282
286struct snd_soc_cpu_dai pxa_i2s_dai = { 283struct snd_soc_dai pxa_i2s_dai = {
287 .name = "pxa2xx-i2s", 284 .name = "pxa2xx-i2s",
288 .id = 0, 285 .id = 0,
289 .type = SND_SOC_DAI_I2S, 286 .type = SND_SOC_DAI_I2S,
diff --git a/sound/soc/pxa/pxa2xx-i2s.h b/sound/soc/pxa/pxa2xx-i2s.h
index 4435bd9f884f..e2def441153e 100644
--- a/sound/soc/pxa/pxa2xx-i2s.h
+++ b/sound/soc/pxa/pxa2xx-i2s.h
@@ -15,6 +15,6 @@
15/* I2S clock */ 15/* I2S clock */
16#define PXA2XX_I2S_SYSCLK 0 16#define PXA2XX_I2S_SYSCLK 0
17 17
18extern struct snd_soc_cpu_dai pxa_i2s_dai; 18extern struct snd_soc_dai pxa_i2s_dai;
19 19
20#endif 20#endif
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 01ad7bf716b7..2df03ee5819e 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -330,7 +330,7 @@ static void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
330 330
331static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK; 331static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK;
332 332
333int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai, 333int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
334 struct snd_pcm *pcm) 334 struct snd_pcm *pcm)
335{ 335{
336 int ret = 0; 336 int ret = 0;
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index d8b8372db00e..64385797da5d 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -12,9 +12,6 @@
12 * Free Software Foundation; either version 2 of the License, or (at your 12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version. 13 * option) any later version.
14 * 14 *
15 * Revision history
16 * 30th Nov 2005 Initial version.
17 *
18 */ 15 */
19 16
20#include <linux/module.h> 17#include <linux/module.h>
@@ -54,60 +51,60 @@ static int spitz_spk_func;
54static void spitz_ext_control(struct snd_soc_codec *codec) 51static void spitz_ext_control(struct snd_soc_codec *codec)
55{ 52{
56 if (spitz_spk_func == SPITZ_SPK_ON) 53 if (spitz_spk_func == SPITZ_SPK_ON)
57 snd_soc_dapm_set_endpoint(codec, "Ext Spk", 1); 54 snd_soc_dapm_enable_pin(codec, "Ext Spk");
58 else 55 else
59 snd_soc_dapm_set_endpoint(codec, "Ext Spk", 0); 56 snd_soc_dapm_disable_pin(codec, "Ext Spk");
60 57
61 /* set up jack connection */ 58 /* set up jack connection */
62 switch (spitz_jack_func) { 59 switch (spitz_jack_func) {
63 case SPITZ_HP: 60 case SPITZ_HP:
64 /* enable and unmute hp jack, disable mic bias */ 61 /* enable and unmute hp jack, disable mic bias */
65 snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0); 62 snd_soc_dapm_disable_pin(codec, "Headset Jack");
66 snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0); 63 snd_soc_dapm_disable_pin(codec, "Mic Jack");
67 snd_soc_dapm_set_endpoint(codec, "Line Jack", 0); 64 snd_soc_dapm_disable_pin(codec, "Line Jack");
68 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1); 65 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
69 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 66 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
70 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 67 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
71 break; 68 break;
72 case SPITZ_MIC: 69 case SPITZ_MIC:
73 /* enable mic jack and bias, mute hp */ 70 /* enable mic jack and bias, mute hp */
74 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0); 71 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
75 snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0); 72 snd_soc_dapm_disable_pin(codec, "Headset Jack");
76 snd_soc_dapm_set_endpoint(codec, "Line Jack", 0); 73 snd_soc_dapm_disable_pin(codec, "Line Jack");
77 snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1); 74 snd_soc_dapm_enable_pin(codec, "Mic Jack");
78 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 75 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
79 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 76 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
80 break; 77 break;
81 case SPITZ_LINE: 78 case SPITZ_LINE:
82 /* enable line jack, disable mic bias and mute hp */ 79 /* enable line jack, disable mic bias and mute hp */
83 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0); 80 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
84 snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0); 81 snd_soc_dapm_disable_pin(codec, "Headset Jack");
85 snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0); 82 snd_soc_dapm_disable_pin(codec, "Mic Jack");
86 snd_soc_dapm_set_endpoint(codec, "Line Jack", 1); 83 snd_soc_dapm_enable_pin(codec, "Line Jack");
87 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 84 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
88 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 85 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
89 break; 86 break;
90 case SPITZ_HEADSET: 87 case SPITZ_HEADSET:
91 /* enable and unmute headset jack enable mic bias, mute L hp */ 88 /* enable and unmute headset jack enable mic bias, mute L hp */
92 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0); 89 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
93 snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1); 90 snd_soc_dapm_enable_pin(codec, "Mic Jack");
94 snd_soc_dapm_set_endpoint(codec, "Line Jack", 0); 91 snd_soc_dapm_disable_pin(codec, "Line Jack");
95 snd_soc_dapm_set_endpoint(codec, "Headset Jack", 1); 92 snd_soc_dapm_enable_pin(codec, "Headset Jack");
96 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 93 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
97 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 94 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
98 break; 95 break;
99 case SPITZ_HP_OFF: 96 case SPITZ_HP_OFF:
100 97
101 /* jack removed, everything off */ 98 /* jack removed, everything off */
102 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0); 99 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
103 snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0); 100 snd_soc_dapm_disable_pin(codec, "Headset Jack");
104 snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0); 101 snd_soc_dapm_disable_pin(codec, "Mic Jack");
105 snd_soc_dapm_set_endpoint(codec, "Line Jack", 0); 102 snd_soc_dapm_disable_pin(codec, "Line Jack");
106 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 103 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
107 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 104 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
108 break; 105 break;
109 } 106 }
110 snd_soc_dapm_sync_endpoints(codec); 107 snd_soc_dapm_sync(codec);
111} 108}
112 109
113static int spitz_startup(struct snd_pcm_substream *substream) 110static int spitz_startup(struct snd_pcm_substream *substream)
@@ -124,8 +121,8 @@ static int spitz_hw_params(struct snd_pcm_substream *substream,
124 struct snd_pcm_hw_params *params) 121 struct snd_pcm_hw_params *params)
125{ 122{
126 struct snd_soc_pcm_runtime *rtd = substream->private_data; 123 struct snd_soc_pcm_runtime *rtd = substream->private_data;
127 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 124 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
128 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 125 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
129 unsigned int clk = 0; 126 unsigned int clk = 0;
130 int ret = 0; 127 int ret = 0;
131 128
@@ -144,25 +141,25 @@ static int spitz_hw_params(struct snd_pcm_substream *substream,
144 } 141 }
145 142
146 /* set codec DAI configuration */ 143 /* set codec DAI configuration */
147 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 144 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
148 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 145 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
149 if (ret < 0) 146 if (ret < 0)
150 return ret; 147 return ret;
151 148
152 /* set cpu DAI configuration */ 149 /* set cpu DAI configuration */
153 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 150 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
154 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 151 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
155 if (ret < 0) 152 if (ret < 0)
156 return ret; 153 return ret;
157 154
158 /* set the codec system clock for DAC and ADC */ 155 /* set the codec system clock for DAC and ADC */
159 ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8750_SYSCLK, clk, 156 ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
160 SND_SOC_CLOCK_IN); 157 SND_SOC_CLOCK_IN);
161 if (ret < 0) 158 if (ret < 0)
162 return ret; 159 return ret;
163 160
164 /* set the I2S system clock as input (unused) */ 161 /* set the I2S system clock as input (unused) */
165 ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0, 162 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
166 SND_SOC_CLOCK_IN); 163 SND_SOC_CLOCK_IN);
167 if (ret < 0) 164 if (ret < 0)
168 return ret; 165 return ret;
@@ -250,7 +247,7 @@ static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
250}; 247};
251 248
252/* Spitz machine audio_map */ 249/* Spitz machine audio_map */
253static const char *audio_map[][3] = { 250static const struct snd_soc_dapm_route audio_map[] = {
254 251
255 /* headphone connected to LOUT1, ROUT1 */ 252 /* headphone connected to LOUT1, ROUT1 */
256 {"Headphone Jack", NULL, "LOUT1"}, 253 {"Headphone Jack", NULL, "LOUT1"},
@@ -269,8 +266,6 @@ static const char *audio_map[][3] = {
269 266
270 /* line is connected to input 1 - no bias */ 267 /* line is connected to input 1 - no bias */
271 {"LINPUT1", NULL, "Line Jack"}, 268 {"LINPUT1", NULL, "Line Jack"},
272
273 {NULL, NULL, NULL},
274}; 269};
275 270
276static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", 271static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
@@ -296,13 +291,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
296 int i, err; 291 int i, err;
297 292
298 /* NC codec pins */ 293 /* NC codec pins */
299 snd_soc_dapm_set_endpoint(codec, "RINPUT1", 0); 294 snd_soc_dapm_disable_pin(codec, "RINPUT1");
300 snd_soc_dapm_set_endpoint(codec, "LINPUT2", 0); 295 snd_soc_dapm_disable_pin(codec, "LINPUT2");
301 snd_soc_dapm_set_endpoint(codec, "RINPUT2", 0); 296 snd_soc_dapm_disable_pin(codec, "RINPUT2");
302 snd_soc_dapm_set_endpoint(codec, "LINPUT3", 0); 297 snd_soc_dapm_disable_pin(codec, "LINPUT3");
303 snd_soc_dapm_set_endpoint(codec, "RINPUT3", 0); 298 snd_soc_dapm_disable_pin(codec, "RINPUT3");
304 snd_soc_dapm_set_endpoint(codec, "OUT3", 0); 299 snd_soc_dapm_disable_pin(codec, "OUT3");
305 snd_soc_dapm_set_endpoint(codec, "MONO", 0); 300 snd_soc_dapm_disable_pin(codec, "MONO");
306 301
307 /* Add spitz specific controls */ 302 /* Add spitz specific controls */
308 for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) { 303 for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
@@ -313,15 +308,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
313 } 308 }
314 309
315 /* Add spitz specific widgets */ 310 /* Add spitz specific widgets */
316 for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) 311 snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets,
317 snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]); 312 ARRAY_SIZE(wm8750_dapm_widgets));
318 313
319 /* Set up spitz specific audio path audio_map */ 314 /* Set up spitz specific audio paths */
320 for (i = 0; audio_map[i][0] != NULL; i++) 315 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
321 snd_soc_dapm_connect_input(codec, audio_map[i][0],
322 audio_map[i][1], audio_map[i][2]);
323 316
324 snd_soc_dapm_sync_endpoints(codec); 317 snd_soc_dapm_sync(codec);
325 return 0; 318 return 0;
326} 319}
327 320
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index 7346d7e5d066..b6edb61a3a30 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -12,9 +12,6 @@
12 * Free Software Foundation; either version 2 of the License, or (at your 12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version. 13 * option) any later version.
14 * 14 *
15 * Revision history
16 * 30th Nov 2005 Initial version.
17 *
18 * GPIO's 15 * GPIO's
19 * 1 - Jack Insertion 16 * 1 - Jack Insertion
20 * 5 - Hookswitch (headset answer/hang up switch) 17 * 5 - Hookswitch (headset answer/hang up switch)
@@ -55,29 +52,31 @@ static int tosa_spk_func;
55 52
56static void tosa_ext_control(struct snd_soc_codec *codec) 53static void tosa_ext_control(struct snd_soc_codec *codec)
57{ 54{
58 int spk = 0, mic_int = 0, hp = 0, hs = 0;
59
60 /* set up jack connection */ 55 /* set up jack connection */
61 switch (tosa_jack_func) { 56 switch (tosa_jack_func) {
62 case TOSA_HP: 57 case TOSA_HP:
63 hp = 1; 58 snd_soc_dapm_disable_pin(codec, "Mic (Internal)");
59 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
60 snd_soc_dapm_disable_pin(codec, "Headset Jack");
64 break; 61 break;
65 case TOSA_MIC_INT: 62 case TOSA_MIC_INT:
66 mic_int = 1; 63 snd_soc_dapm_enable_pin(codec, "Mic (Internal)");
64 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
65 snd_soc_dapm_disable_pin(codec, "Headset Jack");
67 break; 66 break;
68 case TOSA_HEADSET: 67 case TOSA_HEADSET:
69 hs = 1; 68 snd_soc_dapm_disable_pin(codec, "Mic (Internal)");
69 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
70 snd_soc_dapm_enable_pin(codec, "Headset Jack");
70 break; 71 break;
71 } 72 }
72 73
73 if (tosa_spk_func == TOSA_SPK_ON) 74 if (tosa_spk_func == TOSA_SPK_ON)
74 spk = 1; 75 snd_soc_dapm_enable_pin(codec, "Speaker");
76 else
77 snd_soc_dapm_disable_pin(codec, "Speaker");
75 78
76 snd_soc_dapm_set_endpoint(codec, "Speaker", spk); 79 snd_soc_dapm_sync(codec);
77 snd_soc_dapm_set_endpoint(codec, "Mic (Internal)", mic_int);
78 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp);
79 snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs);
80 snd_soc_dapm_sync_endpoints(codec);
81} 80}
82 81
83static int tosa_startup(struct snd_pcm_substream *substream) 82static int tosa_startup(struct snd_pcm_substream *substream)
@@ -154,7 +153,7 @@ SND_SOC_DAPM_SPK("Speaker", NULL),
154}; 153};
155 154
156/* tosa audio map */ 155/* tosa audio map */
157static const char *audio_map[][3] = { 156static const struct snd_soc_dapm_route audio_map[] = {
158 157
159 /* headphone connected to HPOUTL, HPOUTR */ 158 /* headphone connected to HPOUTL, HPOUTR */
160 {"Headphone Jack", NULL, "HPOUTL"}, 159 {"Headphone Jack", NULL, "HPOUTL"},
@@ -173,8 +172,6 @@ static const char *audio_map[][3] = {
173 {"Headset Jack", NULL, "HPOUTR"}, 172 {"Headset Jack", NULL, "HPOUTR"},
174 {"LINEINR", NULL, "Mic Bias"}, 173 {"LINEINR", NULL, "Mic Bias"},
175 {"Mic Bias", NULL, "Headset Jack"}, 174 {"Mic Bias", NULL, "Headset Jack"},
176
177 {NULL, NULL, NULL},
178}; 175};
179 176
180static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", 177static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
@@ -196,8 +193,8 @@ static int tosa_ac97_init(struct snd_soc_codec *codec)
196{ 193{
197 int i, err; 194 int i, err;
198 195
199 snd_soc_dapm_set_endpoint(codec, "OUT3", 0); 196 snd_soc_dapm_disable_pin(codec, "OUT3");
200 snd_soc_dapm_set_endpoint(codec, "MONOOUT", 0); 197 snd_soc_dapm_disable_pin(codec, "MONOOUT");
201 198
202 /* add tosa specific controls */ 199 /* add tosa specific controls */
203 for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) { 200 for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) {
@@ -208,17 +205,13 @@ static int tosa_ac97_init(struct snd_soc_codec *codec)
208 } 205 }
209 206
210 /* add tosa specific widgets */ 207 /* add tosa specific widgets */
211 for (i = 0; i < ARRAY_SIZE(tosa_dapm_widgets); i++) { 208 snd_soc_dapm_new_controls(codec, tosa_dapm_widgets,
212 snd_soc_dapm_new_control(codec, &tosa_dapm_widgets[i]); 209 ARRAY_SIZE(tosa_dapm_widgets));
213 }
214 210
215 /* set up tosa specific audio path audio_map */ 211 /* set up tosa specific audio path audio_map */
216 for (i = 0; audio_map[i][0] != NULL; i++) { 212 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
217 snd_soc_dapm_connect_input(codec, audio_map[i][0],
218 audio_map[i][1], audio_map[i][2]);
219 }
220 213
221 snd_soc_dapm_sync_endpoints(codec); 214 snd_soc_dapm_sync(codec);
222 return 0; 215 return 0;
223} 216}
224 217
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index 1f6dbfc4caa8..b9f2353effeb 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -1,7 +1,6 @@
1config SND_S3C24XX_SOC 1config SND_S3C24XX_SOC
2 tristate "SoC Audio for the Samsung S3C24XX chips" 2 tristate "SoC Audio for the Samsung S3C24XX chips"
3 depends on ARCH_S3C2410 && SND_SOC 3 depends on ARCH_S3C2410
4 select SND_PCM
5 help 4 help
6 Say Y or M if you want to add support for codecs attached to 5 Say Y or M if you want to add support for codecs attached to
7 the S3C24XX AC97, I2S or SSP interface. You will also need 6 the S3C24XX AC97, I2S or SSP interface. You will also need
@@ -16,7 +15,6 @@ config SND_S3C2412_SOC_I2S
16config SND_S3C2443_SOC_AC97 15config SND_S3C2443_SOC_AC97
17 tristate 16 tristate
18 select AC97_BUS 17 select AC97_BUS
19 select SND_AC97_CODEC
20 select SND_SOC_AC97_BUS 18 select SND_SOC_AC97_BUS
21 19
22config SND_S3C24XX_SOC_NEO1973_WM8753 20config SND_S3C24XX_SOC_NEO1973_WM8753
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 0e9d1c5f2484..4d7a9aa15f1a 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -10,10 +10,6 @@
10 * Free Software Foundation; either version 2 of the License, or (at your 10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
12 * 12 *
13 * Revision history
14 * 20th Jan 2007 Initial version.
15 * 05th Feb 2007 Rename all to Neo1973
16 *
17 */ 13 */
18 14
19#include <linux/module.h> 15#include <linux/module.h>
@@ -26,6 +22,7 @@
26#include <sound/pcm.h> 22#include <sound/pcm.h>
27#include <sound/soc.h> 23#include <sound/soc.h>
28#include <sound/soc-dapm.h> 24#include <sound/soc-dapm.h>
25#include <sound/tlv.h>
29 26
30#include <asm/mach-types.h> 27#include <asm/mach-types.h>
31#include <asm/hardware/scoop.h> 28#include <asm/hardware/scoop.h>
@@ -43,6 +40,14 @@
43#include "s3c24xx-pcm.h" 40#include "s3c24xx-pcm.h"
44#include "s3c24xx-i2s.h" 41#include "s3c24xx-i2s.h"
45 42
43/* Debugging stuff */
44#define S3C24XX_SOC_NEO1973_WM8753_DEBUG 0
45#if S3C24XX_SOC_NEO1973_WM8753_DEBUG
46#define DBG(x...) printk(KERN_DEBUG "s3c24xx-soc-neo1973-wm8753: " x)
47#else
48#define DBG(x...)
49#endif
50
46/* define the scenarios */ 51/* define the scenarios */
47#define NEO_AUDIO_OFF 0 52#define NEO_AUDIO_OFF 0
48#define NEO_GSM_CALL_AUDIO_HANDSET 1 53#define NEO_GSM_CALL_AUDIO_HANDSET 1
@@ -61,12 +66,14 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
61 struct snd_pcm_hw_params *params) 66 struct snd_pcm_hw_params *params)
62{ 67{
63 struct snd_soc_pcm_runtime *rtd = substream->private_data; 68 struct snd_soc_pcm_runtime *rtd = substream->private_data;
64 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 69 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
65 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 70 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
66 unsigned int pll_out = 0, bclk = 0; 71 unsigned int pll_out = 0, bclk = 0;
67 int ret = 0; 72 int ret = 0;
68 unsigned long iis_clkrate; 73 unsigned long iis_clkrate;
69 74
75 DBG("Entered %s\n", __func__);
76
70 iis_clkrate = s3c24xx_i2s_get_clockrate(); 77 iis_clkrate = s3c24xx_i2s_get_clockrate();
71 78
72 switch (params_rate(params)) { 79 switch (params_rate(params)) {
@@ -101,44 +108,44 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
101 } 108 }
102 109
103 /* set codec DAI configuration */ 110 /* set codec DAI configuration */
104 ret = codec_dai->dai_ops.set_fmt(codec_dai, 111 ret = snd_soc_dai_set_fmt(codec_dai,
105 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 112 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
106 SND_SOC_DAIFMT_CBM_CFM); 113 SND_SOC_DAIFMT_CBM_CFM);
107 if (ret < 0) 114 if (ret < 0)
108 return ret; 115 return ret;
109 116
110 /* set cpu DAI configuration */ 117 /* set cpu DAI configuration */
111 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, 118 ret = snd_soc_dai_set_fmt(cpu_dai,
112 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 119 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
113 SND_SOC_DAIFMT_CBM_CFM); 120 SND_SOC_DAIFMT_CBM_CFM);
114 if (ret < 0) 121 if (ret < 0)
115 return ret; 122 return ret;
116 123
117 /* set the codec system clock for DAC and ADC */ 124 /* set the codec system clock for DAC and ADC */
118 ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_MCLK, pll_out, 125 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
119 SND_SOC_CLOCK_IN); 126 SND_SOC_CLOCK_IN);
120 if (ret < 0) 127 if (ret < 0)
121 return ret; 128 return ret;
122 129
123 /* set MCLK division for sample rate */ 130 /* set MCLK division for sample rate */
124 ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, 131 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
125 S3C2410_IISMOD_32FS); 132 S3C2410_IISMOD_32FS);
126 if (ret < 0) 133 if (ret < 0)
127 return ret; 134 return ret;
128 135
129 /* set codec BCLK division for sample rate */ 136 /* set codec BCLK division for sample rate */
130 ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk); 137 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);
131 if (ret < 0) 138 if (ret < 0)
132 return ret; 139 return ret;
133 140
134 /* set prescaler division for sample rate */ 141 /* set prescaler division for sample rate */
135 ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, 142 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
136 S3C24XX_PRESCALE(4, 4)); 143 S3C24XX_PRESCALE(4, 4));
137 if (ret < 0) 144 if (ret < 0)
138 return ret; 145 return ret;
139 146
140 /* codec PLL input is PCLK/4 */ 147 /* codec PLL input is PCLK/4 */
141 ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1, 148 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1,
142 iis_clkrate / 4, pll_out); 149 iis_clkrate / 4, pll_out);
143 if (ret < 0) 150 if (ret < 0)
144 return ret; 151 return ret;
@@ -149,10 +156,12 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
149static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) 156static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
150{ 157{
151 struct snd_soc_pcm_runtime *rtd = substream->private_data; 158 struct snd_soc_pcm_runtime *rtd = substream->private_data;
152 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 159 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
160
161 DBG("Entered %s\n", __func__);
153 162
154 /* disable the PLL */ 163 /* disable the PLL */
155 return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1, 0, 0); 164 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0);
156} 165}
157 166
158/* 167/*
@@ -167,11 +176,13 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
167 struct snd_pcm_hw_params *params) 176 struct snd_pcm_hw_params *params)
168{ 177{
169 struct snd_soc_pcm_runtime *rtd = substream->private_data; 178 struct snd_soc_pcm_runtime *rtd = substream->private_data;
170 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 179 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
171 unsigned int pcmdiv = 0; 180 unsigned int pcmdiv = 0;
172 int ret = 0; 181 int ret = 0;
173 unsigned long iis_clkrate; 182 unsigned long iis_clkrate;
174 183
184 DBG("Entered %s\n", __func__);
185
175 iis_clkrate = s3c24xx_i2s_get_clockrate(); 186 iis_clkrate = s3c24xx_i2s_get_clockrate();
176 187
177 if (params_rate(params) != 8000) 188 if (params_rate(params) != 8000)
@@ -183,24 +194,24 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
183 194
184 /* todo: gg check mode (DSP_B) against CSR datasheet */ 195 /* todo: gg check mode (DSP_B) against CSR datasheet */
185 /* set codec DAI configuration */ 196 /* set codec DAI configuration */
186 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | 197 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
187 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 198 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
188 if (ret < 0) 199 if (ret < 0)
189 return ret; 200 return ret;
190 201
191 /* set the codec system clock for DAC and ADC */ 202 /* set the codec system clock for DAC and ADC */
192 ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_PCMCLK, 12288000, 203 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, 12288000,
193 SND_SOC_CLOCK_IN); 204 SND_SOC_CLOCK_IN);
194 if (ret < 0) 205 if (ret < 0)
195 return ret; 206 return ret;
196 207
197 /* set codec PCM division for sample rate */ 208 /* set codec PCM division for sample rate */
198 ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv); 209 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
199 if (ret < 0) 210 if (ret < 0)
200 return ret; 211 return ret;
201 212
202 /* configue and enable PLL for 12.288MHz output */ 213 /* configue and enable PLL for 12.288MHz output */
203 ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2, 214 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2,
204 iis_clkrate / 4, 12288000); 215 iis_clkrate / 4, 12288000);
205 if (ret < 0) 216 if (ret < 0)
206 return ret; 217 return ret;
@@ -211,10 +222,12 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
211static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) 222static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
212{ 223{
213 struct snd_soc_pcm_runtime *rtd = substream->private_data; 224 struct snd_soc_pcm_runtime *rtd = substream->private_data;
214 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 225 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
226
227 DBG("Entered %s\n", __func__);
215 228
216 /* disable the PLL */ 229 /* disable the PLL */
217 return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2, 0, 0); 230 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0);
218} 231}
219 232
220static struct snd_soc_ops neo1973_voice_ops = { 233static struct snd_soc_ops neo1973_voice_ops = {
@@ -233,79 +246,81 @@ static int neo1973_get_scenario(struct snd_kcontrol *kcontrol,
233 246
234static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario) 247static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario)
235{ 248{
249 DBG("Entered %s\n", __func__);
250
236 switch (neo1973_scenario) { 251 switch (neo1973_scenario) {
237 case NEO_AUDIO_OFF: 252 case NEO_AUDIO_OFF:
238 snd_soc_dapm_set_endpoint(codec, "Audio Out", 0); 253 snd_soc_dapm_disable_pin(codec, "Audio Out");
239 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); 254 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
240 snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); 255 snd_soc_dapm_disable_pin(codec, "GSM Line In");
241 snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); 256 snd_soc_dapm_disable_pin(codec, "Headset Mic");
242 snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); 257 snd_soc_dapm_disable_pin(codec, "Call Mic");
243 break; 258 break;
244 case NEO_GSM_CALL_AUDIO_HANDSET: 259 case NEO_GSM_CALL_AUDIO_HANDSET:
245 snd_soc_dapm_set_endpoint(codec, "Audio Out", 1); 260 snd_soc_dapm_enable_pin(codec, "Audio Out");
246 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1); 261 snd_soc_dapm_enable_pin(codec, "GSM Line Out");
247 snd_soc_dapm_set_endpoint(codec, "GSM Line In", 1); 262 snd_soc_dapm_enable_pin(codec, "GSM Line In");
248 snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); 263 snd_soc_dapm_disable_pin(codec, "Headset Mic");
249 snd_soc_dapm_set_endpoint(codec, "Call Mic", 1); 264 snd_soc_dapm_enable_pin(codec, "Call Mic");
250 break; 265 break;
251 case NEO_GSM_CALL_AUDIO_HEADSET: 266 case NEO_GSM_CALL_AUDIO_HEADSET:
252 snd_soc_dapm_set_endpoint(codec, "Audio Out", 1); 267 snd_soc_dapm_enable_pin(codec, "Audio Out");
253 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1); 268 snd_soc_dapm_enable_pin(codec, "GSM Line Out");
254 snd_soc_dapm_set_endpoint(codec, "GSM Line In", 1); 269 snd_soc_dapm_enable_pin(codec, "GSM Line In");
255 snd_soc_dapm_set_endpoint(codec, "Headset Mic", 1); 270 snd_soc_dapm_enable_pin(codec, "Headset Mic");
256 snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); 271 snd_soc_dapm_disable_pin(codec, "Call Mic");
257 break; 272 break;
258 case NEO_GSM_CALL_AUDIO_BLUETOOTH: 273 case NEO_GSM_CALL_AUDIO_BLUETOOTH:
259 snd_soc_dapm_set_endpoint(codec, "Audio Out", 0); 274 snd_soc_dapm_disable_pin(codec, "Audio Out");
260 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1); 275 snd_soc_dapm_enable_pin(codec, "GSM Line Out");
261 snd_soc_dapm_set_endpoint(codec, "GSM Line In", 1); 276 snd_soc_dapm_enable_pin(codec, "GSM Line In");
262 snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); 277 snd_soc_dapm_disable_pin(codec, "Headset Mic");
263 snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); 278 snd_soc_dapm_disable_pin(codec, "Call Mic");
264 break; 279 break;
265 case NEO_STEREO_TO_SPEAKERS: 280 case NEO_STEREO_TO_SPEAKERS:
266 snd_soc_dapm_set_endpoint(codec, "Audio Out", 1); 281 snd_soc_dapm_enable_pin(codec, "Audio Out");
267 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); 282 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
268 snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); 283 snd_soc_dapm_disable_pin(codec, "GSM Line In");
269 snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); 284 snd_soc_dapm_disable_pin(codec, "Headset Mic");
270 snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); 285 snd_soc_dapm_disable_pin(codec, "Call Mic");
271 break; 286 break;
272 case NEO_STEREO_TO_HEADPHONES: 287 case NEO_STEREO_TO_HEADPHONES:
273 snd_soc_dapm_set_endpoint(codec, "Audio Out", 1); 288 snd_soc_dapm_enable_pin(codec, "Audio Out");
274 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); 289 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
275 snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); 290 snd_soc_dapm_disable_pin(codec, "GSM Line In");
276 snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); 291 snd_soc_dapm_disable_pin(codec, "Headset Mic");
277 snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); 292 snd_soc_dapm_disable_pin(codec, "Call Mic");
278 break; 293 break;
279 case NEO_CAPTURE_HANDSET: 294 case NEO_CAPTURE_HANDSET:
280 snd_soc_dapm_set_endpoint(codec, "Audio Out", 0); 295 snd_soc_dapm_disable_pin(codec, "Audio Out");
281 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); 296 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
282 snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); 297 snd_soc_dapm_disable_pin(codec, "GSM Line In");
283 snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); 298 snd_soc_dapm_disable_pin(codec, "Headset Mic");
284 snd_soc_dapm_set_endpoint(codec, "Call Mic", 1); 299 snd_soc_dapm_enable_pin(codec, "Call Mic");
285 break; 300 break;
286 case NEO_CAPTURE_HEADSET: 301 case NEO_CAPTURE_HEADSET:
287 snd_soc_dapm_set_endpoint(codec, "Audio Out", 0); 302 snd_soc_dapm_disable_pin(codec, "Audio Out");
288 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); 303 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
289 snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); 304 snd_soc_dapm_disable_pin(codec, "GSM Line In");
290 snd_soc_dapm_set_endpoint(codec, "Headset Mic", 1); 305 snd_soc_dapm_enable_pin(codec, "Headset Mic");
291 snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); 306 snd_soc_dapm_disable_pin(codec, "Call Mic");
292 break; 307 break;
293 case NEO_CAPTURE_BLUETOOTH: 308 case NEO_CAPTURE_BLUETOOTH:
294 snd_soc_dapm_set_endpoint(codec, "Audio Out", 0); 309 snd_soc_dapm_disable_pin(codec, "Audio Out");
295 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); 310 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
296 snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); 311 snd_soc_dapm_disable_pin(codec, "GSM Line In");
297 snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); 312 snd_soc_dapm_disable_pin(codec, "Headset Mic");
298 snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); 313 snd_soc_dapm_disable_pin(codec, "Call Mic");
299 break; 314 break;
300 default: 315 default:
301 snd_soc_dapm_set_endpoint(codec, "Audio Out", 0); 316 snd_soc_dapm_disable_pin(codec, "Audio Out");
302 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); 317 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
303 snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); 318 snd_soc_dapm_disable_pin(codec, "GSM Line In");
304 snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); 319 snd_soc_dapm_disable_pin(codec, "Headset Mic");
305 snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); 320 snd_soc_dapm_disable_pin(codec, "Call Mic");
306 } 321 }
307 322
308 snd_soc_dapm_sync_endpoints(codec); 323 snd_soc_dapm_sync(codec);
309 324
310 return 0; 325 return 0;
311} 326}
@@ -315,6 +330,8 @@ static int neo1973_set_scenario(struct snd_kcontrol *kcontrol,
315{ 330{
316 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 331 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
317 332
333 DBG("Entered %s\n", __func__);
334
318 if (neo1973_scenario == ucontrol->value.integer.value[0]) 335 if (neo1973_scenario == ucontrol->value.integer.value[0])
319 return 0; 336 return 0;
320 337
@@ -327,6 +344,8 @@ static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0};
327 344
328static void lm4857_write_regs(void) 345static void lm4857_write_regs(void)
329{ 346{
347 DBG("Entered %s\n", __func__);
348
330 if (i2c_master_send(i2c, lm4857_regs, 4) != 4) 349 if (i2c_master_send(i2c, lm4857_regs, 4) != 4)
331 printk(KERN_ERR "lm4857: i2c write failed\n"); 350 printk(KERN_ERR "lm4857: i2c write failed\n");
332} 351}
@@ -338,6 +357,8 @@ static int lm4857_get_reg(struct snd_kcontrol *kcontrol,
338 int shift = (kcontrol->private_value >> 8) & 0x0F; 357 int shift = (kcontrol->private_value >> 8) & 0x0F;
339 int mask = (kcontrol->private_value >> 16) & 0xFF; 358 int mask = (kcontrol->private_value >> 16) & 0xFF;
340 359
360 DBG("Entered %s\n", __func__);
361
341 ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask; 362 ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask;
342 return 0; 363 return 0;
343} 364}
@@ -364,6 +385,8 @@ static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
364{ 385{
365 u8 value = lm4857_regs[LM4857_CTRL] & 0x0F; 386 u8 value = lm4857_regs[LM4857_CTRL] & 0x0F;
366 387
388 DBG("Entered %s\n", __func__);
389
367 if (value) 390 if (value)
368 value -= 5; 391 value -= 5;
369 392
@@ -376,6 +399,8 @@ static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
376{ 399{
377 u8 value = ucontrol->value.integer.value[0]; 400 u8 value = ucontrol->value.integer.value[0];
378 401
402 DBG("Entered %s\n", __func__);
403
379 if (value) 404 if (value)
380 value += 5; 405 value += 5;
381 406
@@ -397,8 +422,7 @@ static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
397}; 422};
398 423
399 424
400/* example machine audio_mapnections */ 425static const struct snd_soc_dapm_route dapm_routes[] = {
401static const char *audio_map[][3] = {
402 426
403 /* Connections to the lm4857 amp */ 427 /* Connections to the lm4857 amp */
404 {"Audio Out", NULL, "LOUT1"}, 428 {"Audio Out", NULL, "LOUT1"},
@@ -421,8 +445,6 @@ static const char *audio_map[][3] = {
421 445
422 /* Connect the ALC pins */ 446 /* Connect the ALC pins */
423 {"ACIN", NULL, "ACOP"}, 447 {"ACIN", NULL, "ACOP"},
424
425 {NULL, NULL, NULL},
426}; 448};
427 449
428static const char *lm4857_mode[] = { 450static const char *lm4857_mode[] = {
@@ -453,13 +475,16 @@ static const struct soc_enum neo_scenario_enum[] = {
453 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(neo_scenarios), neo_scenarios), 475 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(neo_scenarios), neo_scenarios),
454}; 476};
455 477
478static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0);
479static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0);
480
456static const struct snd_kcontrol_new wm8753_neo1973_controls[] = { 481static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {
457 SOC_SINGLE_EXT("Amp Left Playback Volume", LM4857_LVOL, 0, 31, 0, 482 SOC_SINGLE_EXT_TLV("Amp Left Playback Volume", LM4857_LVOL, 0, 31, 0,
458 lm4857_get_reg, lm4857_set_reg), 483 lm4857_get_reg, lm4857_set_reg, stereo_tlv),
459 SOC_SINGLE_EXT("Amp Right Playback Volume", LM4857_RVOL, 0, 31, 0, 484 SOC_SINGLE_EXT_TLV("Amp Right Playback Volume", LM4857_RVOL, 0, 31, 0,
460 lm4857_get_reg, lm4857_set_reg), 485 lm4857_get_reg, lm4857_set_reg, stereo_tlv),
461 SOC_SINGLE_EXT("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0, 486 SOC_SINGLE_EXT_TLV("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0,
462 lm4857_get_reg, lm4857_set_reg), 487 lm4857_get_reg, lm4857_set_reg, mono_tlv),
463 SOC_ENUM_EXT("Amp Mode", lm4857_mode_enum[0], 488 SOC_ENUM_EXT("Amp Mode", lm4857_mode_enum[0],
464 lm4857_get_mode, lm4857_set_mode), 489 lm4857_get_mode, lm4857_set_mode),
465 SOC_ENUM_EXT("Neo Mode", neo_scenario_enum[0], 490 SOC_ENUM_EXT("Neo Mode", neo_scenario_enum[0],
@@ -483,21 +508,23 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
483{ 508{
484 int i, err; 509 int i, err;
485 510
511 DBG("Entered %s\n", __func__);
512
486 /* set up NC codec pins */ 513 /* set up NC codec pins */
487 snd_soc_dapm_set_endpoint(codec, "LOUT2", 0); 514 snd_soc_dapm_disable_pin(codec, "LOUT2");
488 snd_soc_dapm_set_endpoint(codec, "ROUT2", 0); 515 snd_soc_dapm_disable_pin(codec, "ROUT2");
489 snd_soc_dapm_set_endpoint(codec, "OUT3", 0); 516 snd_soc_dapm_disable_pin(codec, "OUT3");
490 snd_soc_dapm_set_endpoint(codec, "OUT4", 0); 517 snd_soc_dapm_disable_pin(codec, "OUT4");
491 snd_soc_dapm_set_endpoint(codec, "LINE1", 0); 518 snd_soc_dapm_disable_pin(codec, "LINE1");
492 snd_soc_dapm_set_endpoint(codec, "LINE2", 0); 519 snd_soc_dapm_disable_pin(codec, "LINE2");
493 520
494 521
495 /* set endpoints to default mode */ 522 /* set endpoints to default mode */
496 set_scenario_endpoints(codec, NEO_AUDIO_OFF); 523 set_scenario_endpoints(codec, NEO_AUDIO_OFF);
497 524
498 /* Add neo1973 specific widgets */ 525 /* Add neo1973 specific widgets */
499 for (i = 0; i < ARRAY_SIZE(wm8753_dapm_widgets); i++) 526 snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
500 snd_soc_dapm_new_control(codec, &wm8753_dapm_widgets[i]); 527 ARRAY_SIZE(wm8753_dapm_widgets));
501 528
502 /* add neo1973 specific controls */ 529 /* add neo1973 specific controls */
503 for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) { 530 for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) {
@@ -508,20 +535,18 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
508 return err; 535 return err;
509 } 536 }
510 537
511 /* set up neo1973 specific audio path audio_mapnects */ 538 /* set up neo1973 specific audio routes */
512 for (i = 0; audio_map[i][0] != NULL; i++) { 539 err = snd_soc_dapm_add_routes(codec, dapm_routes,
513 snd_soc_dapm_connect_input(codec, audio_map[i][0], 540 ARRAY_SIZE(dapm_routes));
514 audio_map[i][1], audio_map[i][2]);
515 }
516 541
517 snd_soc_dapm_sync_endpoints(codec); 542 snd_soc_dapm_sync(codec);
518 return 0; 543 return 0;
519} 544}
520 545
521/* 546/*
522 * BT Codec DAI 547 * BT Codec DAI
523 */ 548 */
524static struct snd_soc_cpu_dai bt_dai = { 549static struct snd_soc_dai bt_dai = {
525 .name = "Bluetooth", 550 .name = "Bluetooth",
526 .id = 0, 551 .id = 0,
527 .type = SND_SOC_DAI_PCM, 552 .type = SND_SOC_DAI_PCM,
@@ -583,6 +608,8 @@ static int lm4857_amp_probe(struct i2c_adapter *adap, int addr, int kind)
583{ 608{
584 int ret; 609 int ret;
585 610
611 DBG("Entered %s\n", __func__);
612
586 client_template.adapter = adap; 613 client_template.adapter = adap;
587 client_template.addr = addr; 614 client_template.addr = addr;
588 615
@@ -606,6 +633,8 @@ exit_err:
606 633
607static int lm4857_i2c_detach(struct i2c_client *client) 634static int lm4857_i2c_detach(struct i2c_client *client)
608{ 635{
636 DBG("Entered %s\n", __func__);
637
609 i2c_detach_client(client); 638 i2c_detach_client(client);
610 kfree(client); 639 kfree(client);
611 return 0; 640 return 0;
@@ -613,6 +642,8 @@ static int lm4857_i2c_detach(struct i2c_client *client)
613 642
614static int lm4857_i2c_attach(struct i2c_adapter *adap) 643static int lm4857_i2c_attach(struct i2c_adapter *adap)
615{ 644{
645 DBG("Entered %s\n", __func__);
646
616 return i2c_probe(adap, &addr_data, lm4857_amp_probe); 647 return i2c_probe(adap, &addr_data, lm4857_amp_probe);
617} 648}
618 649
@@ -620,6 +651,8 @@ static u8 lm4857_state;
620 651
621static int lm4857_suspend(struct i2c_client *dev, pm_message_t state) 652static int lm4857_suspend(struct i2c_client *dev, pm_message_t state)
622{ 653{
654 DBG("Entered %s\n", __func__);
655
623 dev_dbg(&dev->dev, "lm4857_suspend\n"); 656 dev_dbg(&dev->dev, "lm4857_suspend\n");
624 lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf; 657 lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf;
625 if (lm4857_state) { 658 if (lm4857_state) {
@@ -631,6 +664,8 @@ static int lm4857_suspend(struct i2c_client *dev, pm_message_t state)
631 664
632static int lm4857_resume(struct i2c_client *dev) 665static int lm4857_resume(struct i2c_client *dev)
633{ 666{
667 DBG("Entered %s\n", __func__);
668
634 if (lm4857_state) { 669 if (lm4857_state) {
635 lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f); 670 lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f);
636 lm4857_write_regs(); 671 lm4857_write_regs();
@@ -640,6 +675,8 @@ static int lm4857_resume(struct i2c_client *dev)
640 675
641static void lm4857_shutdown(struct i2c_client *dev) 676static void lm4857_shutdown(struct i2c_client *dev)
642{ 677{
678 DBG("Entered %s\n", __func__);
679
643 dev_dbg(&dev->dev, "lm4857_shutdown\n"); 680 dev_dbg(&dev->dev, "lm4857_shutdown\n");
644 lm4857_regs[LM4857_CTRL] &= 0xf0; 681 lm4857_regs[LM4857_CTRL] &= 0xf0;
645 lm4857_write_regs(); 682 lm4857_write_regs();
@@ -671,6 +708,8 @@ static int __init neo1973_init(void)
671{ 708{
672 int ret; 709 int ret;
673 710
711 DBG("Entered %s\n", __func__);
712
674 neo1973_snd_device = platform_device_alloc("soc-audio", -1); 713 neo1973_snd_device = platform_device_alloc("soc-audio", -1);
675 if (!neo1973_snd_device) 714 if (!neo1973_snd_device)
676 return -ENOMEM; 715 return -ENOMEM;
@@ -691,6 +730,8 @@ static int __init neo1973_init(void)
691 730
692static void __exit neo1973_exit(void) 731static void __exit neo1973_exit(void)
693{ 732{
733 DBG("Entered %s\n", __func__);
734
694 i2c_del_driver(&lm4857_i2c_driver); 735 i2c_del_driver(&lm4857_i2c_driver);
695 platform_device_unregister(neo1973_snd_device); 736 platform_device_unregister(neo1973_snd_device);
696} 737}
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c
index c4a46dd589b3..ee4676ed1283 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c
@@ -295,7 +295,7 @@ static inline int s3c2412_snd_is_clkmaster(void)
295/* 295/*
296 * Set S3C2412 I2S DAI format 296 * Set S3C2412 I2S DAI format
297 */ 297 */
298static int s3c2412_i2s_set_fmt(struct snd_soc_cpu_dai *cpu_dai, 298static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
299 unsigned int fmt) 299 unsigned int fmt)
300{ 300{
301 u32 iismod; 301 u32 iismod;
@@ -500,7 +500,7 @@ EXPORT_SYMBOL_GPL(s3c2412_iis_calc_rate);
500/* 500/*
501 * Set S3C2412 Clock source 501 * Set S3C2412 Clock source
502 */ 502 */
503static int s3c2412_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai, 503static int s3c2412_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
504 int clk_id, unsigned int freq, int dir) 504 int clk_id, unsigned int freq, int dir)
505{ 505{
506 u32 iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD); 506 u32 iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
@@ -528,7 +528,7 @@ static int s3c2412_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
528/* 528/*
529 * Set S3C2412 Clock dividers 529 * Set S3C2412 Clock dividers
530 */ 530 */
531static int s3c2412_i2s_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai, 531static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
532 int div_id, int div) 532 int div_id, int div)
533{ 533{
534 struct s3c2412_i2s_info *i2s = &s3c2412_i2s; 534 struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
@@ -601,7 +601,8 @@ struct clk *s3c2412_get_iisclk(void)
601EXPORT_SYMBOL_GPL(s3c2412_get_iisclk); 601EXPORT_SYMBOL_GPL(s3c2412_get_iisclk);
602 602
603 603
604static int s3c2412_i2s_probe(struct platform_device *pdev) 604static int s3c2412_i2s_probe(struct platform_device *pdev,
605 struct snd_soc_dai *dai)
605{ 606{
606 DBG("Entered %s\n", __func__); 607 DBG("Entered %s\n", __func__);
607 608
@@ -647,7 +648,7 @@ static int s3c2412_i2s_probe(struct platform_device *pdev)
647 648
648#ifdef CONFIG_PM 649#ifdef CONFIG_PM
649static int s3c2412_i2s_suspend(struct platform_device *dev, 650static int s3c2412_i2s_suspend(struct platform_device *dev,
650 struct snd_soc_cpu_dai *dai) 651 struct snd_soc_dai *dai)
651{ 652{
652 struct s3c2412_i2s_info *i2s = &s3c2412_i2s; 653 struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
653 u32 iismod; 654 u32 iismod;
@@ -675,7 +676,7 @@ static int s3c2412_i2s_suspend(struct platform_device *dev,
675} 676}
676 677
677static int s3c2412_i2s_resume(struct platform_device *pdev, 678static int s3c2412_i2s_resume(struct platform_device *pdev,
678 struct snd_soc_cpu_dai *dai) 679 struct snd_soc_dai *dai)
679{ 680{
680 struct s3c2412_i2s_info *i2s = &s3c2412_i2s; 681 struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
681 682
@@ -707,7 +708,7 @@ static int s3c2412_i2s_resume(struct platform_device *pdev,
707 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 708 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
708 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) 709 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
709 710
710struct snd_soc_cpu_dai s3c2412_i2s_dai = { 711struct snd_soc_dai s3c2412_i2s_dai = {
711 .name = "s3c2412-i2s", 712 .name = "s3c2412-i2s",
712 .id = 0, 713 .id = 0,
713 .type = SND_SOC_DAI_I2S, 714 .type = SND_SOC_DAI_I2S,
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.h b/sound/soc/s3c24xx/s3c2412-i2s.h
index 27f48e1ffa86..aac08a25e541 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.h
+++ b/sound/soc/s3c24xx/s3c2412-i2s.h
@@ -24,7 +24,7 @@
24 24
25extern struct clk *s3c2412_get_iisclk(void); 25extern struct clk *s3c2412_get_iisclk(void);
26 26
27extern struct snd_soc_cpu_dai s3c2412_i2s_dai; 27extern struct snd_soc_dai s3c2412_i2s_dai;
28 28
29struct s3c2412_rate_calc { 29struct s3c2412_rate_calc {
30 unsigned int clk_div; /* for prescaler */ 30 unsigned int clk_div; /* for prescaler */
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c
index e81d9a6c83da..783349b7fede 100644
--- a/sound/soc/s3c24xx/s3c2443-ac97.c
+++ b/sound/soc/s3c24xx/s3c2443-ac97.c
@@ -10,9 +10,6 @@
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 *
14 * Revision history
15 * 21st Mar 2007 Initial Version
16 */ 13 */
17 14
18#include <linux/init.h> 15#include <linux/init.h>
@@ -212,7 +209,8 @@ static struct s3c24xx_pcm_dma_params s3c2443_ac97_mic_mono_in = {
212 .dma_size = 4, 209 .dma_size = 4,
213}; 210};
214 211
215static int s3c2443_ac97_probe(struct platform_device *pdev) 212static int s3c2443_ac97_probe(struct platform_device *pdev,
213 struct snd_soc_dai *dai)
216{ 214{
217 int ret; 215 int ret;
218 u32 ac_glbctrl; 216 u32 ac_glbctrl;
@@ -263,7 +261,8 @@ static int s3c2443_ac97_probe(struct platform_device *pdev)
263 return ret; 261 return ret;
264} 262}
265 263
266static void s3c2443_ac97_remove(struct platform_device *pdev) 264static void s3c2443_ac97_remove(struct platform_device *pdev,
265 struct snd_soc_dai *dai)
267{ 266{
268 free_irq(IRQ_S3C244x_AC97, NULL); 267 free_irq(IRQ_S3C244x_AC97, NULL);
269 clk_disable(s3c24xx_ac97.ac97_clk); 268 clk_disable(s3c24xx_ac97.ac97_clk);
@@ -275,7 +274,7 @@ static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream,
275 struct snd_pcm_hw_params *params) 274 struct snd_pcm_hw_params *params)
276{ 275{
277 struct snd_soc_pcm_runtime *rtd = substream->private_data; 276 struct snd_soc_pcm_runtime *rtd = substream->private_data;
278 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 277 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
279 278
280 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 279 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
281 cpu_dai->dma_data = &s3c2443_ac97_pcm_stereo_out; 280 cpu_dai->dma_data = &s3c2443_ac97_pcm_stereo_out;
@@ -317,7 +316,7 @@ static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream,
317 struct snd_pcm_hw_params *params) 316 struct snd_pcm_hw_params *params)
318{ 317{
319 struct snd_soc_pcm_runtime *rtd = substream->private_data; 318 struct snd_soc_pcm_runtime *rtd = substream->private_data;
320 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 319 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
321 320
322 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 321 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
323 return -ENODEV; 322 return -ENODEV;
@@ -353,7 +352,7 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
353 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ 352 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
354 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) 353 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
355 354
356struct snd_soc_cpu_dai s3c2443_ac97_dai[] = { 355struct snd_soc_dai s3c2443_ac97_dai[] = {
357{ 356{
358 .name = "s3c2443-ac97", 357 .name = "s3c2443-ac97",
359 .id = 0, 358 .id = 0,
diff --git a/sound/soc/s3c24xx/s3c24xx-ac97.h b/sound/soc/s3c24xx/s3c24xx-ac97.h
index bf03e8ed16c3..a96dcadf28b4 100644
--- a/sound/soc/s3c24xx/s3c24xx-ac97.h
+++ b/sound/soc/s3c24xx/s3c24xx-ac97.h
@@ -26,6 +26,6 @@
26#define IRQ_S3C244x_AC97 IRQ_S3C2443_AC97 26#define IRQ_S3C244x_AC97 IRQ_S3C2443_AC97
27#endif 27#endif
28 28
29extern struct snd_soc_cpu_dai s3c2443_ac97_dai[]; 29extern struct snd_soc_dai s3c2443_ac97_dai[];
30 30
31#endif /*S3C24XXAC97_H_*/ 31#endif /*S3C24XXAC97_H_*/
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index 1ed6afd45459..397524282b57 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -12,11 +12,6 @@
12 * under the terms of the GNU General Public License as published by the 12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your 13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version. 14 * option) any later version.
15 *
16 *
17 * Revision history
18 * 11th Dec 2006 Merged with Simtec driver
19 * 10th Nov 2006 Initial version.
20 */ 15 */
21 16
22#include <linux/init.h> 17#include <linux/init.h>
@@ -180,7 +175,7 @@ static void s3c24xx_snd_rxctrl(int on)
180static int s3c24xx_snd_lrsync(void) 175static int s3c24xx_snd_lrsync(void)
181{ 176{
182 u32 iiscon; 177 u32 iiscon;
183 unsigned long timeout = jiffies + msecs_to_jiffies(5); 178 int timeout = 50; /* 5ms */
184 179
185 DBG("Entered %s\n", __func__); 180 DBG("Entered %s\n", __func__);
186 181
@@ -189,8 +184,9 @@ static int s3c24xx_snd_lrsync(void)
189 if (iiscon & S3C2410_IISCON_LRINDEX) 184 if (iiscon & S3C2410_IISCON_LRINDEX)
190 break; 185 break;
191 186
192 if (time_after(jiffies, timeout)) 187 if (!timeout--)
193 return -ETIMEDOUT; 188 return -ETIMEDOUT;
189 udelay(100);
194 } 190 }
195 191
196 return 0; 192 return 0;
@@ -209,7 +205,7 @@ static inline int s3c24xx_snd_is_clkmaster(void)
209/* 205/*
210 * Set S3C24xx I2S DAI format 206 * Set S3C24xx I2S DAI format
211 */ 207 */
212static int s3c24xx_i2s_set_fmt(struct snd_soc_cpu_dai *cpu_dai, 208static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
213 unsigned int fmt) 209 unsigned int fmt)
214{ 210{
215 u32 iismod; 211 u32 iismod;
@@ -317,7 +313,7 @@ exit_err:
317/* 313/*
318 * Set S3C24xx Clock source 314 * Set S3C24xx Clock source
319 */ 315 */
320static int s3c24xx_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai, 316static int s3c24xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
321 int clk_id, unsigned int freq, int dir) 317 int clk_id, unsigned int freq, int dir)
322{ 318{
323 u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); 319 u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
@@ -343,7 +339,7 @@ static int s3c24xx_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
343/* 339/*
344 * Set S3C24xx Clock dividers 340 * Set S3C24xx Clock dividers
345 */ 341 */
346static int s3c24xx_i2s_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai, 342static int s3c24xx_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
347 int div_id, int div) 343 int div_id, int div)
348{ 344{
349 u32 reg; 345 u32 reg;
@@ -381,7 +377,8 @@ u32 s3c24xx_i2s_get_clockrate(void)
381} 377}
382EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); 378EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate);
383 379
384static int s3c24xx_i2s_probe(struct platform_device *pdev) 380static int s3c24xx_i2s_probe(struct platform_device *pdev,
381 struct snd_soc_dai *dai)
385{ 382{
386 DBG("Entered %s\n", __func__); 383 DBG("Entered %s\n", __func__);
387 384
@@ -414,7 +411,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev)
414 411
415#ifdef CONFIG_PM 412#ifdef CONFIG_PM
416static int s3c24xx_i2s_suspend(struct platform_device *pdev, 413static int s3c24xx_i2s_suspend(struct platform_device *pdev,
417 struct snd_soc_cpu_dai *cpu_dai) 414 struct snd_soc_dai *cpu_dai)
418{ 415{
419 DBG("Entered %s\n", __func__); 416 DBG("Entered %s\n", __func__);
420 417
@@ -429,7 +426,7 @@ static int s3c24xx_i2s_suspend(struct platform_device *pdev,
429} 426}
430 427
431static int s3c24xx_i2s_resume(struct platform_device *pdev, 428static int s3c24xx_i2s_resume(struct platform_device *pdev,
432 struct snd_soc_cpu_dai *cpu_dai) 429 struct snd_soc_dai *cpu_dai)
433{ 430{
434 DBG("Entered %s\n", __func__); 431 DBG("Entered %s\n", __func__);
435 clk_enable(s3c24xx_i2s.iis_clk); 432 clk_enable(s3c24xx_i2s.iis_clk);
@@ -452,7 +449,7 @@ static int s3c24xx_i2s_resume(struct platform_device *pdev,
452 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 449 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
453 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) 450 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
454 451
455struct snd_soc_cpu_dai s3c24xx_i2s_dai = { 452struct snd_soc_dai s3c24xx_i2s_dai = {
456 .name = "s3c24xx-i2s", 453 .name = "s3c24xx-i2s",
457 .id = 0, 454 .id = 0,
458 .type = SND_SOC_DAI_I2S, 455 .type = SND_SOC_DAI_I2S,
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.h b/sound/soc/s3c24xx/s3c24xx-i2s.h
index 537b4ecce8a3..726d91cf4e1c 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.h
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.h
@@ -32,6 +32,6 @@
32 32
33u32 s3c24xx_i2s_get_clockrate(void); 33u32 s3c24xx_i2s_get_clockrate(void);
34 34
35extern struct snd_soc_cpu_dai s3c24xx_i2s_dai; 35extern struct snd_soc_dai s3c24xx_i2s_dai;
36 36
37#endif /*S3C24XXI2S_H_*/ 37#endif /*S3C24XXI2S_H_*/
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index 7806ae614617..cef79b34dc6f 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -12,10 +12,6 @@
12 * under the terms of the GNU General Public License as published by the 12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your 13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version. 14 * option) any later version.
15 *
16 * Revision history
17 * 11th Dec 2006 Merged with Simtec driver
18 * 10th Nov 2006 Initial version.
19 */ 15 */
20 16
21#include <linux/module.h> 17#include <linux/module.h>
@@ -433,7 +429,7 @@ static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
433static u64 s3c24xx_pcm_dmamask = DMA_32BIT_MASK; 429static u64 s3c24xx_pcm_dmamask = DMA_32BIT_MASK;
434 430
435static int s3c24xx_pcm_new(struct snd_card *card, 431static int s3c24xx_pcm_new(struct snd_card *card,
436 struct snd_soc_codec_dai *dai, struct snd_pcm *pcm) 432 struct snd_soc_dai *dai, struct snd_pcm *pcm)
437{ 433{
438 int ret = 0; 434 int ret = 0;
439 435
diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c
index b4a56302b9ab..8515d6ff03f2 100644
--- a/sound/soc/s3c24xx/smdk2443_wm9710.c
+++ b/sound/soc/s3c24xx/smdk2443_wm9710.c
@@ -10,9 +10,6 @@
10 * Free Software Foundation; either version 2 of the License, or (at your 10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
12 * 12 *
13 * Revision history
14 * 8th Mar 2007 Initial version.
15 *
16 */ 13 */
17 14
18#include <linux/module.h> 15#include <linux/module.h>
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 4c1e013381c9..54bd604012af 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -3,7 +3,7 @@ menu "SoC Audio support for SuperH"
3 3
4config SND_SOC_PCM_SH7760 4config SND_SOC_PCM_SH7760
5 tristate "SoC Audio support for Renesas SH7760" 5 tristate "SoC Audio support for Renesas SH7760"
6 depends on CPU_SUBTYPE_SH7760 && SND_SOC && SH_DMABRG 6 depends on CPU_SUBTYPE_SH7760 && SH_DMABRG
7 help 7 help
8 Enable this option for SH7760 AC97/I2S audio support. 8 Enable this option for SH7760 AC97/I2S audio support.
9 9
@@ -13,10 +13,9 @@ config SND_SOC_PCM_SH7760
13## 13##
14 14
15config SND_SOC_SH4_HAC 15config SND_SOC_SH4_HAC
16 tristate
16 select AC97_BUS 17 select AC97_BUS
17 select SND_SOC_AC97_BUS 18 select SND_SOC_AC97_BUS
18 select SND_AC97_CODEC
19 tristate
20 19
21config SND_SOC_SH4_SSI 20config SND_SOC_SH4_SSI
22 tristate 21 tristate
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index 7a3ce80d6727..9faa12622d09 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -326,7 +326,7 @@ static void camelot_pcm_free(struct snd_pcm *pcm)
326} 326}
327 327
328static int camelot_pcm_new(struct snd_card *card, 328static int camelot_pcm_new(struct snd_card *card,
329 struct snd_soc_codec_dai *dai, 329 struct snd_soc_dai *dai,
330 struct snd_pcm *pcm) 330 struct snd_pcm *pcm)
331{ 331{
332 /* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel 332 /* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c
index b7b676b3d671..df7bc345c320 100644
--- a/sound/soc/sh/hac.c
+++ b/sound/soc/sh/hac.c
@@ -266,7 +266,7 @@ static int hac_hw_params(struct snd_pcm_substream *substream,
266#define AC97_FMTS \ 266#define AC97_FMTS \
267 SNDRV_PCM_FMTBIT_S16_LE 267 SNDRV_PCM_FMTBIT_S16_LE
268 268
269struct snd_soc_cpu_dai sh4_hac_dai[] = { 269struct snd_soc_dai sh4_hac_dai[] = {
270{ 270{
271 .name = "HAC0", 271 .name = "HAC0",
272 .id = 0, 272 .id = 0,
diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/sh/sh7760-ac97.c
index 2f91de84c5c7..92bfaf4774a7 100644
--- a/sound/soc/sh/sh7760-ac97.c
+++ b/sound/soc/sh/sh7760-ac97.c
@@ -20,12 +20,12 @@
20#define IPSEL 0xFE400034 20#define IPSEL 0xFE400034
21 21
22/* platform specific structs can be declared here */ 22/* platform specific structs can be declared here */
23extern struct snd_soc_cpu_dai sh4_hac_dai[2]; 23extern struct snd_soc_dai sh4_hac_dai[2];
24extern struct snd_soc_platform sh7760_soc_platform; 24extern struct snd_soc_platform sh7760_soc_platform;
25 25
26static int machine_init(struct snd_soc_codec *codec) 26static int machine_init(struct snd_soc_codec *codec)
27{ 27{
28 snd_soc_dapm_sync_endpoints(codec); 28 snd_soc_dapm_sync(codec);
29 return 0; 29 return 0;
30} 30}
31 31
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
index 3388bc3d62d1..55c3464163ab 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/sh/ssi.c
@@ -208,7 +208,7 @@ static int ssi_hw_params(struct snd_pcm_substream *substream,
208 return 0; 208 return 0;
209} 209}
210 210
211static int ssi_set_sysclk(struct snd_soc_cpu_dai *cpu_dai, int clk_id, 211static int ssi_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
212 unsigned int freq, int dir) 212 unsigned int freq, int dir)
213{ 213{
214 struct ssi_priv *ssi = &ssi_cpu_data[cpu_dai->id]; 214 struct ssi_priv *ssi = &ssi_cpu_data[cpu_dai->id];
@@ -222,7 +222,7 @@ static int ssi_set_sysclk(struct snd_soc_cpu_dai *cpu_dai, int clk_id,
222 * This divider is used to generate the SSI_SCK (I2S bitclock) from the 222 * This divider is used to generate the SSI_SCK (I2S bitclock) from the
223 * clock at the HAC_BIT_CLK ("oversampling clock") pin. 223 * clock at the HAC_BIT_CLK ("oversampling clock") pin.
224 */ 224 */
225static int ssi_set_clkdiv(struct snd_soc_cpu_dai *dai, int did, int div) 225static int ssi_set_clkdiv(struct snd_soc_dai *dai, int did, int div)
226{ 226{
227 struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; 227 struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
228 unsigned long ssicr; 228 unsigned long ssicr;
@@ -245,7 +245,7 @@ static int ssi_set_clkdiv(struct snd_soc_cpu_dai *dai, int did, int div)
245 return 0; 245 return 0;
246} 246}
247 247
248static int ssi_set_fmt(struct snd_soc_cpu_dai *dai, unsigned int fmt) 248static int ssi_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
249{ 249{
250 struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; 250 struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
251 unsigned long ssicr = SSIREG(SSICR); 251 unsigned long ssicr = SSIREG(SSICR);
@@ -332,7 +332,7 @@ static int ssi_set_fmt(struct snd_soc_cpu_dai *dai, unsigned int fmt)
332 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE | \ 332 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE | \
333 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE) 333 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE)
334 334
335struct snd_soc_cpu_dai sh4_ssi_dai[] = { 335struct snd_soc_dai sh4_ssi_dai[] = {
336{ 336{
337 .name = "SSI0", 337 .name = "SSI0",
338 .id = 0, 338 .id = 0,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index e148db940cfc..83f1190293a8 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -14,10 +14,6 @@
14 * Free Software Foundation; either version 2 of the License, or (at your 14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. 15 * option) any later version.
16 * 16 *
17 * Revision history
18 * 12th Aug 2005 Initial version.
19 * 25th Oct 2005 Working Codec, Interface and Platform registration.
20 *
21 * TODO: 17 * TODO:
22 * o Add hw rules to enforce rates, etc. 18 * o Add hw rules to enforce rates, etc.
23 * o More testing with other codecs/machines. 19 * o More testing with other codecs/machines.
@@ -112,9 +108,9 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
112} 108}
113#endif 109#endif
114 110
115static inline const char* get_dai_name(int type) 111static inline const char *get_dai_name(int type)
116{ 112{
117 switch(type) { 113 switch (type) {
118 case SND_SOC_DAI_AC97_BUS: 114 case SND_SOC_DAI_AC97_BUS:
119 case SND_SOC_DAI_AC97: 115 case SND_SOC_DAI_AC97:
120 return "AC97"; 116 return "AC97";
@@ -138,8 +134,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
138 struct snd_pcm_runtime *runtime = substream->runtime; 134 struct snd_pcm_runtime *runtime = substream->runtime;
139 struct snd_soc_dai_link *machine = rtd->dai; 135 struct snd_soc_dai_link *machine = rtd->dai;
140 struct snd_soc_platform *platform = socdev->platform; 136 struct snd_soc_platform *platform = socdev->platform;
141 struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai; 137 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
142 struct snd_soc_codec_dai *codec_dai = machine->codec_dai; 138 struct snd_soc_dai *codec_dai = machine->codec_dai;
143 int ret = 0; 139 int ret = 0;
144 140
145 mutex_lock(&pcm_mutex); 141 mutex_lock(&pcm_mutex);
@@ -182,9 +178,11 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
182 /* Check that the codec and cpu DAI's are compatible */ 178 /* Check that the codec and cpu DAI's are compatible */
183 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 179 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
184 runtime->hw.rate_min = 180 runtime->hw.rate_min =
185 max(codec_dai->playback.rate_min, cpu_dai->playback.rate_min); 181 max(codec_dai->playback.rate_min,
182 cpu_dai->playback.rate_min);
186 runtime->hw.rate_max = 183 runtime->hw.rate_max =
187 min(codec_dai->playback.rate_max, cpu_dai->playback.rate_max); 184 min(codec_dai->playback.rate_max,
185 cpu_dai->playback.rate_max);
188 runtime->hw.channels_min = 186 runtime->hw.channels_min =
189 max(codec_dai->playback.channels_min, 187 max(codec_dai->playback.channels_min,
190 cpu_dai->playback.channels_min); 188 cpu_dai->playback.channels_min);
@@ -197,9 +195,11 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
197 codec_dai->playback.rates & cpu_dai->playback.rates; 195 codec_dai->playback.rates & cpu_dai->playback.rates;
198 } else { 196 } else {
199 runtime->hw.rate_min = 197 runtime->hw.rate_min =
200 max(codec_dai->capture.rate_min, cpu_dai->capture.rate_min); 198 max(codec_dai->capture.rate_min,
199 cpu_dai->capture.rate_min);
201 runtime->hw.rate_max = 200 runtime->hw.rate_max =
202 min(codec_dai->capture.rate_max, cpu_dai->capture.rate_max); 201 min(codec_dai->capture.rate_max,
202 cpu_dai->capture.rate_max);
203 runtime->hw.channels_min = 203 runtime->hw.channels_min =
204 max(codec_dai->capture.channels_min, 204 max(codec_dai->capture.channels_min,
205 cpu_dai->capture.channels_min); 205 cpu_dai->capture.channels_min);
@@ -229,7 +229,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
229 goto machine_err; 229 goto machine_err;
230 } 230 }
231 231
232 dbg("asoc: %s <-> %s info:\n",codec_dai->name, cpu_dai->name); 232 dbg("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
233 dbg("asoc: rate mask 0x%x\n", runtime->hw.rates); 233 dbg("asoc: rate mask 0x%x\n", runtime->hw.rates);
234 dbg("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, 234 dbg("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
235 runtime->hw.channels_max); 235 runtime->hw.channels_max);
@@ -272,11 +272,11 @@ static void close_delayed_work(struct work_struct *work)
272 struct snd_soc_device *socdev = 272 struct snd_soc_device *socdev =
273 container_of(work, struct snd_soc_device, delayed_work.work); 273 container_of(work, struct snd_soc_device, delayed_work.work);
274 struct snd_soc_codec *codec = socdev->codec; 274 struct snd_soc_codec *codec = socdev->codec;
275 struct snd_soc_codec_dai *codec_dai; 275 struct snd_soc_dai *codec_dai;
276 int i; 276 int i;
277 277
278 mutex_lock(&pcm_mutex); 278 mutex_lock(&pcm_mutex);
279 for(i = 0; i < codec->num_dai; i++) { 279 for (i = 0; i < codec->num_dai; i++) {
280 codec_dai = &codec->dai[i]; 280 codec_dai = &codec->dai[i];
281 281
282 dbg("pop wq checking: %s status: %s waiting: %s\n", 282 dbg("pop wq checking: %s status: %s waiting: %s\n",
@@ -287,12 +287,12 @@ static void close_delayed_work(struct work_struct *work)
287 /* are we waiting on this codec DAI stream */ 287 /* are we waiting on this codec DAI stream */
288 if (codec_dai->pop_wait == 1) { 288 if (codec_dai->pop_wait == 1) {
289 289
290 /* power down the codec to D1 if no longer active */ 290 /* Reduce power if no longer active */
291 if (codec->active == 0) { 291 if (codec->active == 0) {
292 dbg("pop wq D1 %s %s\n", codec->name, 292 dbg("pop wq D1 %s %s\n", codec->name,
293 codec_dai->playback.stream_name); 293 codec_dai->playback.stream_name);
294 snd_soc_dapm_device_event(socdev, 294 snd_soc_dapm_set_bias_level(socdev,
295 SNDRV_CTL_POWER_D1); 295 SND_SOC_BIAS_PREPARE);
296 } 296 }
297 297
298 codec_dai->pop_wait = 0; 298 codec_dai->pop_wait = 0;
@@ -300,12 +300,12 @@ static void close_delayed_work(struct work_struct *work)
300 codec_dai->playback.stream_name, 300 codec_dai->playback.stream_name,
301 SND_SOC_DAPM_STREAM_STOP); 301 SND_SOC_DAPM_STREAM_STOP);
302 302
303 /* power down the codec power domain if no longer active */ 303 /* Fall into standby if no longer active */
304 if (codec->active == 0) { 304 if (codec->active == 0) {
305 dbg("pop wq D3 %s %s\n", codec->name, 305 dbg("pop wq D3 %s %s\n", codec->name,
306 codec_dai->playback.stream_name); 306 codec_dai->playback.stream_name);
307 snd_soc_dapm_device_event(socdev, 307 snd_soc_dapm_set_bias_level(socdev,
308 SNDRV_CTL_POWER_D3hot); 308 SND_SOC_BIAS_STANDBY);
309 } 309 }
310 } 310 }
311 } 311 }
@@ -323,8 +323,8 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
323 struct snd_soc_device *socdev = rtd->socdev; 323 struct snd_soc_device *socdev = rtd->socdev;
324 struct snd_soc_dai_link *machine = rtd->dai; 324 struct snd_soc_dai_link *machine = rtd->dai;
325 struct snd_soc_platform *platform = socdev->platform; 325 struct snd_soc_platform *platform = socdev->platform;
326 struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai; 326 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
327 struct snd_soc_codec_dai *codec_dai = machine->codec_dai; 327 struct snd_soc_dai *codec_dai = machine->codec_dai;
328 struct snd_soc_codec *codec = socdev->codec; 328 struct snd_soc_codec *codec = socdev->codec;
329 329
330 mutex_lock(&pcm_mutex); 330 mutex_lock(&pcm_mutex);
@@ -365,8 +365,8 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
365 SND_SOC_DAPM_STREAM_STOP); 365 SND_SOC_DAPM_STREAM_STOP);
366 366
367 if (codec->active == 0 && codec_dai->pop_wait == 0) 367 if (codec->active == 0 && codec_dai->pop_wait == 0)
368 snd_soc_dapm_device_event(socdev, 368 snd_soc_dapm_set_bias_level(socdev,
369 SNDRV_CTL_POWER_D3hot); 369 SND_SOC_BIAS_STANDBY);
370 } 370 }
371 371
372 mutex_unlock(&pcm_mutex); 372 mutex_unlock(&pcm_mutex);
@@ -384,8 +384,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
384 struct snd_soc_device *socdev = rtd->socdev; 384 struct snd_soc_device *socdev = rtd->socdev;
385 struct snd_soc_dai_link *machine = rtd->dai; 385 struct snd_soc_dai_link *machine = rtd->dai;
386 struct snd_soc_platform *platform = socdev->platform; 386 struct snd_soc_platform *platform = socdev->platform;
387 struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai; 387 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
388 struct snd_soc_codec_dai *codec_dai = machine->codec_dai; 388 struct snd_soc_dai *codec_dai = machine->codec_dai;
389 struct snd_soc_codec *codec = socdev->codec; 389 struct snd_soc_codec *codec = socdev->codec;
390 int ret = 0; 390 int ret = 0;
391 391
@@ -434,14 +434,14 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
434 else { 434 else {
435 codec_dai->pop_wait = 0; 435 codec_dai->pop_wait = 0;
436 cancel_delayed_work(&socdev->delayed_work); 436 cancel_delayed_work(&socdev->delayed_work);
437 if (codec_dai->dai_ops.digital_mute) 437 snd_soc_dai_digital_mute(codec_dai, 0);
438 codec_dai->dai_ops.digital_mute(codec_dai, 0);
439 } 438 }
440 } else { 439 } else {
441 /* no delayed work - do we need to power up codec */ 440 /* no delayed work - do we need to power up codec */
442 if (codec->dapm_state != SNDRV_CTL_POWER_D0) { 441 if (codec->bias_level != SND_SOC_BIAS_ON) {
443 442
444 snd_soc_dapm_device_event(socdev, SNDRV_CTL_POWER_D1); 443 snd_soc_dapm_set_bias_level(socdev,
444 SND_SOC_BIAS_PREPARE);
445 445
446 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 446 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
447 snd_soc_dapm_stream_event(codec, 447 snd_soc_dapm_stream_event(codec,
@@ -452,9 +452,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
452 codec_dai->capture.stream_name, 452 codec_dai->capture.stream_name,
453 SND_SOC_DAPM_STREAM_START); 453 SND_SOC_DAPM_STREAM_START);
454 454
455 snd_soc_dapm_device_event(socdev, SNDRV_CTL_POWER_D0); 455 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON);
456 if (codec_dai->dai_ops.digital_mute) 456 snd_soc_dai_digital_mute(codec_dai, 0);
457 codec_dai->dai_ops.digital_mute(codec_dai, 0);
458 457
459 } else { 458 } else {
460 /* codec already powered - power on widgets */ 459 /* codec already powered - power on widgets */
@@ -466,8 +465,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
466 snd_soc_dapm_stream_event(codec, 465 snd_soc_dapm_stream_event(codec,
467 codec_dai->capture.stream_name, 466 codec_dai->capture.stream_name,
468 SND_SOC_DAPM_STREAM_START); 467 SND_SOC_DAPM_STREAM_START);
469 if (codec_dai->dai_ops.digital_mute) 468
470 codec_dai->dai_ops.digital_mute(codec_dai, 0); 469 snd_soc_dai_digital_mute(codec_dai, 0);
471 } 470 }
472 } 471 }
473 472
@@ -488,8 +487,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
488 struct snd_soc_device *socdev = rtd->socdev; 487 struct snd_soc_device *socdev = rtd->socdev;
489 struct snd_soc_dai_link *machine = rtd->dai; 488 struct snd_soc_dai_link *machine = rtd->dai;
490 struct snd_soc_platform *platform = socdev->platform; 489 struct snd_soc_platform *platform = socdev->platform;
491 struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai; 490 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
492 struct snd_soc_codec_dai *codec_dai = machine->codec_dai; 491 struct snd_soc_dai *codec_dai = machine->codec_dai;
493 int ret = 0; 492 int ret = 0;
494 493
495 mutex_lock(&pcm_mutex); 494 mutex_lock(&pcm_mutex);
@@ -514,7 +513,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
514 if (cpu_dai->ops.hw_params) { 513 if (cpu_dai->ops.hw_params) {
515 ret = cpu_dai->ops.hw_params(substream, params); 514 ret = cpu_dai->ops.hw_params(substream, params);
516 if (ret < 0) { 515 if (ret < 0) {
517 printk(KERN_ERR "asoc: can't set interface %s hw params\n", 516 printk(KERN_ERR "asoc: interface %s hw params failed\n",
518 cpu_dai->name); 517 cpu_dai->name);
519 goto interface_err; 518 goto interface_err;
520 } 519 }
@@ -523,7 +522,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
523 if (platform->pcm_ops->hw_params) { 522 if (platform->pcm_ops->hw_params) {
524 ret = platform->pcm_ops->hw_params(substream, params); 523 ret = platform->pcm_ops->hw_params(substream, params);
525 if (ret < 0) { 524 if (ret < 0) {
526 printk(KERN_ERR "asoc: can't set platform %s hw params\n", 525 printk(KERN_ERR "asoc: platform %s hw params failed\n",
527 platform->name); 526 platform->name);
528 goto platform_err; 527 goto platform_err;
529 } 528 }
@@ -542,7 +541,7 @@ interface_err:
542 codec_dai->ops.hw_free(substream); 541 codec_dai->ops.hw_free(substream);
543 542
544codec_err: 543codec_err:
545 if(machine->ops && machine->ops->hw_free) 544 if (machine->ops && machine->ops->hw_free)
546 machine->ops->hw_free(substream); 545 machine->ops->hw_free(substream);
547 546
548 mutex_unlock(&pcm_mutex); 547 mutex_unlock(&pcm_mutex);
@@ -558,15 +557,15 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
558 struct snd_soc_device *socdev = rtd->socdev; 557 struct snd_soc_device *socdev = rtd->socdev;
559 struct snd_soc_dai_link *machine = rtd->dai; 558 struct snd_soc_dai_link *machine = rtd->dai;
560 struct snd_soc_platform *platform = socdev->platform; 559 struct snd_soc_platform *platform = socdev->platform;
561 struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai; 560 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
562 struct snd_soc_codec_dai *codec_dai = machine->codec_dai; 561 struct snd_soc_dai *codec_dai = machine->codec_dai;
563 struct snd_soc_codec *codec = socdev->codec; 562 struct snd_soc_codec *codec = socdev->codec;
564 563
565 mutex_lock(&pcm_mutex); 564 mutex_lock(&pcm_mutex);
566 565
567 /* apply codec digital mute */ 566 /* apply codec digital mute */
568 if (!codec->active && codec_dai->dai_ops.digital_mute) 567 if (!codec->active)
569 codec_dai->dai_ops.digital_mute(codec_dai, 1); 568 snd_soc_dai_digital_mute(codec_dai, 1);
570 569
571 /* free any machine hw params */ 570 /* free any machine hw params */
572 if (machine->ops && machine->ops->hw_free) 571 if (machine->ops && machine->ops->hw_free)
@@ -593,8 +592,8 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
593 struct snd_soc_device *socdev = rtd->socdev; 592 struct snd_soc_device *socdev = rtd->socdev;
594 struct snd_soc_dai_link *machine = rtd->dai; 593 struct snd_soc_dai_link *machine = rtd->dai;
595 struct snd_soc_platform *platform = socdev->platform; 594 struct snd_soc_platform *platform = socdev->platform;
596 struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai; 595 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
597 struct snd_soc_codec_dai *codec_dai = machine->codec_dai; 596 struct snd_soc_dai *codec_dai = machine->codec_dai;
598 int ret; 597 int ret;
599 598
600 if (codec_dai->ops.trigger) { 599 if (codec_dai->ops.trigger) {
@@ -631,16 +630,26 @@ static struct snd_pcm_ops soc_pcm_ops = {
631/* powers down audio subsystem for suspend */ 630/* powers down audio subsystem for suspend */
632static int soc_suspend(struct platform_device *pdev, pm_message_t state) 631static int soc_suspend(struct platform_device *pdev, pm_message_t state)
633{ 632{
634 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 633 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
635 struct snd_soc_machine *machine = socdev->machine; 634 struct snd_soc_machine *machine = socdev->machine;
636 struct snd_soc_platform *platform = socdev->platform; 635 struct snd_soc_platform *platform = socdev->platform;
637 struct snd_soc_codec_device *codec_dev = socdev->codec_dev; 636 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
638 struct snd_soc_codec *codec = socdev->codec; 637 struct snd_soc_codec *codec = socdev->codec;
639 int i; 638 int i;
640 639
640 /* Due to the resume being scheduled into a workqueue we could
641 * suspend before that's finished - wait for it to complete.
642 */
643 snd_power_lock(codec->card);
644 snd_power_wait(codec->card, SNDRV_CTL_POWER_D0);
645 snd_power_unlock(codec->card);
646
647 /* we're going to block userspace touching us until resume completes */
648 snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot);
649
641 /* mute any active DAC's */ 650 /* mute any active DAC's */
642 for(i = 0; i < machine->num_links; i++) { 651 for (i = 0; i < machine->num_links; i++) {
643 struct snd_soc_codec_dai *dai = machine->dai_link[i].codec_dai; 652 struct snd_soc_dai *dai = machine->dai_link[i].codec_dai;
644 if (dai->dai_ops.digital_mute && dai->playback.active) 653 if (dai->dai_ops.digital_mute && dai->playback.active)
645 dai->dai_ops.digital_mute(dai, 1); 654 dai->dai_ops.digital_mute(dai, 1);
646 } 655 }
@@ -652,8 +661,8 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
652 if (machine->suspend_pre) 661 if (machine->suspend_pre)
653 machine->suspend_pre(pdev, state); 662 machine->suspend_pre(pdev, state);
654 663
655 for(i = 0; i < machine->num_links; i++) { 664 for (i = 0; i < machine->num_links; i++) {
656 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai; 665 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
657 if (cpu_dai->suspend && cpu_dai->type != SND_SOC_DAI_AC97) 666 if (cpu_dai->suspend && cpu_dai->type != SND_SOC_DAI_AC97)
658 cpu_dai->suspend(pdev, cpu_dai); 667 cpu_dai->suspend(pdev, cpu_dai);
659 if (platform->suspend) 668 if (platform->suspend)
@@ -662,9 +671,9 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
662 671
663 /* close any waiting streams and save state */ 672 /* close any waiting streams and save state */
664 run_delayed_work(&socdev->delayed_work); 673 run_delayed_work(&socdev->delayed_work);
665 codec->suspend_dapm_state = codec->dapm_state; 674 codec->suspend_bias_level = codec->bias_level;
666 675
667 for(i = 0; i < codec->num_dai; i++) { 676 for (i = 0; i < codec->num_dai; i++) {
668 char *stream = codec->dai[i].playback.stream_name; 677 char *stream = codec->dai[i].playback.stream_name;
669 if (stream != NULL) 678 if (stream != NULL)
670 snd_soc_dapm_stream_event(codec, stream, 679 snd_soc_dapm_stream_event(codec, stream,
@@ -678,8 +687,8 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
678 if (codec_dev->suspend) 687 if (codec_dev->suspend)
679 codec_dev->suspend(pdev, state); 688 codec_dev->suspend(pdev, state);
680 689
681 for(i = 0; i < machine->num_links; i++) { 690 for (i = 0; i < machine->num_links; i++) {
682 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai; 691 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
683 if (cpu_dai->suspend && cpu_dai->type == SND_SOC_DAI_AC97) 692 if (cpu_dai->suspend && cpu_dai->type == SND_SOC_DAI_AC97)
684 cpu_dai->suspend(pdev, cpu_dai); 693 cpu_dai->suspend(pdev, cpu_dai);
685 } 694 }
@@ -690,21 +699,32 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
690 return 0; 699 return 0;
691} 700}
692 701
693/* powers up audio subsystem after a suspend */ 702/* deferred resume work, so resume can complete before we finished
694static int soc_resume(struct platform_device *pdev) 703 * setting our codec back up, which can be very slow on I2C
704 */
705static void soc_resume_deferred(struct work_struct *work)
695{ 706{
696 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 707 struct snd_soc_device *socdev = container_of(work,
697 struct snd_soc_machine *machine = socdev->machine; 708 struct snd_soc_device,
698 struct snd_soc_platform *platform = socdev->platform; 709 deferred_resume_work);
699 struct snd_soc_codec_device *codec_dev = socdev->codec_dev; 710 struct snd_soc_machine *machine = socdev->machine;
711 struct snd_soc_platform *platform = socdev->platform;
712 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
700 struct snd_soc_codec *codec = socdev->codec; 713 struct snd_soc_codec *codec = socdev->codec;
714 struct platform_device *pdev = to_platform_device(socdev->dev);
701 int i; 715 int i;
702 716
717 /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time,
718 * so userspace apps are blocked from touching us
719 */
720
721 dev_info(socdev->dev, "starting resume work\n");
722
703 if (machine->resume_pre) 723 if (machine->resume_pre)
704 machine->resume_pre(pdev); 724 machine->resume_pre(pdev);
705 725
706 for(i = 0; i < machine->num_links; i++) { 726 for (i = 0; i < machine->num_links; i++) {
707 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai; 727 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
708 if (cpu_dai->resume && cpu_dai->type == SND_SOC_DAI_AC97) 728 if (cpu_dai->resume && cpu_dai->type == SND_SOC_DAI_AC97)
709 cpu_dai->resume(pdev, cpu_dai); 729 cpu_dai->resume(pdev, cpu_dai);
710 } 730 }
@@ -712,8 +732,8 @@ static int soc_resume(struct platform_device *pdev)
712 if (codec_dev->resume) 732 if (codec_dev->resume)
713 codec_dev->resume(pdev); 733 codec_dev->resume(pdev);
714 734
715 for(i = 0; i < codec->num_dai; i++) { 735 for (i = 0; i < codec->num_dai; i++) {
716 char* stream = codec->dai[i].playback.stream_name; 736 char *stream = codec->dai[i].playback.stream_name;
717 if (stream != NULL) 737 if (stream != NULL)
718 snd_soc_dapm_stream_event(codec, stream, 738 snd_soc_dapm_stream_event(codec, stream,
719 SND_SOC_DAPM_STREAM_RESUME); 739 SND_SOC_DAPM_STREAM_RESUME);
@@ -723,15 +743,15 @@ static int soc_resume(struct platform_device *pdev)
723 SND_SOC_DAPM_STREAM_RESUME); 743 SND_SOC_DAPM_STREAM_RESUME);
724 } 744 }
725 745
726 /* unmute any active DAC's */ 746 /* unmute any active DACs */
727 for(i = 0; i < machine->num_links; i++) { 747 for (i = 0; i < machine->num_links; i++) {
728 struct snd_soc_codec_dai *dai = machine->dai_link[i].codec_dai; 748 struct snd_soc_dai *dai = machine->dai_link[i].codec_dai;
729 if (dai->dai_ops.digital_mute && dai->playback.active) 749 if (dai->dai_ops.digital_mute && dai->playback.active)
730 dai->dai_ops.digital_mute(dai, 0); 750 dai->dai_ops.digital_mute(dai, 0);
731 } 751 }
732 752
733 for(i = 0; i < machine->num_links; i++) { 753 for (i = 0; i < machine->num_links; i++) {
734 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai; 754 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
735 if (cpu_dai->resume && cpu_dai->type != SND_SOC_DAI_AC97) 755 if (cpu_dai->resume && cpu_dai->type != SND_SOC_DAI_AC97)
736 cpu_dai->resume(pdev, cpu_dai); 756 cpu_dai->resume(pdev, cpu_dai);
737 if (platform->resume) 757 if (platform->resume)
@@ -741,6 +761,22 @@ static int soc_resume(struct platform_device *pdev)
741 if (machine->resume_post) 761 if (machine->resume_post)
742 machine->resume_post(pdev); 762 machine->resume_post(pdev);
743 763
764 dev_info(socdev->dev, "resume work completed\n");
765
766 /* userspace can access us now we are back as we were before */
767 snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0);
768}
769
770/* powers up audio subsystem after a suspend */
771static int soc_resume(struct platform_device *pdev)
772{
773 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
774
775 dev_info(socdev->dev, "scheduling resume work\n");
776
777 if (!schedule_work(&socdev->deferred_resume_work))
778 dev_err(socdev->dev, "work item may be lost\n");
779
744 return 0; 780 return 0;
745} 781}
746 782
@@ -760,33 +796,38 @@ static int soc_probe(struct platform_device *pdev)
760 796
761 if (machine->probe) { 797 if (machine->probe) {
762 ret = machine->probe(pdev); 798 ret = machine->probe(pdev);
763 if(ret < 0) 799 if (ret < 0)
764 return ret; 800 return ret;
765 } 801 }
766 802
767 for (i = 0; i < machine->num_links; i++) { 803 for (i = 0; i < machine->num_links; i++) {
768 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai; 804 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
769 if (cpu_dai->probe) { 805 if (cpu_dai->probe) {
770 ret = cpu_dai->probe(pdev); 806 ret = cpu_dai->probe(pdev, cpu_dai);
771 if(ret < 0) 807 if (ret < 0)
772 goto cpu_dai_err; 808 goto cpu_dai_err;
773 } 809 }
774 } 810 }
775 811
776 if (codec_dev->probe) { 812 if (codec_dev->probe) {
777 ret = codec_dev->probe(pdev); 813 ret = codec_dev->probe(pdev);
778 if(ret < 0) 814 if (ret < 0)
779 goto cpu_dai_err; 815 goto cpu_dai_err;
780 } 816 }
781 817
782 if (platform->probe) { 818 if (platform->probe) {
783 ret = platform->probe(pdev); 819 ret = platform->probe(pdev);
784 if(ret < 0) 820 if (ret < 0)
785 goto platform_err; 821 goto platform_err;
786 } 822 }
787 823
788 /* DAPM stream work */ 824 /* DAPM stream work */
789 INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work); 825 INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work);
826#ifdef CONFIG_PM
827 /* deferred resume work */
828 INIT_WORK(&socdev->deferred_resume_work, soc_resume_deferred);
829#endif
830
790 return 0; 831 return 0;
791 832
792platform_err: 833platform_err:
@@ -795,9 +836,9 @@ platform_err:
795 836
796cpu_dai_err: 837cpu_dai_err:
797 for (i--; i >= 0; i--) { 838 for (i--; i >= 0; i--) {
798 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai; 839 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
799 if (cpu_dai->remove) 840 if (cpu_dai->remove)
800 cpu_dai->remove(pdev); 841 cpu_dai->remove(pdev, cpu_dai);
801 } 842 }
802 843
803 if (machine->remove) 844 if (machine->remove)
@@ -824,9 +865,9 @@ static int soc_remove(struct platform_device *pdev)
824 codec_dev->remove(pdev); 865 codec_dev->remove(pdev);
825 866
826 for (i = 0; i < machine->num_links; i++) { 867 for (i = 0; i < machine->num_links; i++) {
827 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai; 868 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
828 if (cpu_dai->remove) 869 if (cpu_dai->remove)
829 cpu_dai->remove(pdev); 870 cpu_dai->remove(pdev, cpu_dai);
830 } 871 }
831 872
832 if (machine->remove) 873 if (machine->remove)
@@ -852,8 +893,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
852 struct snd_soc_dai_link *dai_link, int num) 893 struct snd_soc_dai_link *dai_link, int num)
853{ 894{
854 struct snd_soc_codec *codec = socdev->codec; 895 struct snd_soc_codec *codec = socdev->codec;
855 struct snd_soc_codec_dai *codec_dai = dai_link->codec_dai; 896 struct snd_soc_dai *codec_dai = dai_link->codec_dai;
856 struct snd_soc_cpu_dai *cpu_dai = dai_link->cpu_dai; 897 struct snd_soc_dai *cpu_dai = dai_link->cpu_dai;
857 struct snd_soc_pcm_runtime *rtd; 898 struct snd_soc_pcm_runtime *rtd;
858 struct snd_pcm *pcm; 899 struct snd_pcm *pcm;
859 char new_name[64]; 900 char new_name[64];
@@ -868,7 +909,7 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
868 codec_dai->codec = socdev->codec; 909 codec_dai->codec = socdev->codec;
869 910
870 /* check client and interface hw capabilities */ 911 /* check client and interface hw capabilities */
871 sprintf(new_name, "%s %s-%s-%d",dai_link->stream_name, codec_dai->name, 912 sprintf(new_name, "%s %s-%s-%d", dai_link->stream_name, codec_dai->name,
872 get_dai_name(cpu_dai->type), num); 913 get_dai_name(cpu_dai->type), num);
873 914
874 if (codec_dai->playback.channels_min) 915 if (codec_dai->playback.channels_min)
@@ -879,7 +920,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
879 ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback, 920 ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback,
880 capture, &pcm); 921 capture, &pcm);
881 if (ret < 0) { 922 if (ret < 0) {
882 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name); 923 printk(KERN_ERR "asoc: can't create pcm for codec %s\n",
924 codec->name);
883 kfree(rtd); 925 kfree(rtd);
884 return ret; 926 return ret;
885 } 927 }
@@ -928,8 +970,9 @@ static ssize_t codec_reg_show(struct device *dev,
928 step = codec->reg_cache_step; 970 step = codec->reg_cache_step;
929 971
930 count += sprintf(buf, "%s registers\n", codec->name); 972 count += sprintf(buf, "%s registers\n", codec->name);
931 for(i = 0; i < codec->reg_cache_size; i += step) 973 for (i = 0; i < codec->reg_cache_size; i += step)
932 count += sprintf(buf + count, "%2x: %4x\n", i, codec->read(codec, i)); 974 count += sprintf(buf + count, "%2x: %4x\n", i,
975 codec->read(codec, i));
933 976
934 return count; 977 return count;
935} 978}
@@ -1072,7 +1115,7 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1072 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver)); 1115 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
1073 1116
1074 /* create the pcms */ 1117 /* create the pcms */
1075 for(i = 0; i < machine->num_links; i++) { 1118 for (i = 0; i < machine->num_links; i++) {
1076 ret = soc_new_pcm(socdev, &machine->dai_link[i], i); 1119 ret = soc_new_pcm(socdev, &machine->dai_link[i], i);
1077 if (ret < 0) { 1120 if (ret < 0) {
1078 printk(KERN_ERR "asoc: can't create pcm %s\n", 1121 printk(KERN_ERR "asoc: can't create pcm %s\n",
@@ -1102,7 +1145,7 @@ int snd_soc_register_card(struct snd_soc_device *socdev)
1102 struct snd_soc_machine *machine = socdev->machine; 1145 struct snd_soc_machine *machine = socdev->machine;
1103 int ret = 0, i, ac97 = 0, err = 0; 1146 int ret = 0, i, ac97 = 0, err = 0;
1104 1147
1105 for(i = 0; i < machine->num_links; i++) { 1148 for (i = 0; i < machine->num_links; i++) {
1106 if (socdev->machine->dai_link[i].init) { 1149 if (socdev->machine->dai_link[i].init) {
1107 err = socdev->machine->dai_link[i].init(codec); 1150 err = socdev->machine->dai_link[i].init(codec);
1108 if (err < 0) { 1151 if (err < 0) {
@@ -1111,7 +1154,7 @@ int snd_soc_register_card(struct snd_soc_device *socdev)
1111 continue; 1154 continue;
1112 } 1155 }
1113 } 1156 }
1114 if (socdev->machine->dai_link[i].codec_dai->type == 1157 if (socdev->machine->dai_link[i].codec_dai->type ==
1115 SND_SOC_DAI_AC97_BUS) 1158 SND_SOC_DAI_AC97_BUS)
1116 ac97 = 1; 1159 ac97 = 1;
1117 } 1160 }
@@ -1122,7 +1165,7 @@ int snd_soc_register_card(struct snd_soc_device *socdev)
1122 1165
1123 ret = snd_card_register(codec->card); 1166 ret = snd_card_register(codec->card);
1124 if (ret < 0) { 1167 if (ret < 0) {
1125 printk(KERN_ERR "asoc: failed to register soundcard for codec %s\n", 1168 printk(KERN_ERR "asoc: failed to register soundcard for %s\n",
1126 codec->name); 1169 codec->name);
1127 goto out; 1170 goto out;
1128 } 1171 }
@@ -1146,7 +1189,7 @@ int snd_soc_register_card(struct snd_soc_device *socdev)
1146 1189
1147 err = device_create_file(socdev->dev, &dev_attr_codec_reg); 1190 err = device_create_file(socdev->dev, &dev_attr_codec_reg);
1148 if (err < 0) 1191 if (err < 0)
1149 printk(KERN_WARNING "asoc: failed to add codec sysfs entries\n"); 1192 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
1150 1193
1151 mutex_unlock(&codec->mutex); 1194 mutex_unlock(&codec->mutex);
1152 1195
@@ -1166,13 +1209,13 @@ void snd_soc_free_pcms(struct snd_soc_device *socdev)
1166{ 1209{
1167 struct snd_soc_codec *codec = socdev->codec; 1210 struct snd_soc_codec *codec = socdev->codec;
1168#ifdef CONFIG_SND_SOC_AC97_BUS 1211#ifdef CONFIG_SND_SOC_AC97_BUS
1169 struct snd_soc_codec_dai *codec_dai; 1212 struct snd_soc_dai *codec_dai;
1170 int i; 1213 int i;
1171#endif 1214#endif
1172 1215
1173 mutex_lock(&codec->mutex); 1216 mutex_lock(&codec->mutex);
1174#ifdef CONFIG_SND_SOC_AC97_BUS 1217#ifdef CONFIG_SND_SOC_AC97_BUS
1175 for(i = 0; i < codec->num_dai; i++) { 1218 for (i = 0; i < codec->num_dai; i++) {
1176 codec_dai = &codec->dai[i]; 1219 codec_dai = &codec->dai[i];
1177 if (codec_dai->type == SND_SOC_DAI_AC97_BUS && codec->ac97) { 1220 if (codec_dai->type == SND_SOC_DAI_AC97_BUS && codec->ac97) {
1178 soc_ac97_dev_unregister(codec); 1221 soc_ac97_dev_unregister(codec);
@@ -1282,7 +1325,8 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
1282 for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) 1325 for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
1283 ; 1326 ;
1284 val = snd_soc_read(codec, e->reg); 1327 val = snd_soc_read(codec, e->reg);
1285 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); 1328 ucontrol->value.enumerated.item[0]
1329 = (val >> e->shift_l) & (bitmask - 1);
1286 if (e->shift_l != e->shift_r) 1330 if (e->shift_l != e->shift_r)
1287 ucontrol->value.enumerated.item[1] = 1331 ucontrol->value.enumerated.item[1] =
1288 (val >> e->shift_r) & (bitmask - 1); 1332 (val >> e->shift_r) & (bitmask - 1);
@@ -1576,7 +1620,8 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
1576 val = val << shift; 1620 val = val << shift;
1577 val2 = val2 << shift; 1621 val2 = val2 << shift;
1578 1622
1579 if ((err = snd_soc_update_bits(codec, reg, val_mask, val)) < 0) 1623 err = snd_soc_update_bits(codec, reg, val_mask, val);
1624 if (err < 0)
1580 return err; 1625 return err;
1581 1626
1582 err = snd_soc_update_bits(codec, reg2, val_mask, val2); 1627 err = snd_soc_update_bits(codec, reg2, val_mask, val2);
@@ -1584,6 +1629,204 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
1584} 1629}
1585EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r); 1630EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
1586 1631
1632/**
1633 * snd_soc_info_volsw_s8 - signed mixer info callback
1634 * @kcontrol: mixer control
1635 * @uinfo: control element information
1636 *
1637 * Callback to provide information about a signed mixer control.
1638 *
1639 * Returns 0 for success.
1640 */
1641int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
1642 struct snd_ctl_elem_info *uinfo)
1643{
1644 int max = (signed char)((kcontrol->private_value >> 16) & 0xff);
1645 int min = (signed char)((kcontrol->private_value >> 24) & 0xff);
1646
1647 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1648 uinfo->count = 2;
1649 uinfo->value.integer.min = 0;
1650 uinfo->value.integer.max = max-min;
1651 return 0;
1652}
1653EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8);
1654
1655/**
1656 * snd_soc_get_volsw_s8 - signed mixer get callback
1657 * @kcontrol: mixer control
1658 * @uinfo: control element information
1659 *
1660 * Callback to get the value of a signed mixer control.
1661 *
1662 * Returns 0 for success.
1663 */
1664int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
1665 struct snd_ctl_elem_value *ucontrol)
1666{
1667 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1668 int reg = kcontrol->private_value & 0xff;
1669 int min = (signed char)((kcontrol->private_value >> 24) & 0xff);
1670 int val = snd_soc_read(codec, reg);
1671
1672 ucontrol->value.integer.value[0] =
1673 ((signed char)(val & 0xff))-min;
1674 ucontrol->value.integer.value[1] =
1675 ((signed char)((val >> 8) & 0xff))-min;
1676 return 0;
1677}
1678EXPORT_SYMBOL_GPL(snd_soc_get_volsw_s8);
1679
1680/**
1681 * snd_soc_put_volsw_sgn - signed mixer put callback
1682 * @kcontrol: mixer control
1683 * @uinfo: control element information
1684 *
1685 * Callback to set the value of a signed mixer control.
1686 *
1687 * Returns 0 for success.
1688 */
1689int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
1690 struct snd_ctl_elem_value *ucontrol)
1691{
1692 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1693 int reg = kcontrol->private_value & 0xff;
1694 int min = (signed char)((kcontrol->private_value >> 24) & 0xff);
1695 unsigned short val;
1696
1697 val = (ucontrol->value.integer.value[0]+min) & 0xff;
1698 val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8;
1699
1700 return snd_soc_update_bits(codec, reg, 0xffff, val);
1701}
1702EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
1703
1704/**
1705 * snd_soc_dai_set_sysclk - configure DAI system or master clock.
1706 * @dai: DAI
1707 * @clk_id: DAI specific clock ID
1708 * @freq: new clock frequency in Hz
1709 * @dir: new clock direction - input/output.
1710 *
1711 * Configures the DAI master (MCLK) or system (SYSCLK) clocking.
1712 */
1713int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
1714 unsigned int freq, int dir)
1715{
1716 if (dai->dai_ops.set_sysclk)
1717 return dai->dai_ops.set_sysclk(dai, clk_id, freq, dir);
1718 else
1719 return -EINVAL;
1720}
1721EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
1722
1723/**
1724 * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
1725 * @dai: DAI
1726 * @clk_id: DAI specific clock divider ID
1727 * @div: new clock divisor.
1728 *
1729 * Configures the clock dividers. This is used to derive the best DAI bit and
1730 * frame clocks from the system or master clock. It's best to set the DAI bit
1731 * and frame clocks as low as possible to save system power.
1732 */
1733int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
1734 int div_id, int div)
1735{
1736 if (dai->dai_ops.set_clkdiv)
1737 return dai->dai_ops.set_clkdiv(dai, div_id, div);
1738 else
1739 return -EINVAL;
1740}
1741EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
1742
1743/**
1744 * snd_soc_dai_set_pll - configure DAI PLL.
1745 * @dai: DAI
1746 * @pll_id: DAI specific PLL ID
1747 * @freq_in: PLL input clock frequency in Hz
1748 * @freq_out: requested PLL output clock frequency in Hz
1749 *
1750 * Configures and enables PLL to generate output clock based on input clock.
1751 */
1752int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
1753 int pll_id, unsigned int freq_in, unsigned int freq_out)
1754{
1755 if (dai->dai_ops.set_pll)
1756 return dai->dai_ops.set_pll(dai, pll_id, freq_in, freq_out);
1757 else
1758 return -EINVAL;
1759}
1760EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
1761
1762/**
1763 * snd_soc_dai_set_fmt - configure DAI hardware audio format.
1764 * @dai: DAI
1765 * @clk_id: DAI specific clock ID
1766 * @fmt: SND_SOC_DAIFMT_ format value.
1767 *
1768 * Configures the DAI hardware format and clocking.
1769 */
1770int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1771{
1772 if (dai->dai_ops.set_fmt)
1773 return dai->dai_ops.set_fmt(dai, fmt);
1774 else
1775 return -EINVAL;
1776}
1777EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
1778
1779/**
1780 * snd_soc_dai_set_tdm_slot - configure DAI TDM.
1781 * @dai: DAI
1782 * @mask: DAI specific mask representing used slots.
1783 * @slots: Number of slots in use.
1784 *
1785 * Configures a DAI for TDM operation. Both mask and slots are codec and DAI
1786 * specific.
1787 */
1788int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
1789 unsigned int mask, int slots)
1790{
1791 if (dai->dai_ops.set_sysclk)
1792 return dai->dai_ops.set_tdm_slot(dai, mask, slots);
1793 else
1794 return -EINVAL;
1795}
1796EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
1797
1798/**
1799 * snd_soc_dai_set_tristate - configure DAI system or master clock.
1800 * @dai: DAI
1801 * @tristate: tristate enable
1802 *
1803 * Tristates the DAI so that others can use it.
1804 */
1805int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
1806{
1807 if (dai->dai_ops.set_sysclk)
1808 return dai->dai_ops.set_tristate(dai, tristate);
1809 else
1810 return -EINVAL;
1811}
1812EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
1813
1814/**
1815 * snd_soc_dai_digital_mute - configure DAI system or master clock.
1816 * @dai: DAI
1817 * @mute: mute enable
1818 *
1819 * Mutes the DAI DAC.
1820 */
1821int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
1822{
1823 if (dai->dai_ops.digital_mute)
1824 return dai->dai_ops.digital_mute(dai, mute);
1825 else
1826 return -EINVAL;
1827}
1828EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
1829
1587static int __devinit snd_soc_init(void) 1830static int __devinit snd_soc_init(void)
1588{ 1831{
1589 printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION); 1832 printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION);
@@ -1592,7 +1835,7 @@ static int __devinit snd_soc_init(void)
1592 1835
1593static void snd_soc_exit(void) 1836static void snd_soc_exit(void)
1594{ 1837{
1595 platform_driver_unregister(&soc_driver); 1838 platform_driver_unregister(&soc_driver);
1596} 1839}
1597 1840
1598module_init(snd_soc_init); 1841module_init(snd_soc_init);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index af3326c63504..2c87061c2a6b 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -10,11 +10,6 @@
10 * Free Software Foundation; either version 2 of the License, or (at your 10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
12 * 12 *
13 * Revision history
14 * 12th Aug 2005 Initial version.
15 * 25th Oct 2005 Implemented path power domain.
16 * 18th Dec 2005 Implemented machine and stream level power domain.
17 *
18 * Features: 13 * Features:
19 * o Changes power status of internal codec blocks depending on the 14 * o Changes power status of internal codec blocks depending on the
20 * dynamic configuration of codec internal audio paths and active 15 * dynamic configuration of codec internal audio paths and active
@@ -50,23 +45,10 @@
50#include <sound/initval.h> 45#include <sound/initval.h>
51 46
52/* debug */ 47/* debug */
53#define DAPM_DEBUG 0 48#ifdef DEBUG
54#if DAPM_DEBUG
55#define dump_dapm(codec, action) dbg_dump_dapm(codec, action) 49#define dump_dapm(codec, action) dbg_dump_dapm(codec, action)
56#define dbg(format, arg...) printk(format, ## arg)
57#else 50#else
58#define dump_dapm(codec, action) 51#define dump_dapm(codec, action)
59#define dbg(format, arg...)
60#endif
61
62#define POP_DEBUG 0
63#if POP_DEBUG
64#define POP_TIME 500 /* 500 msecs - change if pop debug is too fast */
65#define pop_wait(time) schedule_timeout_uninterruptible(msecs_to_jiffies(time))
66#define pop_dbg(format, arg...) printk(format, ## arg); pop_wait(POP_TIME)
67#else
68#define pop_dbg(format, arg...)
69#define pop_wait(time)
70#endif 52#endif
71 53
72/* dapm power sequences - make this per codec in the future */ 54/* dapm power sequences - make this per codec in the future */
@@ -85,6 +67,28 @@ static int dapm_status = 1;
85module_param(dapm_status, int, 0); 67module_param(dapm_status, int, 0);
86MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries"); 68MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
87 69
70static unsigned int pop_time;
71
72static void pop_wait(void)
73{
74 if (pop_time)
75 schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
76}
77
78static void pop_dbg(const char *fmt, ...)
79{
80 va_list args;
81
82 va_start(args, fmt);
83
84 if (pop_time) {
85 vprintk(fmt, args);
86 pop_wait();
87 }
88
89 va_end(args);
90}
91
88/* create a new dapm widget */ 92/* create a new dapm widget */
89static inline struct snd_soc_dapm_widget *dapm_cnew_widget( 93static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
90 const struct snd_soc_dapm_widget *_widget) 94 const struct snd_soc_dapm_widget *_widget)
@@ -222,11 +226,12 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
222 change = old != new; 226 change = old != new;
223 if (change) { 227 if (change) {
224 pop_dbg("pop test %s : %s in %d ms\n", widget->name, 228 pop_dbg("pop test %s : %s in %d ms\n", widget->name,
225 widget->power ? "on" : "off", POP_TIME); 229 widget->power ? "on" : "off", pop_time);
226 snd_soc_write(codec, widget->reg, new); 230 snd_soc_write(codec, widget->reg, new);
227 pop_wait(POP_TIME); 231 pop_wait();
228 } 232 }
229 dbg("reg %x old %x new %x change %d\n", widget->reg, old, new, change); 233 pr_debug("reg %x old %x new %x change %d\n", widget->reg,
234 old, new, change);
230 return change; 235 return change;
231} 236}
232 237
@@ -448,6 +453,25 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
448} 453}
449 454
450/* 455/*
456 * Handler for generic register modifier widget.
457 */
458int dapm_reg_event(struct snd_soc_dapm_widget *w,
459 struct snd_kcontrol *kcontrol, int event)
460{
461 unsigned int val;
462
463 if (SND_SOC_DAPM_EVENT_ON(event))
464 val = w->on_val;
465 else
466 val = w->off_val;
467
468 snd_soc_update_bits(w->codec, -(w->reg + 1),
469 w->mask << w->shift, val << w->shift);
470
471 return 0;
472}
473
474/*
451 * Scan each dapm widget for complete audio path. 475 * Scan each dapm widget for complete audio path.
452 * A complete path is a route that has valid endpoints i.e.:- 476 * A complete path is a route that has valid endpoints i.e.:-
453 * 477 *
@@ -565,8 +589,8 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
565 /* call any power change event handlers */ 589 /* call any power change event handlers */
566 if (power_change) { 590 if (power_change) {
567 if (w->event) { 591 if (w->event) {
568 dbg("power %s event for %s flags %x\n", 592 pr_debug("power %s event for %s flags %x\n",
569 w->power ? "on" : "off", w->name, w->event_flags); 593 w->power ? "on" : "off", w->name, w->event_flags);
570 if (power) { 594 if (power) {
571 /* power up event */ 595 /* power up event */
572 if (w->event_flags & SND_SOC_DAPM_PRE_PMU) { 596 if (w->event_flags & SND_SOC_DAPM_PRE_PMU) {
@@ -608,7 +632,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
608 return ret; 632 return ret;
609} 633}
610 634
611#if DAPM_DEBUG 635#ifdef DEBUG
612static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action) 636static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
613{ 637{
614 struct snd_soc_dapm_widget *w; 638 struct snd_soc_dapm_widget *w;
@@ -693,8 +717,10 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
693 path->connect = 0; /* old connection must be powered down */ 717 path->connect = 0; /* old connection must be powered down */
694 } 718 }
695 719
696 if (found) 720 if (found) {
697 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP); 721 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
722 dump_dapm(widget->codec, "mux power update");
723 }
698 724
699 return 0; 725 return 0;
700} 726}
@@ -730,8 +756,10 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
730 break; 756 break;
731 } 757 }
732 758
733 if (found) 759 if (found) {
734 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP); 760 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
761 dump_dapm(widget->codec, "mixer power update");
762 }
735 763
736 return 0; 764 return 0;
737} 765}
@@ -768,21 +796,18 @@ static ssize_t dapm_widget_show(struct device *dev,
768 } 796 }
769 } 797 }
770 798
771 switch(codec->dapm_state){ 799 switch (codec->bias_level) {
772 case SNDRV_CTL_POWER_D0: 800 case SND_SOC_BIAS_ON:
773 state = "D0"; 801 state = "On";
774 break; 802 break;
775 case SNDRV_CTL_POWER_D1: 803 case SND_SOC_BIAS_PREPARE:
776 state = "D1"; 804 state = "Prepare";
777 break; 805 break;
778 case SNDRV_CTL_POWER_D2: 806 case SND_SOC_BIAS_STANDBY:
779 state = "D2"; 807 state = "Standby";
780 break; 808 break;
781 case SNDRV_CTL_POWER_D3hot: 809 case SND_SOC_BIAS_OFF:
782 state = "D3hot"; 810 state = "Off";
783 break;
784 case SNDRV_CTL_POWER_D3cold:
785 state = "D3cold";
786 break; 811 break;
787 } 812 }
788 count += sprintf(buf + count, "PM State: %s\n", state); 813 count += sprintf(buf + count, "PM State: %s\n", state);
@@ -792,20 +817,51 @@ static ssize_t dapm_widget_show(struct device *dev,
792 817
793static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); 818static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
794 819
820/* pop/click delay times */
821static ssize_t dapm_pop_time_show(struct device *dev,
822 struct device_attribute *attr, char *buf)
823{
824 return sprintf(buf, "%d\n", pop_time);
825}
826
827static ssize_t dapm_pop_time_store(struct device *dev,
828 struct device_attribute *attr,
829 const char *buf, size_t count)
830
831{
832 unsigned long val;
833
834 if (strict_strtoul(buf, 10, &val) >= 0)
835 pop_time = val;
836 else
837 printk(KERN_ERR "Unable to parse pop_time setting\n");
838
839 return count;
840}
841
842static DEVICE_ATTR(dapm_pop_time, 0744, dapm_pop_time_show,
843 dapm_pop_time_store);
844
795int snd_soc_dapm_sys_add(struct device *dev) 845int snd_soc_dapm_sys_add(struct device *dev)
796{ 846{
797 int ret = 0; 847 int ret = 0;
798 848
799 if (dapm_status) 849 if (dapm_status) {
800 ret = device_create_file(dev, &dev_attr_dapm_widget); 850 ret = device_create_file(dev, &dev_attr_dapm_widget);
801 851
852 if (ret == 0)
853 ret = device_create_file(dev, &dev_attr_dapm_pop_time);
854 }
855
802 return ret; 856 return ret;
803} 857}
804 858
805static void snd_soc_dapm_sys_remove(struct device *dev) 859static void snd_soc_dapm_sys_remove(struct device *dev)
806{ 860{
807 if (dapm_status) 861 if (dapm_status) {
862 device_remove_file(dev, &dev_attr_dapm_pop_time);
808 device_remove_file(dev, &dev_attr_dapm_widget); 863 device_remove_file(dev, &dev_attr_dapm_widget);
864 }
809} 865}
810 866
811/* free all dapm widgets and resources */ 867/* free all dapm widgets and resources */
@@ -826,8 +882,25 @@ static void dapm_free_widgets(struct snd_soc_codec *codec)
826 } 882 }
827} 883}
828 884
885static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec,
886 char *pin, int status)
887{
888 struct snd_soc_dapm_widget *w;
889
890 list_for_each_entry(w, &codec->dapm_widgets, list) {
891 if (!strcmp(w->name, pin)) {
892 pr_debug("dapm: %s: pin %s\n", codec->name, pin);
893 w->connected = status;
894 return 0;
895 }
896 }
897
898 pr_err("dapm: %s: configuring unknown pin %s\n", codec->name, pin);
899 return -EINVAL;
900}
901
829/** 902/**
830 * snd_soc_dapm_sync_endpoints - scan and power dapm paths 903 * snd_soc_dapm_sync - scan and power dapm paths
831 * @codec: audio codec 904 * @codec: audio codec
832 * 905 *
833 * Walks all dapm audio paths and powers widgets according to their 906 * Walks all dapm audio paths and powers widgets according to their
@@ -835,27 +908,16 @@ static void dapm_free_widgets(struct snd_soc_codec *codec)
835 * 908 *
836 * Returns 0 for success. 909 * Returns 0 for success.
837 */ 910 */
838int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec) 911int snd_soc_dapm_sync(struct snd_soc_codec *codec)
839{ 912{
840 return dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP); 913 int ret = dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
914 dump_dapm(codec, "sync");
915 return ret;
841} 916}
842EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_endpoints); 917EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
843 918
844/** 919static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
845 * snd_soc_dapm_connect_input - connect dapm widgets 920 const char *sink, const char *control, const char *source)
846 * @codec: audio codec
847 * @sink: name of target widget
848 * @control: mixer control name
849 * @source: name of source name
850 *
851 * Connects 2 dapm widgets together via a named audio path. The sink is
852 * the widget receiving the audio signal, whilst the source is the sender
853 * of the audio signal.
854 *
855 * Returns 0 for success else error.
856 */
857int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
858 const char * control, const char *source)
859{ 921{
860 struct snd_soc_dapm_path *path; 922 struct snd_soc_dapm_path *path;
861 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; 923 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
@@ -957,9 +1019,64 @@ err:
957 kfree(path); 1019 kfree(path);
958 return ret; 1020 return ret;
959} 1021}
1022
1023/**
1024 * snd_soc_dapm_connect_input - connect dapm widgets
1025 * @codec: audio codec
1026 * @sink: name of target widget
1027 * @control: mixer control name
1028 * @source: name of source name
1029 *
1030 * Connects 2 dapm widgets together via a named audio path. The sink is
1031 * the widget receiving the audio signal, whilst the source is the sender
1032 * of the audio signal.
1033 *
1034 * This function has been deprecated in favour of snd_soc_dapm_add_routes().
1035 *
1036 * Returns 0 for success else error.
1037 */
1038int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
1039 const char *control, const char *source)
1040{
1041 return snd_soc_dapm_add_route(codec, sink, control, source);
1042}
960EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input); 1043EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input);
961 1044
962/** 1045/**
1046 * snd_soc_dapm_add_routes - Add routes between DAPM widgets
1047 * @codec: codec
1048 * @route: audio routes
1049 * @num: number of routes
1050 *
1051 * Connects 2 dapm widgets together via a named audio path. The sink is
1052 * the widget receiving the audio signal, whilst the source is the sender
1053 * of the audio signal.
1054 *
1055 * Returns 0 for success else error. On error all resources can be freed
1056 * with a call to snd_soc_card_free().
1057 */
1058int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
1059 const struct snd_soc_dapm_route *route, int num)
1060{
1061 int i, ret;
1062
1063 for (i = 0; i < num; i++) {
1064 ret = snd_soc_dapm_add_route(codec, route->sink,
1065 route->control, route->source);
1066 if (ret < 0) {
1067 printk(KERN_ERR "Failed to add route %s->%s\n",
1068 route->source,
1069 route->sink);
1070 return ret;
1071 }
1072 route++;
1073 }
1074
1075 return 0;
1076}
1077EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
1078
1079/**
963 * snd_soc_dapm_new_widgets - add new dapm widgets 1080 * snd_soc_dapm_new_widgets - add new dapm widgets
964 * @codec: audio codec 1081 * @codec: audio codec
965 * 1082 *
@@ -1234,6 +1351,33 @@ int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
1234EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control); 1351EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
1235 1352
1236/** 1353/**
1354 * snd_soc_dapm_new_controls - create new dapm controls
1355 * @codec: audio codec
1356 * @widget: widget array
1357 * @num: number of widgets
1358 *
1359 * Creates new DAPM controls based upon the templates.
1360 *
1361 * Returns 0 for success else error.
1362 */
1363int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
1364 const struct snd_soc_dapm_widget *widget,
1365 int num)
1366{
1367 int i, ret;
1368
1369 for (i = 0; i < num; i++) {
1370 ret = snd_soc_dapm_new_control(codec, widget);
1371 if (ret < 0)
1372 return ret;
1373 widget++;
1374 }
1375 return 0;
1376}
1377EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
1378
1379
1380/**
1237 * snd_soc_dapm_stream_event - send a stream event to the dapm core 1381 * snd_soc_dapm_stream_event - send a stream event to the dapm core
1238 * @codec: audio codec 1382 * @codec: audio codec
1239 * @stream: stream name 1383 * @stream: stream name
@@ -1257,8 +1401,8 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
1257 { 1401 {
1258 if (!w->sname) 1402 if (!w->sname)
1259 continue; 1403 continue;
1260 dbg("widget %s\n %s stream %s event %d\n", w->name, w->sname, 1404 pr_debug("widget %s\n %s stream %s event %d\n",
1261 stream, event); 1405 w->name, w->sname, stream, event);
1262 if (strstr(w->sname, stream)) { 1406 if (strstr(w->sname, stream)) {
1263 switch(event) { 1407 switch(event) {
1264 case SND_SOC_DAPM_STREAM_START: 1408 case SND_SOC_DAPM_STREAM_START:
@@ -1294,53 +1438,81 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
1294EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); 1438EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
1295 1439
1296/** 1440/**
1297 * snd_soc_dapm_device_event - send a device event to the dapm core 1441 * snd_soc_dapm_set_bias_level - set the bias level for the system
1298 * @socdev: audio device 1442 * @socdev: audio device
1299 * @event: device event 1443 * @level: level to configure
1300 * 1444 *
1301 * Sends a device event to the dapm core. The core then makes any 1445 * Configure the bias (power) levels for the SoC audio device.
1302 * necessary machine or codec power changes..
1303 * 1446 *
1304 * Returns 0 for success else error. 1447 * Returns 0 for success else error.
1305 */ 1448 */
1306int snd_soc_dapm_device_event(struct snd_soc_device *socdev, int event) 1449int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
1450 enum snd_soc_bias_level level)
1307{ 1451{
1308 struct snd_soc_codec *codec = socdev->codec; 1452 struct snd_soc_codec *codec = socdev->codec;
1309 struct snd_soc_machine *machine = socdev->machine; 1453 struct snd_soc_machine *machine = socdev->machine;
1454 int ret = 0;
1310 1455
1311 if (machine->dapm_event) 1456 if (machine->set_bias_level)
1312 machine->dapm_event(machine, event); 1457 ret = machine->set_bias_level(machine, level);
1313 if (codec->dapm_event) 1458 if (ret == 0 && codec->set_bias_level)
1314 codec->dapm_event(codec, event); 1459 ret = codec->set_bias_level(codec, level);
1315 return 0; 1460
1461 return ret;
1316} 1462}
1317EXPORT_SYMBOL_GPL(snd_soc_dapm_device_event);
1318 1463
1319/** 1464/**
1320 * snd_soc_dapm_set_endpoint - set audio endpoint status 1465 * snd_soc_dapm_enable_pin - enable pin.
1466 * @snd_soc_codec: SoC codec
1467 * @pin: pin name
1468 *
1469 * Enables input/output pin and it's parents or children widgets iff there is
1470 * a valid audio route and active audio stream.
1471 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1472 * do any widget power switching.
1473 */
1474int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin)
1475{
1476 return snd_soc_dapm_set_pin(codec, pin, 1);
1477}
1478EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
1479
1480/**
1481 * snd_soc_dapm_disable_pin - disable pin.
1482 * @codec: SoC codec
1483 * @pin: pin name
1484 *
1485 * Disables input/output pin and it's parents or children widgets.
1486 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1487 * do any widget power switching.
1488 */
1489int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin)
1490{
1491 return snd_soc_dapm_set_pin(codec, pin, 0);
1492}
1493EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
1494
1495/**
1496 * snd_soc_dapm_get_pin_status - get audio pin status
1321 * @codec: audio codec 1497 * @codec: audio codec
1322 * @endpoint: audio signal endpoint (or start point) 1498 * @pin: audio signal pin endpoint (or start point)
1323 * @status: point status
1324 * 1499 *
1325 * Set audio endpoint status - connected or disconnected. 1500 * Get audio pin status - connected or disconnected.
1326 * 1501 *
1327 * Returns 0 for success else error. 1502 * Returns 1 for connected otherwise 0.
1328 */ 1503 */
1329int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec, 1504int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin)
1330 char *endpoint, int status)
1331{ 1505{
1332 struct snd_soc_dapm_widget *w; 1506 struct snd_soc_dapm_widget *w;
1333 1507
1334 list_for_each_entry(w, &codec->dapm_widgets, list) { 1508 list_for_each_entry(w, &codec->dapm_widgets, list) {
1335 if (!strcmp(w->name, endpoint)) { 1509 if (!strcmp(w->name, pin))
1336 w->connected = status; 1510 return w->connected;
1337 return 0;
1338 }
1339 } 1511 }
1340 1512
1341 return -ENODEV; 1513 return 0;
1342} 1514}
1343EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint); 1515EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
1344 1516
1345/** 1517/**
1346 * snd_soc_dapm_free - free dapm resources 1518 * snd_soc_dapm_free - free dapm resources