Commit 9745e824a81e54ef009500e120e35b68e387b941

Authored by Mark Brown
1 parent 1593d7dd8c

ASoC: Support non-crystal master clocks for WM8731

Instead of unconditionally enabling the crystal oscillator on the WM8731
only enable it when explicitly selected via set_sysclk(), allowing machine
drivers to specify that they drive a clock into MCLK alone. This avoids
any conflicts between the oscillator and the external MCLK source and saves
power for systems which do not need the oscillator.

This should also deliver a small power saving on systems using the crystal
since the oscillator will only be enabled when the ADC or DAC is active.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Showing 6 changed files with 36 additions and 7 deletions Inline Diff

sound/soc/atmel/sam9g20_wm8731.c
1 /* 1 /*
2 * sam9g20_wm8731 -- SoC audio for AT91SAM9G20-based 2 * sam9g20_wm8731 -- SoC audio for AT91SAM9G20-based
3 * ATMEL AT91SAM9G20ek board. 3 * ATMEL AT91SAM9G20ek board.
4 * 4 *
5 * Copyright (C) 2005 SAN People 5 * Copyright (C) 2005 SAN People
6 * Copyright (C) 2008 Atmel 6 * Copyright (C) 2008 Atmel
7 * 7 *
8 * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com> 8 * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
9 * 9 *
10 * Based on ati_b1_wm8731.c by: 10 * Based on ati_b1_wm8731.c by:
11 * Frank Mandarino <fmandarino@endrelia.com> 11 * Frank Mandarino <fmandarino@endrelia.com>
12 * Copyright 2006 Endrelia Technologies Inc. 12 * Copyright 2006 Endrelia Technologies Inc.
13 * Based on corgi.c by: 13 * Based on corgi.c by:
14 * Copyright 2005 Wolfson Microelectronics PLC. 14 * Copyright 2005 Wolfson Microelectronics PLC.
15 * Copyright 2005 Openedhand Ltd. 15 * Copyright 2005 Openedhand Ltd.
16 * 16 *
17 * This program is free software; you can redistribute it and/or modify 17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by 18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or 19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version. 20 * (at your option) any later version.
21 * 21 *
22 * This program is distributed in the hope that it will be useful, 22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details. 25 * GNU General Public License for more details.
26 * 26 *
27 * You should have received a copy of the GNU General Public License 27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software 28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 */ 30 */
31 31
32 #include <linux/module.h> 32 #include <linux/module.h>
33 #include <linux/moduleparam.h> 33 #include <linux/moduleparam.h>
34 #include <linux/kernel.h> 34 #include <linux/kernel.h>
35 #include <linux/clk.h> 35 #include <linux/clk.h>
36 #include <linux/timer.h> 36 #include <linux/timer.h>
37 #include <linux/interrupt.h> 37 #include <linux/interrupt.h>
38 #include <linux/platform_device.h> 38 #include <linux/platform_device.h>
39 #include <linux/i2c.h> 39 #include <linux/i2c.h>
40 40
41 #include <linux/atmel-ssc.h> 41 #include <linux/atmel-ssc.h>
42 42
43 #include <sound/core.h> 43 #include <sound/core.h>
44 #include <sound/pcm.h> 44 #include <sound/pcm.h>
45 #include <sound/pcm_params.h> 45 #include <sound/pcm_params.h>
46 #include <sound/soc.h> 46 #include <sound/soc.h>
47 #include <sound/soc-dapm.h> 47 #include <sound/soc-dapm.h>
48 48
49 #include <asm/mach-types.h> 49 #include <asm/mach-types.h>
50 #include <mach/hardware.h> 50 #include <mach/hardware.h>
51 #include <mach/gpio.h> 51 #include <mach/gpio.h>
52 52
53 #include "../codecs/wm8731.h" 53 #include "../codecs/wm8731.h"
54 #include "atmel-pcm.h" 54 #include "atmel-pcm.h"
55 #include "atmel_ssc_dai.h" 55 #include "atmel_ssc_dai.h"
56 56
57 #define MCLK_RATE 12000000 57 #define MCLK_RATE 12000000
58 58
59 /* 59 /*
60 * As shipped the board does not have inputs. However, it is relatively 60 * As shipped the board does not have inputs. However, it is relatively
61 * straightforward to modify the board to hook them up so support is left 61 * straightforward to modify the board to hook them up so support is left
62 * in the driver. 62 * in the driver.
63 */ 63 */
64 #undef ENABLE_MIC_INPUT 64 #undef ENABLE_MIC_INPUT
65 65
66 static struct clk *mclk; 66 static struct clk *mclk;
67 67
68 static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream, 68 static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
69 struct snd_pcm_hw_params *params) 69 struct snd_pcm_hw_params *params)
70 { 70 {
71 struct snd_soc_pcm_runtime *rtd = substream->private_data; 71 struct snd_soc_pcm_runtime *rtd = substream->private_data;
72 struct snd_soc_dai *codec_dai = rtd->codec_dai; 72 struct snd_soc_dai *codec_dai = rtd->codec_dai;
73 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 73 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
74 int ret; 74 int ret;
75 75
76 /* set codec DAI configuration */ 76 /* set codec DAI configuration */
77 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 77 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
78 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 78 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
79 if (ret < 0) 79 if (ret < 0)
80 return ret; 80 return ret;
81 81
82 /* set cpu DAI configuration */ 82 /* set cpu DAI configuration */
83 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 83 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
84 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 84 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
85 if (ret < 0) 85 if (ret < 0)
86 return ret; 86 return ret;
87 87
88 return 0; 88 return 0;
89 } 89 }
90 90
91 static struct snd_soc_ops at91sam9g20ek_ops = { 91 static struct snd_soc_ops at91sam9g20ek_ops = {
92 .hw_params = at91sam9g20ek_hw_params, 92 .hw_params = at91sam9g20ek_hw_params,
93 }; 93 };
94 94
95 static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card, 95 static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card,
96 enum snd_soc_bias_level level) 96 enum snd_soc_bias_level level)
97 { 97 {
98 static int mclk_on; 98 static int mclk_on;
99 int ret = 0; 99 int ret = 0;
100 100
101 switch (level) { 101 switch (level) {
102 case SND_SOC_BIAS_ON: 102 case SND_SOC_BIAS_ON:
103 case SND_SOC_BIAS_PREPARE: 103 case SND_SOC_BIAS_PREPARE:
104 if (!mclk_on) 104 if (!mclk_on)
105 ret = clk_enable(mclk); 105 ret = clk_enable(mclk);
106 if (ret == 0) 106 if (ret == 0)
107 mclk_on = 1; 107 mclk_on = 1;
108 break; 108 break;
109 109
110 case SND_SOC_BIAS_OFF: 110 case SND_SOC_BIAS_OFF:
111 case SND_SOC_BIAS_STANDBY: 111 case SND_SOC_BIAS_STANDBY:
112 if (mclk_on) 112 if (mclk_on)
113 clk_disable(mclk); 113 clk_disable(mclk);
114 mclk_on = 0; 114 mclk_on = 0;
115 break; 115 break;
116 } 116 }
117 117
118 return ret; 118 return ret;
119 } 119 }
120 120
121 static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = { 121 static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = {
122 SND_SOC_DAPM_MIC("Int Mic", NULL), 122 SND_SOC_DAPM_MIC("Int Mic", NULL),
123 SND_SOC_DAPM_SPK("Ext Spk", NULL), 123 SND_SOC_DAPM_SPK("Ext Spk", NULL),
124 }; 124 };
125 125
126 static const struct snd_soc_dapm_route intercon[] = { 126 static const struct snd_soc_dapm_route intercon[] = {
127 127
128 /* speaker connected to LHPOUT */ 128 /* speaker connected to LHPOUT */
129 {"Ext Spk", NULL, "LHPOUT"}, 129 {"Ext Spk", NULL, "LHPOUT"},
130 130
131 /* mic is connected to Mic Jack, with WM8731 Mic Bias */ 131 /* mic is connected to Mic Jack, with WM8731 Mic Bias */
132 {"MICIN", NULL, "Mic Bias"}, 132 {"MICIN", NULL, "Mic Bias"},
133 {"Mic Bias", NULL, "Int Mic"}, 133 {"Mic Bias", NULL, "Int Mic"},
134 }; 134 };
135 135
136 /* 136 /*
137 * Logic for a wm8731 as connected on a at91sam9g20ek board. 137 * Logic for a wm8731 as connected on a at91sam9g20ek board.
138 */ 138 */
139 static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) 139 static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
140 { 140 {
141 struct snd_soc_codec *codec = rtd->codec; 141 struct snd_soc_codec *codec = rtd->codec;
142 struct snd_soc_dai *codec_dai = rtd->codec_dai; 142 struct snd_soc_dai *codec_dai = rtd->codec_dai;
143 int ret; 143 int ret;
144 144
145 printk(KERN_DEBUG 145 printk(KERN_DEBUG
146 "at91sam9g20ek_wm8731 " 146 "at91sam9g20ek_wm8731 "
147 ": at91sam9g20ek_wm8731_init() called\n"); 147 ": at91sam9g20ek_wm8731_init() called\n");
148 148
149 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, 149 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
150 MCLK_RATE, SND_SOC_CLOCK_IN); 150 MCLK_RATE, SND_SOC_CLOCK_IN);
151 if (ret < 0) { 151 if (ret < 0) {
152 printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret); 152 printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret);
153 return ret; 153 return ret;
154 } 154 }
155 155
156 /* Add specific widgets */ 156 /* Add specific widgets */
157 snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets, 157 snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets,
158 ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); 158 ARRAY_SIZE(at91sam9g20ek_dapm_widgets));
159 /* Set up specific audio path interconnects */ 159 /* Set up specific audio path interconnects */
160 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 160 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
161 161
162 /* not connected */ 162 /* not connected */
163 snd_soc_dapm_nc_pin(codec, "RLINEIN"); 163 snd_soc_dapm_nc_pin(codec, "RLINEIN");
164 snd_soc_dapm_nc_pin(codec, "LLINEIN"); 164 snd_soc_dapm_nc_pin(codec, "LLINEIN");
165 165
166 #ifdef ENABLE_MIC_INPUT 166 #ifdef ENABLE_MIC_INPUT
167 snd_soc_dapm_enable_pin(codec, "Int Mic"); 167 snd_soc_dapm_enable_pin(codec, "Int Mic");
168 #else 168 #else
169 snd_soc_dapm_nc_pin(codec, "Int Mic"); 169 snd_soc_dapm_nc_pin(codec, "Int Mic");
170 #endif 170 #endif
171 171
172 /* always connected */ 172 /* always connected */
173 snd_soc_dapm_enable_pin(codec, "Ext Spk"); 173 snd_soc_dapm_enable_pin(codec, "Ext Spk");
174 174
175 snd_soc_dapm_sync(codec); 175 snd_soc_dapm_sync(codec);
176 176
177 return 0; 177 return 0;
178 } 178 }
179 179
180 static struct snd_soc_dai_link at91sam9g20ek_dai = { 180 static struct snd_soc_dai_link at91sam9g20ek_dai = {
181 .name = "WM8731", 181 .name = "WM8731",
182 .stream_name = "WM8731 PCM", 182 .stream_name = "WM8731 PCM",
183 .cpu_dai_name = "atmel-ssc-dai.0", 183 .cpu_dai_name = "atmel-ssc-dai.0",
184 .codec_dai_name = "wm8731-hifi", 184 .codec_dai_name = "wm8731-hifi",
185 .init = at91sam9g20ek_wm8731_init, 185 .init = at91sam9g20ek_wm8731_init,
186 .platform_name = "atmel_pcm-audio", 186 .platform_name = "atmel_pcm-audio",
187 .codec_name = "wm8731-codec.0-001a", 187 .codec_name = "wm8731-codec.0-001a",
188 .ops = &at91sam9g20ek_ops, 188 .ops = &at91sam9g20ek_ops,
189 }; 189 };
190 190
191 static struct snd_soc_card snd_soc_at91sam9g20ek = { 191 static struct snd_soc_card snd_soc_at91sam9g20ek = {
192 .name = "AT91SAMG20-EK", 192 .name = "AT91SAMG20-EK",
193 .dai_link = &at91sam9g20ek_dai, 193 .dai_link = &at91sam9g20ek_dai,
194 .num_links = 1, 194 .num_links = 1,
195 .set_bias_level = at91sam9g20ek_set_bias_level, 195 .set_bias_level = at91sam9g20ek_set_bias_level,
196 }; 196 };
197 197
198 static struct platform_device *at91sam9g20ek_snd_device; 198 static struct platform_device *at91sam9g20ek_snd_device;
199 199
200 static int __init at91sam9g20ek_init(void) 200 static int __init at91sam9g20ek_init(void)
201 { 201 {
202 struct clk *pllb; 202 struct clk *pllb;
203 int ret; 203 int ret;
204 204
205 if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc())) 205 if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc()))
206 return -ENODEV; 206 return -ENODEV;
207 207
208 /* 208 /*
209 * Codec MCLK is supplied by PCK0 - set it up. 209 * Codec MCLK is supplied by PCK0 - set it up.
210 */ 210 */
211 mclk = clk_get(NULL, "pck0"); 211 mclk = clk_get(NULL, "pck0");
212 if (IS_ERR(mclk)) { 212 if (IS_ERR(mclk)) {
213 printk(KERN_ERR "ASoC: Failed to get MCLK\n"); 213 printk(KERN_ERR "ASoC: Failed to get MCLK\n");
214 ret = PTR_ERR(mclk); 214 ret = PTR_ERR(mclk);
215 goto err; 215 goto err;
216 } 216 }
217 217
218 pllb = clk_get(NULL, "pllb"); 218 pllb = clk_get(NULL, "pllb");
219 if (IS_ERR(mclk)) { 219 if (IS_ERR(mclk)) {
220 printk(KERN_ERR "ASoC: Failed to get PLLB\n"); 220 printk(KERN_ERR "ASoC: Failed to get PLLB\n");
221 ret = PTR_ERR(mclk); 221 ret = PTR_ERR(mclk);
222 goto err_mclk; 222 goto err_mclk;
223 } 223 }
224 ret = clk_set_parent(mclk, pllb); 224 ret = clk_set_parent(mclk, pllb);
225 clk_put(pllb); 225 clk_put(pllb);
226 if (ret != 0) { 226 if (ret != 0) {
227 printk(KERN_ERR "ASoC: Failed to set MCLK parent\n"); 227 printk(KERN_ERR "ASoC: Failed to set MCLK parent\n");
228 goto err_mclk; 228 goto err_mclk;
229 } 229 }
230 230
231 clk_set_rate(mclk, MCLK_RATE); 231 clk_set_rate(mclk, MCLK_RATE);
232 232
233 at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); 233 at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
234 if (!at91sam9g20ek_snd_device) { 234 if (!at91sam9g20ek_snd_device) {
235 printk(KERN_ERR "ASoC: Platform device allocation failed\n"); 235 printk(KERN_ERR "ASoC: Platform device allocation failed\n");
236 ret = -ENOMEM; 236 ret = -ENOMEM;
237 } 237 }
238 238
239 platform_set_drvdata(at91sam9g20ek_snd_device, 239 platform_set_drvdata(at91sam9g20ek_snd_device,
240 &snd_soc_at91sam9g20ek); 240 &snd_soc_at91sam9g20ek);
241 241
242 ret = platform_device_add(at91sam9g20ek_snd_device); 242 ret = platform_device_add(at91sam9g20ek_snd_device);
243 if (ret) { 243 if (ret) {
244 printk(KERN_ERR "ASoC: Platform device allocation failed\n"); 244 printk(KERN_ERR "ASoC: Platform device allocation failed\n");
245 platform_device_put(at91sam9g20ek_snd_device); 245 platform_device_put(at91sam9g20ek_snd_device);
246 } 246 }
247 247
248 return ret; 248 return ret;
249 249
250 err_mclk: 250 err_mclk:
251 clk_put(mclk); 251 clk_put(mclk);
252 mclk = NULL; 252 mclk = NULL;
253 err: 253 err:
254 return ret; 254 return ret;
255 } 255 }
256 256
257 static void __exit at91sam9g20ek_exit(void) 257 static void __exit at91sam9g20ek_exit(void)
258 { 258 {
259 platform_device_unregister(at91sam9g20ek_snd_device); 259 platform_device_unregister(at91sam9g20ek_snd_device);
260 at91sam9g20ek_snd_device = NULL; 260 at91sam9g20ek_snd_device = NULL;
261 clk_put(mclk); 261 clk_put(mclk);
262 mclk = NULL; 262 mclk = NULL;
263 } 263 }
264 264
265 module_init(at91sam9g20ek_init); 265 module_init(at91sam9g20ek_init);
266 module_exit(at91sam9g20ek_exit); 266 module_exit(at91sam9g20ek_exit);
267 267
268 /* Module information */ 268 /* Module information */
269 MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>"); 269 MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
270 MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731"); 270 MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731");
271 MODULE_LICENSE("GPL"); 271 MODULE_LICENSE("GPL");
272 272
sound/soc/au1x/db1200.c
1 /* 1 /*
2 * DB1200 ASoC audio fabric support code. 2 * DB1200 ASoC audio fabric support code.
3 * 3 *
4 * (c) 2008-9 Manuel Lauss <manuel.lauss@gmail.com> 4 * (c) 2008-9 Manuel Lauss <manuel.lauss@gmail.com>
5 * 5 *
6 */ 6 */
7 7
8 #include <linux/module.h> 8 #include <linux/module.h>
9 #include <linux/moduleparam.h> 9 #include <linux/moduleparam.h>
10 #include <linux/timer.h> 10 #include <linux/timer.h>
11 #include <linux/interrupt.h> 11 #include <linux/interrupt.h>
12 #include <linux/platform_device.h> 12 #include <linux/platform_device.h>
13 #include <sound/core.h> 13 #include <sound/core.h>
14 #include <sound/pcm.h> 14 #include <sound/pcm.h>
15 #include <sound/soc.h> 15 #include <sound/soc.h>
16 #include <sound/soc-dapm.h> 16 #include <sound/soc-dapm.h>
17 #include <asm/mach-au1x00/au1000.h> 17 #include <asm/mach-au1x00/au1000.h>
18 #include <asm/mach-au1x00/au1xxx_psc.h> 18 #include <asm/mach-au1x00/au1xxx_psc.h>
19 #include <asm/mach-au1x00/au1xxx_dbdma.h> 19 #include <asm/mach-au1x00/au1xxx_dbdma.h>
20 #include <asm/mach-db1x00/bcsr.h> 20 #include <asm/mach-db1x00/bcsr.h>
21 21
22 #include "../codecs/wm8731.h" 22 #include "../codecs/wm8731.h"
23 #include "psc.h" 23 #include "psc.h"
24 24
25 /*------------------------- AC97 PART ---------------------------*/ 25 /*------------------------- AC97 PART ---------------------------*/
26 26
27 static struct snd_soc_dai_link db1200_ac97_dai = { 27 static struct snd_soc_dai_link db1200_ac97_dai = {
28 .name = "AC97", 28 .name = "AC97",
29 .stream_name = "AC97 HiFi", 29 .stream_name = "AC97 HiFi",
30 .cpu_dai_name = "au1xpsc-ac97", 30 .cpu_dai_name = "au1xpsc-ac97",
31 .codec_dai_name = "ac97-hifi", 31 .codec_dai_name = "ac97-hifi",
32 .platform_name = "au1xpsc-pcm-audio", 32 .platform_name = "au1xpsc-pcm-audio",
33 .codec_name = "ac97-codec", 33 .codec_name = "ac97-codec",
34 }; 34 };
35 35
36 static struct snd_soc_card db1200_ac97_machine = { 36 static struct snd_soc_card db1200_ac97_machine = {
37 .name = "DB1200_AC97", 37 .name = "DB1200_AC97",
38 .dai_link = &db1200_ac97_dai, 38 .dai_link = &db1200_ac97_dai,
39 .num_links = 1, 39 .num_links = 1,
40 }; 40 };
41 41
42 /*------------------------- I2S PART ---------------------------*/ 42 /*------------------------- I2S PART ---------------------------*/
43 43
44 static int db1200_i2s_startup(struct snd_pcm_substream *substream) 44 static int db1200_i2s_startup(struct snd_pcm_substream *substream)
45 { 45 {
46 struct snd_soc_pcm_runtime *rtd = substream->private_data; 46 struct snd_soc_pcm_runtime *rtd = substream->private_data;
47 struct snd_soc_dai *codec_dai = rtd->codec_dai; 47 struct snd_soc_dai *codec_dai = rtd->codec_dai;
48 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 48 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
49 int ret; 49 int ret;
50 50
51 /* WM8731 has its own 12MHz crystal */ 51 /* WM8731 has its own 12MHz crystal */
52 snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, 52 snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
53 12000000, SND_SOC_CLOCK_IN); 53 12000000, SND_SOC_CLOCK_IN);
54 54
55 /* codec is bitclock and lrclk master */ 55 /* codec is bitclock and lrclk master */
56 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | 56 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J |
57 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 57 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
58 if (ret < 0) 58 if (ret < 0)
59 goto out; 59 goto out;
60 60
61 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_LEFT_J | 61 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_LEFT_J |
62 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 62 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
63 if (ret < 0) 63 if (ret < 0)
64 goto out; 64 goto out;
65 65
66 ret = 0; 66 ret = 0;
67 out: 67 out:
68 return ret; 68 return ret;
69 } 69 }
70 70
71 static struct snd_soc_ops db1200_i2s_wm8731_ops = { 71 static struct snd_soc_ops db1200_i2s_wm8731_ops = {
72 .startup = db1200_i2s_startup, 72 .startup = db1200_i2s_startup,
73 }; 73 };
74 74
75 static struct snd_soc_dai_link db1200_i2s_dai = { 75 static struct snd_soc_dai_link db1200_i2s_dai = {
76 .name = "WM8731", 76 .name = "WM8731",
77 .stream_name = "WM8731 PCM", 77 .stream_name = "WM8731 PCM",
78 .cpu_dai_name = "au1xpsc", 78 .cpu_dai_name = "au1xpsc",
79 .codec_dai_name = "wm8731-hifi" 79 .codec_dai_name = "wm8731-hifi"
80 .platform_name = "au1xpsc-pcm-audio", 80 .platform_name = "au1xpsc-pcm-audio",
81 .codec_name = "wm8731-codec.0-001a", 81 .codec_name = "wm8731-codec.0-001a",
82 .ops = &db1200_i2s_wm8731_ops, 82 .ops = &db1200_i2s_wm8731_ops,
83 }; 83 };
84 84
85 static struct snd_soc_card db1200_i2s_machine = { 85 static struct snd_soc_card db1200_i2s_machine = {
86 .name = "DB1200_I2S", 86 .name = "DB1200_I2S",
87 .dai_link = &db1200_i2s_dai, 87 .dai_link = &db1200_i2s_dai,
88 .num_links = 1, 88 .num_links = 1,
89 }; 89 };
90 90
91 /*------------------------- COMMON PART ---------------------------*/ 91 /*------------------------- COMMON PART ---------------------------*/
92 92
93 static struct platform_device *db1200_asoc_dev; 93 static struct platform_device *db1200_asoc_dev;
94 94
95 static int __init db1200_audio_load(void) 95 static int __init db1200_audio_load(void)
96 { 96 {
97 int ret; 97 int ret;
98 98
99 ret = -ENOMEM; 99 ret = -ENOMEM;
100 db1200_asoc_dev = platform_device_alloc("soc-audio", -1); 100 db1200_asoc_dev = platform_device_alloc("soc-audio", -1);
101 if (!db1200_asoc_dev) 101 if (!db1200_asoc_dev)
102 goto out; 102 goto out;
103 103
104 /* DB1200 board setup set PSC1MUX to preferred audio device */ 104 /* DB1200 board setup set PSC1MUX to preferred audio device */
105 if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX) 105 if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX)
106 platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_machine); 106 platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_machine);
107 else 107 else
108 platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_machine); 108 platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_machine);
109 109
110 ret = platform_device_add(db1200_asoc_dev); 110 ret = platform_device_add(db1200_asoc_dev);
111 111
112 if (ret) { 112 if (ret) {
113 platform_device_put(db1200_asoc_dev); 113 platform_device_put(db1200_asoc_dev);
114 db1200_asoc_dev = NULL; 114 db1200_asoc_dev = NULL;
115 } 115 }
116 out: 116 out:
117 return ret; 117 return ret;
118 } 118 }
119 119
120 static void __exit db1200_audio_unload(void) 120 static void __exit db1200_audio_unload(void)
121 { 121 {
122 platform_device_unregister(db1200_asoc_dev); 122 platform_device_unregister(db1200_asoc_dev);
123 } 123 }
124 124
125 module_init(db1200_audio_load); 125 module_init(db1200_audio_load);
126 module_exit(db1200_audio_unload); 126 module_exit(db1200_audio_unload);
127 127
128 MODULE_LICENSE("GPL"); 128 MODULE_LICENSE("GPL");
129 MODULE_DESCRIPTION("DB1200 ASoC audio support"); 129 MODULE_DESCRIPTION("DB1200 ASoC audio support");
130 MODULE_AUTHOR("Manuel Lauss"); 130 MODULE_AUTHOR("Manuel Lauss");
131 131
sound/soc/codecs/wm8731.c
1 /* 1 /*
2 * wm8731.c -- WM8731 ALSA SoC Audio driver 2 * wm8731.c -- WM8731 ALSA SoC Audio driver
3 * 3 *
4 * Copyright 2005 Openedhand Ltd. 4 * Copyright 2005 Openedhand Ltd.
5 * 5 *
6 * Author: Richard Purdie <richard@openedhand.com> 6 * Author: Richard Purdie <richard@openedhand.com>
7 * 7 *
8 * Based on wm8753.c by Liam Girdwood 8 * Based on wm8753.c by Liam Girdwood
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 */ 13 */
14 14
15 #include <linux/module.h> 15 #include <linux/module.h>
16 #include <linux/moduleparam.h> 16 #include <linux/moduleparam.h>
17 #include <linux/init.h> 17 #include <linux/init.h>
18 #include <linux/delay.h> 18 #include <linux/delay.h>
19 #include <linux/pm.h> 19 #include <linux/pm.h>
20 #include <linux/i2c.h> 20 #include <linux/i2c.h>
21 #include <linux/slab.h> 21 #include <linux/slab.h>
22 #include <linux/platform_device.h> 22 #include <linux/platform_device.h>
23 #include <linux/regulator/consumer.h> 23 #include <linux/regulator/consumer.h>
24 #include <linux/spi/spi.h> 24 #include <linux/spi/spi.h>
25 #include <sound/core.h> 25 #include <sound/core.h>
26 #include <sound/pcm.h> 26 #include <sound/pcm.h>
27 #include <sound/pcm_params.h> 27 #include <sound/pcm_params.h>
28 #include <sound/soc.h> 28 #include <sound/soc.h>
29 #include <sound/soc-dapm.h> 29 #include <sound/soc-dapm.h>
30 #include <sound/initval.h> 30 #include <sound/initval.h>
31 #include <sound/tlv.h> 31 #include <sound/tlv.h>
32 32
33 #include "wm8731.h" 33 #include "wm8731.h"
34 34
35 #define WM8731_NUM_SUPPLIES 4 35 #define WM8731_NUM_SUPPLIES 4
36 static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { 36 static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
37 "AVDD", 37 "AVDD",
38 "HPVDD", 38 "HPVDD",
39 "DCVDD", 39 "DCVDD",
40 "DBVDD", 40 "DBVDD",
41 }; 41 };
42 42
43 /* codec private data */ 43 /* codec private data */
44 struct wm8731_priv { 44 struct wm8731_priv {
45 enum snd_soc_control_type control_type; 45 enum snd_soc_control_type control_type;
46 struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; 46 struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
47 u16 reg_cache[WM8731_CACHEREGNUM]; 47 u16 reg_cache[WM8731_CACHEREGNUM];
48 unsigned int sysclk; 48 unsigned int sysclk;
49 int sysclk_type;
49 }; 50 };
50 51
51 52
52 /* 53 /*
53 * wm8731 register cache 54 * wm8731 register cache
54 * We can't read the WM8731 register space when we are 55 * We can't read the WM8731 register space when we are
55 * using 2 wire for device control, so we cache them instead. 56 * using 2 wire for device control, so we cache them instead.
56 * There is no point in caching the reset register 57 * There is no point in caching the reset register
57 */ 58 */
58 static const u16 wm8731_reg[WM8731_CACHEREGNUM] = { 59 static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
59 0x0097, 0x0097, 0x0079, 0x0079, 60 0x0097, 0x0097, 0x0079, 0x0079,
60 0x000a, 0x0008, 0x009f, 0x000a, 61 0x000a, 0x0008, 0x009f, 0x000a,
61 0x0000, 0x0000 62 0x0000, 0x0000
62 }; 63 };
63 64
64 #define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0) 65 #define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0)
65 66
66 static const char *wm8731_input_select[] = {"Line In", "Mic"}; 67 static const char *wm8731_input_select[] = {"Line In", "Mic"};
67 static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; 68 static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
68 69
69 static const struct soc_enum wm8731_enum[] = { 70 static const struct soc_enum wm8731_enum[] = {
70 SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select), 71 SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select),
71 SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph), 72 SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph),
72 }; 73 };
73 74
74 static const DECLARE_TLV_DB_SCALE(in_tlv, -3450, 150, 0); 75 static const DECLARE_TLV_DB_SCALE(in_tlv, -3450, 150, 0);
75 static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -1500, 300, 0); 76 static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -1500, 300, 0);
76 static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); 77 static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
77 78
78 static const struct snd_kcontrol_new wm8731_snd_controls[] = { 79 static const struct snd_kcontrol_new wm8731_snd_controls[] = {
79 80
80 SOC_DOUBLE_R_TLV("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V, 81 SOC_DOUBLE_R_TLV("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V,
81 0, 127, 0, out_tlv), 82 0, 127, 0, out_tlv),
82 SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V, 83 SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V,
83 7, 1, 0), 84 7, 1, 0),
84 85
85 SOC_DOUBLE_R_TLV("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0, 86 SOC_DOUBLE_R_TLV("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0,
86 in_tlv), 87 in_tlv),
87 SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1), 88 SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1),
88 89
89 SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0), 90 SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0),
90 SOC_SINGLE("Mic Capture Switch", WM8731_APANA, 1, 1, 1), 91 SOC_SINGLE("Mic Capture Switch", WM8731_APANA, 1, 1, 1),
91 92
92 SOC_SINGLE_TLV("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1, 93 SOC_SINGLE_TLV("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1,
93 sidetone_tlv), 94 sidetone_tlv),
94 95
95 SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1), 96 SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1),
96 SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0), 97 SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0),
97 98
98 SOC_ENUM("Playback De-emphasis", wm8731_enum[1]), 99 SOC_ENUM("Playback De-emphasis", wm8731_enum[1]),
99 }; 100 };
100 101
101 /* Output Mixer */ 102 /* Output Mixer */
102 static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = { 103 static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = {
103 SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0), 104 SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
104 SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0), 105 SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
105 SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0), 106 SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
106 }; 107 };
107 108
108 /* Input mux */ 109 /* Input mux */
109 static const struct snd_kcontrol_new wm8731_input_mux_controls = 110 static const struct snd_kcontrol_new wm8731_input_mux_controls =
110 SOC_DAPM_ENUM("Input Select", wm8731_enum[0]); 111 SOC_DAPM_ENUM("Input Select", wm8731_enum[0]);
111 112
112 static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { 113 static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
114 SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0),
113 SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, 115 SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1,
114 &wm8731_output_mixer_controls[0], 116 &wm8731_output_mixer_controls[0],
115 ARRAY_SIZE(wm8731_output_mixer_controls)), 117 ARRAY_SIZE(wm8731_output_mixer_controls)),
116 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8731_PWR, 3, 1), 118 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8731_PWR, 3, 1),
117 SND_SOC_DAPM_OUTPUT("LOUT"), 119 SND_SOC_DAPM_OUTPUT("LOUT"),
118 SND_SOC_DAPM_OUTPUT("LHPOUT"), 120 SND_SOC_DAPM_OUTPUT("LHPOUT"),
119 SND_SOC_DAPM_OUTPUT("ROUT"), 121 SND_SOC_DAPM_OUTPUT("ROUT"),
120 SND_SOC_DAPM_OUTPUT("RHPOUT"), 122 SND_SOC_DAPM_OUTPUT("RHPOUT"),
121 SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8731_PWR, 2, 1), 123 SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8731_PWR, 2, 1),
122 SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &wm8731_input_mux_controls), 124 SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &wm8731_input_mux_controls),
123 SND_SOC_DAPM_PGA("Line Input", WM8731_PWR, 0, 1, NULL, 0), 125 SND_SOC_DAPM_PGA("Line Input", WM8731_PWR, 0, 1, NULL, 0),
124 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8731_PWR, 1, 1), 126 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8731_PWR, 1, 1),
125 SND_SOC_DAPM_INPUT("MICIN"), 127 SND_SOC_DAPM_INPUT("MICIN"),
126 SND_SOC_DAPM_INPUT("RLINEIN"), 128 SND_SOC_DAPM_INPUT("RLINEIN"),
127 SND_SOC_DAPM_INPUT("LLINEIN"), 129 SND_SOC_DAPM_INPUT("LLINEIN"),
128 }; 130 };
129 131
132 static int wm8731_check_osc(struct snd_soc_dapm_widget *source,
133 struct snd_soc_dapm_widget *sink)
134 {
135 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(source->codec);
136
137 return wm8731->sysclk_type == WM8731_SYSCLK_MCLK;
138 }
139
130 static const struct snd_soc_dapm_route intercon[] = { 140 static const struct snd_soc_dapm_route intercon[] = {
141 {"DAC", NULL, "OSC", wm8731_check_osc},
142 {"ADC", NULL, "OSC", wm8731_check_osc},
143
131 /* output mixer */ 144 /* output mixer */
132 {"Output Mixer", "Line Bypass Switch", "Line Input"}, 145 {"Output Mixer", "Line Bypass Switch", "Line Input"},
133 {"Output Mixer", "HiFi Playback Switch", "DAC"}, 146 {"Output Mixer", "HiFi Playback Switch", "DAC"},
134 {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, 147 {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
135 148
136 /* outputs */ 149 /* outputs */
137 {"RHPOUT", NULL, "Output Mixer"}, 150 {"RHPOUT", NULL, "Output Mixer"},
138 {"ROUT", NULL, "Output Mixer"}, 151 {"ROUT", NULL, "Output Mixer"},
139 {"LHPOUT", NULL, "Output Mixer"}, 152 {"LHPOUT", NULL, "Output Mixer"},
140 {"LOUT", NULL, "Output Mixer"}, 153 {"LOUT", NULL, "Output Mixer"},
141 154
142 /* input mux */ 155 /* input mux */
143 {"Input Mux", "Line In", "Line Input"}, 156 {"Input Mux", "Line In", "Line Input"},
144 {"Input Mux", "Mic", "Mic Bias"}, 157 {"Input Mux", "Mic", "Mic Bias"},
145 {"ADC", NULL, "Input Mux"}, 158 {"ADC", NULL, "Input Mux"},
146 159
147 /* inputs */ 160 /* inputs */
148 {"Line Input", NULL, "LLINEIN"}, 161 {"Line Input", NULL, "LLINEIN"},
149 {"Line Input", NULL, "RLINEIN"}, 162 {"Line Input", NULL, "RLINEIN"},
150 {"Mic Bias", NULL, "MICIN"}, 163 {"Mic Bias", NULL, "MICIN"},
151 }; 164 };
152 165
153 static int wm8731_add_widgets(struct snd_soc_codec *codec) 166 static int wm8731_add_widgets(struct snd_soc_codec *codec)
154 { 167 {
155 snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets, 168 snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
156 ARRAY_SIZE(wm8731_dapm_widgets)); 169 ARRAY_SIZE(wm8731_dapm_widgets));
157 170
158 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 171 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
159 172
160 return 0; 173 return 0;
161 } 174 }
162 175
163 struct _coeff_div { 176 struct _coeff_div {
164 u32 mclk; 177 u32 mclk;
165 u32 rate; 178 u32 rate;
166 u16 fs; 179 u16 fs;
167 u8 sr:4; 180 u8 sr:4;
168 u8 bosr:1; 181 u8 bosr:1;
169 u8 usb:1; 182 u8 usb:1;
170 }; 183 };
171 184
172 /* codec mclk clock divider coefficients */ 185 /* codec mclk clock divider coefficients */
173 static const struct _coeff_div coeff_div[] = { 186 static const struct _coeff_div coeff_div[] = {
174 /* 48k */ 187 /* 48k */
175 {12288000, 48000, 256, 0x0, 0x0, 0x0}, 188 {12288000, 48000, 256, 0x0, 0x0, 0x0},
176 {18432000, 48000, 384, 0x0, 0x1, 0x0}, 189 {18432000, 48000, 384, 0x0, 0x1, 0x0},
177 {12000000, 48000, 250, 0x0, 0x0, 0x1}, 190 {12000000, 48000, 250, 0x0, 0x0, 0x1},
178 191
179 /* 32k */ 192 /* 32k */
180 {12288000, 32000, 384, 0x6, 0x0, 0x0}, 193 {12288000, 32000, 384, 0x6, 0x0, 0x0},
181 {18432000, 32000, 576, 0x6, 0x1, 0x0}, 194 {18432000, 32000, 576, 0x6, 0x1, 0x0},
182 {12000000, 32000, 375, 0x6, 0x0, 0x1}, 195 {12000000, 32000, 375, 0x6, 0x0, 0x1},
183 196
184 /* 8k */ 197 /* 8k */
185 {12288000, 8000, 1536, 0x3, 0x0, 0x0}, 198 {12288000, 8000, 1536, 0x3, 0x0, 0x0},
186 {18432000, 8000, 2304, 0x3, 0x1, 0x0}, 199 {18432000, 8000, 2304, 0x3, 0x1, 0x0},
187 {11289600, 8000, 1408, 0xb, 0x0, 0x0}, 200 {11289600, 8000, 1408, 0xb, 0x0, 0x0},
188 {16934400, 8000, 2112, 0xb, 0x1, 0x0}, 201 {16934400, 8000, 2112, 0xb, 0x1, 0x0},
189 {12000000, 8000, 1500, 0x3, 0x0, 0x1}, 202 {12000000, 8000, 1500, 0x3, 0x0, 0x1},
190 203
191 /* 96k */ 204 /* 96k */
192 {12288000, 96000, 128, 0x7, 0x0, 0x0}, 205 {12288000, 96000, 128, 0x7, 0x0, 0x0},
193 {18432000, 96000, 192, 0x7, 0x1, 0x0}, 206 {18432000, 96000, 192, 0x7, 0x1, 0x0},
194 {12000000, 96000, 125, 0x7, 0x0, 0x1}, 207 {12000000, 96000, 125, 0x7, 0x0, 0x1},
195 208
196 /* 44.1k */ 209 /* 44.1k */
197 {11289600, 44100, 256, 0x8, 0x0, 0x0}, 210 {11289600, 44100, 256, 0x8, 0x0, 0x0},
198 {16934400, 44100, 384, 0x8, 0x1, 0x0}, 211 {16934400, 44100, 384, 0x8, 0x1, 0x0},
199 {12000000, 44100, 272, 0x8, 0x1, 0x1}, 212 {12000000, 44100, 272, 0x8, 0x1, 0x1},
200 213
201 /* 88.2k */ 214 /* 88.2k */
202 {11289600, 88200, 128, 0xf, 0x0, 0x0}, 215 {11289600, 88200, 128, 0xf, 0x0, 0x0},
203 {16934400, 88200, 192, 0xf, 0x1, 0x0}, 216 {16934400, 88200, 192, 0xf, 0x1, 0x0},
204 {12000000, 88200, 136, 0xf, 0x1, 0x1}, 217 {12000000, 88200, 136, 0xf, 0x1, 0x1},
205 }; 218 };
206 219
207 static inline int get_coeff(int mclk, int rate) 220 static inline int get_coeff(int mclk, int rate)
208 { 221 {
209 int i; 222 int i;
210 223
211 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { 224 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
212 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) 225 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
213 return i; 226 return i;
214 } 227 }
215 return 0; 228 return 0;
216 } 229 }
217 230
218 static int wm8731_hw_params(struct snd_pcm_substream *substream, 231 static int wm8731_hw_params(struct snd_pcm_substream *substream,
219 struct snd_pcm_hw_params *params, 232 struct snd_pcm_hw_params *params,
220 struct snd_soc_dai *dai) 233 struct snd_soc_dai *dai)
221 { 234 {
222 struct snd_soc_codec *codec = dai->codec; 235 struct snd_soc_codec *codec = dai->codec;
223 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); 236 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
224 u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3; 237 u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3;
225 int i = get_coeff(wm8731->sysclk, params_rate(params)); 238 int i = get_coeff(wm8731->sysclk, params_rate(params));
226 u16 srate = (coeff_div[i].sr << 2) | 239 u16 srate = (coeff_div[i].sr << 2) |
227 (coeff_div[i].bosr << 1) | coeff_div[i].usb; 240 (coeff_div[i].bosr << 1) | coeff_div[i].usb;
228 241
229 snd_soc_write(codec, WM8731_SRATE, srate); 242 snd_soc_write(codec, WM8731_SRATE, srate);
230 243
231 /* bit size */ 244 /* bit size */
232 switch (params_format(params)) { 245 switch (params_format(params)) {
233 case SNDRV_PCM_FORMAT_S16_LE: 246 case SNDRV_PCM_FORMAT_S16_LE:
234 break; 247 break;
235 case SNDRV_PCM_FORMAT_S20_3LE: 248 case SNDRV_PCM_FORMAT_S20_3LE:
236 iface |= 0x0004; 249 iface |= 0x0004;
237 break; 250 break;
238 case SNDRV_PCM_FORMAT_S24_LE: 251 case SNDRV_PCM_FORMAT_S24_LE:
239 iface |= 0x0008; 252 iface |= 0x0008;
240 break; 253 break;
241 } 254 }
242 255
243 snd_soc_write(codec, WM8731_IFACE, iface); 256 snd_soc_write(codec, WM8731_IFACE, iface);
244 return 0; 257 return 0;
245 } 258 }
246 259
247 static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, 260 static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
248 struct snd_soc_dai *dai) 261 struct snd_soc_dai *dai)
249 { 262 {
250 struct snd_soc_codec *codec = dai->codec; 263 struct snd_soc_codec *codec = dai->codec;
251 264
252 /* set active */ 265 /* set active */
253 snd_soc_write(codec, WM8731_ACTIVE, 0x0001); 266 snd_soc_write(codec, WM8731_ACTIVE, 0x0001);
254 267
255 return 0; 268 return 0;
256 } 269 }
257 270
258 static void wm8731_shutdown(struct snd_pcm_substream *substream, 271 static void wm8731_shutdown(struct snd_pcm_substream *substream,
259 struct snd_soc_dai *dai) 272 struct snd_soc_dai *dai)
260 { 273 {
261 struct snd_soc_codec *codec = dai->codec; 274 struct snd_soc_codec *codec = dai->codec;
262 275
263 /* deactivate */ 276 /* deactivate */
264 if (!codec->active) { 277 if (!codec->active) {
265 udelay(50); 278 udelay(50);
266 snd_soc_write(codec, WM8731_ACTIVE, 0x0); 279 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
267 } 280 }
268 } 281 }
269 282
270 static int wm8731_mute(struct snd_soc_dai *dai, int mute) 283 static int wm8731_mute(struct snd_soc_dai *dai, int mute)
271 { 284 {
272 struct snd_soc_codec *codec = dai->codec; 285 struct snd_soc_codec *codec = dai->codec;
273 u16 mute_reg = snd_soc_read(codec, WM8731_APDIGI) & 0xfff7; 286 u16 mute_reg = snd_soc_read(codec, WM8731_APDIGI) & 0xfff7;
274 287
275 if (mute) 288 if (mute)
276 snd_soc_write(codec, WM8731_APDIGI, mute_reg | 0x8); 289 snd_soc_write(codec, WM8731_APDIGI, mute_reg | 0x8);
277 else 290 else
278 snd_soc_write(codec, WM8731_APDIGI, mute_reg); 291 snd_soc_write(codec, WM8731_APDIGI, mute_reg);
279 return 0; 292 return 0;
280 } 293 }
281 294
282 static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai, 295 static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
283 int clk_id, unsigned int freq, int dir) 296 int clk_id, unsigned int freq, int dir)
284 { 297 {
285 struct snd_soc_codec *codec = codec_dai->codec; 298 struct snd_soc_codec *codec = codec_dai->codec;
286 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); 299 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
287 300
301 switch (clk_id) {
302 case WM8731_SYSCLK_XTAL:
303 case WM8731_SYSCLK_MCLK:
304 wm8731->sysclk_type = clk_id;
305 break;
306 default:
307 return -EINVAL;
308 }
309
288 switch (freq) { 310 switch (freq) {
289 case 11289600: 311 case 11289600:
290 case 12000000: 312 case 12000000:
291 case 12288000: 313 case 12288000:
292 case 16934400: 314 case 16934400:
293 case 18432000: 315 case 18432000:
294 wm8731->sysclk = freq; 316 wm8731->sysclk = freq;
295 return 0; 317 break;
318 default:
319 return -EINVAL;
296 } 320 }
297 return -EINVAL; 321
322 snd_soc_dapm_sync(codec);
323
324 return 0;
298 } 325 }
299 326
300 327
301 static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai, 328 static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai,
302 unsigned int fmt) 329 unsigned int fmt)
303 { 330 {
304 struct snd_soc_codec *codec = codec_dai->codec; 331 struct snd_soc_codec *codec = codec_dai->codec;
305 u16 iface = 0; 332 u16 iface = 0;
306 333
307 /* set master/slave audio interface */ 334 /* set master/slave audio interface */
308 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 335 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
309 case SND_SOC_DAIFMT_CBM_CFM: 336 case SND_SOC_DAIFMT_CBM_CFM:
310 iface |= 0x0040; 337 iface |= 0x0040;
311 break; 338 break;
312 case SND_SOC_DAIFMT_CBS_CFS: 339 case SND_SOC_DAIFMT_CBS_CFS:
313 break; 340 break;
314 default: 341 default:
315 return -EINVAL; 342 return -EINVAL;
316 } 343 }
317 344
318 /* interface format */ 345 /* interface format */
319 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 346 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
320 case SND_SOC_DAIFMT_I2S: 347 case SND_SOC_DAIFMT_I2S:
321 iface |= 0x0002; 348 iface |= 0x0002;
322 break; 349 break;
323 case SND_SOC_DAIFMT_RIGHT_J: 350 case SND_SOC_DAIFMT_RIGHT_J:
324 break; 351 break;
325 case SND_SOC_DAIFMT_LEFT_J: 352 case SND_SOC_DAIFMT_LEFT_J:
326 iface |= 0x0001; 353 iface |= 0x0001;
327 break; 354 break;
328 case SND_SOC_DAIFMT_DSP_A: 355 case SND_SOC_DAIFMT_DSP_A:
329 iface |= 0x0003; 356 iface |= 0x0003;
330 break; 357 break;
331 case SND_SOC_DAIFMT_DSP_B: 358 case SND_SOC_DAIFMT_DSP_B:
332 iface |= 0x0013; 359 iface |= 0x0013;
333 break; 360 break;
334 default: 361 default:
335 return -EINVAL; 362 return -EINVAL;
336 } 363 }
337 364
338 /* clock inversion */ 365 /* clock inversion */
339 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 366 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
340 case SND_SOC_DAIFMT_NB_NF: 367 case SND_SOC_DAIFMT_NB_NF:
341 break; 368 break;
342 case SND_SOC_DAIFMT_IB_IF: 369 case SND_SOC_DAIFMT_IB_IF:
343 iface |= 0x0090; 370 iface |= 0x0090;
344 break; 371 break;
345 case SND_SOC_DAIFMT_IB_NF: 372 case SND_SOC_DAIFMT_IB_NF:
346 iface |= 0x0080; 373 iface |= 0x0080;
347 break; 374 break;
348 case SND_SOC_DAIFMT_NB_IF: 375 case SND_SOC_DAIFMT_NB_IF:
349 iface |= 0x0010; 376 iface |= 0x0010;
350 break; 377 break;
351 default: 378 default:
352 return -EINVAL; 379 return -EINVAL;
353 } 380 }
354 381
355 /* set iface */ 382 /* set iface */
356 snd_soc_write(codec, WM8731_IFACE, iface); 383 snd_soc_write(codec, WM8731_IFACE, iface);
357 return 0; 384 return 0;
358 } 385 }
359 386
360 static int wm8731_set_bias_level(struct snd_soc_codec *codec, 387 static int wm8731_set_bias_level(struct snd_soc_codec *codec,
361 enum snd_soc_bias_level level) 388 enum snd_soc_bias_level level)
362 { 389 {
363 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); 390 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
364 int i, ret; 391 int i, ret;
365 u8 data[2]; 392 u8 data[2];
366 u16 *cache = codec->reg_cache; 393 u16 *cache = codec->reg_cache;
367 u16 reg; 394 u16 reg;
368 395
369 switch (level) { 396 switch (level) {
370 case SND_SOC_BIAS_ON: 397 case SND_SOC_BIAS_ON:
371 break; 398 break;
372 case SND_SOC_BIAS_PREPARE: 399 case SND_SOC_BIAS_PREPARE:
373 break; 400 break;
374 case SND_SOC_BIAS_STANDBY: 401 case SND_SOC_BIAS_STANDBY:
375 if (codec->bias_level == SND_SOC_BIAS_OFF) { 402 if (codec->bias_level == SND_SOC_BIAS_OFF) {
376 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), 403 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
377 wm8731->supplies); 404 wm8731->supplies);
378 if (ret != 0) 405 if (ret != 0)
379 return ret; 406 return ret;
380 407
381 /* Sync reg_cache with the hardware */ 408 /* Sync reg_cache with the hardware */
382 for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { 409 for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
383 if (cache[i] == wm8731_reg[i]) 410 if (cache[i] == wm8731_reg[i])
384 continue; 411 continue;
385 412
386 data[0] = (i << 1) | ((cache[i] >> 8) 413 data[0] = (i << 1) | ((cache[i] >> 8)
387 & 0x0001); 414 & 0x0001);
388 data[1] = cache[i] & 0x00ff; 415 data[1] = cache[i] & 0x00ff;
389 codec->hw_write(codec->control_data, data, 2); 416 codec->hw_write(codec->control_data, data, 2);
390 } 417 }
391 } 418 }
392 419
393 /* Clear PWROFF, gate CLKOUT, everything else as-is */ 420 /* Clear PWROFF, gate CLKOUT, everything else as-is */
394 reg = snd_soc_read(codec, WM8731_PWR) & 0xff7f; 421 reg = snd_soc_read(codec, WM8731_PWR) & 0xff7f;
395 snd_soc_write(codec, WM8731_PWR, reg | 0x0040); 422 snd_soc_write(codec, WM8731_PWR, reg | 0x0040);
396 break; 423 break;
397 case SND_SOC_BIAS_OFF: 424 case SND_SOC_BIAS_OFF:
398 snd_soc_write(codec, WM8731_ACTIVE, 0x0); 425 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
399 snd_soc_write(codec, WM8731_PWR, 0xffff); 426 snd_soc_write(codec, WM8731_PWR, 0xffff);
400 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), 427 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
401 wm8731->supplies); 428 wm8731->supplies);
402 break; 429 break;
403 } 430 }
404 codec->bias_level = level; 431 codec->bias_level = level;
405 return 0; 432 return 0;
406 } 433 }
407 434
408 #define WM8731_RATES SNDRV_PCM_RATE_8000_96000 435 #define WM8731_RATES SNDRV_PCM_RATE_8000_96000
409 436
410 #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 437 #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
411 SNDRV_PCM_FMTBIT_S24_LE) 438 SNDRV_PCM_FMTBIT_S24_LE)
412 439
413 static struct snd_soc_dai_ops wm8731_dai_ops = { 440 static struct snd_soc_dai_ops wm8731_dai_ops = {
414 .prepare = wm8731_pcm_prepare, 441 .prepare = wm8731_pcm_prepare,
415 .hw_params = wm8731_hw_params, 442 .hw_params = wm8731_hw_params,
416 .shutdown = wm8731_shutdown, 443 .shutdown = wm8731_shutdown,
417 .digital_mute = wm8731_mute, 444 .digital_mute = wm8731_mute,
418 .set_sysclk = wm8731_set_dai_sysclk, 445 .set_sysclk = wm8731_set_dai_sysclk,
419 .set_fmt = wm8731_set_dai_fmt, 446 .set_fmt = wm8731_set_dai_fmt,
420 }; 447 };
421 448
422 static struct snd_soc_dai_driver wm8731_dai = { 449 static struct snd_soc_dai_driver wm8731_dai = {
423 .name = "wm8731-hifi", 450 .name = "wm8731-hifi",
424 .playback = { 451 .playback = {
425 .stream_name = "Playback", 452 .stream_name = "Playback",
426 .channels_min = 1, 453 .channels_min = 1,
427 .channels_max = 2, 454 .channels_max = 2,
428 .rates = WM8731_RATES, 455 .rates = WM8731_RATES,
429 .formats = WM8731_FORMATS,}, 456 .formats = WM8731_FORMATS,},
430 .capture = { 457 .capture = {
431 .stream_name = "Capture", 458 .stream_name = "Capture",
432 .channels_min = 1, 459 .channels_min = 1,
433 .channels_max = 2, 460 .channels_max = 2,
434 .rates = WM8731_RATES, 461 .rates = WM8731_RATES,
435 .formats = WM8731_FORMATS,}, 462 .formats = WM8731_FORMATS,},
436 .ops = &wm8731_dai_ops, 463 .ops = &wm8731_dai_ops,
437 .symmetric_rates = 1, 464 .symmetric_rates = 1,
438 }; 465 };
439 466
440 #ifdef CONFIG_PM 467 #ifdef CONFIG_PM
441 static int wm8731_suspend(struct snd_soc_codec *codec, pm_message_t state) 468 static int wm8731_suspend(struct snd_soc_codec *codec, pm_message_t state)
442 { 469 {
443 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); 470 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
444 471
445 return 0; 472 return 0;
446 } 473 }
447 474
448 static int wm8731_resume(struct snd_soc_codec *codec) 475 static int wm8731_resume(struct snd_soc_codec *codec)
449 { 476 {
450 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 477 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
451 478
452 return 0; 479 return 0;
453 } 480 }
454 #else 481 #else
455 #define wm8731_suspend NULL 482 #define wm8731_suspend NULL
456 #define wm8731_resume NULL 483 #define wm8731_resume NULL
457 #endif 484 #endif
458 485
459 static int wm8731_probe(struct snd_soc_codec *codec) 486 static int wm8731_probe(struct snd_soc_codec *codec)
460 { 487 {
461 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); 488 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
462 int ret = 0, i; 489 int ret = 0, i;
463 490
464 codec->bias_level = SND_SOC_BIAS_OFF, 491 codec->bias_level = SND_SOC_BIAS_OFF,
465 492
466 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type); 493 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type);
467 if (ret < 0) { 494 if (ret < 0) {
468 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 495 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
469 return ret; 496 return ret;
470 } 497 }
471 498
472 for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) 499 for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++)
473 wm8731->supplies[i].supply = wm8731_supply_names[i]; 500 wm8731->supplies[i].supply = wm8731_supply_names[i];
474 501
475 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies), 502 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies),
476 wm8731->supplies); 503 wm8731->supplies);
477 if (ret != 0) { 504 if (ret != 0) {
478 dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 505 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
479 return ret; 506 return ret;
480 } 507 }
481 508
482 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), 509 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
483 wm8731->supplies); 510 wm8731->supplies);
484 if (ret != 0) { 511 if (ret != 0) {
485 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); 512 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
486 goto err_regulator_get; 513 goto err_regulator_get;
487 } 514 }
488 515
489 ret = wm8731_reset(codec); 516 ret = wm8731_reset(codec);
490 if (ret < 0) { 517 if (ret < 0) {
491 dev_err(codec->dev, "Failed to issue reset: %d\n", ret); 518 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
492 goto err_regulator_enable; 519 goto err_regulator_enable;
493 } 520 }
494 521
495 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 522 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
496 523
497 /* Latch the update bits */ 524 /* Latch the update bits */
498 snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0); 525 snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0);
499 snd_soc_update_bits(codec, WM8731_ROUT1V, 0x100, 0); 526 snd_soc_update_bits(codec, WM8731_ROUT1V, 0x100, 0);
500 snd_soc_update_bits(codec, WM8731_LINVOL, 0x100, 0); 527 snd_soc_update_bits(codec, WM8731_LINVOL, 0x100, 0);
501 snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0); 528 snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0);
502 529
503 /* Disable bypass path by default */ 530 /* Disable bypass path by default */
504 snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0); 531 snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0);
505 532
506 snd_soc_add_controls(codec, wm8731_snd_controls, 533 snd_soc_add_controls(codec, wm8731_snd_controls,
507 ARRAY_SIZE(wm8731_snd_controls)); 534 ARRAY_SIZE(wm8731_snd_controls));
508 wm8731_add_widgets(codec); 535 wm8731_add_widgets(codec);
509 536
510 /* Regulators will have been enabled by bias management */ 537 /* Regulators will have been enabled by bias management */
511 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); 538 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
512 539
513 return 0; 540 return 0;
514 541
515 err_regulator_enable: 542 err_regulator_enable:
516 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); 543 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
517 err_regulator_get: 544 err_regulator_get:
518 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); 545 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
519 546
520 kfree(wm8731); 547 kfree(wm8731);
521 return ret; 548 return ret;
522 } 549 }
523 550
524 /* power down chip */ 551 /* power down chip */
525 static int wm8731_remove(struct snd_soc_codec *codec) 552 static int wm8731_remove(struct snd_soc_codec *codec)
526 { 553 {
527 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); 554 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
528 555
529 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); 556 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
530 557
531 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); 558 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
532 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); 559 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
533 560
534 return 0; 561 return 0;
535 } 562 }
536 563
537 static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { 564 static struct snd_soc_codec_driver soc_codec_dev_wm8731 = {
538 .probe = wm8731_probe, 565 .probe = wm8731_probe,
539 .remove = wm8731_remove, 566 .remove = wm8731_remove,
540 .suspend = wm8731_suspend, 567 .suspend = wm8731_suspend,
541 .resume = wm8731_resume, 568 .resume = wm8731_resume,
542 .set_bias_level = wm8731_set_bias_level, 569 .set_bias_level = wm8731_set_bias_level,
543 .reg_cache_size = sizeof(wm8731_reg), 570 .reg_cache_size = sizeof(wm8731_reg),
544 .reg_word_size = sizeof(u16), 571 .reg_word_size = sizeof(u16),
545 .reg_cache_default = wm8731_reg, 572 .reg_cache_default = wm8731_reg,
546 }; 573 };
547 574
548 #if defined(CONFIG_SPI_MASTER) 575 #if defined(CONFIG_SPI_MASTER)
549 static int __devinit wm8731_spi_probe(struct spi_device *spi) 576 static int __devinit wm8731_spi_probe(struct spi_device *spi)
550 { 577 {
551 struct wm8731_priv *wm8731; 578 struct wm8731_priv *wm8731;
552 int ret; 579 int ret;
553 580
554 wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); 581 wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
555 if (wm8731 == NULL) 582 if (wm8731 == NULL)
556 return -ENOMEM; 583 return -ENOMEM;
557 584
558 wm8731->control_type = SND_SOC_SPI; 585 wm8731->control_type = SND_SOC_SPI;
559 spi_set_drvdata(spi, wm8731); 586 spi_set_drvdata(spi, wm8731);
560 587
561 ret = snd_soc_register_codec(&spi->dev, 588 ret = snd_soc_register_codec(&spi->dev,
562 &soc_codec_dev_wm8731, &wm8731_dai, 1); 589 &soc_codec_dev_wm8731, &wm8731_dai, 1);
563 if (ret < 0) 590 if (ret < 0)
564 kfree(wm8731); 591 kfree(wm8731);
565 return ret; 592 return ret;
566 } 593 }
567 594
568 static int __devexit wm8731_spi_remove(struct spi_device *spi) 595 static int __devexit wm8731_spi_remove(struct spi_device *spi)
569 { 596 {
570 snd_soc_unregister_codec(&spi->dev); 597 snd_soc_unregister_codec(&spi->dev);
571 kfree(spi_get_drvdata(spi)); 598 kfree(spi_get_drvdata(spi));
572 return 0; 599 return 0;
573 } 600 }
574 601
575 static struct spi_driver wm8731_spi_driver = { 602 static struct spi_driver wm8731_spi_driver = {
576 .driver = { 603 .driver = {
577 .name = "wm8731-codec", 604 .name = "wm8731-codec",
578 .bus = &spi_bus_type, 605 .bus = &spi_bus_type,
579 .owner = THIS_MODULE, 606 .owner = THIS_MODULE,
580 }, 607 },
581 .probe = wm8731_spi_probe, 608 .probe = wm8731_spi_probe,
582 .remove = __devexit_p(wm8731_spi_remove), 609 .remove = __devexit_p(wm8731_spi_remove),
583 }; 610 };
584 #endif /* CONFIG_SPI_MASTER */ 611 #endif /* CONFIG_SPI_MASTER */
585 612
586 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 613 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
587 static __devinit int wm8731_i2c_probe(struct i2c_client *i2c, 614 static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
588 const struct i2c_device_id *id) 615 const struct i2c_device_id *id)
589 { 616 {
590 struct wm8731_priv *wm8731; 617 struct wm8731_priv *wm8731;
591 int ret; 618 int ret;
592 619
593 wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); 620 wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
594 if (wm8731 == NULL) 621 if (wm8731 == NULL)
595 return -ENOMEM; 622 return -ENOMEM;
596 623
597 i2c_set_clientdata(i2c, wm8731); 624 i2c_set_clientdata(i2c, wm8731);
598 wm8731->control_type = SND_SOC_I2C; 625 wm8731->control_type = SND_SOC_I2C;
599 626
600 ret = snd_soc_register_codec(&i2c->dev, 627 ret = snd_soc_register_codec(&i2c->dev,
601 &soc_codec_dev_wm8731, &wm8731_dai, 1); 628 &soc_codec_dev_wm8731, &wm8731_dai, 1);
602 if (ret < 0) 629 if (ret < 0)
603 kfree(wm8731); 630 kfree(wm8731);
604 return ret; 631 return ret;
605 } 632 }
606 633
607 static __devexit int wm8731_i2c_remove(struct i2c_client *client) 634 static __devexit int wm8731_i2c_remove(struct i2c_client *client)
608 { 635 {
609 snd_soc_unregister_codec(&client->dev); 636 snd_soc_unregister_codec(&client->dev);
610 kfree(i2c_get_clientdata(client)); 637 kfree(i2c_get_clientdata(client));
611 return 0; 638 return 0;
612 } 639 }
613 640
614 static const struct i2c_device_id wm8731_i2c_id[] = { 641 static const struct i2c_device_id wm8731_i2c_id[] = {
615 { "wm8731", 0 }, 642 { "wm8731", 0 },
616 { } 643 { }
617 }; 644 };
618 MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); 645 MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id);
619 646
620 static struct i2c_driver wm8731_i2c_driver = { 647 static struct i2c_driver wm8731_i2c_driver = {
621 .driver = { 648 .driver = {
622 .name = "wm8731-codec", 649 .name = "wm8731-codec",
623 .owner = THIS_MODULE, 650 .owner = THIS_MODULE,
624 }, 651 },
625 .probe = wm8731_i2c_probe, 652 .probe = wm8731_i2c_probe,
626 .remove = __devexit_p(wm8731_i2c_remove), 653 .remove = __devexit_p(wm8731_i2c_remove),
627 .id_table = wm8731_i2c_id, 654 .id_table = wm8731_i2c_id,
628 }; 655 };
629 #endif 656 #endif
630 657
631 static int __init wm8731_modinit(void) 658 static int __init wm8731_modinit(void)
632 { 659 {
633 int ret = 0; 660 int ret = 0;
634 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 661 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
635 ret = i2c_add_driver(&wm8731_i2c_driver); 662 ret = i2c_add_driver(&wm8731_i2c_driver);
636 if (ret != 0) { 663 if (ret != 0) {
637 printk(KERN_ERR "Failed to register WM8731 I2C driver: %d\n", 664 printk(KERN_ERR "Failed to register WM8731 I2C driver: %d\n",
638 ret); 665 ret);
639 } 666 }
640 #endif 667 #endif
641 #if defined(CONFIG_SPI_MASTER) 668 #if defined(CONFIG_SPI_MASTER)
642 ret = spi_register_driver(&wm8731_spi_driver); 669 ret = spi_register_driver(&wm8731_spi_driver);
643 if (ret != 0) { 670 if (ret != 0) {
644 printk(KERN_ERR "Failed to register WM8731 SPI driver: %d\n", 671 printk(KERN_ERR "Failed to register WM8731 SPI driver: %d\n",
645 ret); 672 ret);
646 } 673 }
647 #endif 674 #endif
648 return ret; 675 return ret;
649 } 676 }
650 module_init(wm8731_modinit); 677 module_init(wm8731_modinit);
651 678
652 static void __exit wm8731_exit(void) 679 static void __exit wm8731_exit(void)
653 { 680 {
654 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 681 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
655 i2c_del_driver(&wm8731_i2c_driver); 682 i2c_del_driver(&wm8731_i2c_driver);
656 #endif 683 #endif
657 #if defined(CONFIG_SPI_MASTER) 684 #if defined(CONFIG_SPI_MASTER)
658 spi_unregister_driver(&wm8731_spi_driver); 685 spi_unregister_driver(&wm8731_spi_driver);
659 #endif 686 #endif
660 } 687 }
661 module_exit(wm8731_exit); 688 module_exit(wm8731_exit);
662 689
663 MODULE_DESCRIPTION("ASoC WM8731 driver"); 690 MODULE_DESCRIPTION("ASoC WM8731 driver");
664 MODULE_AUTHOR("Richard Purdie"); 691 MODULE_AUTHOR("Richard Purdie");
665 MODULE_LICENSE("GPL"); 692 MODULE_LICENSE("GPL");
666 693
sound/soc/codecs/wm8731.h
1 /* 1 /*
2 * wm8731.h -- WM8731 Soc Audio driver 2 * wm8731.h -- WM8731 Soc Audio driver
3 * 3 *
4 * Copyright 2005 Openedhand Ltd. 4 * Copyright 2005 Openedhand Ltd.
5 * 5 *
6 * Author: Richard Purdie <richard@openedhand.com> 6 * Author: Richard Purdie <richard@openedhand.com>
7 * 7 *
8 * Based on wm8753.h 8 * Based on wm8753.h
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 */ 13 */
14 14
15 #ifndef _WM8731_H 15 #ifndef _WM8731_H
16 #define _WM8731_H 16 #define _WM8731_H
17 17
18 /* WM8731 register space */ 18 /* WM8731 register space */
19 19
20 #define WM8731_LINVOL 0x00 20 #define WM8731_LINVOL 0x00
21 #define WM8731_RINVOL 0x01 21 #define WM8731_RINVOL 0x01
22 #define WM8731_LOUT1V 0x02 22 #define WM8731_LOUT1V 0x02
23 #define WM8731_ROUT1V 0x03 23 #define WM8731_ROUT1V 0x03
24 #define WM8731_APANA 0x04 24 #define WM8731_APANA 0x04
25 #define WM8731_APDIGI 0x05 25 #define WM8731_APDIGI 0x05
26 #define WM8731_PWR 0x06 26 #define WM8731_PWR 0x06
27 #define WM8731_IFACE 0x07 27 #define WM8731_IFACE 0x07
28 #define WM8731_SRATE 0x08 28 #define WM8731_SRATE 0x08
29 #define WM8731_ACTIVE 0x09 29 #define WM8731_ACTIVE 0x09
30 #define WM8731_RESET 0x0f 30 #define WM8731_RESET 0x0f
31 31
32 #define WM8731_CACHEREGNUM 10 32 #define WM8731_CACHEREGNUM 10
33 33
34 #define WM8731_SYSCLK 0 34 #define WM8731_SYSCLK_XTAL 1
35 #define WM8731_SYSCLK_MCLK 2
36
35 #define WM8731_DAI 0 37 #define WM8731_DAI 0
36 38
37 #endif 39 #endif
38 40
sound/soc/pxa/corgi.c
1 /* 1 /*
2 * corgi.c -- SoC audio for Corgi 2 * corgi.c -- SoC audio for Corgi
3 * 3 *
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the 11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your 12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version. 13 * option) any later version.
14 */ 14 */
15 15
16 #include <linux/module.h> 16 #include <linux/module.h>
17 #include <linux/moduleparam.h> 17 #include <linux/moduleparam.h>
18 #include <linux/timer.h> 18 #include <linux/timer.h>
19 #include <linux/i2c.h> 19 #include <linux/i2c.h>
20 #include <linux/interrupt.h> 20 #include <linux/interrupt.h>
21 #include <linux/platform_device.h> 21 #include <linux/platform_device.h>
22 #include <linux/gpio.h> 22 #include <linux/gpio.h>
23 #include <sound/core.h> 23 #include <sound/core.h>
24 #include <sound/pcm.h> 24 #include <sound/pcm.h>
25 #include <sound/soc.h> 25 #include <sound/soc.h>
26 #include <sound/soc-dapm.h> 26 #include <sound/soc-dapm.h>
27 27
28 #include <asm/mach-types.h> 28 #include <asm/mach-types.h>
29 #include <mach/corgi.h> 29 #include <mach/corgi.h>
30 #include <mach/audio.h> 30 #include <mach/audio.h>
31 31
32 #include "../codecs/wm8731.h" 32 #include "../codecs/wm8731.h"
33 #include "pxa2xx-i2s.h" 33 #include "pxa2xx-i2s.h"
34 34
35 #define CORGI_HP 0 35 #define CORGI_HP 0
36 #define CORGI_MIC 1 36 #define CORGI_MIC 1
37 #define CORGI_LINE 2 37 #define CORGI_LINE 2
38 #define CORGI_HEADSET 3 38 #define CORGI_HEADSET 3
39 #define CORGI_HP_OFF 4 39 #define CORGI_HP_OFF 4
40 #define CORGI_SPK_ON 0 40 #define CORGI_SPK_ON 0
41 #define CORGI_SPK_OFF 1 41 #define CORGI_SPK_OFF 1
42 42
43 /* audio clock in Hz - rounded from 12.235MHz */ 43 /* audio clock in Hz - rounded from 12.235MHz */
44 #define CORGI_AUDIO_CLOCK 12288000 44 #define CORGI_AUDIO_CLOCK 12288000
45 45
46 static int corgi_jack_func; 46 static int corgi_jack_func;
47 static int corgi_spk_func; 47 static int corgi_spk_func;
48 48
49 static void corgi_ext_control(struct snd_soc_codec *codec) 49 static void corgi_ext_control(struct snd_soc_codec *codec)
50 { 50 {
51 /* set up jack connection */ 51 /* set up jack connection */
52 switch (corgi_jack_func) { 52 switch (corgi_jack_func) {
53 case CORGI_HP: 53 case CORGI_HP:
54 /* set = unmute headphone */ 54 /* set = unmute headphone */
55 gpio_set_value(CORGI_GPIO_MUTE_L, 1); 55 gpio_set_value(CORGI_GPIO_MUTE_L, 1);
56 gpio_set_value(CORGI_GPIO_MUTE_R, 1); 56 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
57 snd_soc_dapm_disable_pin(codec, "Mic Jack"); 57 snd_soc_dapm_disable_pin(codec, "Mic Jack");
58 snd_soc_dapm_disable_pin(codec, "Line Jack"); 58 snd_soc_dapm_disable_pin(codec, "Line Jack");
59 snd_soc_dapm_enable_pin(codec, "Headphone Jack"); 59 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
60 snd_soc_dapm_disable_pin(codec, "Headset Jack"); 60 snd_soc_dapm_disable_pin(codec, "Headset Jack");
61 break; 61 break;
62 case CORGI_MIC: 62 case CORGI_MIC:
63 /* reset = mute headphone */ 63 /* reset = mute headphone */
64 gpio_set_value(CORGI_GPIO_MUTE_L, 0); 64 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
65 gpio_set_value(CORGI_GPIO_MUTE_R, 0); 65 gpio_set_value(CORGI_GPIO_MUTE_R, 0);
66 snd_soc_dapm_enable_pin(codec, "Mic Jack"); 66 snd_soc_dapm_enable_pin(codec, "Mic Jack");
67 snd_soc_dapm_disable_pin(codec, "Line Jack"); 67 snd_soc_dapm_disable_pin(codec, "Line Jack");
68 snd_soc_dapm_disable_pin(codec, "Headphone Jack"); 68 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
69 snd_soc_dapm_disable_pin(codec, "Headset Jack"); 69 snd_soc_dapm_disable_pin(codec, "Headset Jack");
70 break; 70 break;
71 case CORGI_LINE: 71 case CORGI_LINE:
72 gpio_set_value(CORGI_GPIO_MUTE_L, 0); 72 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
73 gpio_set_value(CORGI_GPIO_MUTE_R, 0); 73 gpio_set_value(CORGI_GPIO_MUTE_R, 0);
74 snd_soc_dapm_disable_pin(codec, "Mic Jack"); 74 snd_soc_dapm_disable_pin(codec, "Mic Jack");
75 snd_soc_dapm_enable_pin(codec, "Line Jack"); 75 snd_soc_dapm_enable_pin(codec, "Line Jack");
76 snd_soc_dapm_disable_pin(codec, "Headphone Jack"); 76 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
77 snd_soc_dapm_disable_pin(codec, "Headset Jack"); 77 snd_soc_dapm_disable_pin(codec, "Headset Jack");
78 break; 78 break;
79 case CORGI_HEADSET: 79 case CORGI_HEADSET:
80 gpio_set_value(CORGI_GPIO_MUTE_L, 0); 80 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
81 gpio_set_value(CORGI_GPIO_MUTE_R, 1); 81 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
82 snd_soc_dapm_enable_pin(codec, "Mic Jack"); 82 snd_soc_dapm_enable_pin(codec, "Mic Jack");
83 snd_soc_dapm_disable_pin(codec, "Line Jack"); 83 snd_soc_dapm_disable_pin(codec, "Line Jack");
84 snd_soc_dapm_disable_pin(codec, "Headphone Jack"); 84 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
85 snd_soc_dapm_enable_pin(codec, "Headset Jack"); 85 snd_soc_dapm_enable_pin(codec, "Headset Jack");
86 break; 86 break;
87 } 87 }
88 88
89 if (corgi_spk_func == CORGI_SPK_ON) 89 if (corgi_spk_func == CORGI_SPK_ON)
90 snd_soc_dapm_enable_pin(codec, "Ext Spk"); 90 snd_soc_dapm_enable_pin(codec, "Ext Spk");
91 else 91 else
92 snd_soc_dapm_disable_pin(codec, "Ext Spk"); 92 snd_soc_dapm_disable_pin(codec, "Ext Spk");
93 93
94 /* signal a DAPM event */ 94 /* signal a DAPM event */
95 snd_soc_dapm_sync(codec); 95 snd_soc_dapm_sync(codec);
96 } 96 }
97 97
98 static int corgi_startup(struct snd_pcm_substream *substream) 98 static int corgi_startup(struct snd_pcm_substream *substream)
99 { 99 {
100 struct snd_soc_pcm_runtime *rtd = substream->private_data; 100 struct snd_soc_pcm_runtime *rtd = substream->private_data;
101 struct snd_soc_codec *codec = rtd->codec; 101 struct snd_soc_codec *codec = rtd->codec;
102 102
103 /* check the jack status at stream startup */ 103 /* check the jack status at stream startup */
104 corgi_ext_control(codec); 104 corgi_ext_control(codec);
105 return 0; 105 return 0;
106 } 106 }
107 107
108 /* we need to unmute the HP at shutdown as the mute burns power on corgi */ 108 /* we need to unmute the HP at shutdown as the mute burns power on corgi */
109 static void corgi_shutdown(struct snd_pcm_substream *substream) 109 static void corgi_shutdown(struct snd_pcm_substream *substream)
110 { 110 {
111 /* set = unmute headphone */ 111 /* set = unmute headphone */
112 gpio_set_value(CORGI_GPIO_MUTE_L, 1); 112 gpio_set_value(CORGI_GPIO_MUTE_L, 1);
113 gpio_set_value(CORGI_GPIO_MUTE_R, 1); 113 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
114 } 114 }
115 115
116 static int corgi_hw_params(struct snd_pcm_substream *substream, 116 static int corgi_hw_params(struct snd_pcm_substream *substream,
117 struct snd_pcm_hw_params *params) 117 struct snd_pcm_hw_params *params)
118 { 118 {
119 struct snd_soc_pcm_runtime *rtd = substream->private_data; 119 struct snd_soc_pcm_runtime *rtd = substream->private_data;
120 struct snd_soc_dai *codec_dai = rtd->codec_dai; 120 struct snd_soc_dai *codec_dai = rtd->codec_dai;
121 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 121 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
122 unsigned int clk = 0; 122 unsigned int clk = 0;
123 int ret = 0; 123 int ret = 0;
124 124
125 switch (params_rate(params)) { 125 switch (params_rate(params)) {
126 case 8000: 126 case 8000:
127 case 16000: 127 case 16000:
128 case 48000: 128 case 48000:
129 case 96000: 129 case 96000:
130 clk = 12288000; 130 clk = 12288000;
131 break; 131 break;
132 case 11025: 132 case 11025:
133 case 22050: 133 case 22050:
134 case 44100: 134 case 44100:
135 clk = 11289600; 135 clk = 11289600;
136 break; 136 break;
137 } 137 }
138 138
139 /* set codec DAI configuration */ 139 /* set codec DAI configuration */
140 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 140 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
141 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 141 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
142 if (ret < 0) 142 if (ret < 0)
143 return ret; 143 return ret;
144 144
145 /* set cpu DAI configuration */ 145 /* set cpu DAI configuration */
146 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 146 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
147 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 147 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
148 if (ret < 0) 148 if (ret < 0)
149 return ret; 149 return ret;
150 150
151 /* set the codec system clock for DAC and ADC */ 151 /* set the codec system clock for DAC and ADC */
152 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk, 152 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk,
153 SND_SOC_CLOCK_IN); 153 SND_SOC_CLOCK_IN);
154 if (ret < 0) 154 if (ret < 0)
155 return ret; 155 return ret;
156 156
157 /* set the I2S system clock as input (unused) */ 157 /* set the I2S system clock as input (unused) */
158 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0, 158 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
159 SND_SOC_CLOCK_IN); 159 SND_SOC_CLOCK_IN);
160 if (ret < 0) 160 if (ret < 0)
161 return ret; 161 return ret;
162 162
163 return 0; 163 return 0;
164 } 164 }
165 165
166 static struct snd_soc_ops corgi_ops = { 166 static struct snd_soc_ops corgi_ops = {
167 .startup = corgi_startup, 167 .startup = corgi_startup,
168 .hw_params = corgi_hw_params, 168 .hw_params = corgi_hw_params,
169 .shutdown = corgi_shutdown, 169 .shutdown = corgi_shutdown,
170 }; 170 };
171 171
172 static int corgi_get_jack(struct snd_kcontrol *kcontrol, 172 static int corgi_get_jack(struct snd_kcontrol *kcontrol,
173 struct snd_ctl_elem_value *ucontrol) 173 struct snd_ctl_elem_value *ucontrol)
174 { 174 {
175 ucontrol->value.integer.value[0] = corgi_jack_func; 175 ucontrol->value.integer.value[0] = corgi_jack_func;
176 return 0; 176 return 0;
177 } 177 }
178 178
179 static int corgi_set_jack(struct snd_kcontrol *kcontrol, 179 static int corgi_set_jack(struct snd_kcontrol *kcontrol,
180 struct snd_ctl_elem_value *ucontrol) 180 struct snd_ctl_elem_value *ucontrol)
181 { 181 {
182 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 182 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
183 183
184 if (corgi_jack_func == ucontrol->value.integer.value[0]) 184 if (corgi_jack_func == ucontrol->value.integer.value[0])
185 return 0; 185 return 0;
186 186
187 corgi_jack_func = ucontrol->value.integer.value[0]; 187 corgi_jack_func = ucontrol->value.integer.value[0];
188 corgi_ext_control(codec); 188 corgi_ext_control(codec);
189 return 1; 189 return 1;
190 } 190 }
191 191
192 static int corgi_get_spk(struct snd_kcontrol *kcontrol, 192 static int corgi_get_spk(struct snd_kcontrol *kcontrol,
193 struct snd_ctl_elem_value *ucontrol) 193 struct snd_ctl_elem_value *ucontrol)
194 { 194 {
195 ucontrol->value.integer.value[0] = corgi_spk_func; 195 ucontrol->value.integer.value[0] = corgi_spk_func;
196 return 0; 196 return 0;
197 } 197 }
198 198
199 static int corgi_set_spk(struct snd_kcontrol *kcontrol, 199 static int corgi_set_spk(struct snd_kcontrol *kcontrol,
200 struct snd_ctl_elem_value *ucontrol) 200 struct snd_ctl_elem_value *ucontrol)
201 { 201 {
202 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 202 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
203 203
204 if (corgi_spk_func == ucontrol->value.integer.value[0]) 204 if (corgi_spk_func == ucontrol->value.integer.value[0])
205 return 0; 205 return 0;
206 206
207 corgi_spk_func = ucontrol->value.integer.value[0]; 207 corgi_spk_func = ucontrol->value.integer.value[0];
208 corgi_ext_control(codec); 208 corgi_ext_control(codec);
209 return 1; 209 return 1;
210 } 210 }
211 211
212 static int corgi_amp_event(struct snd_soc_dapm_widget *w, 212 static int corgi_amp_event(struct snd_soc_dapm_widget *w,
213 struct snd_kcontrol *k, int event) 213 struct snd_kcontrol *k, int event)
214 { 214 {
215 gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event)); 215 gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event));
216 return 0; 216 return 0;
217 } 217 }
218 218
219 static int corgi_mic_event(struct snd_soc_dapm_widget *w, 219 static int corgi_mic_event(struct snd_soc_dapm_widget *w,
220 struct snd_kcontrol *k, int event) 220 struct snd_kcontrol *k, int event)
221 { 221 {
222 gpio_set_value(CORGI_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event)); 222 gpio_set_value(CORGI_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event));
223 return 0; 223 return 0;
224 } 224 }
225 225
226 /* corgi machine dapm widgets */ 226 /* corgi machine dapm widgets */
227 static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { 227 static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
228 SND_SOC_DAPM_HP("Headphone Jack", NULL), 228 SND_SOC_DAPM_HP("Headphone Jack", NULL),
229 SND_SOC_DAPM_MIC("Mic Jack", corgi_mic_event), 229 SND_SOC_DAPM_MIC("Mic Jack", corgi_mic_event),
230 SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event), 230 SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event),
231 SND_SOC_DAPM_LINE("Line Jack", NULL), 231 SND_SOC_DAPM_LINE("Line Jack", NULL),
232 SND_SOC_DAPM_HP("Headset Jack", NULL), 232 SND_SOC_DAPM_HP("Headset Jack", NULL),
233 }; 233 };
234 234
235 /* Corgi machine audio map (connections to the codec pins) */ 235 /* Corgi machine audio map (connections to the codec pins) */
236 static const struct snd_soc_dapm_route audio_map[] = { 236 static const struct snd_soc_dapm_route audio_map[] = {
237 237
238 /* headset Jack - in = micin, out = LHPOUT*/ 238 /* headset Jack - in = micin, out = LHPOUT*/
239 {"Headset Jack", NULL, "LHPOUT"}, 239 {"Headset Jack", NULL, "LHPOUT"},
240 240
241 /* headphone connected to LHPOUT1, RHPOUT1 */ 241 /* headphone connected to LHPOUT1, RHPOUT1 */
242 {"Headphone Jack", NULL, "LHPOUT"}, 242 {"Headphone Jack", NULL, "LHPOUT"},
243 {"Headphone Jack", NULL, "RHPOUT"}, 243 {"Headphone Jack", NULL, "RHPOUT"},
244 244
245 /* speaker connected to LOUT, ROUT */ 245 /* speaker connected to LOUT, ROUT */
246 {"Ext Spk", NULL, "ROUT"}, 246 {"Ext Spk", NULL, "ROUT"},
247 {"Ext Spk", NULL, "LOUT"}, 247 {"Ext Spk", NULL, "LOUT"},
248 248
249 /* mic is connected to MICIN (via right channel of headphone jack) */ 249 /* mic is connected to MICIN (via right channel of headphone jack) */
250 {"MICIN", NULL, "Mic Jack"}, 250 {"MICIN", NULL, "Mic Jack"},
251 251
252 /* Same as the above but no mic bias for line signals */ 252 /* Same as the above but no mic bias for line signals */
253 {"MICIN", NULL, "Line Jack"}, 253 {"MICIN", NULL, "Line Jack"},
254 }; 254 };
255 255
256 static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", 256 static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
257 "Off"}; 257 "Off"};
258 static const char *spk_function[] = {"On", "Off"}; 258 static const char *spk_function[] = {"On", "Off"};
259 static const struct soc_enum corgi_enum[] = { 259 static const struct soc_enum corgi_enum[] = {
260 SOC_ENUM_SINGLE_EXT(5, jack_function), 260 SOC_ENUM_SINGLE_EXT(5, jack_function),
261 SOC_ENUM_SINGLE_EXT(2, spk_function), 261 SOC_ENUM_SINGLE_EXT(2, spk_function),
262 }; 262 };
263 263
264 static const struct snd_kcontrol_new wm8731_corgi_controls[] = { 264 static const struct snd_kcontrol_new wm8731_corgi_controls[] = {
265 SOC_ENUM_EXT("Jack Function", corgi_enum[0], corgi_get_jack, 265 SOC_ENUM_EXT("Jack Function", corgi_enum[0], corgi_get_jack,
266 corgi_set_jack), 266 corgi_set_jack),
267 SOC_ENUM_EXT("Speaker Function", corgi_enum[1], corgi_get_spk, 267 SOC_ENUM_EXT("Speaker Function", corgi_enum[1], corgi_get_spk,
268 corgi_set_spk), 268 corgi_set_spk),
269 }; 269 };
270 270
271 /* 271 /*
272 * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device 272 * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
273 */ 273 */
274 static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd) 274 static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd)
275 { 275 {
276 struct snd_soc_codec *codec = rtd->codec; 276 struct snd_soc_codec *codec = rtd->codec;
277 int err; 277 int err;
278 278
279 snd_soc_dapm_nc_pin(codec, "LLINEIN"); 279 snd_soc_dapm_nc_pin(codec, "LLINEIN");
280 snd_soc_dapm_nc_pin(codec, "RLINEIN"); 280 snd_soc_dapm_nc_pin(codec, "RLINEIN");
281 281
282 /* Add corgi specific controls */ 282 /* Add corgi specific controls */
283 err = snd_soc_add_controls(codec, wm8731_corgi_controls, 283 err = snd_soc_add_controls(codec, wm8731_corgi_controls,
284 ARRAY_SIZE(wm8731_corgi_controls)); 284 ARRAY_SIZE(wm8731_corgi_controls));
285 if (err < 0) 285 if (err < 0)
286 return err; 286 return err;
287 287
288 /* Add corgi specific widgets */ 288 /* Add corgi specific widgets */
289 snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets, 289 snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
290 ARRAY_SIZE(wm8731_dapm_widgets)); 290 ARRAY_SIZE(wm8731_dapm_widgets));
291 291
292 /* Set up corgi specific audio path audio_map */ 292 /* Set up corgi specific audio path audio_map */
293 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 293 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
294 294
295 snd_soc_dapm_sync(codec); 295 snd_soc_dapm_sync(codec);
296 return 0; 296 return 0;
297 } 297 }
298 298
299 /* corgi digital audio interface glue - connects codec <--> CPU */ 299 /* corgi digital audio interface glue - connects codec <--> CPU */
300 static struct snd_soc_dai_link corgi_dai = { 300 static struct snd_soc_dai_link corgi_dai = {
301 .name = "WM8731", 301 .name = "WM8731",
302 .stream_name = "WM8731", 302 .stream_name = "WM8731",
303 .cpu_dai_name = "pxa-is2-dai", 303 .cpu_dai_name = "pxa-is2-dai",
304 .codec_dai_name = "wm8731-hifi", 304 .codec_dai_name = "wm8731-hifi",
305 .platform_name = "pxa-pcm-audio", 305 .platform_name = "pxa-pcm-audio",
306 .codec_name = "wm8731-codec-0.001a", 306 .codec_name = "wm8731-codec-0.001a",
307 .init = corgi_wm8731_init, 307 .init = corgi_wm8731_init,
308 .ops = &corgi_ops, 308 .ops = &corgi_ops,
309 }; 309 };
310 310
311 /* corgi audio machine driver */ 311 /* corgi audio machine driver */
312 static struct snd_soc_card snd_soc_corgi = { 312 static struct snd_soc_card snd_soc_corgi = {
313 .name = "Corgi", 313 .name = "Corgi",
314 .dai_link = &corgi_dai, 314 .dai_link = &corgi_dai,
315 .num_links = 1, 315 .num_links = 1,
316 }; 316 };
317 317
318 static struct platform_device *corgi_snd_device; 318 static struct platform_device *corgi_snd_device;
319 319
320 static int __init corgi_init(void) 320 static int __init corgi_init(void)
321 { 321 {
322 int ret; 322 int ret;
323 323
324 if (!(machine_is_corgi() || machine_is_shepherd() || 324 if (!(machine_is_corgi() || machine_is_shepherd() ||
325 machine_is_husky())) 325 machine_is_husky()))
326 return -ENODEV; 326 return -ENODEV;
327 327
328 corgi_snd_device = platform_device_alloc("soc-audio", -1); 328 corgi_snd_device = platform_device_alloc("soc-audio", -1);
329 if (!corgi_snd_device) 329 if (!corgi_snd_device)
330 return -ENOMEM; 330 return -ENOMEM;
331 331
332 platform_set_drvdata(corgi_snd_device, &snd_soc_corgi); 332 platform_set_drvdata(corgi_snd_device, &snd_soc_corgi);
333 ret = platform_device_add(corgi_snd_device); 333 ret = platform_device_add(corgi_snd_device);
334 334
335 if (ret) 335 if (ret)
336 platform_device_put(corgi_snd_device); 336 platform_device_put(corgi_snd_device);
337 337
338 return ret; 338 return ret;
339 } 339 }
340 340
341 static void __exit corgi_exit(void) 341 static void __exit corgi_exit(void)
342 { 342 {
343 platform_device_unregister(corgi_snd_device); 343 platform_device_unregister(corgi_snd_device);
344 } 344 }
345 345
346 module_init(corgi_init); 346 module_init(corgi_init);
347 module_exit(corgi_exit); 347 module_exit(corgi_exit);
348 348
349 /* Module information */ 349 /* Module information */
350 MODULE_AUTHOR("Richard Purdie"); 350 MODULE_AUTHOR("Richard Purdie");
351 MODULE_DESCRIPTION("ALSA SoC Corgi"); 351 MODULE_DESCRIPTION("ALSA SoC Corgi");
352 MODULE_LICENSE("GPL"); 352 MODULE_LICENSE("GPL");
353 353
sound/soc/pxa/poodle.c
1 /* 1 /*
2 * poodle.c -- SoC audio for Poodle 2 * poodle.c -- SoC audio for Poodle
3 * 3 *
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the 11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your 12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version. 13 * option) any later version.
14 * 14 *
15 */ 15 */
16 16
17 #include <linux/module.h> 17 #include <linux/module.h>
18 #include <linux/moduleparam.h> 18 #include <linux/moduleparam.h>
19 #include <linux/timer.h> 19 #include <linux/timer.h>
20 #include <linux/i2c.h> 20 #include <linux/i2c.h>
21 #include <linux/interrupt.h> 21 #include <linux/interrupt.h>
22 #include <linux/platform_device.h> 22 #include <linux/platform_device.h>
23 #include <sound/core.h> 23 #include <sound/core.h>
24 #include <sound/pcm.h> 24 #include <sound/pcm.h>
25 #include <sound/soc.h> 25 #include <sound/soc.h>
26 #include <sound/soc-dapm.h> 26 #include <sound/soc-dapm.h>
27 27
28 #include <asm/mach-types.h> 28 #include <asm/mach-types.h>
29 #include <asm/hardware/locomo.h> 29 #include <asm/hardware/locomo.h>
30 #include <mach/poodle.h> 30 #include <mach/poodle.h>
31 #include <mach/audio.h> 31 #include <mach/audio.h>
32 32
33 #include "../codecs/wm8731.h" 33 #include "../codecs/wm8731.h"
34 #include "pxa2xx-i2s.h" 34 #include "pxa2xx-i2s.h"
35 35
36 #define POODLE_HP 1 36 #define POODLE_HP 1
37 #define POODLE_HP_OFF 0 37 #define POODLE_HP_OFF 0
38 #define POODLE_SPK_ON 1 38 #define POODLE_SPK_ON 1
39 #define POODLE_SPK_OFF 0 39 #define POODLE_SPK_OFF 0
40 40
41 /* audio clock in Hz - rounded from 12.235MHz */ 41 /* audio clock in Hz - rounded from 12.235MHz */
42 #define POODLE_AUDIO_CLOCK 12288000 42 #define POODLE_AUDIO_CLOCK 12288000
43 43
44 static int poodle_jack_func; 44 static int poodle_jack_func;
45 static int poodle_spk_func; 45 static int poodle_spk_func;
46 46
47 static void poodle_ext_control(struct snd_soc_codec *codec) 47 static void poodle_ext_control(struct snd_soc_codec *codec)
48 { 48 {
49 /* set up jack connection */ 49 /* set up jack connection */
50 if (poodle_jack_func == POODLE_HP) { 50 if (poodle_jack_func == POODLE_HP) {
51 /* set = unmute headphone */ 51 /* set = unmute headphone */
52 locomo_gpio_write(&poodle_locomo_device.dev, 52 locomo_gpio_write(&poodle_locomo_device.dev,
53 POODLE_LOCOMO_GPIO_MUTE_L, 1); 53 POODLE_LOCOMO_GPIO_MUTE_L, 1);
54 locomo_gpio_write(&poodle_locomo_device.dev, 54 locomo_gpio_write(&poodle_locomo_device.dev,
55 POODLE_LOCOMO_GPIO_MUTE_R, 1); 55 POODLE_LOCOMO_GPIO_MUTE_R, 1);
56 snd_soc_dapm_enable_pin(codec, "Headphone Jack"); 56 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
57 } else { 57 } else {
58 locomo_gpio_write(&poodle_locomo_device.dev, 58 locomo_gpio_write(&poodle_locomo_device.dev,
59 POODLE_LOCOMO_GPIO_MUTE_L, 0); 59 POODLE_LOCOMO_GPIO_MUTE_L, 0);
60 locomo_gpio_write(&poodle_locomo_device.dev, 60 locomo_gpio_write(&poodle_locomo_device.dev,
61 POODLE_LOCOMO_GPIO_MUTE_R, 0); 61 POODLE_LOCOMO_GPIO_MUTE_R, 0);
62 snd_soc_dapm_disable_pin(codec, "Headphone Jack"); 62 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
63 } 63 }
64 64
65 /* set the enpoints to their new connetion states */ 65 /* set the enpoints to their new connetion states */
66 if (poodle_spk_func == POODLE_SPK_ON) 66 if (poodle_spk_func == POODLE_SPK_ON)
67 snd_soc_dapm_enable_pin(codec, "Ext Spk"); 67 snd_soc_dapm_enable_pin(codec, "Ext Spk");
68 else 68 else
69 snd_soc_dapm_disable_pin(codec, "Ext Spk"); 69 snd_soc_dapm_disable_pin(codec, "Ext Spk");
70 70
71 /* signal a DAPM event */ 71 /* signal a DAPM event */
72 snd_soc_dapm_sync(codec); 72 snd_soc_dapm_sync(codec);
73 } 73 }
74 74
75 static int poodle_startup(struct snd_pcm_substream *substream) 75 static int poodle_startup(struct snd_pcm_substream *substream)
76 { 76 {
77 struct snd_soc_pcm_runtime *rtd = substream->private_data; 77 struct snd_soc_pcm_runtime *rtd = substream->private_data;
78 struct snd_soc_codec *codec = rtd->codec; 78 struct snd_soc_codec *codec = rtd->codec;
79 79
80 /* check the jack status at stream startup */ 80 /* check the jack status at stream startup */
81 poodle_ext_control(codec); 81 poodle_ext_control(codec);
82 return 0; 82 return 0;
83 } 83 }
84 84
85 /* we need to unmute the HP at shutdown as the mute burns power on poodle */ 85 /* we need to unmute the HP at shutdown as the mute burns power on poodle */
86 static void poodle_shutdown(struct snd_pcm_substream *substream) 86 static void poodle_shutdown(struct snd_pcm_substream *substream)
87 { 87 {
88 /* set = unmute headphone */ 88 /* set = unmute headphone */
89 locomo_gpio_write(&poodle_locomo_device.dev, 89 locomo_gpio_write(&poodle_locomo_device.dev,
90 POODLE_LOCOMO_GPIO_MUTE_L, 1); 90 POODLE_LOCOMO_GPIO_MUTE_L, 1);
91 locomo_gpio_write(&poodle_locomo_device.dev, 91 locomo_gpio_write(&poodle_locomo_device.dev,
92 POODLE_LOCOMO_GPIO_MUTE_R, 1); 92 POODLE_LOCOMO_GPIO_MUTE_R, 1);
93 } 93 }
94 94
95 static int poodle_hw_params(struct snd_pcm_substream *substream, 95 static int poodle_hw_params(struct snd_pcm_substream *substream,
96 struct snd_pcm_hw_params *params) 96 struct snd_pcm_hw_params *params)
97 { 97 {
98 struct snd_soc_pcm_runtime *rtd = substream->private_data; 98 struct snd_soc_pcm_runtime *rtd = substream->private_data;
99 struct snd_soc_dai *codec_dai = rtd->codec_dai; 99 struct snd_soc_dai *codec_dai = rtd->codec_dai;
100 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 100 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
101 unsigned int clk = 0; 101 unsigned int clk = 0;
102 int ret = 0; 102 int ret = 0;
103 103
104 switch (params_rate(params)) { 104 switch (params_rate(params)) {
105 case 8000: 105 case 8000:
106 case 16000: 106 case 16000:
107 case 48000: 107 case 48000:
108 case 96000: 108 case 96000:
109 clk = 12288000; 109 clk = 12288000;
110 break; 110 break;
111 case 11025: 111 case 11025:
112 case 22050: 112 case 22050:
113 case 44100: 113 case 44100:
114 clk = 11289600; 114 clk = 11289600;
115 break; 115 break;
116 } 116 }
117 117
118 /* set codec DAI configuration */ 118 /* set codec DAI configuration */
119 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 119 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
120 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 120 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
121 if (ret < 0) 121 if (ret < 0)
122 return ret; 122 return ret;
123 123
124 /* set cpu DAI configuration */ 124 /* set cpu DAI configuration */
125 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 125 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
126 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 126 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
127 if (ret < 0) 127 if (ret < 0)
128 return ret; 128 return ret;
129 129
130 /* set the codec system clock for DAC and ADC */ 130 /* set the codec system clock for DAC and ADC */
131 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk, 131 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk,
132 SND_SOC_CLOCK_IN); 132 SND_SOC_CLOCK_IN);
133 if (ret < 0) 133 if (ret < 0)
134 return ret; 134 return ret;
135 135
136 /* set the I2S system clock as input (unused) */ 136 /* set the I2S system clock as input (unused) */
137 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0, 137 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
138 SND_SOC_CLOCK_IN); 138 SND_SOC_CLOCK_IN);
139 if (ret < 0) 139 if (ret < 0)
140 return ret; 140 return ret;
141 141
142 return 0; 142 return 0;
143 } 143 }
144 144
145 static struct snd_soc_ops poodle_ops = { 145 static struct snd_soc_ops poodle_ops = {
146 .startup = poodle_startup, 146 .startup = poodle_startup,
147 .hw_params = poodle_hw_params, 147 .hw_params = poodle_hw_params,
148 .shutdown = poodle_shutdown, 148 .shutdown = poodle_shutdown,
149 }; 149 };
150 150
151 static int poodle_get_jack(struct snd_kcontrol *kcontrol, 151 static int poodle_get_jack(struct snd_kcontrol *kcontrol,
152 struct snd_ctl_elem_value *ucontrol) 152 struct snd_ctl_elem_value *ucontrol)
153 { 153 {
154 ucontrol->value.integer.value[0] = poodle_jack_func; 154 ucontrol->value.integer.value[0] = poodle_jack_func;
155 return 0; 155 return 0;
156 } 156 }
157 157
158 static int poodle_set_jack(struct snd_kcontrol *kcontrol, 158 static int poodle_set_jack(struct snd_kcontrol *kcontrol,
159 struct snd_ctl_elem_value *ucontrol) 159 struct snd_ctl_elem_value *ucontrol)
160 { 160 {
161 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 161 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
162 162
163 if (poodle_jack_func == ucontrol->value.integer.value[0]) 163 if (poodle_jack_func == ucontrol->value.integer.value[0])
164 return 0; 164 return 0;
165 165
166 poodle_jack_func = ucontrol->value.integer.value[0]; 166 poodle_jack_func = ucontrol->value.integer.value[0];
167 poodle_ext_control(codec); 167 poodle_ext_control(codec);
168 return 1; 168 return 1;
169 } 169 }
170 170
171 static int poodle_get_spk(struct snd_kcontrol *kcontrol, 171 static int poodle_get_spk(struct snd_kcontrol *kcontrol,
172 struct snd_ctl_elem_value *ucontrol) 172 struct snd_ctl_elem_value *ucontrol)
173 { 173 {
174 ucontrol->value.integer.value[0] = poodle_spk_func; 174 ucontrol->value.integer.value[0] = poodle_spk_func;
175 return 0; 175 return 0;
176 } 176 }
177 177
178 static int poodle_set_spk(struct snd_kcontrol *kcontrol, 178 static int poodle_set_spk(struct snd_kcontrol *kcontrol,
179 struct snd_ctl_elem_value *ucontrol) 179 struct snd_ctl_elem_value *ucontrol)
180 { 180 {
181 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 181 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
182 182
183 if (poodle_spk_func == ucontrol->value.integer.value[0]) 183 if (poodle_spk_func == ucontrol->value.integer.value[0])
184 return 0; 184 return 0;
185 185
186 poodle_spk_func = ucontrol->value.integer.value[0]; 186 poodle_spk_func = ucontrol->value.integer.value[0];
187 poodle_ext_control(codec); 187 poodle_ext_control(codec);
188 return 1; 188 return 1;
189 } 189 }
190 190
191 static int poodle_amp_event(struct snd_soc_dapm_widget *w, 191 static int poodle_amp_event(struct snd_soc_dapm_widget *w,
192 struct snd_kcontrol *k, int event) 192 struct snd_kcontrol *k, int event)
193 { 193 {
194 if (SND_SOC_DAPM_EVENT_ON(event)) 194 if (SND_SOC_DAPM_EVENT_ON(event))
195 locomo_gpio_write(&poodle_locomo_device.dev, 195 locomo_gpio_write(&poodle_locomo_device.dev,
196 POODLE_LOCOMO_GPIO_AMP_ON, 0); 196 POODLE_LOCOMO_GPIO_AMP_ON, 0);
197 else 197 else
198 locomo_gpio_write(&poodle_locomo_device.dev, 198 locomo_gpio_write(&poodle_locomo_device.dev,
199 POODLE_LOCOMO_GPIO_AMP_ON, 1); 199 POODLE_LOCOMO_GPIO_AMP_ON, 1);
200 200
201 return 0; 201 return 0;
202 } 202 }
203 203
204 /* poodle machine dapm widgets */ 204 /* poodle machine dapm widgets */
205 static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { 205 static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
206 SND_SOC_DAPM_HP("Headphone Jack", NULL), 206 SND_SOC_DAPM_HP("Headphone Jack", NULL),
207 SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event), 207 SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event),
208 }; 208 };
209 209
210 /* Corgi machine connections to the codec pins */ 210 /* Corgi machine connections to the codec pins */
211 static const struct snd_soc_dapm_route audio_map[] = { 211 static const struct snd_soc_dapm_route audio_map[] = {
212 212
213 /* headphone connected to LHPOUT1, RHPOUT1 */ 213 /* headphone connected to LHPOUT1, RHPOUT1 */
214 {"Headphone Jack", NULL, "LHPOUT"}, 214 {"Headphone Jack", NULL, "LHPOUT"},
215 {"Headphone Jack", NULL, "RHPOUT"}, 215 {"Headphone Jack", NULL, "RHPOUT"},
216 216
217 /* speaker connected to LOUT, ROUT */ 217 /* speaker connected to LOUT, ROUT */
218 {"Ext Spk", NULL, "ROUT"}, 218 {"Ext Spk", NULL, "ROUT"},
219 {"Ext Spk", NULL, "LOUT"}, 219 {"Ext Spk", NULL, "LOUT"},
220 }; 220 };
221 221
222 static const char *jack_function[] = {"Off", "Headphone"}; 222 static const char *jack_function[] = {"Off", "Headphone"};
223 static const char *spk_function[] = {"Off", "On"}; 223 static const char *spk_function[] = {"Off", "On"};
224 static const struct soc_enum poodle_enum[] = { 224 static const struct soc_enum poodle_enum[] = {
225 SOC_ENUM_SINGLE_EXT(2, jack_function), 225 SOC_ENUM_SINGLE_EXT(2, jack_function),
226 SOC_ENUM_SINGLE_EXT(2, spk_function), 226 SOC_ENUM_SINGLE_EXT(2, spk_function),
227 }; 227 };
228 228
229 static const struct snd_kcontrol_new wm8731_poodle_controls[] = { 229 static const struct snd_kcontrol_new wm8731_poodle_controls[] = {
230 SOC_ENUM_EXT("Jack Function", poodle_enum[0], poodle_get_jack, 230 SOC_ENUM_EXT("Jack Function", poodle_enum[0], poodle_get_jack,
231 poodle_set_jack), 231 poodle_set_jack),
232 SOC_ENUM_EXT("Speaker Function", poodle_enum[1], poodle_get_spk, 232 SOC_ENUM_EXT("Speaker Function", poodle_enum[1], poodle_get_spk,
233 poodle_set_spk), 233 poodle_set_spk),
234 }; 234 };
235 235
236 /* 236 /*
237 * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device 237 * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
238 */ 238 */
239 static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd) 239 static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd)
240 { 240 {
241 struct snd_soc_codec *codec = rtd->codec; 241 struct snd_soc_codec *codec = rtd->codec;
242 int err; 242 int err;
243 243
244 snd_soc_dapm_nc_pin(codec, "LLINEIN"); 244 snd_soc_dapm_nc_pin(codec, "LLINEIN");
245 snd_soc_dapm_nc_pin(codec, "RLINEIN"); 245 snd_soc_dapm_nc_pin(codec, "RLINEIN");
246 snd_soc_dapm_enable_pin(codec, "MICIN"); 246 snd_soc_dapm_enable_pin(codec, "MICIN");
247 247
248 /* Add poodle specific controls */ 248 /* Add poodle specific controls */
249 err = snd_soc_add_controls(codec, wm8731_poodle_controls, 249 err = snd_soc_add_controls(codec, wm8731_poodle_controls,
250 ARRAY_SIZE(wm8731_poodle_controls)); 250 ARRAY_SIZE(wm8731_poodle_controls));
251 if (err < 0) 251 if (err < 0)
252 return err; 252 return err;
253 253
254 /* Add poodle specific widgets */ 254 /* Add poodle specific widgets */
255 snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets, 255 snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
256 ARRAY_SIZE(wm8731_dapm_widgets)); 256 ARRAY_SIZE(wm8731_dapm_widgets));
257 257
258 /* Set up poodle specific audio path audio_map */ 258 /* Set up poodle specific audio path audio_map */
259 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 259 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
260 260
261 snd_soc_dapm_sync(codec); 261 snd_soc_dapm_sync(codec);
262 return 0; 262 return 0;
263 } 263 }
264 264
265 /* poodle digital audio interface glue - connects codec <--> CPU */ 265 /* poodle digital audio interface glue - connects codec <--> CPU */
266 static struct snd_soc_dai_link poodle_dai = { 266 static struct snd_soc_dai_link poodle_dai = {
267 .name = "WM8731", 267 .name = "WM8731",
268 .stream_name = "WM8731", 268 .stream_name = "WM8731",
269 .cpu_dai_name = "pxa-i2s", 269 .cpu_dai_name = "pxa-i2s",
270 .codec_dai_name = "wm8731-hifi", 270 .codec_dai_name = "wm8731-hifi",
271 .platform_name = "pxa-pcm-audio", 271 .platform_name = "pxa-pcm-audio",
272 .codec_name = "wm8731-codec.0-001a", 272 .codec_name = "wm8731-codec.0-001a",
273 .init = poodle_wm8731_init, 273 .init = poodle_wm8731_init,
274 .ops = &poodle_ops, 274 .ops = &poodle_ops,
275 }; 275 };
276 276
277 /* poodle audio machine driver */ 277 /* poodle audio machine driver */
278 static struct snd_soc_card snd_soc_poodle = { 278 static struct snd_soc_card snd_soc_poodle = {
279 .name = "Poodle", 279 .name = "Poodle",
280 .dai_link = &poodle_dai, 280 .dai_link = &poodle_dai,
281 .num_links = 1, 281 .num_links = 1,
282 .owner = THIS_MODULE, 282 .owner = THIS_MODULE,
283 }; 283 };
284 284
285 static struct platform_device *poodle_snd_device; 285 static struct platform_device *poodle_snd_device;
286 286
287 static int __init poodle_init(void) 287 static int __init poodle_init(void)
288 { 288 {
289 int ret; 289 int ret;
290 290
291 if (!machine_is_poodle()) 291 if (!machine_is_poodle())
292 return -ENODEV; 292 return -ENODEV;
293 293
294 locomo_gpio_set_dir(&poodle_locomo_device.dev, 294 locomo_gpio_set_dir(&poodle_locomo_device.dev,
295 POODLE_LOCOMO_GPIO_AMP_ON, 0); 295 POODLE_LOCOMO_GPIO_AMP_ON, 0);
296 /* should we mute HP at startup - burning power ?*/ 296 /* should we mute HP at startup - burning power ?*/
297 locomo_gpio_set_dir(&poodle_locomo_device.dev, 297 locomo_gpio_set_dir(&poodle_locomo_device.dev,
298 POODLE_LOCOMO_GPIO_MUTE_L, 0); 298 POODLE_LOCOMO_GPIO_MUTE_L, 0);
299 locomo_gpio_set_dir(&poodle_locomo_device.dev, 299 locomo_gpio_set_dir(&poodle_locomo_device.dev,
300 POODLE_LOCOMO_GPIO_MUTE_R, 0); 300 POODLE_LOCOMO_GPIO_MUTE_R, 0);
301 301
302 poodle_snd_device = platform_device_alloc("soc-audio", -1); 302 poodle_snd_device = platform_device_alloc("soc-audio", -1);
303 if (!poodle_snd_device) 303 if (!poodle_snd_device)
304 return -ENOMEM; 304 return -ENOMEM;
305 305
306 platform_set_drvdata(poodle_snd_device, &snd_soc_poodle); 306 platform_set_drvdata(poodle_snd_device, &snd_soc_poodle);
307 ret = platform_device_add(poodle_snd_device); 307 ret = platform_device_add(poodle_snd_device);
308 308
309 if (ret) 309 if (ret)
310 platform_device_put(poodle_snd_device); 310 platform_device_put(poodle_snd_device);
311 311
312 return ret; 312 return ret;
313 } 313 }
314 314
315 static void __exit poodle_exit(void) 315 static void __exit poodle_exit(void)
316 { 316 {
317 platform_device_unregister(poodle_snd_device); 317 platform_device_unregister(poodle_snd_device);
318 } 318 }
319 319
320 module_init(poodle_init); 320 module_init(poodle_init);
321 module_exit(poodle_exit); 321 module_exit(poodle_exit);
322 322
323 /* Module information */ 323 /* Module information */
324 MODULE_AUTHOR("Richard Purdie"); 324 MODULE_AUTHOR("Richard Purdie");
325 MODULE_DESCRIPTION("ALSA SoC Poodle"); 325 MODULE_DESCRIPTION("ALSA SoC Poodle");
326 MODULE_LICENSE("GPL"); 326 MODULE_LICENSE("GPL");
327 327