diff options
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/Kconfig | 8 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 4 | ||||
-rw-r--r-- | sound/soc/codecs/ad1836.c | 1 | ||||
-rw-r--r-- | sound/soc/codecs/ad1938.c | 1 | ||||
-rw-r--r-- | sound/soc/codecs/ak4642.c | 502 | ||||
-rw-r--r-- | sound/soc/codecs/ak4642.h | 20 | ||||
-rw-r--r-- | sound/soc/codecs/ak4671.c | 825 | ||||
-rw-r--r-- | sound/soc/codecs/ak4671.h | 156 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic3x.c | 222 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic3x.h | 2 | ||||
-rw-r--r-- | sound/soc/codecs/wm8350.c | 13 | ||||
-rw-r--r-- | sound/soc/codecs/wm8400.c | 3 | ||||
-rw-r--r-- | sound/soc/codecs/wm8510.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/wm8580.c | 8 | ||||
-rw-r--r-- | sound/soc/codecs/wm8753.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/wm8900.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/wm8940.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/wm8960.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/wm8974.c | 5 | ||||
-rw-r--r-- | sound/soc/codecs/wm8990.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/wm8993.c | 90 | ||||
-rw-r--r-- | sound/soc/codecs/wm9705.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/wm9713.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/wm_hubs.c | 19 |
24 files changed, 1752 insertions, 157 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 20ebf7437f98..3c46f34928ec 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -18,6 +18,8 @@ config SND_SOC_ALL_CODECS | |||
18 | select SND_SOC_AD73311 if I2C | 18 | select SND_SOC_AD73311 if I2C |
19 | select SND_SOC_AK4104 if SPI_MASTER | 19 | select SND_SOC_AK4104 if SPI_MASTER |
20 | select SND_SOC_AK4535 if I2C | 20 | select SND_SOC_AK4535 if I2C |
21 | select SND_SOC_AK4642 if I2C | ||
22 | select SND_SOC_AK4671 if I2C | ||
21 | select SND_SOC_CS4270 if I2C | 23 | select SND_SOC_CS4270 if I2C |
22 | select SND_SOC_MAX9877 if I2C | 24 | select SND_SOC_MAX9877 if I2C |
23 | select SND_SOC_PCM3008 | 25 | select SND_SOC_PCM3008 |
@@ -93,6 +95,12 @@ config SND_SOC_AK4104 | |||
93 | config SND_SOC_AK4535 | 95 | config SND_SOC_AK4535 |
94 | tristate | 96 | tristate |
95 | 97 | ||
98 | config SND_SOC_AK4642 | ||
99 | tristate | ||
100 | |||
101 | config SND_SOC_AK4671 | ||
102 | tristate | ||
103 | |||
96 | # Cirrus Logic CS4270 Codec | 104 | # Cirrus Logic CS4270 Codec |
97 | config SND_SOC_CS4270 | 105 | config SND_SOC_CS4270 |
98 | tristate | 106 | tristate |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 711d8f5887de..fc1c458cbe2f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -5,6 +5,8 @@ snd-soc-ad1980-objs := ad1980.o | |||
5 | snd-soc-ad73311-objs := ad73311.o | 5 | snd-soc-ad73311-objs := ad73311.o |
6 | snd-soc-ak4104-objs := ak4104.o | 6 | snd-soc-ak4104-objs := ak4104.o |
7 | snd-soc-ak4535-objs := ak4535.o | 7 | snd-soc-ak4535-objs := ak4535.o |
8 | snd-soc-ak4642-objs := ak4642.o | ||
9 | snd-soc-ak4671-objs := ak4671.o | ||
8 | snd-soc-cs4270-objs := cs4270.o | 10 | snd-soc-cs4270-objs := cs4270.o |
9 | snd-soc-cx20442-objs := cx20442.o | 11 | snd-soc-cx20442-objs := cx20442.o |
10 | snd-soc-l3-objs := l3.o | 12 | snd-soc-l3-objs := l3.o |
@@ -55,6 +57,8 @@ obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o | |||
55 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o | 57 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o |
56 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o | 58 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o |
57 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o | 59 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o |
60 | obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o | ||
61 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o | ||
58 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o | 62 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o |
59 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | 63 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
60 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o | 64 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o |
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 3612bb92df90..01343dc984fd 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
@@ -18,7 +18,6 @@ | |||
18 | 18 | ||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/version.h> | ||
22 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
23 | #include <linux/device.h> | 22 | #include <linux/device.h> |
24 | #include <sound/core.h> | 23 | #include <sound/core.h> |
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c index e62b27701a49..9a049a1995a3 100644 --- a/sound/soc/codecs/ad1938.c +++ b/sound/soc/codecs/ad1938.c | |||
@@ -28,7 +28,6 @@ | |||
28 | 28 | ||
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/version.h> | ||
32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
33 | #include <linux/device.h> | 32 | #include <linux/device.h> |
34 | #include <sound/core.h> | 33 | #include <sound/core.h> |
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c new file mode 100644 index 000000000000..e057c7b578df --- /dev/null +++ b/sound/soc/codecs/ak4642.c | |||
@@ -0,0 +1,502 @@ | |||
1 | /* | ||
2 | * ak4642.c -- AK4642/AK4643 ALSA Soc Audio driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <morimoto.kuninori@renesas.com> | ||
6 | * | ||
7 | * Based on wm8731.c by Richard Purdie | ||
8 | * Based on ak4535.c by Richard Purdie | ||
9 | * Based on wm8753.c by Liam Girdwood | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | /* ** CAUTION ** | ||
17 | * | ||
18 | * This is very simple driver. | ||
19 | * It can use headphone output / stereo input only | ||
20 | * | ||
21 | * AK4642 is not tested. | ||
22 | * AK4643 is tested. | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/pm.h> | ||
30 | #include <linux/i2c.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <sound/core.h> | ||
33 | #include <sound/pcm.h> | ||
34 | #include <sound/pcm_params.h> | ||
35 | #include <sound/soc.h> | ||
36 | #include <sound/soc-dapm.h> | ||
37 | #include <sound/initval.h> | ||
38 | |||
39 | #include "ak4642.h" | ||
40 | |||
41 | #define AK4642_VERSION "0.0.1" | ||
42 | |||
43 | #define PW_MGMT1 0x00 | ||
44 | #define PW_MGMT2 0x01 | ||
45 | #define SG_SL1 0x02 | ||
46 | #define SG_SL2 0x03 | ||
47 | #define MD_CTL1 0x04 | ||
48 | #define MD_CTL2 0x05 | ||
49 | #define TIMER 0x06 | ||
50 | #define ALC_CTL1 0x07 | ||
51 | #define ALC_CTL2 0x08 | ||
52 | #define L_IVC 0x09 | ||
53 | #define L_DVC 0x0a | ||
54 | #define ALC_CTL3 0x0b | ||
55 | #define R_IVC 0x0c | ||
56 | #define R_DVC 0x0d | ||
57 | #define MD_CTL3 0x0e | ||
58 | #define MD_CTL4 0x0f | ||
59 | #define PW_MGMT3 0x10 | ||
60 | #define DF_S 0x11 | ||
61 | #define FIL3_0 0x12 | ||
62 | #define FIL3_1 0x13 | ||
63 | #define FIL3_2 0x14 | ||
64 | #define FIL3_3 0x15 | ||
65 | #define EQ_0 0x16 | ||
66 | #define EQ_1 0x17 | ||
67 | #define EQ_2 0x18 | ||
68 | #define EQ_3 0x19 | ||
69 | #define EQ_4 0x1a | ||
70 | #define EQ_5 0x1b | ||
71 | #define FIL1_0 0x1c | ||
72 | #define FIL1_1 0x1d | ||
73 | #define FIL1_2 0x1e | ||
74 | #define FIL1_3 0x1f | ||
75 | #define PW_MGMT4 0x20 | ||
76 | #define MD_CTL5 0x21 | ||
77 | #define LO_MS 0x22 | ||
78 | #define HP_MS 0x23 | ||
79 | #define SPK_MS 0x24 | ||
80 | |||
81 | #define AK4642_CACHEREGNUM 0x25 | ||
82 | |||
83 | struct snd_soc_codec_device soc_codec_dev_ak4642; | ||
84 | |||
85 | /* codec private data */ | ||
86 | struct ak4642_priv { | ||
87 | struct snd_soc_codec codec; | ||
88 | unsigned int sysclk; | ||
89 | }; | ||
90 | |||
91 | static struct snd_soc_codec *ak4642_codec; | ||
92 | |||
93 | /* | ||
94 | * ak4642 register cache | ||
95 | */ | ||
96 | static const u16 ak4642_reg[AK4642_CACHEREGNUM] = { | ||
97 | 0x0000, 0x0000, 0x0001, 0x0000, | ||
98 | 0x0002, 0x0000, 0x0000, 0x0000, | ||
99 | 0x00e1, 0x00e1, 0x0018, 0x0000, | ||
100 | 0x00e1, 0x0018, 0x0011, 0x0008, | ||
101 | 0x0000, 0x0000, 0x0000, 0x0000, | ||
102 | 0x0000, 0x0000, 0x0000, 0x0000, | ||
103 | 0x0000, 0x0000, 0x0000, 0x0000, | ||
104 | 0x0000, 0x0000, 0x0000, 0x0000, | ||
105 | 0x0000, 0x0000, 0x0000, 0x0000, | ||
106 | 0x0000, | ||
107 | }; | ||
108 | |||
109 | /* | ||
110 | * read ak4642 register cache | ||
111 | */ | ||
112 | static inline unsigned int ak4642_read_reg_cache(struct snd_soc_codec *codec, | ||
113 | unsigned int reg) | ||
114 | { | ||
115 | u16 *cache = codec->reg_cache; | ||
116 | if (reg >= AK4642_CACHEREGNUM) | ||
117 | return -1; | ||
118 | return cache[reg]; | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * write ak4642 register cache | ||
123 | */ | ||
124 | static inline void ak4642_write_reg_cache(struct snd_soc_codec *codec, | ||
125 | u16 reg, unsigned int value) | ||
126 | { | ||
127 | u16 *cache = codec->reg_cache; | ||
128 | if (reg >= AK4642_CACHEREGNUM) | ||
129 | return; | ||
130 | |||
131 | cache[reg] = value; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * write to the AK4642 register space | ||
136 | */ | ||
137 | static int ak4642_write(struct snd_soc_codec *codec, unsigned int reg, | ||
138 | unsigned int value) | ||
139 | { | ||
140 | u8 data[2]; | ||
141 | |||
142 | /* data is | ||
143 | * D15..D8 AK4642 register offset | ||
144 | * D7...D0 register data | ||
145 | */ | ||
146 | data[0] = reg & 0xff; | ||
147 | data[1] = value & 0xff; | ||
148 | |||
149 | if (codec->hw_write(codec->control_data, data, 2) == 2) { | ||
150 | ak4642_write_reg_cache(codec, reg, value); | ||
151 | return 0; | ||
152 | } else | ||
153 | return -EIO; | ||
154 | } | ||
155 | |||
156 | static int ak4642_sync(struct snd_soc_codec *codec) | ||
157 | { | ||
158 | u16 *cache = codec->reg_cache; | ||
159 | int i, r = 0; | ||
160 | |||
161 | for (i = 0; i < AK4642_CACHEREGNUM; i++) | ||
162 | r |= ak4642_write(codec, i, cache[i]); | ||
163 | |||
164 | return r; | ||
165 | }; | ||
166 | |||
167 | static int ak4642_dai_startup(struct snd_pcm_substream *substream, | ||
168 | struct snd_soc_dai *dai) | ||
169 | { | ||
170 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
171 | struct snd_soc_codec *codec = dai->codec; | ||
172 | |||
173 | if (is_play) { | ||
174 | /* | ||
175 | * start headphone output | ||
176 | * | ||
177 | * PLL, Master Mode | ||
178 | * Audio I/F Format :MSB justified (ADC & DAC) | ||
179 | * Sampling Frequency: 44.1kHz | ||
180 | * Digital Volume: −8dB | ||
181 | * Bass Boost Level : Middle | ||
182 | * | ||
183 | * This operation came from example code of | ||
184 | * "ASAHI KASEI AK4642" (japanese) manual p97. | ||
185 | * | ||
186 | * Example code use 0x39, 0x79 value for 0x01 address, | ||
187 | * But we need MCKO (0x02) bit now | ||
188 | */ | ||
189 | ak4642_write(codec, 0x05, 0x27); | ||
190 | ak4642_write(codec, 0x0f, 0x09); | ||
191 | ak4642_write(codec, 0x0e, 0x19); | ||
192 | ak4642_write(codec, 0x09, 0x91); | ||
193 | ak4642_write(codec, 0x0c, 0x91); | ||
194 | ak4642_write(codec, 0x0a, 0x28); | ||
195 | ak4642_write(codec, 0x0d, 0x28); | ||
196 | ak4642_write(codec, 0x00, 0x64); | ||
197 | ak4642_write(codec, 0x01, 0x3b); /* + MCKO bit */ | ||
198 | ak4642_write(codec, 0x01, 0x7b); /* + MCKO bit */ | ||
199 | } else { | ||
200 | /* | ||
201 | * start stereo input | ||
202 | * | ||
203 | * PLL Master Mode | ||
204 | * Audio I/F Format:MSB justified (ADC & DAC) | ||
205 | * Sampling Frequency:44.1kHz | ||
206 | * Pre MIC AMP:+20dB | ||
207 | * MIC Power On | ||
208 | * ALC setting:Refer to Table 35 | ||
209 | * ALC bit=“1” | ||
210 | * | ||
211 | * This operation came from example code of | ||
212 | * "ASAHI KASEI AK4642" (japanese) manual p94. | ||
213 | */ | ||
214 | ak4642_write(codec, 0x05, 0x27); | ||
215 | ak4642_write(codec, 0x02, 0x05); | ||
216 | ak4642_write(codec, 0x06, 0x3c); | ||
217 | ak4642_write(codec, 0x08, 0xe1); | ||
218 | ak4642_write(codec, 0x0b, 0x00); | ||
219 | ak4642_write(codec, 0x07, 0x21); | ||
220 | ak4642_write(codec, 0x00, 0x41); | ||
221 | ak4642_write(codec, 0x10, 0x01); | ||
222 | } | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static void ak4642_dai_shutdown(struct snd_pcm_substream *substream, | ||
228 | struct snd_soc_dai *dai) | ||
229 | { | ||
230 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
231 | struct snd_soc_codec *codec = dai->codec; | ||
232 | |||
233 | if (is_play) { | ||
234 | /* stop headphone output */ | ||
235 | ak4642_write(codec, 0x01, 0x3b); | ||
236 | ak4642_write(codec, 0x01, 0x0b); | ||
237 | ak4642_write(codec, 0x00, 0x40); | ||
238 | ak4642_write(codec, 0x0e, 0x11); | ||
239 | ak4642_write(codec, 0x0f, 0x08); | ||
240 | } else { | ||
241 | /* stop stereo input */ | ||
242 | ak4642_write(codec, 0x00, 0x40); | ||
243 | ak4642_write(codec, 0x10, 0x00); | ||
244 | ak4642_write(codec, 0x07, 0x01); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | static int ak4642_dai_set_sysclk(struct snd_soc_dai *codec_dai, | ||
249 | int clk_id, unsigned int freq, int dir) | ||
250 | { | ||
251 | struct snd_soc_codec *codec = codec_dai->codec; | ||
252 | struct ak4642_priv *ak4642 = codec->private_data; | ||
253 | |||
254 | ak4642->sysclk = freq; | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static struct snd_soc_dai_ops ak4642_dai_ops = { | ||
259 | .startup = ak4642_dai_startup, | ||
260 | .shutdown = ak4642_dai_shutdown, | ||
261 | .set_sysclk = ak4642_dai_set_sysclk, | ||
262 | }; | ||
263 | |||
264 | struct snd_soc_dai ak4642_dai = { | ||
265 | .name = "AK4642", | ||
266 | .playback = { | ||
267 | .stream_name = "Playback", | ||
268 | .channels_min = 1, | ||
269 | .channels_max = 2, | ||
270 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
271 | .formats = SNDRV_PCM_FMTBIT_S16_LE }, | ||
272 | .capture = { | ||
273 | .stream_name = "Capture", | ||
274 | .channels_min = 1, | ||
275 | .channels_max = 2, | ||
276 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
277 | .formats = SNDRV_PCM_FMTBIT_S16_LE }, | ||
278 | .ops = &ak4642_dai_ops, | ||
279 | }; | ||
280 | EXPORT_SYMBOL_GPL(ak4642_dai); | ||
281 | |||
282 | static int ak4642_resume(struct platform_device *pdev) | ||
283 | { | ||
284 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
285 | struct snd_soc_codec *codec = socdev->card->codec; | ||
286 | |||
287 | ak4642_sync(codec); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * initialise the AK4642 driver | ||
293 | * register the mixer and dsp interfaces with the kernel | ||
294 | */ | ||
295 | static int ak4642_init(struct ak4642_priv *ak4642) | ||
296 | { | ||
297 | struct snd_soc_codec *codec = &ak4642->codec; | ||
298 | int ret = 0; | ||
299 | |||
300 | if (ak4642_codec) { | ||
301 | dev_err(codec->dev, "Another ak4642 is registered\n"); | ||
302 | return -EINVAL; | ||
303 | } | ||
304 | |||
305 | mutex_init(&codec->mutex); | ||
306 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
307 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
308 | |||
309 | codec->private_data = ak4642; | ||
310 | codec->name = "AK4642"; | ||
311 | codec->owner = THIS_MODULE; | ||
312 | codec->read = ak4642_read_reg_cache; | ||
313 | codec->write = ak4642_write; | ||
314 | codec->dai = &ak4642_dai; | ||
315 | codec->num_dai = 1; | ||
316 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
317 | codec->reg_cache_size = ARRAY_SIZE(ak4642_reg); | ||
318 | codec->reg_cache = kmemdup(ak4642_reg, | ||
319 | sizeof(ak4642_reg), GFP_KERNEL); | ||
320 | |||
321 | if (!codec->reg_cache) | ||
322 | return -ENOMEM; | ||
323 | |||
324 | ak4642_dai.dev = codec->dev; | ||
325 | ak4642_codec = codec; | ||
326 | |||
327 | ret = snd_soc_register_codec(codec); | ||
328 | if (ret) { | ||
329 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
330 | goto reg_cache_err; | ||
331 | } | ||
332 | |||
333 | ret = snd_soc_register_dai(&ak4642_dai); | ||
334 | if (ret) { | ||
335 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
336 | snd_soc_unregister_codec(codec); | ||
337 | goto reg_cache_err; | ||
338 | } | ||
339 | |||
340 | /* | ||
341 | * clock setting | ||
342 | * | ||
343 | * Audio I/F Format: MSB justified (ADC & DAC) | ||
344 | * BICK frequency at Master Mode: 64fs | ||
345 | * Input Master Clock Select at PLL Mode: 11.2896MHz | ||
346 | * MCKO: Enable | ||
347 | * Sampling Frequency: 44.1kHz | ||
348 | * | ||
349 | * This operation came from example code of | ||
350 | * "ASAHI KASEI AK4642" (japanese) manual p89. | ||
351 | * | ||
352 | * please fix-me | ||
353 | */ | ||
354 | ak4642_write(codec, 0x01, 0x08); | ||
355 | ak4642_write(codec, 0x04, 0x4a); | ||
356 | ak4642_write(codec, 0x05, 0x27); | ||
357 | ak4642_write(codec, 0x00, 0x40); | ||
358 | ak4642_write(codec, 0x01, 0x0b); | ||
359 | |||
360 | return ret; | ||
361 | |||
362 | reg_cache_err: | ||
363 | kfree(codec->reg_cache); | ||
364 | codec->reg_cache = NULL; | ||
365 | |||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
370 | static int ak4642_i2c_probe(struct i2c_client *i2c, | ||
371 | const struct i2c_device_id *id) | ||
372 | { | ||
373 | struct ak4642_priv *ak4642; | ||
374 | struct snd_soc_codec *codec; | ||
375 | int ret; | ||
376 | |||
377 | ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL); | ||
378 | if (!ak4642) | ||
379 | return -ENOMEM; | ||
380 | |||
381 | codec = &ak4642->codec; | ||
382 | codec->dev = &i2c->dev; | ||
383 | |||
384 | i2c_set_clientdata(i2c, ak4642); | ||
385 | codec->control_data = i2c; | ||
386 | |||
387 | ret = ak4642_init(ak4642); | ||
388 | if (ret < 0) | ||
389 | printk(KERN_ERR "failed to initialise AK4642\n"); | ||
390 | |||
391 | return ret; | ||
392 | } | ||
393 | |||
394 | static int ak4642_i2c_remove(struct i2c_client *client) | ||
395 | { | ||
396 | struct ak4642_priv *ak4642 = i2c_get_clientdata(client); | ||
397 | |||
398 | snd_soc_unregister_dai(&ak4642_dai); | ||
399 | snd_soc_unregister_codec(&ak4642->codec); | ||
400 | kfree(ak4642->codec.reg_cache); | ||
401 | kfree(ak4642); | ||
402 | ak4642_codec = NULL; | ||
403 | |||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | static const struct i2c_device_id ak4642_i2c_id[] = { | ||
408 | { "ak4642", 0 }, | ||
409 | { "ak4643", 0 }, | ||
410 | { } | ||
411 | }; | ||
412 | MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id); | ||
413 | |||
414 | static struct i2c_driver ak4642_i2c_driver = { | ||
415 | .driver = { | ||
416 | .name = "AK4642 I2C Codec", | ||
417 | .owner = THIS_MODULE, | ||
418 | }, | ||
419 | .probe = ak4642_i2c_probe, | ||
420 | .remove = ak4642_i2c_remove, | ||
421 | .id_table = ak4642_i2c_id, | ||
422 | }; | ||
423 | |||
424 | #endif | ||
425 | |||
426 | static int ak4642_probe(struct platform_device *pdev) | ||
427 | { | ||
428 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
429 | int ret; | ||
430 | |||
431 | if (!ak4642_codec) { | ||
432 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
433 | return -ENODEV; | ||
434 | } | ||
435 | |||
436 | socdev->card->codec = ak4642_codec; | ||
437 | |||
438 | /* register pcms */ | ||
439 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
440 | if (ret < 0) { | ||
441 | printk(KERN_ERR "ak4642: failed to create pcms\n"); | ||
442 | goto pcm_err; | ||
443 | } | ||
444 | |||
445 | ret = snd_soc_init_card(socdev); | ||
446 | if (ret < 0) { | ||
447 | printk(KERN_ERR "ak4642: failed to register card\n"); | ||
448 | goto card_err; | ||
449 | } | ||
450 | |||
451 | dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION); | ||
452 | return ret; | ||
453 | |||
454 | card_err: | ||
455 | snd_soc_free_pcms(socdev); | ||
456 | snd_soc_dapm_free(socdev); | ||
457 | pcm_err: | ||
458 | return ret; | ||
459 | |||
460 | } | ||
461 | |||
462 | /* power down chip */ | ||
463 | static int ak4642_remove(struct platform_device *pdev) | ||
464 | { | ||
465 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
466 | |||
467 | snd_soc_free_pcms(socdev); | ||
468 | snd_soc_dapm_free(socdev); | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | struct snd_soc_codec_device soc_codec_dev_ak4642 = { | ||
474 | .probe = ak4642_probe, | ||
475 | .remove = ak4642_remove, | ||
476 | .resume = ak4642_resume, | ||
477 | }; | ||
478 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642); | ||
479 | |||
480 | static int __init ak4642_modinit(void) | ||
481 | { | ||
482 | int ret; | ||
483 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
484 | ret = i2c_add_driver(&ak4642_i2c_driver); | ||
485 | #endif | ||
486 | return ret; | ||
487 | |||
488 | } | ||
489 | module_init(ak4642_modinit); | ||
490 | |||
491 | static void __exit ak4642_exit(void) | ||
492 | { | ||
493 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
494 | i2c_del_driver(&ak4642_i2c_driver); | ||
495 | #endif | ||
496 | |||
497 | } | ||
498 | module_exit(ak4642_exit); | ||
499 | |||
500 | MODULE_DESCRIPTION("Soc AK4642 driver"); | ||
501 | MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>"); | ||
502 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/ak4642.h b/sound/soc/codecs/ak4642.h new file mode 100644 index 000000000000..e476833d314e --- /dev/null +++ b/sound/soc/codecs/ak4642.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * ak4642.h -- AK4642 Soc Audio driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <morimoto.kuninori@renesas.com> | ||
6 | * | ||
7 | * Based on ak4535.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #ifndef _AK4642_H | ||
15 | #define _AK4642_H | ||
16 | |||
17 | extern struct snd_soc_dai ak4642_dai; | ||
18 | extern struct snd_soc_codec_device soc_codec_dev_ak4642; | ||
19 | |||
20 | #endif | ||
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c new file mode 100644 index 000000000000..b61214d1c5de --- /dev/null +++ b/sound/soc/codecs/ak4671.c | |||
@@ -0,0 +1,825 @@ | |||
1 | /* | ||
2 | * ak4671.c -- audio driver for AK4671 | ||
3 | * | ||
4 | * Copyright (C) 2009 Samsung Electronics Co.Ltd | ||
5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <sound/soc-dapm.h> | ||
20 | #include <sound/initval.h> | ||
21 | #include <sound/tlv.h> | ||
22 | |||
23 | #include "ak4671.h" | ||
24 | |||
25 | static struct snd_soc_codec *ak4671_codec; | ||
26 | |||
27 | /* codec private data */ | ||
28 | struct ak4671_priv { | ||
29 | struct snd_soc_codec codec; | ||
30 | u8 reg_cache[AK4671_CACHEREGNUM]; | ||
31 | }; | ||
32 | |||
33 | /* ak4671 register cache & default register settings */ | ||
34 | static const u8 ak4671_reg[AK4671_CACHEREGNUM] = { | ||
35 | 0x00, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */ | ||
36 | 0xf6, /* AK4671_PLL_MODE_SELECT0 (0x01) */ | ||
37 | 0x00, /* AK4671_PLL_MODE_SELECT1 (0x02) */ | ||
38 | 0x02, /* AK4671_FORMAT_SELECT (0x03) */ | ||
39 | 0x00, /* AK4671_MIC_SIGNAL_SELECT (0x04) */ | ||
40 | 0x55, /* AK4671_MIC_AMP_GAIN (0x05) */ | ||
41 | 0x00, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */ | ||
42 | 0x00, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */ | ||
43 | 0xb5, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */ | ||
44 | 0x00, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */ | ||
45 | 0x00, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */ | ||
46 | 0x00, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */ | ||
47 | 0x00, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */ | ||
48 | 0x00, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */ | ||
49 | 0x00, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */ | ||
50 | 0x00, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */ | ||
51 | 0x00, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */ | ||
52 | 0x80, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */ | ||
53 | 0x91, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */ | ||
54 | 0x91, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */ | ||
55 | 0xe1, /* AK4671_ALC_REFERENCE_SELECT (0x14) */ | ||
56 | 0x00, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */ | ||
57 | 0x00, /* AK4671_ALC_TIMER_SELECT (0x16) */ | ||
58 | 0x00, /* AK4671_ALC_MODE_CONTROL (0x17) */ | ||
59 | 0x02, /* AK4671_MODE_CONTROL1 (0x18) */ | ||
60 | 0x01, /* AK4671_MODE_CONTROL2 (0x19) */ | ||
61 | 0x18, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */ | ||
62 | 0x18, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */ | ||
63 | 0x00, /* AK4671_SIDETONE_A_CONTROL (0x1c) */ | ||
64 | 0x02, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */ | ||
65 | 0x00, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */ | ||
66 | 0x00, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */ | ||
67 | 0x00, /* AK4671_FIL3_COEFFICIENT2 (0x20) */ | ||
68 | 0x00, /* AK4671_FIL3_COEFFICIENT3 (0x21) */ | ||
69 | 0x00, /* AK4671_EQ_COEFFICIENT0 (0x22) */ | ||
70 | 0x00, /* AK4671_EQ_COEFFICIENT1 (0x23) */ | ||
71 | 0x00, /* AK4671_EQ_COEFFICIENT2 (0x24) */ | ||
72 | 0x00, /* AK4671_EQ_COEFFICIENT3 (0x25) */ | ||
73 | 0x00, /* AK4671_EQ_COEFFICIENT4 (0x26) */ | ||
74 | 0x00, /* AK4671_EQ_COEFFICIENT5 (0x27) */ | ||
75 | 0xa9, /* AK4671_FIL1_COEFFICIENT0 (0x28) */ | ||
76 | 0x1f, /* AK4671_FIL1_COEFFICIENT1 (0x29) */ | ||
77 | 0xad, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */ | ||
78 | 0x20, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */ | ||
79 | 0x00, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */ | ||
80 | 0x00, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */ | ||
81 | 0x00, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */ | ||
82 | 0x00, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */ | ||
83 | 0x00, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */ | ||
84 | 0x00, /* this register not used */ | ||
85 | 0x00, /* AK4671_E1_COEFFICIENT0 (0x32) */ | ||
86 | 0x00, /* AK4671_E1_COEFFICIENT1 (0x33) */ | ||
87 | 0x00, /* AK4671_E1_COEFFICIENT2 (0x34) */ | ||
88 | 0x00, /* AK4671_E1_COEFFICIENT3 (0x35) */ | ||
89 | 0x00, /* AK4671_E1_COEFFICIENT4 (0x36) */ | ||
90 | 0x00, /* AK4671_E1_COEFFICIENT5 (0x37) */ | ||
91 | 0x00, /* AK4671_E2_COEFFICIENT0 (0x38) */ | ||
92 | 0x00, /* AK4671_E2_COEFFICIENT1 (0x39) */ | ||
93 | 0x00, /* AK4671_E2_COEFFICIENT2 (0x3a) */ | ||
94 | 0x00, /* AK4671_E2_COEFFICIENT3 (0x3b) */ | ||
95 | 0x00, /* AK4671_E2_COEFFICIENT4 (0x3c) */ | ||
96 | 0x00, /* AK4671_E2_COEFFICIENT5 (0x3d) */ | ||
97 | 0x00, /* AK4671_E3_COEFFICIENT0 (0x3e) */ | ||
98 | 0x00, /* AK4671_E3_COEFFICIENT1 (0x3f) */ | ||
99 | 0x00, /* AK4671_E3_COEFFICIENT2 (0x40) */ | ||
100 | 0x00, /* AK4671_E3_COEFFICIENT3 (0x41) */ | ||
101 | 0x00, /* AK4671_E3_COEFFICIENT4 (0x42) */ | ||
102 | 0x00, /* AK4671_E3_COEFFICIENT5 (0x43) */ | ||
103 | 0x00, /* AK4671_E4_COEFFICIENT0 (0x44) */ | ||
104 | 0x00, /* AK4671_E4_COEFFICIENT1 (0x45) */ | ||
105 | 0x00, /* AK4671_E4_COEFFICIENT2 (0x46) */ | ||
106 | 0x00, /* AK4671_E4_COEFFICIENT3 (0x47) */ | ||
107 | 0x00, /* AK4671_E4_COEFFICIENT4 (0x48) */ | ||
108 | 0x00, /* AK4671_E4_COEFFICIENT5 (0x49) */ | ||
109 | 0x00, /* AK4671_E5_COEFFICIENT0 (0x4a) */ | ||
110 | 0x00, /* AK4671_E5_COEFFICIENT1 (0x4b) */ | ||
111 | 0x00, /* AK4671_E5_COEFFICIENT2 (0x4c) */ | ||
112 | 0x00, /* AK4671_E5_COEFFICIENT3 (0x4d) */ | ||
113 | 0x00, /* AK4671_E5_COEFFICIENT4 (0x4e) */ | ||
114 | 0x00, /* AK4671_E5_COEFFICIENT5 (0x4f) */ | ||
115 | 0x88, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */ | ||
116 | 0x88, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */ | ||
117 | 0x08, /* AK4671_EQ_CONTRO_10KHZ (0x52) */ | ||
118 | 0x00, /* AK4671_PCM_IF_CONTROL0 (0x53) */ | ||
119 | 0x00, /* AK4671_PCM_IF_CONTROL1 (0x54) */ | ||
120 | 0x00, /* AK4671_PCM_IF_CONTROL2 (0x55) */ | ||
121 | 0x18, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */ | ||
122 | 0x18, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */ | ||
123 | 0x00, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */ | ||
124 | 0x00, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */ | ||
125 | 0x00, /* AK4671_SAR_ADC_CONTROL (0x5a) */ | ||
126 | }; | ||
127 | |||
128 | /* | ||
129 | * LOUT1/ROUT1 output volume control: | ||
130 | * from -24 to 6 dB in 6 dB steps (mute instead of -30 dB) | ||
131 | */ | ||
132 | static DECLARE_TLV_DB_SCALE(out1_tlv, -3000, 600, 1); | ||
133 | |||
134 | /* | ||
135 | * LOUT2/ROUT2 output volume control: | ||
136 | * from -33 to 6 dB in 3 dB steps (mute instead of -33 dB) | ||
137 | */ | ||
138 | static DECLARE_TLV_DB_SCALE(out2_tlv, -3300, 300, 1); | ||
139 | |||
140 | /* | ||
141 | * LOUT3/ROUT3 output volume control: | ||
142 | * from -6 to 3 dB in 3 dB steps | ||
143 | */ | ||
144 | static DECLARE_TLV_DB_SCALE(out3_tlv, -600, 300, 0); | ||
145 | |||
146 | /* | ||
147 | * Mic amp gain control: | ||
148 | * from -15 to 30 dB in 3 dB steps | ||
149 | * REVISIT: The actual min value(0x01) is -12 dB and the reg value 0x00 is not | ||
150 | * available | ||
151 | */ | ||
152 | static DECLARE_TLV_DB_SCALE(mic_amp_tlv, -1500, 300, 0); | ||
153 | |||
154 | static const struct snd_kcontrol_new ak4671_snd_controls[] = { | ||
155 | /* Common playback gain controls */ | ||
156 | SOC_SINGLE_TLV("Line Output1 Playback Volume", | ||
157 | AK4671_OUTPUT_VOLUME_CONTROL, 0, 0x6, 0, out1_tlv), | ||
158 | SOC_SINGLE_TLV("Headphone Output2 Playback Volume", | ||
159 | AK4671_OUTPUT_VOLUME_CONTROL, 4, 0xd, 0, out2_tlv), | ||
160 | SOC_SINGLE_TLV("Line Output3 Playback Volume", | ||
161 | AK4671_LOUT3_POWER_MANAGERMENT, 6, 0x3, 0, out3_tlv), | ||
162 | |||
163 | /* Common capture gain controls */ | ||
164 | SOC_DOUBLE_TLV("Mic Amp Capture Volume", | ||
165 | AK4671_MIC_AMP_GAIN, 0, 4, 0xf, 0, mic_amp_tlv), | ||
166 | }; | ||
167 | |||
168 | /* event handlers */ | ||
169 | static int ak4671_out2_event(struct snd_soc_dapm_widget *w, | ||
170 | struct snd_kcontrol *kcontrol, int event) | ||
171 | { | ||
172 | struct snd_soc_codec *codec = w->codec; | ||
173 | u8 reg; | ||
174 | |||
175 | switch (event) { | ||
176 | case SND_SOC_DAPM_POST_PMU: | ||
177 | reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT); | ||
178 | reg |= AK4671_MUTEN; | ||
179 | snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg); | ||
180 | break; | ||
181 | case SND_SOC_DAPM_PRE_PMD: | ||
182 | reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT); | ||
183 | reg &= ~AK4671_MUTEN; | ||
184 | snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg); | ||
185 | break; | ||
186 | } | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | /* Output Mixers */ | ||
192 | static const struct snd_kcontrol_new ak4671_lout1_mixer_controls[] = { | ||
193 | SOC_DAPM_SINGLE("DACL", AK4671_LOUT1_SIGNAL_SELECT, 0, 1, 0), | ||
194 | SOC_DAPM_SINGLE("LINL1", AK4671_LOUT1_SIGNAL_SELECT, 1, 1, 0), | ||
195 | SOC_DAPM_SINGLE("LINL2", AK4671_LOUT1_SIGNAL_SELECT, 2, 1, 0), | ||
196 | SOC_DAPM_SINGLE("LINL3", AK4671_LOUT1_SIGNAL_SELECT, 3, 1, 0), | ||
197 | SOC_DAPM_SINGLE("LINL4", AK4671_LOUT1_SIGNAL_SELECT, 4, 1, 0), | ||
198 | SOC_DAPM_SINGLE("LOOPL", AK4671_LOUT1_SIGNAL_SELECT, 5, 1, 0), | ||
199 | }; | ||
200 | |||
201 | static const struct snd_kcontrol_new ak4671_rout1_mixer_controls[] = { | ||
202 | SOC_DAPM_SINGLE("DACR", AK4671_ROUT1_SIGNAL_SELECT, 0, 1, 0), | ||
203 | SOC_DAPM_SINGLE("RINR1", AK4671_ROUT1_SIGNAL_SELECT, 1, 1, 0), | ||
204 | SOC_DAPM_SINGLE("RINR2", AK4671_ROUT1_SIGNAL_SELECT, 2, 1, 0), | ||
205 | SOC_DAPM_SINGLE("RINR3", AK4671_ROUT1_SIGNAL_SELECT, 3, 1, 0), | ||
206 | SOC_DAPM_SINGLE("RINR4", AK4671_ROUT1_SIGNAL_SELECT, 4, 1, 0), | ||
207 | SOC_DAPM_SINGLE("LOOPR", AK4671_ROUT1_SIGNAL_SELECT, 5, 1, 0), | ||
208 | }; | ||
209 | |||
210 | static const struct snd_kcontrol_new ak4671_lout2_mixer_controls[] = { | ||
211 | SOC_DAPM_SINGLE("DACHL", AK4671_LOUT2_SIGNAL_SELECT, 0, 1, 0), | ||
212 | SOC_DAPM_SINGLE("LINH1", AK4671_LOUT2_SIGNAL_SELECT, 1, 1, 0), | ||
213 | SOC_DAPM_SINGLE("LINH2", AK4671_LOUT2_SIGNAL_SELECT, 2, 1, 0), | ||
214 | SOC_DAPM_SINGLE("LINH3", AK4671_LOUT2_SIGNAL_SELECT, 3, 1, 0), | ||
215 | SOC_DAPM_SINGLE("LINH4", AK4671_LOUT2_SIGNAL_SELECT, 4, 1, 0), | ||
216 | SOC_DAPM_SINGLE("LOOPHL", AK4671_LOUT2_SIGNAL_SELECT, 5, 1, 0), | ||
217 | }; | ||
218 | |||
219 | static const struct snd_kcontrol_new ak4671_rout2_mixer_controls[] = { | ||
220 | SOC_DAPM_SINGLE("DACHR", AK4671_ROUT2_SIGNAL_SELECT, 0, 1, 0), | ||
221 | SOC_DAPM_SINGLE("RINH1", AK4671_ROUT2_SIGNAL_SELECT, 1, 1, 0), | ||
222 | SOC_DAPM_SINGLE("RINH2", AK4671_ROUT2_SIGNAL_SELECT, 2, 1, 0), | ||
223 | SOC_DAPM_SINGLE("RINH3", AK4671_ROUT2_SIGNAL_SELECT, 3, 1, 0), | ||
224 | SOC_DAPM_SINGLE("RINH4", AK4671_ROUT2_SIGNAL_SELECT, 4, 1, 0), | ||
225 | SOC_DAPM_SINGLE("LOOPHR", AK4671_ROUT2_SIGNAL_SELECT, 5, 1, 0), | ||
226 | }; | ||
227 | |||
228 | static const struct snd_kcontrol_new ak4671_lout3_mixer_controls[] = { | ||
229 | SOC_DAPM_SINGLE("DACSL", AK4671_LOUT3_SIGNAL_SELECT, 0, 1, 0), | ||
230 | SOC_DAPM_SINGLE("LINS1", AK4671_LOUT3_SIGNAL_SELECT, 1, 1, 0), | ||
231 | SOC_DAPM_SINGLE("LINS2", AK4671_LOUT3_SIGNAL_SELECT, 2, 1, 0), | ||
232 | SOC_DAPM_SINGLE("LINS3", AK4671_LOUT3_SIGNAL_SELECT, 3, 1, 0), | ||
233 | SOC_DAPM_SINGLE("LINS4", AK4671_LOUT3_SIGNAL_SELECT, 4, 1, 0), | ||
234 | SOC_DAPM_SINGLE("LOOPSL", AK4671_LOUT3_SIGNAL_SELECT, 5, 1, 0), | ||
235 | }; | ||
236 | |||
237 | static const struct snd_kcontrol_new ak4671_rout3_mixer_controls[] = { | ||
238 | SOC_DAPM_SINGLE("DACSR", AK4671_ROUT3_SIGNAL_SELECT, 0, 1, 0), | ||
239 | SOC_DAPM_SINGLE("RINS1", AK4671_ROUT3_SIGNAL_SELECT, 1, 1, 0), | ||
240 | SOC_DAPM_SINGLE("RINS2", AK4671_ROUT3_SIGNAL_SELECT, 2, 1, 0), | ||
241 | SOC_DAPM_SINGLE("RINS3", AK4671_ROUT3_SIGNAL_SELECT, 3, 1, 0), | ||
242 | SOC_DAPM_SINGLE("RINS4", AK4671_ROUT3_SIGNAL_SELECT, 4, 1, 0), | ||
243 | SOC_DAPM_SINGLE("LOOPSR", AK4671_ROUT3_SIGNAL_SELECT, 5, 1, 0), | ||
244 | }; | ||
245 | |||
246 | /* Input MUXs */ | ||
247 | static const char *ak4671_lin_mux_texts[] = | ||
248 | {"LIN1", "LIN2", "LIN3", "LIN4"}; | ||
249 | static const struct soc_enum ak4671_lin_mux_enum = | ||
250 | SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 0, | ||
251 | ARRAY_SIZE(ak4671_lin_mux_texts), | ||
252 | ak4671_lin_mux_texts); | ||
253 | static const struct snd_kcontrol_new ak4671_lin_mux_control = | ||
254 | SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum); | ||
255 | |||
256 | static const char *ak4671_rin_mux_texts[] = | ||
257 | {"RIN1", "RIN2", "RIN3", "RIN4"}; | ||
258 | static const struct soc_enum ak4671_rin_mux_enum = | ||
259 | SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 2, | ||
260 | ARRAY_SIZE(ak4671_rin_mux_texts), | ||
261 | ak4671_rin_mux_texts); | ||
262 | static const struct snd_kcontrol_new ak4671_rin_mux_control = | ||
263 | SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum); | ||
264 | |||
265 | static const struct snd_soc_dapm_widget ak4671_dapm_widgets[] = { | ||
266 | /* Inputs */ | ||
267 | SND_SOC_DAPM_INPUT("LIN1"), | ||
268 | SND_SOC_DAPM_INPUT("RIN1"), | ||
269 | SND_SOC_DAPM_INPUT("LIN2"), | ||
270 | SND_SOC_DAPM_INPUT("RIN2"), | ||
271 | SND_SOC_DAPM_INPUT("LIN3"), | ||
272 | SND_SOC_DAPM_INPUT("RIN3"), | ||
273 | SND_SOC_DAPM_INPUT("LIN4"), | ||
274 | SND_SOC_DAPM_INPUT("RIN4"), | ||
275 | |||
276 | /* Outputs */ | ||
277 | SND_SOC_DAPM_OUTPUT("LOUT1"), | ||
278 | SND_SOC_DAPM_OUTPUT("ROUT1"), | ||
279 | SND_SOC_DAPM_OUTPUT("LOUT2"), | ||
280 | SND_SOC_DAPM_OUTPUT("ROUT2"), | ||
281 | SND_SOC_DAPM_OUTPUT("LOUT3"), | ||
282 | SND_SOC_DAPM_OUTPUT("ROUT3"), | ||
283 | |||
284 | /* DAC */ | ||
285 | SND_SOC_DAPM_DAC("DAC Left", "Left HiFi Playback", | ||
286 | AK4671_AD_DA_POWER_MANAGEMENT, 6, 0), | ||
287 | SND_SOC_DAPM_DAC("DAC Right", "Right HiFi Playback", | ||
288 | AK4671_AD_DA_POWER_MANAGEMENT, 7, 0), | ||
289 | |||
290 | /* ADC */ | ||
291 | SND_SOC_DAPM_ADC("ADC Left", "Left HiFi Capture", | ||
292 | AK4671_AD_DA_POWER_MANAGEMENT, 4, 0), | ||
293 | SND_SOC_DAPM_ADC("ADC Right", "Right HiFi Capture", | ||
294 | AK4671_AD_DA_POWER_MANAGEMENT, 5, 0), | ||
295 | |||
296 | /* PGA */ | ||
297 | SND_SOC_DAPM_PGA("LOUT2 Mix Amp", | ||
298 | AK4671_LOUT2_POWER_MANAGERMENT, 5, 0, NULL, 0), | ||
299 | SND_SOC_DAPM_PGA("ROUT2 Mix Amp", | ||
300 | AK4671_LOUT2_POWER_MANAGERMENT, 6, 0, NULL, 0), | ||
301 | |||
302 | SND_SOC_DAPM_PGA("LIN1 Mixing Circuit", | ||
303 | AK4671_MIXING_POWER_MANAGEMENT1, 0, 0, NULL, 0), | ||
304 | SND_SOC_DAPM_PGA("RIN1 Mixing Circuit", | ||
305 | AK4671_MIXING_POWER_MANAGEMENT1, 1, 0, NULL, 0), | ||
306 | SND_SOC_DAPM_PGA("LIN2 Mixing Circuit", | ||
307 | AK4671_MIXING_POWER_MANAGEMENT1, 2, 0, NULL, 0), | ||
308 | SND_SOC_DAPM_PGA("RIN2 Mixing Circuit", | ||
309 | AK4671_MIXING_POWER_MANAGEMENT1, 3, 0, NULL, 0), | ||
310 | SND_SOC_DAPM_PGA("LIN3 Mixing Circuit", | ||
311 | AK4671_MIXING_POWER_MANAGEMENT1, 4, 0, NULL, 0), | ||
312 | SND_SOC_DAPM_PGA("RIN3 Mixing Circuit", | ||
313 | AK4671_MIXING_POWER_MANAGEMENT1, 5, 0, NULL, 0), | ||
314 | SND_SOC_DAPM_PGA("LIN4 Mixing Circuit", | ||
315 | AK4671_MIXING_POWER_MANAGEMENT1, 6, 0, NULL, 0), | ||
316 | SND_SOC_DAPM_PGA("RIN4 Mixing Circuit", | ||
317 | AK4671_MIXING_POWER_MANAGEMENT1, 7, 0, NULL, 0), | ||
318 | |||
319 | /* Output Mixers */ | ||
320 | SND_SOC_DAPM_MIXER("LOUT1 Mixer", AK4671_LOUT1_POWER_MANAGERMENT, 0, 0, | ||
321 | &ak4671_lout1_mixer_controls[0], | ||
322 | ARRAY_SIZE(ak4671_lout1_mixer_controls)), | ||
323 | SND_SOC_DAPM_MIXER("ROUT1 Mixer", AK4671_LOUT1_POWER_MANAGERMENT, 1, 0, | ||
324 | &ak4671_rout1_mixer_controls[0], | ||
325 | ARRAY_SIZE(ak4671_rout1_mixer_controls)), | ||
326 | SND_SOC_DAPM_MIXER_E("LOUT2 Mixer", AK4671_LOUT2_POWER_MANAGERMENT, | ||
327 | 0, 0, &ak4671_lout2_mixer_controls[0], | ||
328 | ARRAY_SIZE(ak4671_lout2_mixer_controls), | ||
329 | ak4671_out2_event, | ||
330 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD), | ||
331 | SND_SOC_DAPM_MIXER_E("ROUT2 Mixer", AK4671_LOUT2_POWER_MANAGERMENT, | ||
332 | 1, 0, &ak4671_rout2_mixer_controls[0], | ||
333 | ARRAY_SIZE(ak4671_rout2_mixer_controls), | ||
334 | ak4671_out2_event, | ||
335 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD), | ||
336 | SND_SOC_DAPM_MIXER("LOUT3 Mixer", AK4671_LOUT3_POWER_MANAGERMENT, 0, 0, | ||
337 | &ak4671_lout3_mixer_controls[0], | ||
338 | ARRAY_SIZE(ak4671_lout3_mixer_controls)), | ||
339 | SND_SOC_DAPM_MIXER("ROUT3 Mixer", AK4671_LOUT3_POWER_MANAGERMENT, 1, 0, | ||
340 | &ak4671_rout3_mixer_controls[0], | ||
341 | ARRAY_SIZE(ak4671_rout3_mixer_controls)), | ||
342 | |||
343 | /* Input MUXs */ | ||
344 | SND_SOC_DAPM_MUX("LIN MUX", AK4671_AD_DA_POWER_MANAGEMENT, 2, 0, | ||
345 | &ak4671_lin_mux_control), | ||
346 | SND_SOC_DAPM_MUX("RIN MUX", AK4671_AD_DA_POWER_MANAGEMENT, 3, 0, | ||
347 | &ak4671_rin_mux_control), | ||
348 | |||
349 | /* Mic Power */ | ||
350 | SND_SOC_DAPM_MICBIAS("Mic Bias", AK4671_AD_DA_POWER_MANAGEMENT, 1, 0), | ||
351 | |||
352 | /* Supply */ | ||
353 | SND_SOC_DAPM_SUPPLY("PMPLL", AK4671_PLL_MODE_SELECT1, 0, 0, NULL, 0), | ||
354 | }; | ||
355 | |||
356 | static const struct snd_soc_dapm_route intercon[] = { | ||
357 | {"DAC Left", "NULL", "PMPLL"}, | ||
358 | {"DAC Right", "NULL", "PMPLL"}, | ||
359 | {"ADC Left", "NULL", "PMPLL"}, | ||
360 | {"ADC Right", "NULL", "PMPLL"}, | ||
361 | |||
362 | /* Outputs */ | ||
363 | {"LOUT1", "NULL", "LOUT1 Mixer"}, | ||
364 | {"ROUT1", "NULL", "ROUT1 Mixer"}, | ||
365 | {"LOUT2", "NULL", "LOUT2 Mix Amp"}, | ||
366 | {"ROUT2", "NULL", "ROUT2 Mix Amp"}, | ||
367 | {"LOUT3", "NULL", "LOUT3 Mixer"}, | ||
368 | {"ROUT3", "NULL", "ROUT3 Mixer"}, | ||
369 | |||
370 | {"LOUT1 Mixer", "DACL", "DAC Left"}, | ||
371 | {"ROUT1 Mixer", "DACR", "DAC Right"}, | ||
372 | {"LOUT2 Mixer", "DACHL", "DAC Left"}, | ||
373 | {"ROUT2 Mixer", "DACHR", "DAC Right"}, | ||
374 | {"LOUT2 Mix Amp", "NULL", "LOUT2 Mixer"}, | ||
375 | {"ROUT2 Mix Amp", "NULL", "ROUT2 Mixer"}, | ||
376 | {"LOUT3 Mixer", "DACSL", "DAC Left"}, | ||
377 | {"ROUT3 Mixer", "DACSR", "DAC Right"}, | ||
378 | |||
379 | /* Inputs */ | ||
380 | {"LIN MUX", "LIN1", "LIN1"}, | ||
381 | {"LIN MUX", "LIN2", "LIN2"}, | ||
382 | {"LIN MUX", "LIN3", "LIN3"}, | ||
383 | {"LIN MUX", "LIN4", "LIN4"}, | ||
384 | |||
385 | {"RIN MUX", "RIN1", "RIN1"}, | ||
386 | {"RIN MUX", "RIN2", "RIN2"}, | ||
387 | {"RIN MUX", "RIN3", "RIN3"}, | ||
388 | {"RIN MUX", "RIN4", "RIN4"}, | ||
389 | |||
390 | {"LIN1", NULL, "Mic Bias"}, | ||
391 | {"RIN1", NULL, "Mic Bias"}, | ||
392 | {"LIN2", NULL, "Mic Bias"}, | ||
393 | {"RIN2", NULL, "Mic Bias"}, | ||
394 | |||
395 | {"ADC Left", "NULL", "LIN MUX"}, | ||
396 | {"ADC Right", "NULL", "RIN MUX"}, | ||
397 | |||
398 | /* Analog Loops */ | ||
399 | {"LIN1 Mixing Circuit", "NULL", "LIN1"}, | ||
400 | {"RIN1 Mixing Circuit", "NULL", "RIN1"}, | ||
401 | {"LIN2 Mixing Circuit", "NULL", "LIN2"}, | ||
402 | {"RIN2 Mixing Circuit", "NULL", "RIN2"}, | ||
403 | {"LIN3 Mixing Circuit", "NULL", "LIN3"}, | ||
404 | {"RIN3 Mixing Circuit", "NULL", "RIN3"}, | ||
405 | {"LIN4 Mixing Circuit", "NULL", "LIN4"}, | ||
406 | {"RIN4 Mixing Circuit", "NULL", "RIN4"}, | ||
407 | |||
408 | {"LOUT1 Mixer", "LINL1", "LIN1 Mixing Circuit"}, | ||
409 | {"ROUT1 Mixer", "RINR1", "RIN1 Mixing Circuit"}, | ||
410 | {"LOUT2 Mixer", "LINH1", "LIN1 Mixing Circuit"}, | ||
411 | {"ROUT2 Mixer", "RINH1", "RIN1 Mixing Circuit"}, | ||
412 | {"LOUT3 Mixer", "LINS1", "LIN1 Mixing Circuit"}, | ||
413 | {"ROUT3 Mixer", "RINS1", "RIN1 Mixing Circuit"}, | ||
414 | |||
415 | {"LOUT1 Mixer", "LINL2", "LIN2 Mixing Circuit"}, | ||
416 | {"ROUT1 Mixer", "RINR2", "RIN2 Mixing Circuit"}, | ||
417 | {"LOUT2 Mixer", "LINH2", "LIN2 Mixing Circuit"}, | ||
418 | {"ROUT2 Mixer", "RINH2", "RIN2 Mixing Circuit"}, | ||
419 | {"LOUT3 Mixer", "LINS2", "LIN2 Mixing Circuit"}, | ||
420 | {"ROUT3 Mixer", "RINS2", "RIN2 Mixing Circuit"}, | ||
421 | |||
422 | {"LOUT1 Mixer", "LINL3", "LIN3 Mixing Circuit"}, | ||
423 | {"ROUT1 Mixer", "RINR3", "RIN3 Mixing Circuit"}, | ||
424 | {"LOUT2 Mixer", "LINH3", "LIN3 Mixing Circuit"}, | ||
425 | {"ROUT2 Mixer", "RINH3", "RIN3 Mixing Circuit"}, | ||
426 | {"LOUT3 Mixer", "LINS3", "LIN3 Mixing Circuit"}, | ||
427 | {"ROUT3 Mixer", "RINS3", "RIN3 Mixing Circuit"}, | ||
428 | |||
429 | {"LOUT1 Mixer", "LINL4", "LIN4 Mixing Circuit"}, | ||
430 | {"ROUT1 Mixer", "RINR4", "RIN4 Mixing Circuit"}, | ||
431 | {"LOUT2 Mixer", "LINH4", "LIN4 Mixing Circuit"}, | ||
432 | {"ROUT2 Mixer", "RINH4", "RIN4 Mixing Circuit"}, | ||
433 | {"LOUT3 Mixer", "LINS4", "LIN4 Mixing Circuit"}, | ||
434 | {"ROUT3 Mixer", "RINS4", "RIN4 Mixing Circuit"}, | ||
435 | }; | ||
436 | |||
437 | static int ak4671_add_widgets(struct snd_soc_codec *codec) | ||
438 | { | ||
439 | snd_soc_dapm_new_controls(codec, ak4671_dapm_widgets, | ||
440 | ARRAY_SIZE(ak4671_dapm_widgets)); | ||
441 | |||
442 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | ||
443 | |||
444 | snd_soc_dapm_new_widgets(codec); | ||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | static int ak4671_hw_params(struct snd_pcm_substream *substream, | ||
449 | struct snd_pcm_hw_params *params, | ||
450 | struct snd_soc_dai *dai) | ||
451 | { | ||
452 | struct snd_soc_codec *codec = dai->codec; | ||
453 | u8 fs; | ||
454 | |||
455 | fs = snd_soc_read(codec, AK4671_PLL_MODE_SELECT0); | ||
456 | fs &= ~AK4671_FS; | ||
457 | |||
458 | switch (params_rate(params)) { | ||
459 | case 8000: | ||
460 | fs |= AK4671_FS_8KHZ; | ||
461 | break; | ||
462 | case 12000: | ||
463 | fs |= AK4671_FS_12KHZ; | ||
464 | break; | ||
465 | case 16000: | ||
466 | fs |= AK4671_FS_16KHZ; | ||
467 | break; | ||
468 | case 24000: | ||
469 | fs |= AK4671_FS_24KHZ; | ||
470 | break; | ||
471 | case 11025: | ||
472 | fs |= AK4671_FS_11_025KHZ; | ||
473 | break; | ||
474 | case 22050: | ||
475 | fs |= AK4671_FS_22_05KHZ; | ||
476 | break; | ||
477 | case 32000: | ||
478 | fs |= AK4671_FS_32KHZ; | ||
479 | break; | ||
480 | case 44100: | ||
481 | fs |= AK4671_FS_44_1KHZ; | ||
482 | break; | ||
483 | case 48000: | ||
484 | fs |= AK4671_FS_48KHZ; | ||
485 | break; | ||
486 | default: | ||
487 | return -EINVAL; | ||
488 | } | ||
489 | |||
490 | snd_soc_write(codec, AK4671_PLL_MODE_SELECT0, fs); | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static int ak4671_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
496 | unsigned int freq, int dir) | ||
497 | { | ||
498 | struct snd_soc_codec *codec = dai->codec; | ||
499 | u8 pll; | ||
500 | |||
501 | pll = snd_soc_read(codec, AK4671_PLL_MODE_SELECT0); | ||
502 | pll &= ~AK4671_PLL; | ||
503 | |||
504 | switch (freq) { | ||
505 | case 11289600: | ||
506 | pll |= AK4671_PLL_11_2896MHZ; | ||
507 | break; | ||
508 | case 12000000: | ||
509 | pll |= AK4671_PLL_12MHZ; | ||
510 | break; | ||
511 | case 12288000: | ||
512 | pll |= AK4671_PLL_12_288MHZ; | ||
513 | break; | ||
514 | case 13000000: | ||
515 | pll |= AK4671_PLL_13MHZ; | ||
516 | break; | ||
517 | case 13500000: | ||
518 | pll |= AK4671_PLL_13_5MHZ; | ||
519 | break; | ||
520 | case 19200000: | ||
521 | pll |= AK4671_PLL_19_2MHZ; | ||
522 | break; | ||
523 | case 24000000: | ||
524 | pll |= AK4671_PLL_24MHZ; | ||
525 | break; | ||
526 | case 26000000: | ||
527 | pll |= AK4671_PLL_26MHZ; | ||
528 | break; | ||
529 | case 27000000: | ||
530 | pll |= AK4671_PLL_27MHZ; | ||
531 | break; | ||
532 | default: | ||
533 | return -EINVAL; | ||
534 | } | ||
535 | |||
536 | snd_soc_write(codec, AK4671_PLL_MODE_SELECT0, pll); | ||
537 | |||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
542 | { | ||
543 | struct snd_soc_codec *codec = dai->codec; | ||
544 | u8 mode; | ||
545 | u8 format; | ||
546 | |||
547 | /* set master/slave audio interface */ | ||
548 | mode = snd_soc_read(codec, AK4671_PLL_MODE_SELECT1); | ||
549 | |||
550 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
551 | case SND_SOC_DAIFMT_CBM_CFM: | ||
552 | mode |= AK4671_M_S; | ||
553 | break; | ||
554 | case SND_SOC_DAIFMT_CBM_CFS: | ||
555 | mode &= ~(AK4671_M_S); | ||
556 | break; | ||
557 | default: | ||
558 | return -EINVAL; | ||
559 | } | ||
560 | |||
561 | /* interface format */ | ||
562 | format = snd_soc_read(codec, AK4671_FORMAT_SELECT); | ||
563 | format &= ~AK4671_DIF; | ||
564 | |||
565 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
566 | case SND_SOC_DAIFMT_I2S: | ||
567 | format |= AK4671_DIF_I2S_MODE; | ||
568 | break; | ||
569 | case SND_SOC_DAIFMT_LEFT_J: | ||
570 | format |= AK4671_DIF_MSB_MODE; | ||
571 | break; | ||
572 | case SND_SOC_DAIFMT_DSP_A: | ||
573 | format |= AK4671_DIF_DSP_MODE; | ||
574 | format |= AK4671_BCKP; | ||
575 | format |= AK4671_MSBS; | ||
576 | break; | ||
577 | default: | ||
578 | return -EINVAL; | ||
579 | } | ||
580 | |||
581 | /* set mode and format */ | ||
582 | snd_soc_write(codec, AK4671_PLL_MODE_SELECT1, mode); | ||
583 | snd_soc_write(codec, AK4671_FORMAT_SELECT, format); | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | static int ak4671_set_bias_level(struct snd_soc_codec *codec, | ||
589 | enum snd_soc_bias_level level) | ||
590 | { | ||
591 | u8 reg; | ||
592 | |||
593 | switch (level) { | ||
594 | case SND_SOC_BIAS_ON: | ||
595 | case SND_SOC_BIAS_PREPARE: | ||
596 | case SND_SOC_BIAS_STANDBY: | ||
597 | reg = snd_soc_read(codec, AK4671_AD_DA_POWER_MANAGEMENT); | ||
598 | snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, | ||
599 | reg | AK4671_PMVCM); | ||
600 | break; | ||
601 | case SND_SOC_BIAS_OFF: | ||
602 | snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00); | ||
603 | break; | ||
604 | } | ||
605 | codec->bias_level = level; | ||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | #define AK4671_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | ||
610 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ | ||
611 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ | ||
612 | SNDRV_PCM_RATE_48000) | ||
613 | |||
614 | #define AK4671_FORMATS SNDRV_PCM_FMTBIT_S16_LE | ||
615 | |||
616 | static struct snd_soc_dai_ops ak4671_dai_ops = { | ||
617 | .hw_params = ak4671_hw_params, | ||
618 | .set_sysclk = ak4671_set_dai_sysclk, | ||
619 | .set_fmt = ak4671_set_dai_fmt, | ||
620 | }; | ||
621 | |||
622 | struct snd_soc_dai ak4671_dai = { | ||
623 | .name = "AK4671", | ||
624 | .playback = { | ||
625 | .stream_name = "Playback", | ||
626 | .channels_min = 1, | ||
627 | .channels_max = 2, | ||
628 | .rates = AK4671_RATES, | ||
629 | .formats = AK4671_FORMATS,}, | ||
630 | .capture = { | ||
631 | .stream_name = "Capture", | ||
632 | .channels_min = 1, | ||
633 | .channels_max = 2, | ||
634 | .rates = AK4671_RATES, | ||
635 | .formats = AK4671_FORMATS,}, | ||
636 | .ops = &ak4671_dai_ops, | ||
637 | }; | ||
638 | EXPORT_SYMBOL_GPL(ak4671_dai); | ||
639 | |||
640 | static int ak4671_probe(struct platform_device *pdev) | ||
641 | { | ||
642 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
643 | struct snd_soc_codec *codec; | ||
644 | int ret = 0; | ||
645 | |||
646 | if (ak4671_codec == NULL) { | ||
647 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
648 | return -ENODEV; | ||
649 | } | ||
650 | |||
651 | socdev->card->codec = ak4671_codec; | ||
652 | codec = ak4671_codec; | ||
653 | |||
654 | /* register pcms */ | ||
655 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
656 | if (ret < 0) { | ||
657 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
658 | goto pcm_err; | ||
659 | } | ||
660 | |||
661 | snd_soc_add_controls(codec, ak4671_snd_controls, | ||
662 | ARRAY_SIZE(ak4671_snd_controls)); | ||
663 | ak4671_add_widgets(codec); | ||
664 | |||
665 | ret = snd_soc_init_card(socdev); | ||
666 | if (ret < 0) { | ||
667 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
668 | goto card_err; | ||
669 | } | ||
670 | |||
671 | ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
672 | |||
673 | return ret; | ||
674 | |||
675 | card_err: | ||
676 | snd_soc_free_pcms(socdev); | ||
677 | snd_soc_dapm_free(socdev); | ||
678 | pcm_err: | ||
679 | return ret; | ||
680 | } | ||
681 | |||
682 | static int ak4671_remove(struct platform_device *pdev) | ||
683 | { | ||
684 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
685 | |||
686 | snd_soc_free_pcms(socdev); | ||
687 | snd_soc_dapm_free(socdev); | ||
688 | |||
689 | return 0; | ||
690 | } | ||
691 | |||
692 | struct snd_soc_codec_device soc_codec_dev_ak4671 = { | ||
693 | .probe = ak4671_probe, | ||
694 | .remove = ak4671_remove, | ||
695 | }; | ||
696 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671); | ||
697 | |||
698 | static int ak4671_register(struct ak4671_priv *ak4671, | ||
699 | enum snd_soc_control_type control) | ||
700 | { | ||
701 | int ret; | ||
702 | struct snd_soc_codec *codec = &ak4671->codec; | ||
703 | |||
704 | if (ak4671_codec) { | ||
705 | dev_err(codec->dev, "Another AK4671 is registered\n"); | ||
706 | ret = -EINVAL; | ||
707 | goto err; | ||
708 | } | ||
709 | |||
710 | mutex_init(&codec->mutex); | ||
711 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
712 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
713 | |||
714 | codec->private_data = ak4671; | ||
715 | codec->name = "AK4671"; | ||
716 | codec->owner = THIS_MODULE; | ||
717 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
718 | codec->set_bias_level = ak4671_set_bias_level; | ||
719 | codec->dai = &ak4671_dai; | ||
720 | codec->num_dai = 1; | ||
721 | codec->reg_cache_size = AK4671_CACHEREGNUM; | ||
722 | codec->reg_cache = &ak4671->reg_cache; | ||
723 | |||
724 | memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg)); | ||
725 | |||
726 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, control); | ||
727 | if (ret < 0) { | ||
728 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
729 | goto err; | ||
730 | } | ||
731 | |||
732 | ak4671_dai.dev = codec->dev; | ||
733 | ak4671_codec = codec; | ||
734 | |||
735 | ret = snd_soc_register_codec(codec); | ||
736 | if (ret != 0) { | ||
737 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
738 | goto err; | ||
739 | } | ||
740 | |||
741 | ret = snd_soc_register_dai(&ak4671_dai); | ||
742 | if (ret != 0) { | ||
743 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
744 | goto err_codec; | ||
745 | } | ||
746 | |||
747 | return 0; | ||
748 | |||
749 | err_codec: | ||
750 | snd_soc_unregister_codec(codec); | ||
751 | err: | ||
752 | kfree(ak4671); | ||
753 | return ret; | ||
754 | } | ||
755 | |||
756 | static void ak4671_unregister(struct ak4671_priv *ak4671) | ||
757 | { | ||
758 | ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF); | ||
759 | snd_soc_unregister_dai(&ak4671_dai); | ||
760 | snd_soc_unregister_codec(&ak4671->codec); | ||
761 | kfree(ak4671); | ||
762 | ak4671_codec = NULL; | ||
763 | } | ||
764 | |||
765 | static int __devinit ak4671_i2c_probe(struct i2c_client *client, | ||
766 | const struct i2c_device_id *id) | ||
767 | { | ||
768 | struct ak4671_priv *ak4671; | ||
769 | struct snd_soc_codec *codec; | ||
770 | |||
771 | ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL); | ||
772 | if (ak4671 == NULL) | ||
773 | return -ENOMEM; | ||
774 | |||
775 | codec = &ak4671->codec; | ||
776 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
777 | |||
778 | i2c_set_clientdata(client, ak4671); | ||
779 | codec->control_data = client; | ||
780 | |||
781 | codec->dev = &client->dev; | ||
782 | |||
783 | return ak4671_register(ak4671, SND_SOC_I2C); | ||
784 | } | ||
785 | |||
786 | static __devexit int ak4671_i2c_remove(struct i2c_client *client) | ||
787 | { | ||
788 | struct ak4671_priv *ak4671 = i2c_get_clientdata(client); | ||
789 | |||
790 | ak4671_unregister(ak4671); | ||
791 | |||
792 | return 0; | ||
793 | } | ||
794 | |||
795 | static const struct i2c_device_id ak4671_i2c_id[] = { | ||
796 | { "ak4671", 0 }, | ||
797 | { } | ||
798 | }; | ||
799 | MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id); | ||
800 | |||
801 | static struct i2c_driver ak4671_i2c_driver = { | ||
802 | .driver = { | ||
803 | .name = "ak4671", | ||
804 | .owner = THIS_MODULE, | ||
805 | }, | ||
806 | .probe = ak4671_i2c_probe, | ||
807 | .remove = __devexit_p(ak4671_i2c_remove), | ||
808 | .id_table = ak4671_i2c_id, | ||
809 | }; | ||
810 | |||
811 | static int __init ak4671_modinit(void) | ||
812 | { | ||
813 | return i2c_add_driver(&ak4671_i2c_driver); | ||
814 | } | ||
815 | module_init(ak4671_modinit); | ||
816 | |||
817 | static void __exit ak4671_exit(void) | ||
818 | { | ||
819 | i2c_del_driver(&ak4671_i2c_driver); | ||
820 | } | ||
821 | module_exit(ak4671_exit); | ||
822 | |||
823 | MODULE_DESCRIPTION("ASoC AK4671 codec driver"); | ||
824 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | ||
825 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h new file mode 100644 index 000000000000..e2fad964e88b --- /dev/null +++ b/sound/soc/codecs/ak4671.h | |||
@@ -0,0 +1,156 @@ | |||
1 | /* | ||
2 | * ak4671.h -- audio driver for AK4671 | ||
3 | * | ||
4 | * Copyright (C) 2009 Samsung Electronics Co.Ltd | ||
5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifndef _AK4671_H | ||
15 | #define _AK4671_H | ||
16 | |||
17 | #define AK4671_AD_DA_POWER_MANAGEMENT 0x00 | ||
18 | #define AK4671_PLL_MODE_SELECT0 0x01 | ||
19 | #define AK4671_PLL_MODE_SELECT1 0x02 | ||
20 | #define AK4671_FORMAT_SELECT 0x03 | ||
21 | #define AK4671_MIC_SIGNAL_SELECT 0x04 | ||
22 | #define AK4671_MIC_AMP_GAIN 0x05 | ||
23 | #define AK4671_MIXING_POWER_MANAGEMENT0 0x06 | ||
24 | #define AK4671_MIXING_POWER_MANAGEMENT1 0x07 | ||
25 | #define AK4671_OUTPUT_VOLUME_CONTROL 0x08 | ||
26 | #define AK4671_LOUT1_SIGNAL_SELECT 0x09 | ||
27 | #define AK4671_ROUT1_SIGNAL_SELECT 0x0a | ||
28 | #define AK4671_LOUT2_SIGNAL_SELECT 0x0b | ||
29 | #define AK4671_ROUT2_SIGNAL_SELECT 0x0c | ||
30 | #define AK4671_LOUT3_SIGNAL_SELECT 0x0d | ||
31 | #define AK4671_ROUT3_SIGNAL_SELECT 0x0e | ||
32 | #define AK4671_LOUT1_POWER_MANAGERMENT 0x0f | ||
33 | #define AK4671_LOUT2_POWER_MANAGERMENT 0x10 | ||
34 | #define AK4671_LOUT3_POWER_MANAGERMENT 0x11 | ||
35 | #define AK4671_LCH_INPUT_VOLUME_CONTROL 0x12 | ||
36 | #define AK4671_RCH_INPUT_VOLUME_CONTROL 0x13 | ||
37 | #define AK4671_ALC_REFERENCE_SELECT 0x14 | ||
38 | #define AK4671_DIGITAL_MIXING_CONTROL 0x15 | ||
39 | #define AK4671_ALC_TIMER_SELECT 0x16 | ||
40 | #define AK4671_ALC_MODE_CONTROL 0x17 | ||
41 | #define AK4671_MODE_CONTROL1 0x18 | ||
42 | #define AK4671_MODE_CONTROL2 0x19 | ||
43 | #define AK4671_LCH_OUTPUT_VOLUME_CONTROL 0x1a | ||
44 | #define AK4671_RCH_OUTPUT_VOLUME_CONTROL 0x1b | ||
45 | #define AK4671_SIDETONE_A_CONTROL 0x1c | ||
46 | #define AK4671_DIGITAL_FILTER_SELECT 0x1d | ||
47 | #define AK4671_FIL3_COEFFICIENT0 0x1e | ||
48 | #define AK4671_FIL3_COEFFICIENT1 0x1f | ||
49 | #define AK4671_FIL3_COEFFICIENT2 0x20 | ||
50 | #define AK4671_FIL3_COEFFICIENT3 0x21 | ||
51 | #define AK4671_EQ_COEFFICIENT0 0x22 | ||
52 | #define AK4671_EQ_COEFFICIENT1 0x23 | ||
53 | #define AK4671_EQ_COEFFICIENT2 0x24 | ||
54 | #define AK4671_EQ_COEFFICIENT3 0x25 | ||
55 | #define AK4671_EQ_COEFFICIENT4 0x26 | ||
56 | #define AK4671_EQ_COEFFICIENT5 0x27 | ||
57 | #define AK4671_FIL1_COEFFICIENT0 0x28 | ||
58 | #define AK4671_FIL1_COEFFICIENT1 0x29 | ||
59 | #define AK4671_FIL1_COEFFICIENT2 0x2a | ||
60 | #define AK4671_FIL1_COEFFICIENT3 0x2b | ||
61 | #define AK4671_FIL2_COEFFICIENT0 0x2c | ||
62 | #define AK4671_FIL2_COEFFICIENT1 0x2d | ||
63 | #define AK4671_FIL2_COEFFICIENT2 0x2e | ||
64 | #define AK4671_FIL2_COEFFICIENT3 0x2f | ||
65 | #define AK4671_DIGITAL_FILTER_SELECT2 0x30 | ||
66 | #define AK4671_E1_COEFFICIENT0 0x32 | ||
67 | #define AK4671_E1_COEFFICIENT1 0x33 | ||
68 | #define AK4671_E1_COEFFICIENT2 0x34 | ||
69 | #define AK4671_E1_COEFFICIENT3 0x35 | ||
70 | #define AK4671_E1_COEFFICIENT4 0x36 | ||
71 | #define AK4671_E1_COEFFICIENT5 0x37 | ||
72 | #define AK4671_E2_COEFFICIENT0 0x38 | ||
73 | #define AK4671_E2_COEFFICIENT1 0x39 | ||
74 | #define AK4671_E2_COEFFICIENT2 0x3a | ||
75 | #define AK4671_E2_COEFFICIENT3 0x3b | ||
76 | #define AK4671_E2_COEFFICIENT4 0x3c | ||
77 | #define AK4671_E2_COEFFICIENT5 0x3d | ||
78 | #define AK4671_E3_COEFFICIENT0 0x3e | ||
79 | #define AK4671_E3_COEFFICIENT1 0x3f | ||
80 | #define AK4671_E3_COEFFICIENT2 0x40 | ||
81 | #define AK4671_E3_COEFFICIENT3 0x41 | ||
82 | #define AK4671_E3_COEFFICIENT4 0x42 | ||
83 | #define AK4671_E3_COEFFICIENT5 0x43 | ||
84 | #define AK4671_E4_COEFFICIENT0 0x44 | ||
85 | #define AK4671_E4_COEFFICIENT1 0x45 | ||
86 | #define AK4671_E4_COEFFICIENT2 0x46 | ||
87 | #define AK4671_E4_COEFFICIENT3 0x47 | ||
88 | #define AK4671_E4_COEFFICIENT4 0x48 | ||
89 | #define AK4671_E4_COEFFICIENT5 0x49 | ||
90 | #define AK4671_E5_COEFFICIENT0 0x4a | ||
91 | #define AK4671_E5_COEFFICIENT1 0x4b | ||
92 | #define AK4671_E5_COEFFICIENT2 0x4c | ||
93 | #define AK4671_E5_COEFFICIENT3 0x4d | ||
94 | #define AK4671_E5_COEFFICIENT4 0x4e | ||
95 | #define AK4671_E5_COEFFICIENT5 0x4f | ||
96 | #define AK4671_EQ_CONTROL_250HZ_100HZ 0x50 | ||
97 | #define AK4671_EQ_CONTROL_3500HZ_1KHZ 0x51 | ||
98 | #define AK4671_EQ_CONTRO_10KHZ 0x52 | ||
99 | #define AK4671_PCM_IF_CONTROL0 0x53 | ||
100 | #define AK4671_PCM_IF_CONTROL1 0x54 | ||
101 | #define AK4671_PCM_IF_CONTROL2 0x55 | ||
102 | #define AK4671_DIGITAL_VOLUME_B_CONTROL 0x56 | ||
103 | #define AK4671_DIGITAL_VOLUME_C_CONTROL 0x57 | ||
104 | #define AK4671_SIDETONE_VOLUME_CONTROL 0x58 | ||
105 | #define AK4671_DIGITAL_MIXING_CONTROL2 0x59 | ||
106 | #define AK4671_SAR_ADC_CONTROL 0x5a | ||
107 | |||
108 | #define AK4671_CACHEREGNUM (AK4671_SAR_ADC_CONTROL + 1) | ||
109 | |||
110 | /* Bitfield Definitions */ | ||
111 | |||
112 | /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */ | ||
113 | #define AK4671_PMVCM 0x01 | ||
114 | |||
115 | /* AK4671_PLL_MODE_SELECT0 (0x01) Fields */ | ||
116 | #define AK4671_PLL 0x0f | ||
117 | #define AK4671_PLL_11_2896MHZ (4 << 0) | ||
118 | #define AK4671_PLL_12_288MHZ (5 << 0) | ||
119 | #define AK4671_PLL_12MHZ (6 << 0) | ||
120 | #define AK4671_PLL_24MHZ (7 << 0) | ||
121 | #define AK4671_PLL_19_2MHZ (8 << 0) | ||
122 | #define AK4671_PLL_13_5MHZ (12 << 0) | ||
123 | #define AK4671_PLL_27MHZ (13 << 0) | ||
124 | #define AK4671_PLL_13MHZ (14 << 0) | ||
125 | #define AK4671_PLL_26MHZ (15 << 0) | ||
126 | #define AK4671_FS 0xf0 | ||
127 | #define AK4671_FS_8KHZ (0 << 4) | ||
128 | #define AK4671_FS_12KHZ (1 << 4) | ||
129 | #define AK4671_FS_16KHZ (2 << 4) | ||
130 | #define AK4671_FS_24KHZ (3 << 4) | ||
131 | #define AK4671_FS_11_025KHZ (5 << 4) | ||
132 | #define AK4671_FS_22_05KHZ (7 << 4) | ||
133 | #define AK4671_FS_32KHZ (10 << 4) | ||
134 | #define AK4671_FS_48KHZ (11 << 4) | ||
135 | #define AK4671_FS_44_1KHZ (15 << 4) | ||
136 | |||
137 | /* AK4671_PLL_MODE_SELECT1 (0x02) Fields */ | ||
138 | #define AK4671_PMPLL 0x01 | ||
139 | #define AK4671_M_S 0x02 | ||
140 | |||
141 | /* AK4671_FORMAT_SELECT (0x03) Fields */ | ||
142 | #define AK4671_DIF 0x03 | ||
143 | #define AK4671_DIF_DSP_MODE (0 << 0) | ||
144 | #define AK4671_DIF_MSB_MODE (2 << 0) | ||
145 | #define AK4671_DIF_I2S_MODE (3 << 0) | ||
146 | #define AK4671_BCKP 0x04 | ||
147 | #define AK4671_MSBS 0x08 | ||
148 | #define AK4671_SDOD 0x10 | ||
149 | |||
150 | /* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */ | ||
151 | #define AK4671_MUTEN 0x04 | ||
152 | |||
153 | extern struct snd_soc_dai ak4671_dai; | ||
154 | extern struct snd_soc_codec_device soc_codec_dev_ak4671; | ||
155 | |||
156 | #endif | ||
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 126b15b18aeb..3395cf945d56 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -53,6 +53,7 @@ | |||
53 | 53 | ||
54 | /* codec private data */ | 54 | /* codec private data */ |
55 | struct aic3x_priv { | 55 | struct aic3x_priv { |
56 | struct snd_soc_codec codec; | ||
56 | unsigned int sysclk; | 57 | unsigned int sysclk; |
57 | int master; | 58 | int master; |
58 | }; | 59 | }; |
@@ -1156,11 +1157,13 @@ static int aic3x_resume(struct platform_device *pdev) | |||
1156 | * initialise the AIC3X driver | 1157 | * initialise the AIC3X driver |
1157 | * register the mixer and dsp interfaces with the kernel | 1158 | * register the mixer and dsp interfaces with the kernel |
1158 | */ | 1159 | */ |
1159 | static int aic3x_init(struct snd_soc_device *socdev) | 1160 | static int aic3x_init(struct snd_soc_codec *codec) |
1160 | { | 1161 | { |
1161 | struct snd_soc_codec *codec = socdev->card->codec; | 1162 | int reg; |
1162 | struct aic3x_setup_data *setup = socdev->codec_data; | 1163 | |
1163 | int reg, ret = 0; | 1164 | mutex_init(&codec->mutex); |
1165 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1166 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1164 | 1167 | ||
1165 | codec->name = "tlv320aic3x"; | 1168 | codec->name = "tlv320aic3x"; |
1166 | codec->owner = THIS_MODULE; | 1169 | codec->owner = THIS_MODULE; |
@@ -1177,13 +1180,6 @@ static int aic3x_init(struct snd_soc_device *socdev) | |||
1177 | aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); | 1180 | aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); |
1178 | aic3x_write(codec, AIC3X_RESET, SOFT_RESET); | 1181 | aic3x_write(codec, AIC3X_RESET, SOFT_RESET); |
1179 | 1182 | ||
1180 | /* register pcms */ | ||
1181 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1182 | if (ret < 0) { | ||
1183 | printk(KERN_ERR "aic3x: failed to create pcms\n"); | ||
1184 | goto pcm_err; | ||
1185 | } | ||
1186 | |||
1187 | /* DAC default volume and mute */ | 1183 | /* DAC default volume and mute */ |
1188 | aic3x_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON); | 1184 | aic3x_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON); |
1189 | aic3x_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON); | 1185 | aic3x_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON); |
@@ -1250,30 +1246,51 @@ static int aic3x_init(struct snd_soc_device *socdev) | |||
1250 | /* off, with power on */ | 1246 | /* off, with power on */ |
1251 | aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1247 | aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1252 | 1248 | ||
1253 | /* setup GPIO functions */ | 1249 | return 0; |
1254 | aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4); | 1250 | } |
1255 | aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4); | ||
1256 | 1251 | ||
1257 | snd_soc_add_controls(codec, aic3x_snd_controls, | 1252 | static struct snd_soc_codec *aic3x_codec; |
1258 | ARRAY_SIZE(aic3x_snd_controls)); | 1253 | |
1259 | aic3x_add_widgets(codec); | 1254 | static int aic3x_register(struct snd_soc_codec *codec) |
1260 | ret = snd_soc_init_card(socdev); | 1255 | { |
1256 | int ret; | ||
1257 | |||
1258 | ret = aic3x_init(codec); | ||
1261 | if (ret < 0) { | 1259 | if (ret < 0) { |
1262 | printk(KERN_ERR "aic3x: failed to register card\n"); | 1260 | dev_err(codec->dev, "Failed to initialise device\n"); |
1263 | goto card_err; | 1261 | return ret; |
1264 | } | 1262 | } |
1265 | 1263 | ||
1266 | return ret; | 1264 | aic3x_codec = codec; |
1267 | 1265 | ||
1268 | card_err: | 1266 | ret = snd_soc_register_codec(codec); |
1269 | snd_soc_free_pcms(socdev); | 1267 | if (ret) { |
1270 | snd_soc_dapm_free(socdev); | 1268 | dev_err(codec->dev, "Failed to register codec\n"); |
1271 | pcm_err: | 1269 | return ret; |
1272 | kfree(codec->reg_cache); | 1270 | } |
1273 | return ret; | 1271 | |
1272 | ret = snd_soc_register_dai(&aic3x_dai); | ||
1273 | if (ret) { | ||
1274 | dev_err(codec->dev, "Failed to register dai\n"); | ||
1275 | snd_soc_unregister_codec(codec); | ||
1276 | return ret; | ||
1277 | } | ||
1278 | |||
1279 | return 0; | ||
1274 | } | 1280 | } |
1275 | 1281 | ||
1276 | static struct snd_soc_device *aic3x_socdev; | 1282 | static int aic3x_unregister(struct aic3x_priv *aic3x) |
1283 | { | ||
1284 | aic3x_set_bias_level(&aic3x->codec, SND_SOC_BIAS_OFF); | ||
1285 | |||
1286 | snd_soc_unregister_dai(&aic3x_dai); | ||
1287 | snd_soc_unregister_codec(&aic3x->codec); | ||
1288 | |||
1289 | kfree(aic3x); | ||
1290 | aic3x_codec = NULL; | ||
1291 | |||
1292 | return 0; | ||
1293 | } | ||
1277 | 1294 | ||
1278 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1295 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1279 | /* | 1296 | /* |
@@ -1288,28 +1305,36 @@ static struct snd_soc_device *aic3x_socdev; | |||
1288 | static int aic3x_i2c_probe(struct i2c_client *i2c, | 1305 | static int aic3x_i2c_probe(struct i2c_client *i2c, |
1289 | const struct i2c_device_id *id) | 1306 | const struct i2c_device_id *id) |
1290 | { | 1307 | { |
1291 | struct snd_soc_device *socdev = aic3x_socdev; | 1308 | struct snd_soc_codec *codec; |
1292 | struct snd_soc_codec *codec = socdev->card->codec; | 1309 | struct aic3x_priv *aic3x; |
1293 | int ret; | 1310 | |
1311 | aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); | ||
1312 | if (aic3x == NULL) { | ||
1313 | dev_err(&i2c->dev, "failed to create private data\n"); | ||
1314 | return -ENOMEM; | ||
1315 | } | ||
1294 | 1316 | ||
1295 | i2c_set_clientdata(i2c, codec); | 1317 | codec = &aic3x->codec; |
1318 | codec->dev = &i2c->dev; | ||
1319 | codec->private_data = aic3x; | ||
1296 | codec->control_data = i2c; | 1320 | codec->control_data = i2c; |
1321 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
1297 | 1322 | ||
1298 | ret = aic3x_init(socdev); | 1323 | i2c_set_clientdata(i2c, aic3x); |
1299 | if (ret < 0) | 1324 | |
1300 | printk(KERN_ERR "aic3x: failed to initialise AIC3X\n"); | 1325 | return aic3x_register(codec); |
1301 | return ret; | ||
1302 | } | 1326 | } |
1303 | 1327 | ||
1304 | static int aic3x_i2c_remove(struct i2c_client *client) | 1328 | static int aic3x_i2c_remove(struct i2c_client *client) |
1305 | { | 1329 | { |
1306 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 1330 | struct aic3x_priv *aic3x = i2c_get_clientdata(client); |
1307 | kfree(codec->reg_cache); | 1331 | |
1308 | return 0; | 1332 | return aic3x_unregister(aic3x); |
1309 | } | 1333 | } |
1310 | 1334 | ||
1311 | static const struct i2c_device_id aic3x_i2c_id[] = { | 1335 | static const struct i2c_device_id aic3x_i2c_id[] = { |
1312 | { "tlv320aic3x", 0 }, | 1336 | { "tlv320aic3x", 0 }, |
1337 | { "tlv320aic33", 0 }, | ||
1313 | { } | 1338 | { } |
1314 | }; | 1339 | }; |
1315 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); | 1340 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); |
@@ -1320,50 +1345,28 @@ static struct i2c_driver aic3x_i2c_driver = { | |||
1320 | .name = "aic3x I2C Codec", | 1345 | .name = "aic3x I2C Codec", |
1321 | .owner = THIS_MODULE, | 1346 | .owner = THIS_MODULE, |
1322 | }, | 1347 | }, |
1323 | .probe = aic3x_i2c_probe, | 1348 | .probe = aic3x_i2c_probe, |
1324 | .remove = aic3x_i2c_remove, | 1349 | .remove = aic3x_i2c_remove, |
1325 | .id_table = aic3x_i2c_id, | 1350 | .id_table = aic3x_i2c_id, |
1326 | }; | 1351 | }; |
1327 | 1352 | ||
1328 | static int aic3x_add_i2c_device(struct platform_device *pdev, | 1353 | static inline void aic3x_i2c_init(void) |
1329 | const struct aic3x_setup_data *setup) | ||
1330 | { | 1354 | { |
1331 | struct i2c_board_info info; | ||
1332 | struct i2c_adapter *adapter; | ||
1333 | struct i2c_client *client; | ||
1334 | int ret; | 1355 | int ret; |
1335 | 1356 | ||
1336 | ret = i2c_add_driver(&aic3x_i2c_driver); | 1357 | ret = i2c_add_driver(&aic3x_i2c_driver); |
1337 | if (ret != 0) { | 1358 | if (ret) |
1338 | dev_err(&pdev->dev, "can't add i2c driver\n"); | 1359 | printk(KERN_ERR "%s: error regsitering i2c driver, %d\n", |
1339 | return ret; | 1360 | __func__, ret); |
1340 | } | 1361 | } |
1341 | |||
1342 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
1343 | info.addr = setup->i2c_address; | ||
1344 | strlcpy(info.type, "tlv320aic3x", I2C_NAME_SIZE); | ||
1345 | |||
1346 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
1347 | if (!adapter) { | ||
1348 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
1349 | setup->i2c_bus); | ||
1350 | goto err_driver; | ||
1351 | } | ||
1352 | |||
1353 | client = i2c_new_device(adapter, &info); | ||
1354 | i2c_put_adapter(adapter); | ||
1355 | if (!client) { | ||
1356 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
1357 | (unsigned int)info.addr); | ||
1358 | goto err_driver; | ||
1359 | } | ||
1360 | |||
1361 | return 0; | ||
1362 | 1362 | ||
1363 | err_driver: | 1363 | static inline void aic3x_i2c_exit(void) |
1364 | { | ||
1364 | i2c_del_driver(&aic3x_i2c_driver); | 1365 | i2c_del_driver(&aic3x_i2c_driver); |
1365 | return -ENODEV; | ||
1366 | } | 1366 | } |
1367 | #else | ||
1368 | static inline void aic3x_i2c_init(void) { } | ||
1369 | static inline void aic3x_i2c_exit(void) { } | ||
1367 | #endif | 1370 | #endif |
1368 | 1371 | ||
1369 | static int aic3x_probe(struct platform_device *pdev) | 1372 | static int aic3x_probe(struct platform_device *pdev) |
@@ -1371,42 +1374,51 @@ static int aic3x_probe(struct platform_device *pdev) | |||
1371 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1374 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1372 | struct aic3x_setup_data *setup; | 1375 | struct aic3x_setup_data *setup; |
1373 | struct snd_soc_codec *codec; | 1376 | struct snd_soc_codec *codec; |
1374 | struct aic3x_priv *aic3x; | ||
1375 | int ret = 0; | 1377 | int ret = 0; |
1376 | 1378 | ||
1377 | printk(KERN_INFO "AIC3X Audio Codec %s\n", AIC3X_VERSION); | 1379 | codec = aic3x_codec; |
1380 | if (!codec) { | ||
1381 | dev_err(&pdev->dev, "Codec not registered\n"); | ||
1382 | return -ENODEV; | ||
1383 | } | ||
1378 | 1384 | ||
1385 | socdev->card->codec = codec; | ||
1379 | setup = socdev->codec_data; | 1386 | setup = socdev->codec_data; |
1380 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
1381 | if (codec == NULL) | ||
1382 | return -ENOMEM; | ||
1383 | 1387 | ||
1384 | aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); | 1388 | if (setup) { |
1385 | if (aic3x == NULL) { | 1389 | /* setup GPIO functions */ |
1386 | kfree(codec); | 1390 | aic3x_write(codec, AIC3X_GPIO1_REG, |
1387 | return -ENOMEM; | 1391 | (setup->gpio_func[0] & 0xf) << 4); |
1392 | aic3x_write(codec, AIC3X_GPIO2_REG, | ||
1393 | (setup->gpio_func[1] & 0xf) << 4); | ||
1388 | } | 1394 | } |
1389 | 1395 | ||
1390 | codec->private_data = aic3x; | 1396 | /* register pcms */ |
1391 | socdev->card->codec = codec; | 1397 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
1392 | mutex_init(&codec->mutex); | 1398 | if (ret < 0) { |
1393 | INIT_LIST_HEAD(&codec->dapm_widgets); | 1399 | printk(KERN_ERR "aic3x: failed to create pcms\n"); |
1394 | INIT_LIST_HEAD(&codec->dapm_paths); | 1400 | goto pcm_err; |
1395 | |||
1396 | aic3x_socdev = socdev; | ||
1397 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1398 | if (setup->i2c_address) { | ||
1399 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
1400 | ret = aic3x_add_i2c_device(pdev, setup); | ||
1401 | } | 1401 | } |
1402 | #else | ||
1403 | /* Add other interfaces here */ | ||
1404 | #endif | ||
1405 | 1402 | ||
1406 | if (ret != 0) { | 1403 | snd_soc_add_controls(codec, aic3x_snd_controls, |
1407 | kfree(codec->private_data); | 1404 | ARRAY_SIZE(aic3x_snd_controls)); |
1408 | kfree(codec); | 1405 | |
1406 | aic3x_add_widgets(codec); | ||
1407 | |||
1408 | ret = snd_soc_init_card(socdev); | ||
1409 | if (ret < 0) { | ||
1410 | printk(KERN_ERR "aic3x: failed to register card\n"); | ||
1411 | goto card_err; | ||
1409 | } | 1412 | } |
1413 | |||
1414 | return ret; | ||
1415 | |||
1416 | card_err: | ||
1417 | snd_soc_free_pcms(socdev); | ||
1418 | snd_soc_dapm_free(socdev); | ||
1419 | |||
1420 | pcm_err: | ||
1421 | kfree(codec->reg_cache); | ||
1410 | return ret; | 1422 | return ret; |
1411 | } | 1423 | } |
1412 | 1424 | ||
@@ -1421,12 +1433,8 @@ static int aic3x_remove(struct platform_device *pdev) | |||
1421 | 1433 | ||
1422 | snd_soc_free_pcms(socdev); | 1434 | snd_soc_free_pcms(socdev); |
1423 | snd_soc_dapm_free(socdev); | 1435 | snd_soc_dapm_free(socdev); |
1424 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1436 | |
1425 | i2c_unregister_device(codec->control_data); | 1437 | kfree(codec->reg_cache); |
1426 | i2c_del_driver(&aic3x_i2c_driver); | ||
1427 | #endif | ||
1428 | kfree(codec->private_data); | ||
1429 | kfree(codec); | ||
1430 | 1438 | ||
1431 | return 0; | 1439 | return 0; |
1432 | } | 1440 | } |
@@ -1441,13 +1449,15 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x); | |||
1441 | 1449 | ||
1442 | static int __init aic3x_modinit(void) | 1450 | static int __init aic3x_modinit(void) |
1443 | { | 1451 | { |
1444 | return snd_soc_register_dai(&aic3x_dai); | 1452 | aic3x_i2c_init(); |
1453 | |||
1454 | return 0; | ||
1445 | } | 1455 | } |
1446 | module_init(aic3x_modinit); | 1456 | module_init(aic3x_modinit); |
1447 | 1457 | ||
1448 | static void __exit aic3x_exit(void) | 1458 | static void __exit aic3x_exit(void) |
1449 | { | 1459 | { |
1450 | snd_soc_unregister_dai(&aic3x_dai); | 1460 | aic3x_i2c_exit(); |
1451 | } | 1461 | } |
1452 | module_exit(aic3x_exit); | 1462 | module_exit(aic3x_exit); |
1453 | 1463 | ||
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index ac827e578c4d..9af1c886213c 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h | |||
@@ -282,8 +282,6 @@ int aic3x_headset_detected(struct snd_soc_codec *codec); | |||
282 | int aic3x_button_pressed(struct snd_soc_codec *codec); | 282 | int aic3x_button_pressed(struct snd_soc_codec *codec); |
283 | 283 | ||
284 | struct aic3x_setup_data { | 284 | struct aic3x_setup_data { |
285 | int i2c_bus; | ||
286 | unsigned short i2c_address; | ||
287 | unsigned int gpio_func[2]; | 285 | unsigned int gpio_func[2]; |
288 | }; | 286 | }; |
289 | 287 | ||
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 4ded0e3a35e0..3f7e8a8b387e 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -63,6 +63,8 @@ struct wm8350_data { | |||
63 | struct wm8350_jack_data hpl; | 63 | struct wm8350_jack_data hpl; |
64 | struct wm8350_jack_data hpr; | 64 | struct wm8350_jack_data hpr; |
65 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | 65 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; |
66 | int fll_freq_out; | ||
67 | int fll_freq_in; | ||
66 | }; | 68 | }; |
67 | 69 | ||
68 | static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec, | 70 | static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec, |
@@ -610,7 +612,7 @@ SOC_DAPM_SINGLE("Switch", WM8350_BEEP_VOLUME, 15, 1, 1); | |||
610 | 612 | ||
611 | /* Out4 Capture Mux */ | 613 | /* Out4 Capture Mux */ |
612 | static const struct snd_kcontrol_new wm8350_out4_capture_controls = | 614 | static const struct snd_kcontrol_new wm8350_out4_capture_controls = |
613 | SOC_DAPM_ENUM("Route", wm8350_enum[8]); | 615 | SOC_DAPM_ENUM("Route", wm8350_enum[7]); |
614 | 616 | ||
615 | static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = { | 617 | static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = { |
616 | 618 | ||
@@ -1099,15 +1101,19 @@ static inline int fll_factors(struct _fll_div *fll_div, unsigned int input, | |||
1099 | } | 1101 | } |
1100 | 1102 | ||
1101 | static int wm8350_set_fll(struct snd_soc_dai *codec_dai, | 1103 | static int wm8350_set_fll(struct snd_soc_dai *codec_dai, |
1102 | int pll_id, unsigned int freq_in, | 1104 | int pll_id, int source, unsigned int freq_in, |
1103 | unsigned int freq_out) | 1105 | unsigned int freq_out) |
1104 | { | 1106 | { |
1105 | struct snd_soc_codec *codec = codec_dai->codec; | 1107 | struct snd_soc_codec *codec = codec_dai->codec; |
1106 | struct wm8350 *wm8350 = codec->control_data; | 1108 | struct wm8350 *wm8350 = codec->control_data; |
1109 | struct wm8350_data *priv = codec->private_data; | ||
1107 | struct _fll_div fll_div; | 1110 | struct _fll_div fll_div; |
1108 | int ret = 0; | 1111 | int ret = 0; |
1109 | u16 fll_1, fll_4; | 1112 | u16 fll_1, fll_4; |
1110 | 1113 | ||
1114 | if (freq_in == priv->fll_freq_in && freq_out == priv->fll_freq_out) | ||
1115 | return 0; | ||
1116 | |||
1111 | /* power down FLL - we need to do this for reconfiguration */ | 1117 | /* power down FLL - we need to do this for reconfiguration */ |
1112 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, | 1118 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, |
1113 | WM8350_FLL_ENA | WM8350_FLL_OSC_ENA); | 1119 | WM8350_FLL_ENA | WM8350_FLL_OSC_ENA); |
@@ -1142,6 +1148,9 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai, | |||
1142 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA); | 1148 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA); |
1143 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA); | 1149 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA); |
1144 | 1150 | ||
1151 | priv->fll_freq_out = freq_out; | ||
1152 | priv->fll_freq_in = freq_in; | ||
1153 | |||
1145 | return 0; | 1154 | return 0; |
1146 | } | 1155 | } |
1147 | 1156 | ||
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index b9ef4d915221..9cb8e50f0fbb 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -1011,7 +1011,8 @@ static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors, | |||
1011 | } | 1011 | } |
1012 | 1012 | ||
1013 | static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | 1013 | static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
1014 | unsigned int freq_in, unsigned int freq_out) | 1014 | int source, unsigned int freq_in, |
1015 | unsigned int freq_out) | ||
1015 | { | 1016 | { |
1016 | struct snd_soc_codec *codec = codec_dai->codec; | 1017 | struct snd_soc_codec *codec = codec_dai->codec; |
1017 | struct wm8400_priv *wm8400 = codec->private_data; | 1018 | struct wm8400_priv *wm8400 = codec->private_data; |
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 060d5d06ba95..5702435af81b 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -271,8 +271,8 @@ static void pll_factors(unsigned int target, unsigned int source) | |||
271 | pll_div.k = K; | 271 | pll_div.k = K; |
272 | } | 272 | } |
273 | 273 | ||
274 | static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, | 274 | static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
275 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 275 | int source, unsigned int freq_in, unsigned int freq_out) |
276 | { | 276 | { |
277 | struct snd_soc_codec *codec = codec_dai->codec; | 277 | struct snd_soc_codec *codec = codec_dai->codec; |
278 | u16 reg; | 278 | u16 reg; |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index d5473473a1e3..3be5c0b2552c 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -407,8 +407,8 @@ static int pll_factors(struct _pll_div *pll_div, unsigned int target, | |||
407 | return 0; | 407 | return 0; |
408 | } | 408 | } |
409 | 409 | ||
410 | static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, | 410 | static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
411 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 411 | int source, unsigned int freq_in, unsigned int freq_out) |
412 | { | 412 | { |
413 | int offset; | 413 | int offset; |
414 | struct snd_soc_codec *codec = codec_dai->codec; | 414 | struct snd_soc_codec *codec = codec_dai->codec; |
@@ -458,12 +458,12 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, | |||
458 | return 0; | 458 | return 0; |
459 | 459 | ||
460 | snd_soc_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff); | 460 | snd_soc_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff); |
461 | snd_soc_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff); | 461 | snd_soc_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0x1ff); |
462 | snd_soc_write(codec, WM8580_PLLA3 + offset, | 462 | snd_soc_write(codec, WM8580_PLLA3 + offset, |
463 | (pll_div.k >> 18 & 0xf) | (pll_div.n << 4)); | 463 | (pll_div.k >> 18 & 0xf) | (pll_div.n << 4)); |
464 | 464 | ||
465 | reg = snd_soc_read(codec, WM8580_PLLA4 + offset); | 465 | reg = snd_soc_read(codec, WM8580_PLLA4 + offset); |
466 | reg &= ~0x3f; | 466 | reg &= ~0x1b; |
467 | reg |= pll_div.prescale | pll_div.postscale << 1 | | 467 | reg |= pll_div.prescale | pll_div.postscale << 1 | |
468 | pll_div.freqmode << 3; | 468 | pll_div.freqmode << 3; |
469 | 469 | ||
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index d80d414cfbbd..f60f3a02d1f8 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -723,8 +723,8 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target, | |||
723 | pll_div->k = K; | 723 | pll_div->k = K; |
724 | } | 724 | } |
725 | 725 | ||
726 | static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, | 726 | static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
727 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 727 | int source, unsigned int freq_in, unsigned int freq_out) |
728 | { | 728 | { |
729 | u16 reg, enable; | 729 | u16 reg, enable; |
730 | int offset; | 730 | int offset; |
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5e9c855c0036..882604ef768c 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -814,8 +814,8 @@ reenable: | |||
814 | return 0; | 814 | return 0; |
815 | } | 815 | } |
816 | 816 | ||
817 | static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, | 817 | static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
818 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 818 | int source, unsigned int freq_in, unsigned int freq_out) |
819 | { | 819 | { |
820 | return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out); | 820 | return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out); |
821 | } | 821 | } |
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index da97aae475a2..914d788a2b76 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -536,8 +536,8 @@ static void pll_factors(unsigned int target, unsigned int source) | |||
536 | } | 536 | } |
537 | 537 | ||
538 | /* Untested at the moment */ | 538 | /* Untested at the moment */ |
539 | static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, | 539 | static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
540 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 540 | int source, unsigned int freq_in, unsigned int freq_out) |
541 | { | 541 | { |
542 | struct snd_soc_codec *codec = codec_dai->codec; | 542 | struct snd_soc_codec *codec = codec_dai->codec; |
543 | u16 reg; | 543 | u16 reg; |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index f59703be61c8..416fb3c17018 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -540,8 +540,8 @@ static int pll_factors(unsigned int source, unsigned int target, | |||
540 | return 0; | 540 | return 0; |
541 | } | 541 | } |
542 | 542 | ||
543 | static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, | 543 | static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
544 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 544 | int source, unsigned int freq_in, unsigned int freq_out) |
545 | { | 545 | { |
546 | struct snd_soc_codec *codec = codec_dai->codec; | 546 | struct snd_soc_codec *codec = codec_dai->codec; |
547 | u16 reg; | 547 | u16 reg; |
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index d8a013ab3177..93d66e30f109 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
@@ -12,7 +12,6 @@ | |||
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/moduleparam.h> | 14 | #include <linux/moduleparam.h> |
15 | #include <linux/version.h> | ||
16 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
17 | #include <linux/init.h> | 16 | #include <linux/init.h> |
18 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
@@ -329,8 +328,8 @@ static void pll_factors(unsigned int target, unsigned int source) | |||
329 | pll_div.k = K; | 328 | pll_div.k = K; |
330 | } | 329 | } |
331 | 330 | ||
332 | static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, | 331 | static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
333 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 332 | int source, unsigned int freq_in, unsigned int freq_out) |
334 | { | 333 | { |
335 | struct snd_soc_codec *codec = codec_dai->codec; | 334 | struct snd_soc_codec *codec = codec_dai->codec; |
336 | u16 reg; | 335 | u16 reg; |
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 2d702db4131d..f657e9a5fe26 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -972,8 +972,8 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target, | |||
972 | pll_div->k = K; | 972 | pll_div->k = K; |
973 | } | 973 | } |
974 | 974 | ||
975 | static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, | 975 | static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
976 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 976 | int source, unsigned int freq_in, unsigned int freq_out) |
977 | { | 977 | { |
978 | u16 reg; | 978 | u16 reg; |
979 | struct snd_soc_codec *codec = codec_dai->codec; | 979 | struct snd_soc_codec *codec = codec_dai->codec; |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 13befa338247..6b32a2852603 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -422,7 +422,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, | |||
422 | return 0; | 422 | return 0; |
423 | } | 423 | } |
424 | 424 | ||
425 | static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, | 425 | static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, |
426 | unsigned int Fref, unsigned int Fout) | 426 | unsigned int Fref, unsigned int Fout) |
427 | { | 427 | { |
428 | struct snd_soc_codec *codec = dai->codec; | 428 | struct snd_soc_codec *codec = dai->codec; |
@@ -846,18 +846,76 @@ SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 2, 1, 0), | |||
846 | SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 0, 1, 0), | 846 | SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 0, 1, 0), |
847 | }; | 847 | }; |
848 | 848 | ||
849 | static const char *aif_text[] = { | ||
850 | "Left", "Right" | ||
851 | }; | ||
852 | |||
853 | static const struct soc_enum aifoutl_enum = | ||
854 | SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 15, 2, aif_text); | ||
855 | |||
856 | static const struct snd_kcontrol_new aifoutl_mux = | ||
857 | SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); | ||
858 | |||
859 | static const struct soc_enum aifoutr_enum = | ||
860 | SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 14, 2, aif_text); | ||
861 | |||
862 | static const struct snd_kcontrol_new aifoutr_mux = | ||
863 | SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); | ||
864 | |||
865 | static const struct soc_enum aifinl_enum = | ||
866 | SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 15, 2, aif_text); | ||
867 | |||
868 | static const struct snd_kcontrol_new aifinl_mux = | ||
869 | SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); | ||
870 | |||
871 | static const struct soc_enum aifinr_enum = | ||
872 | SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 14, 2, aif_text); | ||
873 | |||
874 | static const struct snd_kcontrol_new aifinr_mux = | ||
875 | SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); | ||
876 | |||
877 | static const char *sidetone_text[] = { | ||
878 | "None", "Left", "Right" | ||
879 | }; | ||
880 | |||
881 | static const struct soc_enum sidetonel_enum = | ||
882 | SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 2, 3, sidetone_text); | ||
883 | |||
884 | static const struct snd_kcontrol_new sidetonel_mux = | ||
885 | SOC_DAPM_ENUM("Left Sidetone", sidetonel_enum); | ||
886 | |||
887 | static const struct soc_enum sidetoner_enum = | ||
888 | SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 0, 3, sidetone_text); | ||
889 | |||
890 | static const struct snd_kcontrol_new sidetoner_mux = | ||
891 | SOC_DAPM_ENUM("Right Sidetone", sidetoner_enum); | ||
892 | |||
849 | static const struct snd_soc_dapm_widget wm8993_dapm_widgets[] = { | 893 | static const struct snd_soc_dapm_widget wm8993_dapm_widgets[] = { |
850 | SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event, | 894 | SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event, |
851 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | 895 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
852 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0), | 896 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0), |
853 | SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0), | 897 | SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0), |
854 | 898 | ||
899 | SND_SOC_DAPM_ADC("ADCL", NULL, WM8993_POWER_MANAGEMENT_2, 1, 0), | ||
900 | SND_SOC_DAPM_ADC("ADCR", NULL, WM8993_POWER_MANAGEMENT_2, 0, 0), | ||
901 | |||
902 | SND_SOC_DAPM_MUX("AIFOUTL Mux", SND_SOC_NOPM, 0, 0, &aifoutl_mux), | ||
903 | SND_SOC_DAPM_MUX("AIFOUTR Mux", SND_SOC_NOPM, 0, 0, &aifoutr_mux), | ||
904 | |||
905 | SND_SOC_DAPM_AIF_OUT("AIFOUTL", "Capture", 0, SND_SOC_NOPM, 0, 0), | ||
906 | SND_SOC_DAPM_AIF_OUT("AIFOUTR", "Capture", 1, SND_SOC_NOPM, 0, 0), | ||
855 | 907 | ||
856 | SND_SOC_DAPM_ADC("ADCL", "Capture", WM8993_POWER_MANAGEMENT_2, 1, 0), | 908 | SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0), |
857 | SND_SOC_DAPM_ADC("ADCR", "Capture", WM8993_POWER_MANAGEMENT_2, 0, 0), | 909 | SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0), |
858 | 910 | ||
859 | SND_SOC_DAPM_DAC("DACL", "Playback", WM8993_POWER_MANAGEMENT_3, 1, 0), | 911 | SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &aifinl_mux), |
860 | SND_SOC_DAPM_DAC("DACR", "Playback", WM8993_POWER_MANAGEMENT_3, 0, 0), | 912 | SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &aifinr_mux), |
913 | |||
914 | SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &sidetonel_mux), | ||
915 | SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &sidetoner_mux), | ||
916 | |||
917 | SND_SOC_DAPM_DAC("DACL", NULL, WM8993_POWER_MANAGEMENT_3, 1, 0), | ||
918 | SND_SOC_DAPM_DAC("DACR", NULL, WM8993_POWER_MANAGEMENT_3, 0, 0), | ||
861 | 919 | ||
862 | SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), | 920 | SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), |
863 | SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), | 921 | SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), |
@@ -875,10 +933,32 @@ static const struct snd_soc_dapm_route routes[] = { | |||
875 | { "ADCR", NULL, "CLK_SYS" }, | 933 | { "ADCR", NULL, "CLK_SYS" }, |
876 | { "ADCR", NULL, "CLK_DSP" }, | 934 | { "ADCR", NULL, "CLK_DSP" }, |
877 | 935 | ||
936 | { "AIFOUTL Mux", "Left", "ADCL" }, | ||
937 | { "AIFOUTL Mux", "Right", "ADCR" }, | ||
938 | { "AIFOUTR Mux", "Left", "ADCL" }, | ||
939 | { "AIFOUTR Mux", "Right", "ADCR" }, | ||
940 | |||
941 | { "AIFOUTL", NULL, "AIFOUTL Mux" }, | ||
942 | { "AIFOUTR", NULL, "AIFOUTR Mux" }, | ||
943 | |||
944 | { "DACL Mux", "Left", "AIFINL" }, | ||
945 | { "DACL Mux", "Right", "AIFINR" }, | ||
946 | { "DACR Mux", "Left", "AIFINL" }, | ||
947 | { "DACR Mux", "Right", "AIFINR" }, | ||
948 | |||
949 | { "DACL Sidetone", "Left", "ADCL" }, | ||
950 | { "DACL Sidetone", "Right", "ADCR" }, | ||
951 | { "DACR Sidetone", "Left", "ADCL" }, | ||
952 | { "DACR Sidetone", "Right", "ADCR" }, | ||
953 | |||
878 | { "DACL", NULL, "CLK_SYS" }, | 954 | { "DACL", NULL, "CLK_SYS" }, |
879 | { "DACL", NULL, "CLK_DSP" }, | 955 | { "DACL", NULL, "CLK_DSP" }, |
956 | { "DACL", NULL, "DACL Mux" }, | ||
957 | { "DACL", NULL, "DACL Sidetone" }, | ||
880 | { "DACR", NULL, "CLK_SYS" }, | 958 | { "DACR", NULL, "CLK_SYS" }, |
881 | { "DACR", NULL, "CLK_DSP" }, | 959 | { "DACR", NULL, "CLK_DSP" }, |
960 | { "DACR", NULL, "DACR Mux" }, | ||
961 | { "DACR", NULL, "DACR Sidetone" }, | ||
882 | 962 | ||
883 | { "Left Output Mixer", "DAC Switch", "DACL" }, | 963 | { "Left Output Mixer", "DAC Switch", "DACL" }, |
884 | 964 | ||
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index fa88b463e71f..e7d2840d9e59 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c | |||
@@ -406,7 +406,7 @@ static int wm9705_soc_probe(struct platform_device *pdev) | |||
406 | ret = snd_soc_init_card(socdev); | 406 | ret = snd_soc_init_card(socdev); |
407 | if (ret < 0) { | 407 | if (ret < 0) { |
408 | printk(KERN_ERR "wm9705: failed to register card\n"); | 408 | printk(KERN_ERR "wm9705: failed to register card\n"); |
409 | goto pcm_err; | 409 | goto reset_err; |
410 | } | 410 | } |
411 | 411 | ||
412 | return 0; | 412 | return 0; |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index abed37acf787..ca3d449ed89e 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -800,8 +800,8 @@ static int wm9713_set_pll(struct snd_soc_codec *codec, | |||
800 | return 0; | 800 | return 0; |
801 | } | 801 | } |
802 | 802 | ||
803 | static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai, | 803 | static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
804 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 804 | int source, unsigned int freq_in, unsigned int freq_out) |
805 | { | 805 | { |
806 | struct snd_soc_codec *codec = codec_dai->codec; | 806 | struct snd_soc_codec *codec = codec_dai->codec; |
807 | return wm9713_set_pll(codec, pll_id, freq_in, freq_out); | 807 | return wm9713_set_pll(codec, pll_id, freq_in, freq_out); |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index e8fc474ba5cf..e542027eea89 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/regulator/consumer.h> | ||
22 | #include <sound/core.h> | 21 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | 23 | #include <sound/pcm_params.h> |
@@ -274,17 +273,12 @@ static int hp_event(struct snd_soc_dapm_widget *w, | |||
274 | 273 | ||
275 | /* Start the DC servo */ | 274 | /* Start the DC servo */ |
276 | snd_soc_update_bits(codec, WM8993_DC_SERVO_0, | 275 | snd_soc_update_bits(codec, WM8993_DC_SERVO_0, |
277 | WM8993_DCS_ENA_CHAN_0 | | 276 | 0xFFFF, |
278 | WM8993_DCS_ENA_CHAN_1 | | ||
279 | WM8993_DCS_TRIG_STARTUP_1 | | ||
280 | WM8993_DCS_TRIG_STARTUP_0, | ||
281 | WM8993_DCS_ENA_CHAN_0 | | 277 | WM8993_DCS_ENA_CHAN_0 | |
282 | WM8993_DCS_ENA_CHAN_1 | | 278 | WM8993_DCS_ENA_CHAN_1 | |
283 | WM8993_DCS_TRIG_STARTUP_1 | | 279 | WM8993_DCS_TRIG_STARTUP_1 | |
284 | WM8993_DCS_TRIG_STARTUP_0); | 280 | WM8993_DCS_TRIG_STARTUP_0); |
285 | wait_for_dc_servo(codec); | 281 | wait_for_dc_servo(codec); |
286 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, | ||
287 | WM8993_DCS_TIMER_PERIOD_01_MASK, 0xa); | ||
288 | 282 | ||
289 | reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | | 283 | reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | |
290 | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; | 284 | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; |
@@ -299,11 +293,8 @@ static int hp_event(struct snd_soc_dapm_widget *w, | |||
299 | WM8993_HPOUT1R_DLY | | 293 | WM8993_HPOUT1R_DLY | |
300 | WM8993_HPOUT1R_OUTP); | 294 | WM8993_HPOUT1R_OUTP); |
301 | 295 | ||
302 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, | ||
303 | WM8993_DCS_TIMER_PERIOD_01_MASK, 0); | ||
304 | snd_soc_update_bits(codec, WM8993_DC_SERVO_0, | 296 | snd_soc_update_bits(codec, WM8993_DC_SERVO_0, |
305 | WM8993_DCS_ENA_CHAN_0 | | 297 | 0xffff, 0); |
306 | WM8993_DCS_ENA_CHAN_1, 0); | ||
307 | 298 | ||
308 | snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); | 299 | snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); |
309 | snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, | 300 | snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, |
@@ -474,12 +465,6 @@ SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0, | |||
474 | SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0, | 465 | SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0, |
475 | mixinr, ARRAY_SIZE(mixinr)), | 466 | mixinr, ARRAY_SIZE(mixinr)), |
476 | 467 | ||
477 | SND_SOC_DAPM_ADC("ADCL", "Capture", WM8993_POWER_MANAGEMENT_2, 1, 0), | ||
478 | SND_SOC_DAPM_ADC("ADCR", "Capture", WM8993_POWER_MANAGEMENT_2, 0, 0), | ||
479 | |||
480 | SND_SOC_DAPM_DAC("DACL", "Playback", WM8993_POWER_MANAGEMENT_3, 1, 0), | ||
481 | SND_SOC_DAPM_DAC("DACR", "Playback", WM8993_POWER_MANAGEMENT_3, 0, 0), | ||
482 | |||
483 | SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0, | 468 | SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0, |
484 | left_output_mixer, ARRAY_SIZE(left_output_mixer)), | 469 | left_output_mixer, ARRAY_SIZE(left_output_mixer)), |
485 | SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0, | 470 | SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0, |