Commit 87bea31c7b59a07fe5a1c827eb01db3b7c3ae672

Authored by Mark Brown
1 parent 4f4c007222

ASoC: Remove redundant snd_soc_dapm_sync() calls from machine drivers

The core will sync DAPM as part of the card initialization, there is no
need for machine drivers to do so during their setup.

OMAP drivers are omitted as I know Peter already has patches for them.

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

Showing 31 changed files with 0 additions and 73 deletions Inline Diff

sound/soc/atmel/playpaq_wm8510.c
1 /* sound/soc/at32/playpaq_wm8510.c 1 /* sound/soc/at32/playpaq_wm8510.c
2 * ASoC machine driver for PlayPaq using WM8510 codec 2 * ASoC machine driver for PlayPaq using WM8510 codec
3 * 3 *
4 * Copyright (C) 2008 Long Range Systems 4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org> 5 * Geoffrey Wossum <gwossum@acm.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 * 10 *
11 * This code is largely inspired by sound/soc/at91/eti_b1_wm8731.c 11 * This code is largely inspired by sound/soc/at91/eti_b1_wm8731.c
12 * 12 *
13 * NOTE: If you don't have the AT32 enhanced portmux configured (which 13 * NOTE: If you don't have the AT32 enhanced portmux configured (which
14 * isn't currently in the mainline or Atmel patched kernel), you will 14 * isn't currently in the mainline or Atmel patched kernel), you will
15 * need to set the MCLK pin (PA30) to peripheral A in your board initialization 15 * need to set the MCLK pin (PA30) to peripheral A in your board initialization
16 * code. Something like: 16 * code. Something like:
17 * at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); 17 * at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0);
18 * 18 *
19 */ 19 */
20 20
21 /* #define DEBUG */ 21 /* #define DEBUG */
22 22
23 #include <linux/module.h> 23 #include <linux/module.h>
24 #include <linux/moduleparam.h> 24 #include <linux/moduleparam.h>
25 #include <linux/kernel.h> 25 #include <linux/kernel.h>
26 #include <linux/errno.h> 26 #include <linux/errno.h>
27 #include <linux/clk.h> 27 #include <linux/clk.h>
28 #include <linux/timer.h> 28 #include <linux/timer.h>
29 #include <linux/interrupt.h> 29 #include <linux/interrupt.h>
30 #include <linux/platform_device.h> 30 #include <linux/platform_device.h>
31 31
32 #include <sound/core.h> 32 #include <sound/core.h>
33 #include <sound/pcm.h> 33 #include <sound/pcm.h>
34 #include <sound/pcm_params.h> 34 #include <sound/pcm_params.h>
35 #include <sound/soc.h> 35 #include <sound/soc.h>
36 36
37 #include <mach/at32ap700x.h> 37 #include <mach/at32ap700x.h>
38 #include <mach/portmux.h> 38 #include <mach/portmux.h>
39 39
40 #include "../codecs/wm8510.h" 40 #include "../codecs/wm8510.h"
41 #include "atmel-pcm.h" 41 #include "atmel-pcm.h"
42 #include "atmel_ssc_dai.h" 42 #include "atmel_ssc_dai.h"
43 43
44 44
45 /*-------------------------------------------------------------------------*\ 45 /*-------------------------------------------------------------------------*\
46 * constants 46 * constants
47 \*-------------------------------------------------------------------------*/ 47 \*-------------------------------------------------------------------------*/
48 #define MCLK_PIN GPIO_PIN_PA(30) 48 #define MCLK_PIN GPIO_PIN_PA(30)
49 #define MCLK_PERIPH GPIO_PERIPH_A 49 #define MCLK_PERIPH GPIO_PERIPH_A
50 50
51 51
52 /*-------------------------------------------------------------------------*\ 52 /*-------------------------------------------------------------------------*\
53 * data types 53 * data types
54 \*-------------------------------------------------------------------------*/ 54 \*-------------------------------------------------------------------------*/
55 /* SSC clocking data */ 55 /* SSC clocking data */
56 struct ssc_clock_data { 56 struct ssc_clock_data {
57 /* CMR div */ 57 /* CMR div */
58 unsigned int cmr_div; 58 unsigned int cmr_div;
59 59
60 /* Frame period (as needed by xCMR.PERIOD) */ 60 /* Frame period (as needed by xCMR.PERIOD) */
61 unsigned int period; 61 unsigned int period;
62 62
63 /* The SSC clock rate these settings where calculated for */ 63 /* The SSC clock rate these settings where calculated for */
64 unsigned long ssc_rate; 64 unsigned long ssc_rate;
65 }; 65 };
66 66
67 67
68 /*-------------------------------------------------------------------------*\ 68 /*-------------------------------------------------------------------------*\
69 * module data 69 * module data
70 \*-------------------------------------------------------------------------*/ 70 \*-------------------------------------------------------------------------*/
71 static struct clk *_gclk0; 71 static struct clk *_gclk0;
72 static struct clk *_pll0; 72 static struct clk *_pll0;
73 73
74 #define CODEC_CLK (_gclk0) 74 #define CODEC_CLK (_gclk0)
75 75
76 76
77 /*-------------------------------------------------------------------------*\ 77 /*-------------------------------------------------------------------------*\
78 * Sound SOC operations 78 * Sound SOC operations
79 \*-------------------------------------------------------------------------*/ 79 \*-------------------------------------------------------------------------*/
80 #if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE 80 #if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
81 static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock( 81 static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock(
82 struct snd_pcm_hw_params *params, 82 struct snd_pcm_hw_params *params,
83 struct snd_soc_dai *cpu_dai) 83 struct snd_soc_dai *cpu_dai)
84 { 84 {
85 struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); 85 struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);
86 struct ssc_device *ssc = ssc_p->ssc; 86 struct ssc_device *ssc = ssc_p->ssc;
87 struct ssc_clock_data cd; 87 struct ssc_clock_data cd;
88 unsigned int rate, width_bits, channels; 88 unsigned int rate, width_bits, channels;
89 unsigned int bitrate, ssc_div; 89 unsigned int bitrate, ssc_div;
90 unsigned actual_rate; 90 unsigned actual_rate;
91 91
92 92
93 /* 93 /*
94 * Figure out required bitrate 94 * Figure out required bitrate
95 */ 95 */
96 rate = params_rate(params); 96 rate = params_rate(params);
97 channels = params_channels(params); 97 channels = params_channels(params);
98 width_bits = snd_pcm_format_physical_width(params_format(params)); 98 width_bits = snd_pcm_format_physical_width(params_format(params));
99 bitrate = rate * width_bits * channels; 99 bitrate = rate * width_bits * channels;
100 100
101 101
102 /* 102 /*
103 * Figure out required SSC divider and period for required bitrate 103 * Figure out required SSC divider and period for required bitrate
104 */ 104 */
105 cd.ssc_rate = clk_get_rate(ssc->clk); 105 cd.ssc_rate = clk_get_rate(ssc->clk);
106 ssc_div = cd.ssc_rate / bitrate; 106 ssc_div = cd.ssc_rate / bitrate;
107 cd.cmr_div = ssc_div / 2; 107 cd.cmr_div = ssc_div / 2;
108 if (ssc_div & 1) { 108 if (ssc_div & 1) {
109 /* round cmr_div up */ 109 /* round cmr_div up */
110 cd.cmr_div++; 110 cd.cmr_div++;
111 } 111 }
112 cd.period = width_bits - 1; 112 cd.period = width_bits - 1;
113 113
114 114
115 /* 115 /*
116 * Find actual rate, compare to requested rate 116 * Find actual rate, compare to requested rate
117 */ 117 */
118 actual_rate = (cd.ssc_rate / (cd.cmr_div * 2)) / (2 * (cd.period + 1)); 118 actual_rate = (cd.ssc_rate / (cd.cmr_div * 2)) / (2 * (cd.period + 1));
119 pr_debug("playpaq_wm8510: Request rate = %u, actual rate = %u\n", 119 pr_debug("playpaq_wm8510: Request rate = %u, actual rate = %u\n",
120 rate, actual_rate); 120 rate, actual_rate);
121 121
122 122
123 return cd; 123 return cd;
124 } 124 }
125 #endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ 125 #endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
126 126
127 127
128 128
129 static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream, 129 static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream,
130 struct snd_pcm_hw_params *params) 130 struct snd_pcm_hw_params *params)
131 { 131 {
132 struct snd_soc_pcm_runtime *rtd = substream->private_data; 132 struct snd_soc_pcm_runtime *rtd = substream->private_data;
133 struct snd_soc_dai *codec_dai = rtd->codec_dai; 133 struct snd_soc_dai *codec_dai = rtd->codec_dai;
134 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 134 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
135 struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); 135 struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);
136 struct ssc_device *ssc = ssc_p->ssc; 136 struct ssc_device *ssc = ssc_p->ssc;
137 unsigned int pll_out = 0, bclk = 0, mclk_div = 0; 137 unsigned int pll_out = 0, bclk = 0, mclk_div = 0;
138 int ret; 138 int ret;
139 139
140 140
141 /* Due to difficulties with getting the correct clocks from the AT32's 141 /* Due to difficulties with getting the correct clocks from the AT32's
142 * PLL0, we're going to let the CODEC be in charge of all the clocks 142 * PLL0, we're going to let the CODEC be in charge of all the clocks
143 */ 143 */
144 #if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE 144 #if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
145 const unsigned int fmt = (SND_SOC_DAIFMT_I2S | 145 const unsigned int fmt = (SND_SOC_DAIFMT_I2S |
146 SND_SOC_DAIFMT_NB_NF | 146 SND_SOC_DAIFMT_NB_NF |
147 SND_SOC_DAIFMT_CBM_CFM); 147 SND_SOC_DAIFMT_CBM_CFM);
148 #else 148 #else
149 struct ssc_clock_data cd; 149 struct ssc_clock_data cd;
150 const unsigned int fmt = (SND_SOC_DAIFMT_I2S | 150 const unsigned int fmt = (SND_SOC_DAIFMT_I2S |
151 SND_SOC_DAIFMT_NB_NF | 151 SND_SOC_DAIFMT_NB_NF |
152 SND_SOC_DAIFMT_CBS_CFS); 152 SND_SOC_DAIFMT_CBS_CFS);
153 #endif 153 #endif
154 154
155 if (ssc == NULL) { 155 if (ssc == NULL) {
156 pr_warning("playpaq_wm8510_hw_params: ssc is NULL!\n"); 156 pr_warning("playpaq_wm8510_hw_params: ssc is NULL!\n");
157 return -EINVAL; 157 return -EINVAL;
158 } 158 }
159 159
160 160
161 /* 161 /*
162 * Figure out PLL and BCLK dividers for WM8510 162 * Figure out PLL and BCLK dividers for WM8510
163 */ 163 */
164 switch (params_rate(params)) { 164 switch (params_rate(params)) {
165 case 48000: 165 case 48000:
166 pll_out = 24576000; 166 pll_out = 24576000;
167 mclk_div = WM8510_MCLKDIV_2; 167 mclk_div = WM8510_MCLKDIV_2;
168 bclk = WM8510_BCLKDIV_8; 168 bclk = WM8510_BCLKDIV_8;
169 break; 169 break;
170 170
171 case 44100: 171 case 44100:
172 pll_out = 22579200; 172 pll_out = 22579200;
173 mclk_div = WM8510_MCLKDIV_2; 173 mclk_div = WM8510_MCLKDIV_2;
174 bclk = WM8510_BCLKDIV_8; 174 bclk = WM8510_BCLKDIV_8;
175 break; 175 break;
176 176
177 case 22050: 177 case 22050:
178 pll_out = 22579200; 178 pll_out = 22579200;
179 mclk_div = WM8510_MCLKDIV_4; 179 mclk_div = WM8510_MCLKDIV_4;
180 bclk = WM8510_BCLKDIV_8; 180 bclk = WM8510_BCLKDIV_8;
181 break; 181 break;
182 182
183 case 16000: 183 case 16000:
184 pll_out = 24576000; 184 pll_out = 24576000;
185 mclk_div = WM8510_MCLKDIV_6; 185 mclk_div = WM8510_MCLKDIV_6;
186 bclk = WM8510_BCLKDIV_8; 186 bclk = WM8510_BCLKDIV_8;
187 break; 187 break;
188 188
189 case 11025: 189 case 11025:
190 pll_out = 22579200; 190 pll_out = 22579200;
191 mclk_div = WM8510_MCLKDIV_8; 191 mclk_div = WM8510_MCLKDIV_8;
192 bclk = WM8510_BCLKDIV_8; 192 bclk = WM8510_BCLKDIV_8;
193 break; 193 break;
194 194
195 case 8000: 195 case 8000:
196 pll_out = 24576000; 196 pll_out = 24576000;
197 mclk_div = WM8510_MCLKDIV_12; 197 mclk_div = WM8510_MCLKDIV_12;
198 bclk = WM8510_BCLKDIV_8; 198 bclk = WM8510_BCLKDIV_8;
199 break; 199 break;
200 200
201 default: 201 default:
202 pr_warning("playpaq_wm8510: Unsupported sample rate %d\n", 202 pr_warning("playpaq_wm8510: Unsupported sample rate %d\n",
203 params_rate(params)); 203 params_rate(params));
204 return -EINVAL; 204 return -EINVAL;
205 } 205 }
206 206
207 207
208 /* 208 /*
209 * set CPU and CODEC DAI configuration 209 * set CPU and CODEC DAI configuration
210 */ 210 */
211 ret = snd_soc_dai_set_fmt(codec_dai, fmt); 211 ret = snd_soc_dai_set_fmt(codec_dai, fmt);
212 if (ret < 0) { 212 if (ret < 0) {
213 pr_warning("playpaq_wm8510: " 213 pr_warning("playpaq_wm8510: "
214 "Failed to set CODEC DAI format (%d)\n", 214 "Failed to set CODEC DAI format (%d)\n",
215 ret); 215 ret);
216 return ret; 216 return ret;
217 } 217 }
218 ret = snd_soc_dai_set_fmt(cpu_dai, fmt); 218 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
219 if (ret < 0) { 219 if (ret < 0) {
220 pr_warning("playpaq_wm8510: " 220 pr_warning("playpaq_wm8510: "
221 "Failed to set CPU DAI format (%d)\n", 221 "Failed to set CPU DAI format (%d)\n",
222 ret); 222 ret);
223 return ret; 223 return ret;
224 } 224 }
225 225
226 226
227 /* 227 /*
228 * Set CPU clock configuration 228 * Set CPU clock configuration
229 */ 229 */
230 #if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE 230 #if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
231 cd = playpaq_wm8510_calc_ssc_clock(params, cpu_dai); 231 cd = playpaq_wm8510_calc_ssc_clock(params, cpu_dai);
232 pr_debug("playpaq_wm8510: cmr_div = %d, period = %d\n", 232 pr_debug("playpaq_wm8510: cmr_div = %d, period = %d\n",
233 cd.cmr_div, cd.period); 233 cd.cmr_div, cd.period);
234 ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_CMR_DIV, cd.cmr_div); 234 ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_CMR_DIV, cd.cmr_div);
235 if (ret < 0) { 235 if (ret < 0) {
236 pr_warning("playpaq_wm8510: Failed to set CPU CMR_DIV (%d)\n", 236 pr_warning("playpaq_wm8510: Failed to set CPU CMR_DIV (%d)\n",
237 ret); 237 ret);
238 return ret; 238 return ret;
239 } 239 }
240 ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_TCMR_PERIOD, 240 ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_TCMR_PERIOD,
241 cd.period); 241 cd.period);
242 if (ret < 0) { 242 if (ret < 0) {
243 pr_warning("playpaq_wm8510: " 243 pr_warning("playpaq_wm8510: "
244 "Failed to set CPU transmit period (%d)\n", 244 "Failed to set CPU transmit period (%d)\n",
245 ret); 245 ret);
246 return ret; 246 return ret;
247 } 247 }
248 #endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ 248 #endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
249 249
250 250
251 /* 251 /*
252 * Set CODEC clock configuration 252 * Set CODEC clock configuration
253 */ 253 */
254 pr_debug("playpaq_wm8510: " 254 pr_debug("playpaq_wm8510: "
255 "pll_in = %ld, pll_out = %u, bclk = %x, mclk = %x\n", 255 "pll_in = %ld, pll_out = %u, bclk = %x, mclk = %x\n",
256 clk_get_rate(CODEC_CLK), pll_out, bclk, mclk_div); 256 clk_get_rate(CODEC_CLK), pll_out, bclk, mclk_div);
257 257
258 258
259 #if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE 259 #if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
260 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_BCLKDIV, bclk); 260 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_BCLKDIV, bclk);
261 if (ret < 0) { 261 if (ret < 0) {
262 pr_warning 262 pr_warning
263 ("playpaq_wm8510: Failed to set CODEC DAI BCLKDIV (%d)\n", 263 ("playpaq_wm8510: Failed to set CODEC DAI BCLKDIV (%d)\n",
264 ret); 264 ret);
265 return ret; 265 return ret;
266 } 266 }
267 #endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ 267 #endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
268 268
269 269
270 ret = snd_soc_dai_set_pll(codec_dai, 0, 0, 270 ret = snd_soc_dai_set_pll(codec_dai, 0, 0,
271 clk_get_rate(CODEC_CLK), pll_out); 271 clk_get_rate(CODEC_CLK), pll_out);
272 if (ret < 0) { 272 if (ret < 0) {
273 pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n", 273 pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n",
274 ret); 274 ret);
275 return ret; 275 return ret;
276 } 276 }
277 277
278 278
279 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_MCLKDIV, mclk_div); 279 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_MCLKDIV, mclk_div);
280 if (ret < 0) { 280 if (ret < 0) {
281 pr_warning("playpaq_wm8510: Failed to set CODEC MCLKDIV (%d)\n", 281 pr_warning("playpaq_wm8510: Failed to set CODEC MCLKDIV (%d)\n",
282 ret); 282 ret);
283 return ret; 283 return ret;
284 } 284 }
285 285
286 286
287 return 0; 287 return 0;
288 } 288 }
289 289
290 290
291 291
292 static struct snd_soc_ops playpaq_wm8510_ops = { 292 static struct snd_soc_ops playpaq_wm8510_ops = {
293 .hw_params = playpaq_wm8510_hw_params, 293 .hw_params = playpaq_wm8510_hw_params,
294 }; 294 };
295 295
296 296
297 297
298 static const struct snd_soc_dapm_widget playpaq_dapm_widgets[] = { 298 static const struct snd_soc_dapm_widget playpaq_dapm_widgets[] = {
299 SND_SOC_DAPM_MIC("Int Mic", NULL), 299 SND_SOC_DAPM_MIC("Int Mic", NULL),
300 SND_SOC_DAPM_SPK("Ext Spk", NULL), 300 SND_SOC_DAPM_SPK("Ext Spk", NULL),
301 }; 301 };
302 302
303 303
304 304
305 static const struct snd_soc_dapm_route intercon[] = { 305 static const struct snd_soc_dapm_route intercon[] = {
306 /* speaker connected to SPKOUT */ 306 /* speaker connected to SPKOUT */
307 {"Ext Spk", NULL, "SPKOUTP"}, 307 {"Ext Spk", NULL, "SPKOUTP"},
308 {"Ext Spk", NULL, "SPKOUTN"}, 308 {"Ext Spk", NULL, "SPKOUTN"},
309 309
310 {"Mic Bias", NULL, "Int Mic"}, 310 {"Mic Bias", NULL, "Int Mic"},
311 {"MICN", NULL, "Mic Bias"}, 311 {"MICN", NULL, "Mic Bias"},
312 {"MICP", NULL, "Mic Bias"}, 312 {"MICP", NULL, "Mic Bias"},
313 }; 313 };
314 314
315 315
316 316
317 static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd) 317 static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd)
318 { 318 {
319 struct snd_soc_codec *codec = rtd->codec; 319 struct snd_soc_codec *codec = rtd->codec;
320 struct snd_soc_dapm_context *dapm = &codec->dapm; 320 struct snd_soc_dapm_context *dapm = &codec->dapm;
321 int i; 321 int i;
322 322
323 /* 323 /*
324 * Add DAPM widgets 324 * Add DAPM widgets
325 */ 325 */
326 for (i = 0; i < ARRAY_SIZE(playpaq_dapm_widgets); i++) 326 for (i = 0; i < ARRAY_SIZE(playpaq_dapm_widgets); i++)
327 snd_soc_dapm_new_control(dapm, &playpaq_dapm_widgets[i]); 327 snd_soc_dapm_new_control(dapm, &playpaq_dapm_widgets[i]);
328 328
329 329
330 330
331 /* 331 /*
332 * Setup audio path interconnects 332 * Setup audio path interconnects
333 */ 333 */
334 snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); 334 snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
335 335
336 336
337 337
338 /* always connected pins */ 338 /* always connected pins */
339 snd_soc_dapm_enable_pin(dapm, "Int Mic"); 339 snd_soc_dapm_enable_pin(dapm, "Int Mic");
340 snd_soc_dapm_enable_pin(dapm, "Ext Spk"); 340 snd_soc_dapm_enable_pin(dapm, "Ext Spk");
341 snd_soc_dapm_sync(dapm);
342 341
343 342
344 343
345 /* Make CSB show PLL rate */ 344 /* Make CSB show PLL rate */
346 snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV, 345 snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV,
347 WM8510_OPCLKDIV_1 | 4); 346 WM8510_OPCLKDIV_1 | 4);
348 347
349 return 0; 348 return 0;
350 } 349 }
351 350
352 351
353 352
354 static struct snd_soc_dai_link playpaq_wm8510_dai = { 353 static struct snd_soc_dai_link playpaq_wm8510_dai = {
355 .name = "WM8510", 354 .name = "WM8510",
356 .stream_name = "WM8510 PCM", 355 .stream_name = "WM8510 PCM",
357 .cpu_dai_name= "atmel-ssc-dai.0", 356 .cpu_dai_name= "atmel-ssc-dai.0",
358 .platform_name = "atmel-pcm-audio", 357 .platform_name = "atmel-pcm-audio",
359 .codec_name = "wm8510-codec.0-0x1a", 358 .codec_name = "wm8510-codec.0-0x1a",
360 .codec_dai_name = "wm8510-hifi", 359 .codec_dai_name = "wm8510-hifi",
361 .init = playpaq_wm8510_init, 360 .init = playpaq_wm8510_init,
362 .ops = &playpaq_wm8510_ops, 361 .ops = &playpaq_wm8510_ops,
363 }; 362 };
364 363
365 364
366 365
367 static struct snd_soc_card snd_soc_playpaq = { 366 static struct snd_soc_card snd_soc_playpaq = {
368 .name = "LRS_PlayPaq_WM8510", 367 .name = "LRS_PlayPaq_WM8510",
369 .dai_link = &playpaq_wm8510_dai, 368 .dai_link = &playpaq_wm8510_dai,
370 .num_links = 1, 369 .num_links = 1,
371 }; 370 };
372 371
373 static struct platform_device *playpaq_snd_device; 372 static struct platform_device *playpaq_snd_device;
374 373
375 374
376 static int __init playpaq_asoc_init(void) 375 static int __init playpaq_asoc_init(void)
377 { 376 {
378 int ret = 0; 377 int ret = 0;
379 378
380 /* 379 /*
381 * Configure MCLK for WM8510 380 * Configure MCLK for WM8510
382 */ 381 */
383 _gclk0 = clk_get(NULL, "gclk0"); 382 _gclk0 = clk_get(NULL, "gclk0");
384 if (IS_ERR(_gclk0)) { 383 if (IS_ERR(_gclk0)) {
385 _gclk0 = NULL; 384 _gclk0 = NULL;
386 ret = PTR_ERR(_gclk0); 385 ret = PTR_ERR(_gclk0);
387 goto err_gclk0; 386 goto err_gclk0;
388 } 387 }
389 _pll0 = clk_get(NULL, "pll0"); 388 _pll0 = clk_get(NULL, "pll0");
390 if (IS_ERR(_pll0)) { 389 if (IS_ERR(_pll0)) {
391 _pll0 = NULL; 390 _pll0 = NULL;
392 ret = PTR_ERR(_pll0); 391 ret = PTR_ERR(_pll0);
393 goto err_pll0; 392 goto err_pll0;
394 } 393 }
395 ret = clk_set_parent(_gclk0, _pll0); 394 ret = clk_set_parent(_gclk0, _pll0);
396 if (ret) { 395 if (ret) {
397 pr_warning("snd-soc-playpaq: " 396 pr_warning("snd-soc-playpaq: "
398 "Failed to set PLL0 as parent for DAC clock\n"); 397 "Failed to set PLL0 as parent for DAC clock\n");
399 goto err_set_clk; 398 goto err_set_clk;
400 } 399 }
401 clk_set_rate(CODEC_CLK, 12000000); 400 clk_set_rate(CODEC_CLK, 12000000);
402 clk_enable(CODEC_CLK); 401 clk_enable(CODEC_CLK);
403 402
404 #if defined CONFIG_AT32_ENHANCED_PORTMUX 403 #if defined CONFIG_AT32_ENHANCED_PORTMUX
405 at32_select_periph(MCLK_PIN, MCLK_PERIPH, 0); 404 at32_select_periph(MCLK_PIN, MCLK_PERIPH, 0);
406 #endif 405 #endif
407 406
408 407
409 /* 408 /*
410 * Create and register platform device 409 * Create and register platform device
411 */ 410 */
412 playpaq_snd_device = platform_device_alloc("soc-audio", 0); 411 playpaq_snd_device = platform_device_alloc("soc-audio", 0);
413 if (playpaq_snd_device == NULL) { 412 if (playpaq_snd_device == NULL) {
414 ret = -ENOMEM; 413 ret = -ENOMEM;
415 goto err_device_alloc; 414 goto err_device_alloc;
416 } 415 }
417 416
418 platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq); 417 platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq);
419 418
420 ret = platform_device_add(playpaq_snd_device); 419 ret = platform_device_add(playpaq_snd_device);
421 if (ret) { 420 if (ret) {
422 pr_warning("playpaq_wm8510: platform_device_add failed (%d)\n", 421 pr_warning("playpaq_wm8510: platform_device_add failed (%d)\n",
423 ret); 422 ret);
424 goto err_device_add; 423 goto err_device_add;
425 } 424 }
426 425
427 return 0; 426 return 0;
428 427
429 428
430 err_device_add: 429 err_device_add:
431 if (playpaq_snd_device != NULL) { 430 if (playpaq_snd_device != NULL) {
432 platform_device_put(playpaq_snd_device); 431 platform_device_put(playpaq_snd_device);
433 playpaq_snd_device = NULL; 432 playpaq_snd_device = NULL;
434 } 433 }
435 err_device_alloc: 434 err_device_alloc:
436 err_set_clk: 435 err_set_clk:
437 if (_pll0 != NULL) { 436 if (_pll0 != NULL) {
438 clk_put(_pll0); 437 clk_put(_pll0);
439 _pll0 = NULL; 438 _pll0 = NULL;
440 } 439 }
441 err_pll0: 440 err_pll0:
442 if (_gclk0 != NULL) { 441 if (_gclk0 != NULL) {
443 clk_put(_gclk0); 442 clk_put(_gclk0);
444 _gclk0 = NULL; 443 _gclk0 = NULL;
445 } 444 }
446 return ret; 445 return ret;
447 } 446 }
448 447
449 448
450 static void __exit playpaq_asoc_exit(void) 449 static void __exit playpaq_asoc_exit(void)
451 { 450 {
452 if (_gclk0 != NULL) { 451 if (_gclk0 != NULL) {
453 clk_put(_gclk0); 452 clk_put(_gclk0);
454 _gclk0 = NULL; 453 _gclk0 = NULL;
455 } 454 }
456 if (_pll0 != NULL) { 455 if (_pll0 != NULL) {
457 clk_put(_pll0); 456 clk_put(_pll0);
458 _pll0 = NULL; 457 _pll0 = NULL;
459 } 458 }
460 459
461 #if defined CONFIG_AT32_ENHANCED_PORTMUX 460 #if defined CONFIG_AT32_ENHANCED_PORTMUX
462 at32_free_pin(MCLK_PIN); 461 at32_free_pin(MCLK_PIN);
463 #endif 462 #endif
464 463
465 platform_device_unregister(playpaq_snd_device); 464 platform_device_unregister(playpaq_snd_device);
466 playpaq_snd_device = NULL; 465 playpaq_snd_device = NULL;
467 } 466 }
468 467
469 module_init(playpaq_asoc_init); 468 module_init(playpaq_asoc_init);
470 module_exit(playpaq_asoc_exit); 469 module_exit(playpaq_asoc_exit);
471 470
472 MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>"); 471 MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
473 MODULE_DESCRIPTION("ASoC machine driver for LRS PlayPaq"); 472 MODULE_DESCRIPTION("ASoC machine driver for LRS PlayPaq");
474 MODULE_LICENSE("GPL"); 473 MODULE_LICENSE("GPL");
475 474
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 47
48 #include <asm/mach-types.h> 48 #include <asm/mach-types.h>
49 #include <mach/hardware.h> 49 #include <mach/hardware.h>
50 #include <mach/gpio.h> 50 #include <mach/gpio.h>
51 51
52 #include "../codecs/wm8731.h" 52 #include "../codecs/wm8731.h"
53 #include "atmel-pcm.h" 53 #include "atmel-pcm.h"
54 #include "atmel_ssc_dai.h" 54 #include "atmel_ssc_dai.h"
55 55
56 #define MCLK_RATE 12000000 56 #define MCLK_RATE 12000000
57 57
58 /* 58 /*
59 * As shipped the board does not have inputs. However, it is relatively 59 * As shipped the board does not have inputs. However, it is relatively
60 * straightforward to modify the board to hook them up so support is left 60 * straightforward to modify the board to hook them up so support is left
61 * in the driver. 61 * in the driver.
62 */ 62 */
63 #undef ENABLE_MIC_INPUT 63 #undef ENABLE_MIC_INPUT
64 64
65 static struct clk *mclk; 65 static struct clk *mclk;
66 66
67 static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream, 67 static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
68 struct snd_pcm_hw_params *params) 68 struct snd_pcm_hw_params *params)
69 { 69 {
70 struct snd_soc_pcm_runtime *rtd = substream->private_data; 70 struct snd_soc_pcm_runtime *rtd = substream->private_data;
71 struct snd_soc_dai *codec_dai = rtd->codec_dai; 71 struct snd_soc_dai *codec_dai = rtd->codec_dai;
72 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 72 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
73 int ret; 73 int ret;
74 74
75 /* set codec DAI configuration */ 75 /* set codec DAI configuration */
76 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 76 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
77 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 77 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
78 if (ret < 0) 78 if (ret < 0)
79 return ret; 79 return ret;
80 80
81 /* set cpu DAI configuration */ 81 /* set cpu DAI configuration */
82 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 82 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
83 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 83 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
84 if (ret < 0) 84 if (ret < 0)
85 return ret; 85 return ret;
86 86
87 return 0; 87 return 0;
88 } 88 }
89 89
90 static struct snd_soc_ops at91sam9g20ek_ops = { 90 static struct snd_soc_ops at91sam9g20ek_ops = {
91 .hw_params = at91sam9g20ek_hw_params, 91 .hw_params = at91sam9g20ek_hw_params,
92 }; 92 };
93 93
94 static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card, 94 static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card,
95 struct snd_soc_dapm_context *dapm, 95 struct snd_soc_dapm_context *dapm,
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 struct snd_soc_dapm_context *dapm = &codec->dapm; 143 struct snd_soc_dapm_context *dapm = &codec->dapm;
144 int ret; 144 int ret;
145 145
146 printk(KERN_DEBUG 146 printk(KERN_DEBUG
147 "at91sam9g20ek_wm8731 " 147 "at91sam9g20ek_wm8731 "
148 ": at91sam9g20ek_wm8731_init() called\n"); 148 ": at91sam9g20ek_wm8731_init() called\n");
149 149
150 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_MCLK, 150 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_MCLK,
151 MCLK_RATE, SND_SOC_CLOCK_IN); 151 MCLK_RATE, SND_SOC_CLOCK_IN);
152 if (ret < 0) { 152 if (ret < 0) {
153 printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret); 153 printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret);
154 return ret; 154 return ret;
155 } 155 }
156 156
157 /* Add specific widgets */ 157 /* Add specific widgets */
158 snd_soc_dapm_new_controls(dapm, at91sam9g20ek_dapm_widgets, 158 snd_soc_dapm_new_controls(dapm, at91sam9g20ek_dapm_widgets,
159 ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); 159 ARRAY_SIZE(at91sam9g20ek_dapm_widgets));
160 /* Set up specific audio path interconnects */ 160 /* Set up specific audio path interconnects */
161 snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); 161 snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
162 162
163 /* not connected */ 163 /* not connected */
164 snd_soc_dapm_nc_pin(dapm, "RLINEIN"); 164 snd_soc_dapm_nc_pin(dapm, "RLINEIN");
165 snd_soc_dapm_nc_pin(dapm, "LLINEIN"); 165 snd_soc_dapm_nc_pin(dapm, "LLINEIN");
166 166
167 #ifdef ENABLE_MIC_INPUT 167 #ifdef ENABLE_MIC_INPUT
168 snd_soc_dapm_enable_pin(dapm, "Int Mic"); 168 snd_soc_dapm_enable_pin(dapm, "Int Mic");
169 #else 169 #else
170 snd_soc_dapm_nc_pin(dapm, "Int Mic"); 170 snd_soc_dapm_nc_pin(dapm, "Int Mic");
171 #endif 171 #endif
172 172
173 /* always connected */ 173 /* always connected */
174 snd_soc_dapm_enable_pin(dapm, "Ext Spk"); 174 snd_soc_dapm_enable_pin(dapm, "Ext Spk");
175 175
176 snd_soc_dapm_sync(dapm);
177
178 return 0; 176 return 0;
179 } 177 }
180 178
181 static struct snd_soc_dai_link at91sam9g20ek_dai = { 179 static struct snd_soc_dai_link at91sam9g20ek_dai = {
182 .name = "WM8731", 180 .name = "WM8731",
183 .stream_name = "WM8731 PCM", 181 .stream_name = "WM8731 PCM",
184 .cpu_dai_name = "atmel-ssc-dai.0", 182 .cpu_dai_name = "atmel-ssc-dai.0",
185 .codec_dai_name = "wm8731-hifi", 183 .codec_dai_name = "wm8731-hifi",
186 .init = at91sam9g20ek_wm8731_init, 184 .init = at91sam9g20ek_wm8731_init,
187 .platform_name = "atmel-pcm-audio", 185 .platform_name = "atmel-pcm-audio",
188 .codec_name = "wm8731.0-001b", 186 .codec_name = "wm8731.0-001b",
189 .ops = &at91sam9g20ek_ops, 187 .ops = &at91sam9g20ek_ops,
190 }; 188 };
191 189
192 static struct snd_soc_card snd_soc_at91sam9g20ek = { 190 static struct snd_soc_card snd_soc_at91sam9g20ek = {
193 .name = "AT91SAMG20-EK", 191 .name = "AT91SAMG20-EK",
194 .dai_link = &at91sam9g20ek_dai, 192 .dai_link = &at91sam9g20ek_dai,
195 .num_links = 1, 193 .num_links = 1,
196 .set_bias_level = at91sam9g20ek_set_bias_level, 194 .set_bias_level = at91sam9g20ek_set_bias_level,
197 }; 195 };
198 196
199 static struct platform_device *at91sam9g20ek_snd_device; 197 static struct platform_device *at91sam9g20ek_snd_device;
200 198
201 static int __init at91sam9g20ek_init(void) 199 static int __init at91sam9g20ek_init(void)
202 { 200 {
203 struct clk *pllb; 201 struct clk *pllb;
204 int ret; 202 int ret;
205 203
206 if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc())) 204 if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc()))
207 return -ENODEV; 205 return -ENODEV;
208 206
209 ret = atmel_ssc_set_audio(0); 207 ret = atmel_ssc_set_audio(0);
210 if (ret != 0) { 208 if (ret != 0) {
211 pr_err("Failed to set SSC 0 for audio: %d\n", ret); 209 pr_err("Failed to set SSC 0 for audio: %d\n", ret);
212 return ret; 210 return ret;
213 } 211 }
214 212
215 /* 213 /*
216 * Codec MCLK is supplied by PCK0 - set it up. 214 * Codec MCLK is supplied by PCK0 - set it up.
217 */ 215 */
218 mclk = clk_get(NULL, "pck0"); 216 mclk = clk_get(NULL, "pck0");
219 if (IS_ERR(mclk)) { 217 if (IS_ERR(mclk)) {
220 printk(KERN_ERR "ASoC: Failed to get MCLK\n"); 218 printk(KERN_ERR "ASoC: Failed to get MCLK\n");
221 ret = PTR_ERR(mclk); 219 ret = PTR_ERR(mclk);
222 goto err; 220 goto err;
223 } 221 }
224 222
225 pllb = clk_get(NULL, "pllb"); 223 pllb = clk_get(NULL, "pllb");
226 if (IS_ERR(pllb)) { 224 if (IS_ERR(pllb)) {
227 printk(KERN_ERR "ASoC: Failed to get PLLB\n"); 225 printk(KERN_ERR "ASoC: Failed to get PLLB\n");
228 ret = PTR_ERR(pllb); 226 ret = PTR_ERR(pllb);
229 goto err_mclk; 227 goto err_mclk;
230 } 228 }
231 ret = clk_set_parent(mclk, pllb); 229 ret = clk_set_parent(mclk, pllb);
232 clk_put(pllb); 230 clk_put(pllb);
233 if (ret != 0) { 231 if (ret != 0) {
234 printk(KERN_ERR "ASoC: Failed to set MCLK parent\n"); 232 printk(KERN_ERR "ASoC: Failed to set MCLK parent\n");
235 goto err_mclk; 233 goto err_mclk;
236 } 234 }
237 235
238 clk_set_rate(mclk, MCLK_RATE); 236 clk_set_rate(mclk, MCLK_RATE);
239 237
240 at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); 238 at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
241 if (!at91sam9g20ek_snd_device) { 239 if (!at91sam9g20ek_snd_device) {
242 printk(KERN_ERR "ASoC: Platform device allocation failed\n"); 240 printk(KERN_ERR "ASoC: Platform device allocation failed\n");
243 ret = -ENOMEM; 241 ret = -ENOMEM;
244 goto err_mclk; 242 goto err_mclk;
245 } 243 }
246 244
247 platform_set_drvdata(at91sam9g20ek_snd_device, 245 platform_set_drvdata(at91sam9g20ek_snd_device,
248 &snd_soc_at91sam9g20ek); 246 &snd_soc_at91sam9g20ek);
249 247
250 ret = platform_device_add(at91sam9g20ek_snd_device); 248 ret = platform_device_add(at91sam9g20ek_snd_device);
251 if (ret) { 249 if (ret) {
252 printk(KERN_ERR "ASoC: Platform device allocation failed\n"); 250 printk(KERN_ERR "ASoC: Platform device allocation failed\n");
253 goto err_device_add; 251 goto err_device_add;
254 } 252 }
255 253
256 return ret; 254 return ret;
257 255
258 err_device_add: 256 err_device_add:
259 platform_device_put(at91sam9g20ek_snd_device); 257 platform_device_put(at91sam9g20ek_snd_device);
260 err_mclk: 258 err_mclk:
261 clk_put(mclk); 259 clk_put(mclk);
262 mclk = NULL; 260 mclk = NULL;
263 err: 261 err:
264 return ret; 262 return ret;
265 } 263 }
266 264
267 static void __exit at91sam9g20ek_exit(void) 265 static void __exit at91sam9g20ek_exit(void)
268 { 266 {
269 platform_device_unregister(at91sam9g20ek_snd_device); 267 platform_device_unregister(at91sam9g20ek_snd_device);
270 at91sam9g20ek_snd_device = NULL; 268 at91sam9g20ek_snd_device = NULL;
271 clk_put(mclk); 269 clk_put(mclk);
272 mclk = NULL; 270 mclk = NULL;
273 } 271 }
274 272
275 module_init(at91sam9g20ek_init); 273 module_init(at91sam9g20ek_init);
276 module_exit(at91sam9g20ek_exit); 274 module_exit(at91sam9g20ek_exit);
277 275
278 /* Module information */ 276 /* Module information */
279 MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>"); 277 MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
280 MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731"); 278 MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731");
281 MODULE_LICENSE("GPL"); 279 MODULE_LICENSE("GPL");
282 280
sound/soc/atmel/snd-soc-afeb9260.c
1 /* 1 /*
2 * afeb9260.c -- SoC audio for AFEB9260 2 * afeb9260.c -- SoC audio for AFEB9260
3 * 3 *
4 * Copyright (C) 2009 Sergey Lapin <slapin@ossfans.org> 4 * Copyright (C) 2009 Sergey Lapin <slapin@ossfans.org>
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License 7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation. 8 * version 2 as published by the Free Software Foundation.
9 * 9 *
10 * This program is distributed in the hope that it will be useful, but 10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details. 13 * General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU General Public License 15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software 16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA 18 * 02110-1301 USA
19 * 19 *
20 */ 20 */
21 21
22 #include <linux/module.h> 22 #include <linux/module.h>
23 #include <linux/moduleparam.h> 23 #include <linux/moduleparam.h>
24 #include <linux/kernel.h> 24 #include <linux/kernel.h>
25 #include <linux/clk.h> 25 #include <linux/clk.h>
26 #include <linux/platform_device.h> 26 #include <linux/platform_device.h>
27 27
28 #include <linux/atmel-ssc.h> 28 #include <linux/atmel-ssc.h>
29 #include <sound/core.h> 29 #include <sound/core.h>
30 #include <sound/pcm.h> 30 #include <sound/pcm.h>
31 #include <sound/pcm_params.h> 31 #include <sound/pcm_params.h>
32 #include <sound/soc.h> 32 #include <sound/soc.h>
33 33
34 #include <asm/mach-types.h> 34 #include <asm/mach-types.h>
35 #include <mach/hardware.h> 35 #include <mach/hardware.h>
36 #include <linux/gpio.h> 36 #include <linux/gpio.h>
37 37
38 #include "../codecs/tlv320aic23.h" 38 #include "../codecs/tlv320aic23.h"
39 #include "atmel-pcm.h" 39 #include "atmel-pcm.h"
40 #include "atmel_ssc_dai.h" 40 #include "atmel_ssc_dai.h"
41 41
42 #define CODEC_CLOCK 12000000 42 #define CODEC_CLOCK 12000000
43 43
44 static int afeb9260_hw_params(struct snd_pcm_substream *substream, 44 static int afeb9260_hw_params(struct snd_pcm_substream *substream,
45 struct snd_pcm_hw_params *params) 45 struct snd_pcm_hw_params *params)
46 { 46 {
47 struct snd_soc_pcm_runtime *rtd = substream->private_data; 47 struct snd_soc_pcm_runtime *rtd = substream->private_data;
48 struct snd_soc_dai *codec_dai = rtd->codec_dai; 48 struct snd_soc_dai *codec_dai = rtd->codec_dai;
49 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 49 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
50 int err; 50 int err;
51 51
52 /* Set codec DAI configuration */ 52 /* Set codec DAI configuration */
53 err = snd_soc_dai_set_fmt(codec_dai, 53 err = snd_soc_dai_set_fmt(codec_dai,
54 SND_SOC_DAIFMT_I2S| 54 SND_SOC_DAIFMT_I2S|
55 SND_SOC_DAIFMT_NB_IF | 55 SND_SOC_DAIFMT_NB_IF |
56 SND_SOC_DAIFMT_CBM_CFM); 56 SND_SOC_DAIFMT_CBM_CFM);
57 if (err < 0) { 57 if (err < 0) {
58 printk(KERN_ERR "can't set codec DAI configuration\n"); 58 printk(KERN_ERR "can't set codec DAI configuration\n");
59 return err; 59 return err;
60 } 60 }
61 61
62 /* Set cpu DAI configuration */ 62 /* Set cpu DAI configuration */
63 err = snd_soc_dai_set_fmt(cpu_dai, 63 err = snd_soc_dai_set_fmt(cpu_dai,
64 SND_SOC_DAIFMT_I2S | 64 SND_SOC_DAIFMT_I2S |
65 SND_SOC_DAIFMT_NB_IF | 65 SND_SOC_DAIFMT_NB_IF |
66 SND_SOC_DAIFMT_CBM_CFM); 66 SND_SOC_DAIFMT_CBM_CFM);
67 if (err < 0) { 67 if (err < 0) {
68 printk(KERN_ERR "can't set cpu DAI configuration\n"); 68 printk(KERN_ERR "can't set cpu DAI configuration\n");
69 return err; 69 return err;
70 } 70 }
71 71
72 /* Set the codec system clock for DAC and ADC */ 72 /* Set the codec system clock for DAC and ADC */
73 err = 73 err =
74 snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN); 74 snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
75 75
76 if (err < 0) { 76 if (err < 0) {
77 printk(KERN_ERR "can't set codec system clock\n"); 77 printk(KERN_ERR "can't set codec system clock\n");
78 return err; 78 return err;
79 } 79 }
80 80
81 return err; 81 return err;
82 } 82 }
83 83
84 static struct snd_soc_ops afeb9260_ops = { 84 static struct snd_soc_ops afeb9260_ops = {
85 .hw_params = afeb9260_hw_params, 85 .hw_params = afeb9260_hw_params,
86 }; 86 };
87 87
88 static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = { 88 static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
89 SND_SOC_DAPM_HP("Headphone Jack", NULL), 89 SND_SOC_DAPM_HP("Headphone Jack", NULL),
90 SND_SOC_DAPM_LINE("Line In", NULL), 90 SND_SOC_DAPM_LINE("Line In", NULL),
91 SND_SOC_DAPM_MIC("Mic Jack", NULL), 91 SND_SOC_DAPM_MIC("Mic Jack", NULL),
92 }; 92 };
93 93
94 static const struct snd_soc_dapm_route audio_map[] = { 94 static const struct snd_soc_dapm_route audio_map[] = {
95 {"Headphone Jack", NULL, "LHPOUT"}, 95 {"Headphone Jack", NULL, "LHPOUT"},
96 {"Headphone Jack", NULL, "RHPOUT"}, 96 {"Headphone Jack", NULL, "RHPOUT"},
97 97
98 {"LLINEIN", NULL, "Line In"}, 98 {"LLINEIN", NULL, "Line In"},
99 {"RLINEIN", NULL, "Line In"}, 99 {"RLINEIN", NULL, "Line In"},
100 100
101 {"MICIN", NULL, "Mic Jack"}, 101 {"MICIN", NULL, "Mic Jack"},
102 }; 102 };
103 103
104 static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) 104 static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
105 { 105 {
106 struct snd_soc_codec *codec = rtd->codec; 106 struct snd_soc_codec *codec = rtd->codec;
107 struct snd_soc_dapm_context *dapm = &codec->dapm; 107 struct snd_soc_dapm_context *dapm = &codec->dapm;
108 108
109 /* Add afeb9260 specific widgets */ 109 /* Add afeb9260 specific widgets */
110 snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets, 110 snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
111 ARRAY_SIZE(tlv320aic23_dapm_widgets)); 111 ARRAY_SIZE(tlv320aic23_dapm_widgets));
112 112
113 /* Set up afeb9260 specific audio path audio_map */ 113 /* Set up afeb9260 specific audio path audio_map */
114 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 114 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
115 115
116 snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); 116 snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
117 snd_soc_dapm_enable_pin(dapm, "Line In"); 117 snd_soc_dapm_enable_pin(dapm, "Line In");
118 snd_soc_dapm_enable_pin(dapm, "Mic Jack"); 118 snd_soc_dapm_enable_pin(dapm, "Mic Jack");
119 119
120 snd_soc_dapm_sync(dapm);
121
122 return 0; 120 return 0;
123 } 121 }
124 122
125 /* Digital audio interface glue - connects codec <--> CPU */ 123 /* Digital audio interface glue - connects codec <--> CPU */
126 static struct snd_soc_dai_link afeb9260_dai = { 124 static struct snd_soc_dai_link afeb9260_dai = {
127 .name = "TLV320AIC23", 125 .name = "TLV320AIC23",
128 .stream_name = "AIC23", 126 .stream_name = "AIC23",
129 .cpu_dai_name = "atmel-ssc-dai.0", 127 .cpu_dai_name = "atmel-ssc-dai.0",
130 .codec_dai_name = "tlv320aic23-hifi", 128 .codec_dai_name = "tlv320aic23-hifi",
131 .platform_name = "atmel_pcm-audio", 129 .platform_name = "atmel_pcm-audio",
132 .codec_name = "tlv320aic23-codec.0-001a", 130 .codec_name = "tlv320aic23-codec.0-001a",
133 .init = afeb9260_tlv320aic23_init, 131 .init = afeb9260_tlv320aic23_init,
134 .ops = &afeb9260_ops, 132 .ops = &afeb9260_ops,
135 }; 133 };
136 134
137 /* Audio machine driver */ 135 /* Audio machine driver */
138 static struct snd_soc_card snd_soc_machine_afeb9260 = { 136 static struct snd_soc_card snd_soc_machine_afeb9260 = {
139 .name = "AFEB9260", 137 .name = "AFEB9260",
140 .dai_link = &afeb9260_dai, 138 .dai_link = &afeb9260_dai,
141 .num_links = 1, 139 .num_links = 1,
142 }; 140 };
143 141
144 static struct platform_device *afeb9260_snd_device; 142 static struct platform_device *afeb9260_snd_device;
145 143
146 static int __init afeb9260_soc_init(void) 144 static int __init afeb9260_soc_init(void)
147 { 145 {
148 int err; 146 int err;
149 struct device *dev; 147 struct device *dev;
150 148
151 if (!(machine_is_afeb9260())) 149 if (!(machine_is_afeb9260()))
152 return -ENODEV; 150 return -ENODEV;
153 151
154 152
155 afeb9260_snd_device = platform_device_alloc("soc-audio", -1); 153 afeb9260_snd_device = platform_device_alloc("soc-audio", -1);
156 if (!afeb9260_snd_device) { 154 if (!afeb9260_snd_device) {
157 printk(KERN_ERR "ASoC: Platform device allocation failed\n"); 155 printk(KERN_ERR "ASoC: Platform device allocation failed\n");
158 return -ENOMEM; 156 return -ENOMEM;
159 } 157 }
160 158
161 platform_set_drvdata(afeb9260_snd_device, &snd_soc_machine_afeb9260); 159 platform_set_drvdata(afeb9260_snd_device, &snd_soc_machine_afeb9260);
162 err = platform_device_add(afeb9260_snd_device); 160 err = platform_device_add(afeb9260_snd_device);
163 if (err) 161 if (err)
164 goto err1; 162 goto err1;
165 163
166 dev = &afeb9260_snd_device->dev; 164 dev = &afeb9260_snd_device->dev;
167 165
168 return 0; 166 return 0;
169 err1: 167 err1:
170 platform_device_put(afeb9260_snd_device); 168 platform_device_put(afeb9260_snd_device);
171 return err; 169 return err;
172 } 170 }
173 171
174 static void __exit afeb9260_soc_exit(void) 172 static void __exit afeb9260_soc_exit(void)
175 { 173 {
176 platform_device_unregister(afeb9260_snd_device); 174 platform_device_unregister(afeb9260_snd_device);
177 } 175 }
178 176
179 module_init(afeb9260_soc_init); 177 module_init(afeb9260_soc_init);
180 module_exit(afeb9260_soc_exit); 178 module_exit(afeb9260_soc_exit);
181 179
182 MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>"); 180 MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>");
183 MODULE_DESCRIPTION("ALSA SoC for AFEB9260"); 181 MODULE_DESCRIPTION("ALSA SoC for AFEB9260");
184 MODULE_LICENSE("GPL"); 182 MODULE_LICENSE("GPL");
185 183
186 184
sound/soc/davinci/davinci-evm.c
1 /* 1 /*
2 * ASoC driver for TI DAVINCI EVM platform 2 * ASoC driver for TI DAVINCI EVM platform
3 * 3 *
4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com> 4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> 5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 */ 10 */
11 11
12 #include <linux/module.h> 12 #include <linux/module.h>
13 #include <linux/moduleparam.h> 13 #include <linux/moduleparam.h>
14 #include <linux/timer.h> 14 #include <linux/timer.h>
15 #include <linux/interrupt.h> 15 #include <linux/interrupt.h>
16 #include <linux/platform_device.h> 16 #include <linux/platform_device.h>
17 #include <linux/i2c.h> 17 #include <linux/i2c.h>
18 #include <sound/core.h> 18 #include <sound/core.h>
19 #include <sound/pcm.h> 19 #include <sound/pcm.h>
20 #include <sound/soc.h> 20 #include <sound/soc.h>
21 21
22 #include <asm/dma.h> 22 #include <asm/dma.h>
23 #include <asm/mach-types.h> 23 #include <asm/mach-types.h>
24 24
25 #include <mach/asp.h> 25 #include <mach/asp.h>
26 #include <mach/edma.h> 26 #include <mach/edma.h>
27 #include <mach/mux.h> 27 #include <mach/mux.h>
28 28
29 #include "davinci-pcm.h" 29 #include "davinci-pcm.h"
30 #include "davinci-i2s.h" 30 #include "davinci-i2s.h"
31 #include "davinci-mcasp.h" 31 #include "davinci-mcasp.h"
32 32
33 #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ 33 #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
34 SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) 34 SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
35 static int evm_hw_params(struct snd_pcm_substream *substream, 35 static int evm_hw_params(struct snd_pcm_substream *substream,
36 struct snd_pcm_hw_params *params) 36 struct snd_pcm_hw_params *params)
37 { 37 {
38 struct snd_soc_pcm_runtime *rtd = substream->private_data; 38 struct snd_soc_pcm_runtime *rtd = substream->private_data;
39 struct snd_soc_dai *codec_dai = rtd->codec_dai; 39 struct snd_soc_dai *codec_dai = rtd->codec_dai;
40 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 40 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
41 int ret = 0; 41 int ret = 0;
42 unsigned sysclk; 42 unsigned sysclk;
43 43
44 /* ASP1 on DM355 EVM is clocked by an external oscillator */ 44 /* ASP1 on DM355 EVM is clocked by an external oscillator */
45 if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() || 45 if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() ||
46 machine_is_davinci_dm365_evm()) 46 machine_is_davinci_dm365_evm())
47 sysclk = 27000000; 47 sysclk = 27000000;
48 48
49 /* ASP0 in DM6446 EVM is clocked by U55, as configured by 49 /* ASP0 in DM6446 EVM is clocked by U55, as configured by
50 * board-dm644x-evm.c using GPIOs from U18. There are six 50 * board-dm644x-evm.c using GPIOs from U18. There are six
51 * options; here we "know" we use a 48 KHz sample rate. 51 * options; here we "know" we use a 48 KHz sample rate.
52 */ 52 */
53 else if (machine_is_davinci_evm()) 53 else if (machine_is_davinci_evm())
54 sysclk = 12288000; 54 sysclk = 12288000;
55 55
56 else if (machine_is_davinci_da830_evm() || 56 else if (machine_is_davinci_da830_evm() ||
57 machine_is_davinci_da850_evm()) 57 machine_is_davinci_da850_evm())
58 sysclk = 24576000; 58 sysclk = 24576000;
59 59
60 else 60 else
61 return -EINVAL; 61 return -EINVAL;
62 62
63 /* set codec DAI configuration */ 63 /* set codec DAI configuration */
64 ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT); 64 ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT);
65 if (ret < 0) 65 if (ret < 0)
66 return ret; 66 return ret;
67 67
68 /* set cpu DAI configuration */ 68 /* set cpu DAI configuration */
69 ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); 69 ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
70 if (ret < 0) 70 if (ret < 0)
71 return ret; 71 return ret;
72 72
73 /* set the codec system clock */ 73 /* set the codec system clock */
74 ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT); 74 ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
75 if (ret < 0) 75 if (ret < 0)
76 return ret; 76 return ret;
77 77
78 return 0; 78 return 0;
79 } 79 }
80 80
81 static int evm_spdif_hw_params(struct snd_pcm_substream *substream, 81 static int evm_spdif_hw_params(struct snd_pcm_substream *substream,
82 struct snd_pcm_hw_params *params) 82 struct snd_pcm_hw_params *params)
83 { 83 {
84 struct snd_soc_pcm_runtime *rtd = substream->private_data; 84 struct snd_soc_pcm_runtime *rtd = substream->private_data;
85 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 85 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
86 86
87 /* set cpu DAI configuration */ 87 /* set cpu DAI configuration */
88 return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); 88 return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
89 } 89 }
90 90
91 static struct snd_soc_ops evm_ops = { 91 static struct snd_soc_ops evm_ops = {
92 .hw_params = evm_hw_params, 92 .hw_params = evm_hw_params,
93 }; 93 };
94 94
95 static struct snd_soc_ops evm_spdif_ops = { 95 static struct snd_soc_ops evm_spdif_ops = {
96 .hw_params = evm_spdif_hw_params, 96 .hw_params = evm_spdif_hw_params,
97 }; 97 };
98 98
99 /* davinci-evm machine dapm widgets */ 99 /* davinci-evm machine dapm widgets */
100 static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { 100 static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
101 SND_SOC_DAPM_HP("Headphone Jack", NULL), 101 SND_SOC_DAPM_HP("Headphone Jack", NULL),
102 SND_SOC_DAPM_LINE("Line Out", NULL), 102 SND_SOC_DAPM_LINE("Line Out", NULL),
103 SND_SOC_DAPM_MIC("Mic Jack", NULL), 103 SND_SOC_DAPM_MIC("Mic Jack", NULL),
104 SND_SOC_DAPM_LINE("Line In", NULL), 104 SND_SOC_DAPM_LINE("Line In", NULL),
105 }; 105 };
106 106
107 /* davinci-evm machine audio_mapnections to the codec pins */ 107 /* davinci-evm machine audio_mapnections to the codec pins */
108 static const struct snd_soc_dapm_route audio_map[] = { 108 static const struct snd_soc_dapm_route audio_map[] = {
109 /* Headphone connected to HPLOUT, HPROUT */ 109 /* Headphone connected to HPLOUT, HPROUT */
110 {"Headphone Jack", NULL, "HPLOUT"}, 110 {"Headphone Jack", NULL, "HPLOUT"},
111 {"Headphone Jack", NULL, "HPROUT"}, 111 {"Headphone Jack", NULL, "HPROUT"},
112 112
113 /* Line Out connected to LLOUT, RLOUT */ 113 /* Line Out connected to LLOUT, RLOUT */
114 {"Line Out", NULL, "LLOUT"}, 114 {"Line Out", NULL, "LLOUT"},
115 {"Line Out", NULL, "RLOUT"}, 115 {"Line Out", NULL, "RLOUT"},
116 116
117 /* Mic connected to (MIC3L | MIC3R) */ 117 /* Mic connected to (MIC3L | MIC3R) */
118 {"MIC3L", NULL, "Mic Bias 2V"}, 118 {"MIC3L", NULL, "Mic Bias 2V"},
119 {"MIC3R", NULL, "Mic Bias 2V"}, 119 {"MIC3R", NULL, "Mic Bias 2V"},
120 {"Mic Bias 2V", NULL, "Mic Jack"}, 120 {"Mic Bias 2V", NULL, "Mic Jack"},
121 121
122 /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */ 122 /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */
123 {"LINE1L", NULL, "Line In"}, 123 {"LINE1L", NULL, "Line In"},
124 {"LINE2L", NULL, "Line In"}, 124 {"LINE2L", NULL, "Line In"},
125 {"LINE1R", NULL, "Line In"}, 125 {"LINE1R", NULL, "Line In"},
126 {"LINE2R", NULL, "Line In"}, 126 {"LINE2R", NULL, "Line In"},
127 }; 127 };
128 128
129 /* Logic for a aic3x as connected on a davinci-evm */ 129 /* Logic for a aic3x as connected on a davinci-evm */
130 static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) 130 static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
131 { 131 {
132 struct snd_soc_codec *codec = rtd->codec; 132 struct snd_soc_codec *codec = rtd->codec;
133 struct snd_soc_dapm_context *dapm = &codec->dapm; 133 struct snd_soc_dapm_context *dapm = &codec->dapm;
134 134
135 /* Add davinci-evm specific widgets */ 135 /* Add davinci-evm specific widgets */
136 snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, 136 snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
137 ARRAY_SIZE(aic3x_dapm_widgets)); 137 ARRAY_SIZE(aic3x_dapm_widgets));
138 138
139 /* Set up davinci-evm specific audio path audio_map */ 139 /* Set up davinci-evm specific audio path audio_map */
140 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 140 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
141 141
142 /* not connected */ 142 /* not connected */
143 snd_soc_dapm_disable_pin(dapm, "MONO_LOUT"); 143 snd_soc_dapm_disable_pin(dapm, "MONO_LOUT");
144 snd_soc_dapm_disable_pin(dapm, "HPLCOM"); 144 snd_soc_dapm_disable_pin(dapm, "HPLCOM");
145 snd_soc_dapm_disable_pin(dapm, "HPRCOM"); 145 snd_soc_dapm_disable_pin(dapm, "HPRCOM");
146 146
147 /* always connected */ 147 /* always connected */
148 snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); 148 snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
149 snd_soc_dapm_enable_pin(dapm, "Line Out"); 149 snd_soc_dapm_enable_pin(dapm, "Line Out");
150 snd_soc_dapm_enable_pin(dapm, "Mic Jack"); 150 snd_soc_dapm_enable_pin(dapm, "Mic Jack");
151 snd_soc_dapm_enable_pin(dapm, "Line In"); 151 snd_soc_dapm_enable_pin(dapm, "Line In");
152 152
153 snd_soc_dapm_sync(dapm);
154
155 return 0; 153 return 0;
156 } 154 }
157 155
158 /* davinci-evm digital audio interface glue - connects codec <--> CPU */ 156 /* davinci-evm digital audio interface glue - connects codec <--> CPU */
159 static struct snd_soc_dai_link dm6446_evm_dai = { 157 static struct snd_soc_dai_link dm6446_evm_dai = {
160 .name = "TLV320AIC3X", 158 .name = "TLV320AIC3X",
161 .stream_name = "AIC3X", 159 .stream_name = "AIC3X",
162 .cpu_dai_name = "davinci-mcbsp", 160 .cpu_dai_name = "davinci-mcbsp",
163 .codec_dai_name = "tlv320aic3x-hifi", 161 .codec_dai_name = "tlv320aic3x-hifi",
164 .codec_name = "tlv320aic3x-codec.1-001b", 162 .codec_name = "tlv320aic3x-codec.1-001b",
165 .platform_name = "davinci-pcm-audio", 163 .platform_name = "davinci-pcm-audio",
166 .init = evm_aic3x_init, 164 .init = evm_aic3x_init,
167 .ops = &evm_ops, 165 .ops = &evm_ops,
168 }; 166 };
169 167
170 static struct snd_soc_dai_link dm355_evm_dai = { 168 static struct snd_soc_dai_link dm355_evm_dai = {
171 .name = "TLV320AIC3X", 169 .name = "TLV320AIC3X",
172 .stream_name = "AIC3X", 170 .stream_name = "AIC3X",
173 .cpu_dai_name = "davinci-mcbsp.1", 171 .cpu_dai_name = "davinci-mcbsp.1",
174 .codec_dai_name = "tlv320aic3x-hifi", 172 .codec_dai_name = "tlv320aic3x-hifi",
175 .codec_name = "tlv320aic3x-codec.1-001b", 173 .codec_name = "tlv320aic3x-codec.1-001b",
176 .platform_name = "davinci-pcm-audio", 174 .platform_name = "davinci-pcm-audio",
177 .init = evm_aic3x_init, 175 .init = evm_aic3x_init,
178 .ops = &evm_ops, 176 .ops = &evm_ops,
179 }; 177 };
180 178
181 static struct snd_soc_dai_link dm365_evm_dai = { 179 static struct snd_soc_dai_link dm365_evm_dai = {
182 #ifdef CONFIG_SND_DM365_AIC3X_CODEC 180 #ifdef CONFIG_SND_DM365_AIC3X_CODEC
183 .name = "TLV320AIC3X", 181 .name = "TLV320AIC3X",
184 .stream_name = "AIC3X", 182 .stream_name = "AIC3X",
185 .cpu_dai_name = "davinci-mcbsp", 183 .cpu_dai_name = "davinci-mcbsp",
186 .codec_dai_name = "tlv320aic3x-hifi", 184 .codec_dai_name = "tlv320aic3x-hifi",
187 .init = evm_aic3x_init, 185 .init = evm_aic3x_init,
188 .codec_name = "tlv320aic3x-codec.1-0018", 186 .codec_name = "tlv320aic3x-codec.1-0018",
189 .ops = &evm_ops, 187 .ops = &evm_ops,
190 #elif defined(CONFIG_SND_DM365_VOICE_CODEC) 188 #elif defined(CONFIG_SND_DM365_VOICE_CODEC)
191 .name = "Voice Codec - CQ93VC", 189 .name = "Voice Codec - CQ93VC",
192 .stream_name = "CQ93", 190 .stream_name = "CQ93",
193 .cpu_dai_name = "davinci-vcif", 191 .cpu_dai_name = "davinci-vcif",
194 .codec_dai_name = "cq93vc-hifi", 192 .codec_dai_name = "cq93vc-hifi",
195 .codec_name = "cq93vc-codec", 193 .codec_name = "cq93vc-codec",
196 #endif 194 #endif
197 .platform_name = "davinci-pcm-audio", 195 .platform_name = "davinci-pcm-audio",
198 }; 196 };
199 197
200 static struct snd_soc_dai_link dm6467_evm_dai[] = { 198 static struct snd_soc_dai_link dm6467_evm_dai[] = {
201 { 199 {
202 .name = "TLV320AIC3X", 200 .name = "TLV320AIC3X",
203 .stream_name = "AIC3X", 201 .stream_name = "AIC3X",
204 .cpu_dai_name= "davinci-mcasp.0", 202 .cpu_dai_name= "davinci-mcasp.0",
205 .codec_dai_name = "tlv320aic3x-hifi", 203 .codec_dai_name = "tlv320aic3x-hifi",
206 .platform_name ="davinci-pcm-audio", 204 .platform_name ="davinci-pcm-audio",
207 .codec_name = "tlv320aic3x-codec.0-001a", 205 .codec_name = "tlv320aic3x-codec.0-001a",
208 .init = evm_aic3x_init, 206 .init = evm_aic3x_init,
209 .ops = &evm_ops, 207 .ops = &evm_ops,
210 }, 208 },
211 { 209 {
212 .name = "McASP", 210 .name = "McASP",
213 .stream_name = "spdif", 211 .stream_name = "spdif",
214 .cpu_dai_name= "davinci-mcasp.1", 212 .cpu_dai_name= "davinci-mcasp.1",
215 .codec_dai_name = "dit-hifi", 213 .codec_dai_name = "dit-hifi",
216 .codec_name = "spdif_dit", 214 .codec_name = "spdif_dit",
217 .platform_name = "davinci-pcm-audio", 215 .platform_name = "davinci-pcm-audio",
218 .ops = &evm_spdif_ops, 216 .ops = &evm_spdif_ops,
219 }, 217 },
220 }; 218 };
221 219
222 static struct snd_soc_dai_link da830_evm_dai = { 220 static struct snd_soc_dai_link da830_evm_dai = {
223 .name = "TLV320AIC3X", 221 .name = "TLV320AIC3X",
224 .stream_name = "AIC3X", 222 .stream_name = "AIC3X",
225 .cpu_dai_name = "davinci-mcasp.1", 223 .cpu_dai_name = "davinci-mcasp.1",
226 .codec_dai_name = "tlv320aic3x-hifi", 224 .codec_dai_name = "tlv320aic3x-hifi",
227 .codec_name = "tlv320aic3x-codec.1-0018", 225 .codec_name = "tlv320aic3x-codec.1-0018",
228 .platform_name = "davinci-pcm-audio", 226 .platform_name = "davinci-pcm-audio",
229 .init = evm_aic3x_init, 227 .init = evm_aic3x_init,
230 .ops = &evm_ops, 228 .ops = &evm_ops,
231 }; 229 };
232 230
233 static struct snd_soc_dai_link da850_evm_dai = { 231 static struct snd_soc_dai_link da850_evm_dai = {
234 .name = "TLV320AIC3X", 232 .name = "TLV320AIC3X",
235 .stream_name = "AIC3X", 233 .stream_name = "AIC3X",
236 .cpu_dai_name= "davinci-mcasp.0", 234 .cpu_dai_name= "davinci-mcasp.0",
237 .codec_dai_name = "tlv320aic3x-hifi", 235 .codec_dai_name = "tlv320aic3x-hifi",
238 .codec_name = "tlv320aic3x-codec.1-0018", 236 .codec_name = "tlv320aic3x-codec.1-0018",
239 .platform_name = "davinci-pcm-audio", 237 .platform_name = "davinci-pcm-audio",
240 .init = evm_aic3x_init, 238 .init = evm_aic3x_init,
241 .ops = &evm_ops, 239 .ops = &evm_ops,
242 }; 240 };
243 241
244 /* davinci dm6446 evm audio machine driver */ 242 /* davinci dm6446 evm audio machine driver */
245 static struct snd_soc_card dm6446_snd_soc_card_evm = { 243 static struct snd_soc_card dm6446_snd_soc_card_evm = {
246 .name = "DaVinci DM6446 EVM", 244 .name = "DaVinci DM6446 EVM",
247 .dai_link = &dm6446_evm_dai, 245 .dai_link = &dm6446_evm_dai,
248 .num_links = 1, 246 .num_links = 1,
249 }; 247 };
250 248
251 /* davinci dm355 evm audio machine driver */ 249 /* davinci dm355 evm audio machine driver */
252 static struct snd_soc_card dm355_snd_soc_card_evm = { 250 static struct snd_soc_card dm355_snd_soc_card_evm = {
253 .name = "DaVinci DM355 EVM", 251 .name = "DaVinci DM355 EVM",
254 .dai_link = &dm355_evm_dai, 252 .dai_link = &dm355_evm_dai,
255 .num_links = 1, 253 .num_links = 1,
256 }; 254 };
257 255
258 /* davinci dm365 evm audio machine driver */ 256 /* davinci dm365 evm audio machine driver */
259 static struct snd_soc_card dm365_snd_soc_card_evm = { 257 static struct snd_soc_card dm365_snd_soc_card_evm = {
260 .name = "DaVinci DM365 EVM", 258 .name = "DaVinci DM365 EVM",
261 .dai_link = &dm365_evm_dai, 259 .dai_link = &dm365_evm_dai,
262 .num_links = 1, 260 .num_links = 1,
263 }; 261 };
264 262
265 /* davinci dm6467 evm audio machine driver */ 263 /* davinci dm6467 evm audio machine driver */
266 static struct snd_soc_card dm6467_snd_soc_card_evm = { 264 static struct snd_soc_card dm6467_snd_soc_card_evm = {
267 .name = "DaVinci DM6467 EVM", 265 .name = "DaVinci DM6467 EVM",
268 .dai_link = dm6467_evm_dai, 266 .dai_link = dm6467_evm_dai,
269 .num_links = ARRAY_SIZE(dm6467_evm_dai), 267 .num_links = ARRAY_SIZE(dm6467_evm_dai),
270 }; 268 };
271 269
272 static struct snd_soc_card da830_snd_soc_card = { 270 static struct snd_soc_card da830_snd_soc_card = {
273 .name = "DA830/OMAP-L137 EVM", 271 .name = "DA830/OMAP-L137 EVM",
274 .dai_link = &da830_evm_dai, 272 .dai_link = &da830_evm_dai,
275 .num_links = 1, 273 .num_links = 1,
276 }; 274 };
277 275
278 static struct snd_soc_card da850_snd_soc_card = { 276 static struct snd_soc_card da850_snd_soc_card = {
279 .name = "DA850/OMAP-L138 EVM", 277 .name = "DA850/OMAP-L138 EVM",
280 .dai_link = &da850_evm_dai, 278 .dai_link = &da850_evm_dai,
281 .num_links = 1, 279 .num_links = 1,
282 }; 280 };
283 281
284 static struct platform_device *evm_snd_device; 282 static struct platform_device *evm_snd_device;
285 283
286 static int __init evm_init(void) 284 static int __init evm_init(void)
287 { 285 {
288 struct snd_soc_card *evm_snd_dev_data; 286 struct snd_soc_card *evm_snd_dev_data;
289 int index; 287 int index;
290 int ret; 288 int ret;
291 289
292 if (machine_is_davinci_evm()) { 290 if (machine_is_davinci_evm()) {
293 evm_snd_dev_data = &dm6446_snd_soc_card_evm; 291 evm_snd_dev_data = &dm6446_snd_soc_card_evm;
294 index = 0; 292 index = 0;
295 } else if (machine_is_davinci_dm355_evm()) { 293 } else if (machine_is_davinci_dm355_evm()) {
296 evm_snd_dev_data = &dm355_snd_soc_card_evm; 294 evm_snd_dev_data = &dm355_snd_soc_card_evm;
297 index = 1; 295 index = 1;
298 } else if (machine_is_davinci_dm365_evm()) { 296 } else if (machine_is_davinci_dm365_evm()) {
299 evm_snd_dev_data = &dm365_snd_soc_card_evm; 297 evm_snd_dev_data = &dm365_snd_soc_card_evm;
300 index = 0; 298 index = 0;
301 } else if (machine_is_davinci_dm6467_evm()) { 299 } else if (machine_is_davinci_dm6467_evm()) {
302 evm_snd_dev_data = &dm6467_snd_soc_card_evm; 300 evm_snd_dev_data = &dm6467_snd_soc_card_evm;
303 index = 0; 301 index = 0;
304 } else if (machine_is_davinci_da830_evm()) { 302 } else if (machine_is_davinci_da830_evm()) {
305 evm_snd_dev_data = &da830_snd_soc_card; 303 evm_snd_dev_data = &da830_snd_soc_card;
306 index = 1; 304 index = 1;
307 } else if (machine_is_davinci_da850_evm()) { 305 } else if (machine_is_davinci_da850_evm()) {
308 evm_snd_dev_data = &da850_snd_soc_card; 306 evm_snd_dev_data = &da850_snd_soc_card;
309 index = 0; 307 index = 0;
310 } else 308 } else
311 return -EINVAL; 309 return -EINVAL;
312 310
313 evm_snd_device = platform_device_alloc("soc-audio", index); 311 evm_snd_device = platform_device_alloc("soc-audio", index);
314 if (!evm_snd_device) 312 if (!evm_snd_device)
315 return -ENOMEM; 313 return -ENOMEM;
316 314
317 platform_set_drvdata(evm_snd_device, evm_snd_dev_data); 315 platform_set_drvdata(evm_snd_device, evm_snd_dev_data);
318 ret = platform_device_add(evm_snd_device); 316 ret = platform_device_add(evm_snd_device);
319 if (ret) 317 if (ret)
320 platform_device_put(evm_snd_device); 318 platform_device_put(evm_snd_device);
321 319
322 return ret; 320 return ret;
323 } 321 }
324 322
325 static void __exit evm_exit(void) 323 static void __exit evm_exit(void)
326 { 324 {
327 platform_device_unregister(evm_snd_device); 325 platform_device_unregister(evm_snd_device);
328 } 326 }
329 327
330 module_init(evm_init); 328 module_init(evm_init);
331 module_exit(evm_exit); 329 module_exit(evm_exit);
332 330
333 MODULE_AUTHOR("Vladimir Barinov"); 331 MODULE_AUTHOR("Vladimir Barinov");
334 MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver"); 332 MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver");
335 MODULE_LICENSE("GPL"); 333 MODULE_LICENSE("GPL");
336 334
sound/soc/kirkwood/kirkwood-t5325.c
1 /* 1 /*
2 * kirkwood-t5325.c 2 * kirkwood-t5325.c
3 * 3 *
4 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org> 4 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your 8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. 9 * option) any later version.
10 */ 10 */
11 11
12 #include <linux/module.h> 12 #include <linux/module.h>
13 #include <linux/moduleparam.h> 13 #include <linux/moduleparam.h>
14 #include <linux/interrupt.h> 14 #include <linux/interrupt.h>
15 #include <linux/platform_device.h> 15 #include <linux/platform_device.h>
16 #include <linux/slab.h> 16 #include <linux/slab.h>
17 #include <sound/soc.h> 17 #include <sound/soc.h>
18 #include <mach/kirkwood.h> 18 #include <mach/kirkwood.h>
19 #include <plat/audio.h> 19 #include <plat/audio.h>
20 #include <asm/mach-types.h> 20 #include <asm/mach-types.h>
21 #include "../codecs/alc5623.h" 21 #include "../codecs/alc5623.h"
22 22
23 static int t5325_hw_params(struct snd_pcm_substream *substream, 23 static int t5325_hw_params(struct snd_pcm_substream *substream,
24 struct snd_pcm_hw_params *params) 24 struct snd_pcm_hw_params *params)
25 { 25 {
26 struct snd_soc_pcm_runtime *rtd = substream->private_data; 26 struct snd_soc_pcm_runtime *rtd = substream->private_data;
27 struct snd_soc_dai *codec_dai = rtd->codec_dai; 27 struct snd_soc_dai *codec_dai = rtd->codec_dai;
28 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 28 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
29 int ret; 29 int ret;
30 unsigned int freq, fmt; 30 unsigned int freq, fmt;
31 31
32 fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS; 32 fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;
33 ret = snd_soc_dai_set_fmt(cpu_dai, fmt); 33 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
34 if (ret < 0) 34 if (ret < 0)
35 return ret; 35 return ret;
36 36
37 ret = snd_soc_dai_set_fmt(codec_dai, fmt); 37 ret = snd_soc_dai_set_fmt(codec_dai, fmt);
38 if (ret < 0) 38 if (ret < 0)
39 return ret; 39 return ret;
40 40
41 freq = params_rate(params) * 256; 41 freq = params_rate(params) * 256;
42 42
43 return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN); 43 return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN);
44 44
45 } 45 }
46 46
47 static struct snd_soc_ops t5325_ops = { 47 static struct snd_soc_ops t5325_ops = {
48 .hw_params = t5325_hw_params, 48 .hw_params = t5325_hw_params,
49 }; 49 };
50 50
51 static const struct snd_soc_dapm_widget t5325_dapm_widgets[] = { 51 static const struct snd_soc_dapm_widget t5325_dapm_widgets[] = {
52 SND_SOC_DAPM_HP("Headphone Jack", NULL), 52 SND_SOC_DAPM_HP("Headphone Jack", NULL),
53 SND_SOC_DAPM_SPK("Speaker", NULL), 53 SND_SOC_DAPM_SPK("Speaker", NULL),
54 SND_SOC_DAPM_MIC("Mic Jack", NULL), 54 SND_SOC_DAPM_MIC("Mic Jack", NULL),
55 }; 55 };
56 56
57 static const struct snd_soc_dapm_route t5325_route[] = { 57 static const struct snd_soc_dapm_route t5325_route[] = {
58 { "Headphone Jack", NULL, "HPL" }, 58 { "Headphone Jack", NULL, "HPL" },
59 { "Headphone Jack", NULL, "HPR" }, 59 { "Headphone Jack", NULL, "HPR" },
60 60
61 {"Speaker", NULL, "SPKOUT"}, 61 {"Speaker", NULL, "SPKOUT"},
62 {"Speaker", NULL, "SPKOUTN"}, 62 {"Speaker", NULL, "SPKOUTN"},
63 63
64 { "MIC1", NULL, "Mic Jack" }, 64 { "MIC1", NULL, "Mic Jack" },
65 { "MIC2", NULL, "Mic Jack" }, 65 { "MIC2", NULL, "Mic Jack" },
66 }; 66 };
67 67
68 static int t5325_dai_init(struct snd_soc_pcm_runtime *rtd) 68 static int t5325_dai_init(struct snd_soc_pcm_runtime *rtd)
69 { 69 {
70 struct snd_soc_codec *codec = rtd->codec; 70 struct snd_soc_codec *codec = rtd->codec;
71 struct snd_soc_dapm_context *dapm = &codec->dapm; 71 struct snd_soc_dapm_context *dapm = &codec->dapm;
72 72
73 snd_soc_dapm_new_controls(dapm, t5325_dapm_widgets, 73 snd_soc_dapm_new_controls(dapm, t5325_dapm_widgets,
74 ARRAY_SIZE(t5325_dapm_widgets)); 74 ARRAY_SIZE(t5325_dapm_widgets));
75 75
76 snd_soc_dapm_add_routes(dapm, t5325_route, ARRAY_SIZE(t5325_route)); 76 snd_soc_dapm_add_routes(dapm, t5325_route, ARRAY_SIZE(t5325_route));
77 77
78 snd_soc_dapm_enable_pin(dapm, "Mic Jack"); 78 snd_soc_dapm_enable_pin(dapm, "Mic Jack");
79 snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); 79 snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
80 snd_soc_dapm_enable_pin(dapm, "Speaker"); 80 snd_soc_dapm_enable_pin(dapm, "Speaker");
81 81
82 snd_soc_dapm_sync(dapm);
83
84 return 0; 82 return 0;
85 } 83 }
86 84
87 static struct snd_soc_dai_link t5325_dai[] = { 85 static struct snd_soc_dai_link t5325_dai[] = {
88 { 86 {
89 .name = "ALC5621", 87 .name = "ALC5621",
90 .stream_name = "ALC5621 HiFi", 88 .stream_name = "ALC5621 HiFi",
91 .cpu_dai_name = "kirkwood-i2s", 89 .cpu_dai_name = "kirkwood-i2s",
92 .platform_name = "kirkwood-pcm-audio", 90 .platform_name = "kirkwood-pcm-audio",
93 .codec_dai_name = "alc5621-hifi", 91 .codec_dai_name = "alc5621-hifi",
94 .codec_name = "alc562x-codec.0-001a", 92 .codec_name = "alc562x-codec.0-001a",
95 .ops = &t5325_ops, 93 .ops = &t5325_ops,
96 .init = t5325_dai_init, 94 .init = t5325_dai_init,
97 }, 95 },
98 }; 96 };
99 97
100 98
101 static struct snd_soc_card t5325 = { 99 static struct snd_soc_card t5325 = {
102 .name = "t5325", 100 .name = "t5325",
103 .dai_link = t5325_dai, 101 .dai_link = t5325_dai,
104 .num_links = ARRAY_SIZE(t5325_dai), 102 .num_links = ARRAY_SIZE(t5325_dai),
105 }; 103 };
106 104
107 static struct platform_device *t5325_snd_device; 105 static struct platform_device *t5325_snd_device;
108 106
109 static int __init t5325_init(void) 107 static int __init t5325_init(void)
110 { 108 {
111 int ret; 109 int ret;
112 110
113 if (!machine_is_t5325()) 111 if (!machine_is_t5325())
114 return 0; 112 return 0;
115 113
116 t5325_snd_device = platform_device_alloc("soc-audio", -1); 114 t5325_snd_device = platform_device_alloc("soc-audio", -1);
117 if (!t5325_snd_device) 115 if (!t5325_snd_device)
118 return -ENOMEM; 116 return -ENOMEM;
119 117
120 platform_set_drvdata(t5325_snd_device, 118 platform_set_drvdata(t5325_snd_device,
121 &t5325); 119 &t5325);
122 120
123 ret = platform_device_add(t5325_snd_device); 121 ret = platform_device_add(t5325_snd_device);
124 if (ret) { 122 if (ret) {
125 printk(KERN_ERR "%s: platform_device_add failed\n", __func__); 123 printk(KERN_ERR "%s: platform_device_add failed\n", __func__);
126 platform_device_put(t5325_snd_device); 124 platform_device_put(t5325_snd_device);
127 } 125 }
128 126
129 return ret; 127 return ret;
130 } 128 }
131 module_init(t5325_init); 129 module_init(t5325_init);
132 130
133 static void __exit t5325_exit(void) 131 static void __exit t5325_exit(void)
134 { 132 {
135 platform_device_unregister(t5325_snd_device); 133 platform_device_unregister(t5325_snd_device);
136 } 134 }
137 module_exit(t5325_exit); 135 module_exit(t5325_exit);
138 136
139 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); 137 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
140 MODULE_DESCRIPTION("ALSA SoC t5325 audio client"); 138 MODULE_DESCRIPTION("ALSA SoC t5325 audio client");
141 MODULE_LICENSE("GPL"); 139 MODULE_LICENSE("GPL");
142 140
sound/soc/mid-x86/mfld_machine.c
1 /* 1 /*
2 * mfld_machine.c - ASoc Machine driver for Intel Medfield MID platform 2 * mfld_machine.c - ASoc Machine driver for Intel Medfield MID platform
3 * 3 *
4 * Copyright (C) 2010 Intel Corp 4 * Copyright (C) 2010 Intel Corp
5 * Author: Vinod Koul <vinod.koul@intel.com> 5 * Author: Vinod Koul <vinod.koul@intel.com>
6 * Author: Harsha Priya <priya.harsha@intel.com> 6 * Author: Harsha Priya <priya.harsha@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License. 11 * the Free Software Foundation; version 2 of the License.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, but 13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details. 16 * General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License along 18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc., 19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 * 21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */ 23 */
24 24
25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26 26
27 #include <linux/init.h> 27 #include <linux/init.h>
28 #include <linux/device.h> 28 #include <linux/device.h>
29 #include <linux/slab.h> 29 #include <linux/slab.h>
30 #include <linux/io.h> 30 #include <linux/io.h>
31 #include <sound/pcm.h> 31 #include <sound/pcm.h>
32 #include <sound/pcm_params.h> 32 #include <sound/pcm_params.h>
33 #include <sound/soc.h> 33 #include <sound/soc.h>
34 #include <sound/jack.h> 34 #include <sound/jack.h>
35 #include "../codecs/sn95031.h" 35 #include "../codecs/sn95031.h"
36 36
37 #define MID_MONO 1 37 #define MID_MONO 1
38 #define MID_STEREO 2 38 #define MID_STEREO 2
39 #define MID_MAX_CAP 5 39 #define MID_MAX_CAP 5
40 #define MFLD_JACK_INSERT 0x04 40 #define MFLD_JACK_INSERT 0x04
41 41
42 enum soc_mic_bias_zones { 42 enum soc_mic_bias_zones {
43 MFLD_MV_START = 0, 43 MFLD_MV_START = 0,
44 /* mic bias volutage range for Headphones*/ 44 /* mic bias volutage range for Headphones*/
45 MFLD_MV_HP = 400, 45 MFLD_MV_HP = 400,
46 /* mic bias volutage range for American Headset*/ 46 /* mic bias volutage range for American Headset*/
47 MFLD_MV_AM_HS = 650, 47 MFLD_MV_AM_HS = 650,
48 /* mic bias volutage range for Headset*/ 48 /* mic bias volutage range for Headset*/
49 MFLD_MV_HS = 2000, 49 MFLD_MV_HS = 2000,
50 MFLD_MV_UNDEFINED, 50 MFLD_MV_UNDEFINED,
51 }; 51 };
52 52
53 static unsigned int hs_switch; 53 static unsigned int hs_switch;
54 static unsigned int lo_dac; 54 static unsigned int lo_dac;
55 55
56 struct mfld_mc_private { 56 struct mfld_mc_private {
57 void __iomem *int_base; 57 void __iomem *int_base;
58 u8 interrupt_status; 58 u8 interrupt_status;
59 }; 59 };
60 60
61 struct snd_soc_jack mfld_jack; 61 struct snd_soc_jack mfld_jack;
62 62
63 /*Headset jack detection DAPM pins */ 63 /*Headset jack detection DAPM pins */
64 static struct snd_soc_jack_pin mfld_jack_pins[] = { 64 static struct snd_soc_jack_pin mfld_jack_pins[] = {
65 { 65 {
66 .pin = "Headphones", 66 .pin = "Headphones",
67 .mask = SND_JACK_HEADPHONE, 67 .mask = SND_JACK_HEADPHONE,
68 }, 68 },
69 { 69 {
70 .pin = "AMIC1", 70 .pin = "AMIC1",
71 .mask = SND_JACK_MICROPHONE, 71 .mask = SND_JACK_MICROPHONE,
72 }, 72 },
73 }; 73 };
74 74
75 /* jack detection voltage zones */ 75 /* jack detection voltage zones */
76 static struct snd_soc_jack_zone mfld_zones[] = { 76 static struct snd_soc_jack_zone mfld_zones[] = {
77 {MFLD_MV_START, MFLD_MV_AM_HS, SND_JACK_HEADPHONE}, 77 {MFLD_MV_START, MFLD_MV_AM_HS, SND_JACK_HEADPHONE},
78 {MFLD_MV_AM_HS, MFLD_MV_HS, SND_JACK_HEADSET}, 78 {MFLD_MV_AM_HS, MFLD_MV_HS, SND_JACK_HEADSET},
79 }; 79 };
80 80
81 /* sound card controls */ 81 /* sound card controls */
82 static const char *headset_switch_text[] = {"Earpiece", "Headset"}; 82 static const char *headset_switch_text[] = {"Earpiece", "Headset"};
83 83
84 static const char *lo_text[] = {"Vibra", "Headset", "IHF", "None"}; 84 static const char *lo_text[] = {"Vibra", "Headset", "IHF", "None"};
85 85
86 static const struct soc_enum headset_enum = 86 static const struct soc_enum headset_enum =
87 SOC_ENUM_SINGLE_EXT(2, headset_switch_text); 87 SOC_ENUM_SINGLE_EXT(2, headset_switch_text);
88 88
89 static const struct soc_enum lo_enum = 89 static const struct soc_enum lo_enum =
90 SOC_ENUM_SINGLE_EXT(4, lo_text); 90 SOC_ENUM_SINGLE_EXT(4, lo_text);
91 91
92 static int headset_get_switch(struct snd_kcontrol *kcontrol, 92 static int headset_get_switch(struct snd_kcontrol *kcontrol,
93 struct snd_ctl_elem_value *ucontrol) 93 struct snd_ctl_elem_value *ucontrol)
94 { 94 {
95 ucontrol->value.integer.value[0] = hs_switch; 95 ucontrol->value.integer.value[0] = hs_switch;
96 return 0; 96 return 0;
97 } 97 }
98 98
99 static int headset_set_switch(struct snd_kcontrol *kcontrol, 99 static int headset_set_switch(struct snd_kcontrol *kcontrol,
100 struct snd_ctl_elem_value *ucontrol) 100 struct snd_ctl_elem_value *ucontrol)
101 { 101 {
102 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 102 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
103 103
104 if (ucontrol->value.integer.value[0] == hs_switch) 104 if (ucontrol->value.integer.value[0] == hs_switch)
105 return 0; 105 return 0;
106 106
107 if (ucontrol->value.integer.value[0]) { 107 if (ucontrol->value.integer.value[0]) {
108 pr_debug("hs_set HS path\n"); 108 pr_debug("hs_set HS path\n");
109 snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); 109 snd_soc_dapm_enable_pin(&codec->dapm, "Headphones");
110 snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); 110 snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
111 } else { 111 } else {
112 pr_debug("hs_set EP path\n"); 112 pr_debug("hs_set EP path\n");
113 snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); 113 snd_soc_dapm_disable_pin(&codec->dapm, "Headphones");
114 snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); 114 snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT");
115 } 115 }
116 snd_soc_dapm_sync(&codec->dapm); 116 snd_soc_dapm_sync(&codec->dapm);
117 hs_switch = ucontrol->value.integer.value[0]; 117 hs_switch = ucontrol->value.integer.value[0];
118 118
119 return 0; 119 return 0;
120 } 120 }
121 121
122 static void lo_enable_out_pins(struct snd_soc_codec *codec) 122 static void lo_enable_out_pins(struct snd_soc_codec *codec)
123 { 123 {
124 snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTL"); 124 snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTL");
125 snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTR"); 125 snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTR");
126 snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTL"); 126 snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTL");
127 snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTR"); 127 snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTR");
128 snd_soc_dapm_enable_pin(&codec->dapm, "VIB1OUT"); 128 snd_soc_dapm_enable_pin(&codec->dapm, "VIB1OUT");
129 snd_soc_dapm_enable_pin(&codec->dapm, "VIB2OUT"); 129 snd_soc_dapm_enable_pin(&codec->dapm, "VIB2OUT");
130 if (hs_switch) { 130 if (hs_switch) {
131 snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); 131 snd_soc_dapm_enable_pin(&codec->dapm, "Headphones");
132 snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); 132 snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
133 } else { 133 } else {
134 snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); 134 snd_soc_dapm_disable_pin(&codec->dapm, "Headphones");
135 snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); 135 snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT");
136 } 136 }
137 } 137 }
138 138
139 static int lo_get_switch(struct snd_kcontrol *kcontrol, 139 static int lo_get_switch(struct snd_kcontrol *kcontrol,
140 struct snd_ctl_elem_value *ucontrol) 140 struct snd_ctl_elem_value *ucontrol)
141 { 141 {
142 ucontrol->value.integer.value[0] = lo_dac; 142 ucontrol->value.integer.value[0] = lo_dac;
143 return 0; 143 return 0;
144 } 144 }
145 145
146 static int lo_set_switch(struct snd_kcontrol *kcontrol, 146 static int lo_set_switch(struct snd_kcontrol *kcontrol,
147 struct snd_ctl_elem_value *ucontrol) 147 struct snd_ctl_elem_value *ucontrol)
148 { 148 {
149 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 149 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
150 150
151 if (ucontrol->value.integer.value[0] == lo_dac) 151 if (ucontrol->value.integer.value[0] == lo_dac)
152 return 0; 152 return 0;
153 153
154 /* we dont want to work with last state of lineout so just enable all 154 /* we dont want to work with last state of lineout so just enable all
155 * pins and then disable pins not required 155 * pins and then disable pins not required
156 */ 156 */
157 lo_enable_out_pins(codec); 157 lo_enable_out_pins(codec);
158 switch (ucontrol->value.integer.value[0]) { 158 switch (ucontrol->value.integer.value[0]) {
159 case 0: 159 case 0:
160 pr_debug("set vibra path\n"); 160 pr_debug("set vibra path\n");
161 snd_soc_dapm_disable_pin(&codec->dapm, "VIB1OUT"); 161 snd_soc_dapm_disable_pin(&codec->dapm, "VIB1OUT");
162 snd_soc_dapm_disable_pin(&codec->dapm, "VIB2OUT"); 162 snd_soc_dapm_disable_pin(&codec->dapm, "VIB2OUT");
163 snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0); 163 snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0);
164 break; 164 break;
165 165
166 case 1: 166 case 1:
167 pr_debug("set hs path\n"); 167 pr_debug("set hs path\n");
168 snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); 168 snd_soc_dapm_disable_pin(&codec->dapm, "Headphones");
169 snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); 169 snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
170 snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22); 170 snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22);
171 break; 171 break;
172 172
173 case 2: 173 case 2:
174 pr_debug("set spkr path\n"); 174 pr_debug("set spkr path\n");
175 snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTL"); 175 snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTL");
176 snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTR"); 176 snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTR");
177 snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44); 177 snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44);
178 break; 178 break;
179 179
180 case 3: 180 case 3:
181 pr_debug("set null path\n"); 181 pr_debug("set null path\n");
182 snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTL"); 182 snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTL");
183 snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTR"); 183 snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTR");
184 snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66); 184 snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66);
185 break; 185 break;
186 } 186 }
187 snd_soc_dapm_sync(&codec->dapm); 187 snd_soc_dapm_sync(&codec->dapm);
188 lo_dac = ucontrol->value.integer.value[0]; 188 lo_dac = ucontrol->value.integer.value[0];
189 return 0; 189 return 0;
190 } 190 }
191 191
192 static const struct snd_kcontrol_new mfld_snd_controls[] = { 192 static const struct snd_kcontrol_new mfld_snd_controls[] = {
193 SOC_ENUM_EXT("Playback Switch", headset_enum, 193 SOC_ENUM_EXT("Playback Switch", headset_enum,
194 headset_get_switch, headset_set_switch), 194 headset_get_switch, headset_set_switch),
195 SOC_ENUM_EXT("Lineout Mux", lo_enum, 195 SOC_ENUM_EXT("Lineout Mux", lo_enum,
196 lo_get_switch, lo_set_switch), 196 lo_get_switch, lo_set_switch),
197 }; 197 };
198 198
199 static const struct snd_soc_dapm_widget mfld_widgets[] = { 199 static const struct snd_soc_dapm_widget mfld_widgets[] = {
200 SND_SOC_DAPM_HP("Headphones", NULL), 200 SND_SOC_DAPM_HP("Headphones", NULL),
201 SND_SOC_DAPM_MIC("Mic", NULL), 201 SND_SOC_DAPM_MIC("Mic", NULL),
202 }; 202 };
203 203
204 static const struct snd_soc_dapm_route mfld_map[] = { 204 static const struct snd_soc_dapm_route mfld_map[] = {
205 {"Headphones", NULL, "HPOUTR"}, 205 {"Headphones", NULL, "HPOUTR"},
206 {"Headphones", NULL, "HPOUTL"}, 206 {"Headphones", NULL, "HPOUTL"},
207 {"Mic", NULL, "AMIC1"}, 207 {"Mic", NULL, "AMIC1"},
208 }; 208 };
209 209
210 static void mfld_jack_check(unsigned int intr_status) 210 static void mfld_jack_check(unsigned int intr_status)
211 { 211 {
212 struct mfld_jack_data jack_data; 212 struct mfld_jack_data jack_data;
213 213
214 jack_data.mfld_jack = &mfld_jack; 214 jack_data.mfld_jack = &mfld_jack;
215 jack_data.intr_id = intr_status; 215 jack_data.intr_id = intr_status;
216 216
217 sn95031_jack_detection(&jack_data); 217 sn95031_jack_detection(&jack_data);
218 /* TODO: add american headset detection post gpiolib support */ 218 /* TODO: add american headset detection post gpiolib support */
219 } 219 }
220 220
221 static int mfld_init(struct snd_soc_pcm_runtime *runtime) 221 static int mfld_init(struct snd_soc_pcm_runtime *runtime)
222 { 222 {
223 struct snd_soc_codec *codec = runtime->codec; 223 struct snd_soc_codec *codec = runtime->codec;
224 struct snd_soc_dapm_context *dapm = &codec->dapm; 224 struct snd_soc_dapm_context *dapm = &codec->dapm;
225 int ret_val; 225 int ret_val;
226 226
227 /* Add jack sense widgets */ 227 /* Add jack sense widgets */
228 snd_soc_dapm_new_controls(dapm, mfld_widgets, ARRAY_SIZE(mfld_widgets)); 228 snd_soc_dapm_new_controls(dapm, mfld_widgets, ARRAY_SIZE(mfld_widgets));
229 229
230 /* Set up the map */ 230 /* Set up the map */
231 snd_soc_dapm_add_routes(dapm, mfld_map, ARRAY_SIZE(mfld_map)); 231 snd_soc_dapm_add_routes(dapm, mfld_map, ARRAY_SIZE(mfld_map));
232 232
233 /* always connected */ 233 /* always connected */
234 snd_soc_dapm_enable_pin(dapm, "Headphones"); 234 snd_soc_dapm_enable_pin(dapm, "Headphones");
235 snd_soc_dapm_enable_pin(dapm, "Mic"); 235 snd_soc_dapm_enable_pin(dapm, "Mic");
236 snd_soc_dapm_sync(dapm);
237 236
238 ret_val = snd_soc_add_controls(codec, mfld_snd_controls, 237 ret_val = snd_soc_add_controls(codec, mfld_snd_controls,
239 ARRAY_SIZE(mfld_snd_controls)); 238 ARRAY_SIZE(mfld_snd_controls));
240 if (ret_val) { 239 if (ret_val) {
241 pr_err("soc_add_controls failed %d", ret_val); 240 pr_err("soc_add_controls failed %d", ret_val);
242 return ret_val; 241 return ret_val;
243 } 242 }
244 /* default is earpiece pin, userspace sets it explcitly */ 243 /* default is earpiece pin, userspace sets it explcitly */
245 snd_soc_dapm_disable_pin(dapm, "Headphones"); 244 snd_soc_dapm_disable_pin(dapm, "Headphones");
246 /* default is lineout NC, userspace sets it explcitly */ 245 /* default is lineout NC, userspace sets it explcitly */
247 snd_soc_dapm_disable_pin(dapm, "LINEOUTL"); 246 snd_soc_dapm_disable_pin(dapm, "LINEOUTL");
248 snd_soc_dapm_disable_pin(dapm, "LINEOUTR"); 247 snd_soc_dapm_disable_pin(dapm, "LINEOUTR");
249 lo_dac = 3; 248 lo_dac = 3;
250 hs_switch = 0; 249 hs_switch = 0;
251 /* we dont use linein in this so set to NC */ 250 /* we dont use linein in this so set to NC */
252 snd_soc_dapm_disable_pin(dapm, "LINEINL"); 251 snd_soc_dapm_disable_pin(dapm, "LINEINL");
253 snd_soc_dapm_disable_pin(dapm, "LINEINR"); 252 snd_soc_dapm_disable_pin(dapm, "LINEINR");
254 snd_soc_dapm_sync(dapm);
255 253
256 /* Headset and button jack detection */ 254 /* Headset and button jack detection */
257 ret_val = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack", 255 ret_val = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack",
258 SND_JACK_HEADSET | SND_JACK_BTN_0 | 256 SND_JACK_HEADSET | SND_JACK_BTN_0 |
259 SND_JACK_BTN_1, &mfld_jack); 257 SND_JACK_BTN_1, &mfld_jack);
260 if (ret_val) { 258 if (ret_val) {
261 pr_err("jack creation failed\n"); 259 pr_err("jack creation failed\n");
262 return ret_val; 260 return ret_val;
263 } 261 }
264 262
265 ret_val = snd_soc_jack_add_pins(&mfld_jack, 263 ret_val = snd_soc_jack_add_pins(&mfld_jack,
266 ARRAY_SIZE(mfld_jack_pins), mfld_jack_pins); 264 ARRAY_SIZE(mfld_jack_pins), mfld_jack_pins);
267 if (ret_val) { 265 if (ret_val) {
268 pr_err("adding jack pins failed\n"); 266 pr_err("adding jack pins failed\n");
269 return ret_val; 267 return ret_val;
270 } 268 }
271 ret_val = snd_soc_jack_add_zones(&mfld_jack, 269 ret_val = snd_soc_jack_add_zones(&mfld_jack,
272 ARRAY_SIZE(mfld_zones), mfld_zones); 270 ARRAY_SIZE(mfld_zones), mfld_zones);
273 if (ret_val) { 271 if (ret_val) {
274 pr_err("adding jack zones failed\n"); 272 pr_err("adding jack zones failed\n");
275 return ret_val; 273 return ret_val;
276 } 274 }
277 275
278 /* we want to check if anything is inserted at boot, 276 /* we want to check if anything is inserted at boot,
279 * so send a fake event to codec and it will read adc 277 * so send a fake event to codec and it will read adc
280 * to find if anything is there or not */ 278 * to find if anything is there or not */
281 mfld_jack_check(MFLD_JACK_INSERT); 279 mfld_jack_check(MFLD_JACK_INSERT);
282 return ret_val; 280 return ret_val;
283 } 281 }
284 282
285 struct snd_soc_dai_link mfld_msic_dailink[] = { 283 struct snd_soc_dai_link mfld_msic_dailink[] = {
286 { 284 {
287 .name = "Medfield Headset", 285 .name = "Medfield Headset",
288 .stream_name = "Headset", 286 .stream_name = "Headset",
289 .cpu_dai_name = "Headset-cpu-dai", 287 .cpu_dai_name = "Headset-cpu-dai",
290 .codec_dai_name = "SN95031 Headset", 288 .codec_dai_name = "SN95031 Headset",
291 .codec_name = "sn95031", 289 .codec_name = "sn95031",
292 .platform_name = "sst-platform", 290 .platform_name = "sst-platform",
293 .init = mfld_init, 291 .init = mfld_init,
294 }, 292 },
295 { 293 {
296 .name = "Medfield Speaker", 294 .name = "Medfield Speaker",
297 .stream_name = "Speaker", 295 .stream_name = "Speaker",
298 .cpu_dai_name = "Speaker-cpu-dai", 296 .cpu_dai_name = "Speaker-cpu-dai",
299 .codec_dai_name = "SN95031 Speaker", 297 .codec_dai_name = "SN95031 Speaker",
300 .codec_name = "sn95031", 298 .codec_name = "sn95031",
301 .platform_name = "sst-platform", 299 .platform_name = "sst-platform",
302 .init = NULL, 300 .init = NULL,
303 }, 301 },
304 { 302 {
305 .name = "Medfield Vibra", 303 .name = "Medfield Vibra",
306 .stream_name = "Vibra1", 304 .stream_name = "Vibra1",
307 .cpu_dai_name = "Vibra1-cpu-dai", 305 .cpu_dai_name = "Vibra1-cpu-dai",
308 .codec_dai_name = "SN95031 Vibra1", 306 .codec_dai_name = "SN95031 Vibra1",
309 .codec_name = "sn95031", 307 .codec_name = "sn95031",
310 .platform_name = "sst-platform", 308 .platform_name = "sst-platform",
311 .init = NULL, 309 .init = NULL,
312 }, 310 },
313 { 311 {
314 .name = "Medfield Haptics", 312 .name = "Medfield Haptics",
315 .stream_name = "Vibra2", 313 .stream_name = "Vibra2",
316 .cpu_dai_name = "Vibra2-cpu-dai", 314 .cpu_dai_name = "Vibra2-cpu-dai",
317 .codec_dai_name = "SN95031 Vibra2", 315 .codec_dai_name = "SN95031 Vibra2",
318 .codec_name = "sn95031", 316 .codec_name = "sn95031",
319 .platform_name = "sst-platform", 317 .platform_name = "sst-platform",
320 .init = NULL, 318 .init = NULL,
321 }, 319 },
322 }; 320 };
323 321
324 /* SoC card */ 322 /* SoC card */
325 static struct snd_soc_card snd_soc_card_mfld = { 323 static struct snd_soc_card snd_soc_card_mfld = {
326 .name = "medfield_audio", 324 .name = "medfield_audio",
327 .dai_link = mfld_msic_dailink, 325 .dai_link = mfld_msic_dailink,
328 .num_links = ARRAY_SIZE(mfld_msic_dailink), 326 .num_links = ARRAY_SIZE(mfld_msic_dailink),
329 }; 327 };
330 328
331 static irqreturn_t snd_mfld_jack_intr_handler(int irq, void *dev) 329 static irqreturn_t snd_mfld_jack_intr_handler(int irq, void *dev)
332 { 330 {
333 struct mfld_mc_private *mc_private = (struct mfld_mc_private *) dev; 331 struct mfld_mc_private *mc_private = (struct mfld_mc_private *) dev;
334 332
335 memcpy_fromio(&mc_private->interrupt_status, 333 memcpy_fromio(&mc_private->interrupt_status,
336 ((void *)(mc_private->int_base)), 334 ((void *)(mc_private->int_base)),
337 sizeof(u8)); 335 sizeof(u8));
338 return IRQ_WAKE_THREAD; 336 return IRQ_WAKE_THREAD;
339 } 337 }
340 338
341 static irqreturn_t snd_mfld_jack_detection(int irq, void *data) 339 static irqreturn_t snd_mfld_jack_detection(int irq, void *data)
342 { 340 {
343 struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data; 341 struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data;
344 342
345 if (mfld_jack.codec == NULL) 343 if (mfld_jack.codec == NULL)
346 return IRQ_HANDLED; 344 return IRQ_HANDLED;
347 mfld_jack_check(mc_drv_ctx->interrupt_status); 345 mfld_jack_check(mc_drv_ctx->interrupt_status);
348 346
349 return IRQ_HANDLED; 347 return IRQ_HANDLED;
350 } 348 }
351 349
352 static int __devinit snd_mfld_mc_probe(struct platform_device *pdev) 350 static int __devinit snd_mfld_mc_probe(struct platform_device *pdev)
353 { 351 {
354 int ret_val = 0, irq; 352 int ret_val = 0, irq;
355 struct mfld_mc_private *mc_drv_ctx; 353 struct mfld_mc_private *mc_drv_ctx;
356 struct resource *irq_mem; 354 struct resource *irq_mem;
357 355
358 pr_debug("snd_mfld_mc_probe called\n"); 356 pr_debug("snd_mfld_mc_probe called\n");
359 357
360 /* retrive the irq number */ 358 /* retrive the irq number */
361 irq = platform_get_irq(pdev, 0); 359 irq = platform_get_irq(pdev, 0);
362 360
363 /* audio interrupt base of SRAM location where 361 /* audio interrupt base of SRAM location where
364 * interrupts are stored by System FW */ 362 * interrupts are stored by System FW */
365 mc_drv_ctx = kzalloc(sizeof(*mc_drv_ctx), GFP_ATOMIC); 363 mc_drv_ctx = kzalloc(sizeof(*mc_drv_ctx), GFP_ATOMIC);
366 if (!mc_drv_ctx) { 364 if (!mc_drv_ctx) {
367 pr_err("allocation failed\n"); 365 pr_err("allocation failed\n");
368 return -ENOMEM; 366 return -ENOMEM;
369 } 367 }
370 368
371 irq_mem = platform_get_resource_byname( 369 irq_mem = platform_get_resource_byname(
372 pdev, IORESOURCE_MEM, "IRQ_BASE"); 370 pdev, IORESOURCE_MEM, "IRQ_BASE");
373 if (!irq_mem) { 371 if (!irq_mem) {
374 pr_err("no mem resource given\n"); 372 pr_err("no mem resource given\n");
375 ret_val = -ENODEV; 373 ret_val = -ENODEV;
376 goto unalloc; 374 goto unalloc;
377 } 375 }
378 mc_drv_ctx->int_base = ioremap_nocache(irq_mem->start, 376 mc_drv_ctx->int_base = ioremap_nocache(irq_mem->start,
379 resource_size(irq_mem)); 377 resource_size(irq_mem));
380 if (!mc_drv_ctx->int_base) { 378 if (!mc_drv_ctx->int_base) {
381 pr_err("Mapping of cache failed\n"); 379 pr_err("Mapping of cache failed\n");
382 ret_val = -ENOMEM; 380 ret_val = -ENOMEM;
383 goto unalloc; 381 goto unalloc;
384 } 382 }
385 /* register for interrupt */ 383 /* register for interrupt */
386 ret_val = request_threaded_irq(irq, snd_mfld_jack_intr_handler, 384 ret_val = request_threaded_irq(irq, snd_mfld_jack_intr_handler,
387 snd_mfld_jack_detection, 385 snd_mfld_jack_detection,
388 IRQF_SHARED, pdev->dev.driver->name, mc_drv_ctx); 386 IRQF_SHARED, pdev->dev.driver->name, mc_drv_ctx);
389 if (ret_val) { 387 if (ret_val) {
390 pr_err("cannot register IRQ\n"); 388 pr_err("cannot register IRQ\n");
391 goto unalloc; 389 goto unalloc;
392 } 390 }
393 /* register the soc card */ 391 /* register the soc card */
394 snd_soc_card_mfld.dev = &pdev->dev; 392 snd_soc_card_mfld.dev = &pdev->dev;
395 ret_val = snd_soc_register_card(&snd_soc_card_mfld); 393 ret_val = snd_soc_register_card(&snd_soc_card_mfld);
396 if (ret_val) { 394 if (ret_val) {
397 pr_debug("snd_soc_register_card failed %d\n", ret_val); 395 pr_debug("snd_soc_register_card failed %d\n", ret_val);
398 goto freeirq; 396 goto freeirq;
399 } 397 }
400 platform_set_drvdata(pdev, mc_drv_ctx); 398 platform_set_drvdata(pdev, mc_drv_ctx);
401 pr_debug("successfully exited probe\n"); 399 pr_debug("successfully exited probe\n");
402 return ret_val; 400 return ret_val;
403 401
404 freeirq: 402 freeirq:
405 free_irq(irq, mc_drv_ctx); 403 free_irq(irq, mc_drv_ctx);
406 unalloc: 404 unalloc:
407 kfree(mc_drv_ctx); 405 kfree(mc_drv_ctx);
408 return ret_val; 406 return ret_val;
409 } 407 }
410 408
411 static int __devexit snd_mfld_mc_remove(struct platform_device *pdev) 409 static int __devexit snd_mfld_mc_remove(struct platform_device *pdev)
412 { 410 {
413 struct mfld_mc_private *mc_drv_ctx = platform_get_drvdata(pdev); 411 struct mfld_mc_private *mc_drv_ctx = platform_get_drvdata(pdev);
414 412
415 pr_debug("snd_mfld_mc_remove called\n"); 413 pr_debug("snd_mfld_mc_remove called\n");
416 free_irq(platform_get_irq(pdev, 0), mc_drv_ctx); 414 free_irq(platform_get_irq(pdev, 0), mc_drv_ctx);
417 snd_soc_unregister_card(&snd_soc_card_mfld); 415 snd_soc_unregister_card(&snd_soc_card_mfld);
418 kfree(mc_drv_ctx); 416 kfree(mc_drv_ctx);
419 platform_set_drvdata(pdev, NULL); 417 platform_set_drvdata(pdev, NULL);
420 return 0; 418 return 0;
421 } 419 }
422 420
423 static struct platform_driver snd_mfld_mc_driver = { 421 static struct platform_driver snd_mfld_mc_driver = {
424 .driver = { 422 .driver = {
425 .owner = THIS_MODULE, 423 .owner = THIS_MODULE,
426 .name = "msic_audio", 424 .name = "msic_audio",
427 }, 425 },
428 .probe = snd_mfld_mc_probe, 426 .probe = snd_mfld_mc_probe,
429 .remove = __devexit_p(snd_mfld_mc_remove), 427 .remove = __devexit_p(snd_mfld_mc_remove),
430 }; 428 };
431 429
432 static int __init snd_mfld_driver_init(void) 430 static int __init snd_mfld_driver_init(void)
433 { 431 {
434 pr_debug("snd_mfld_driver_init called\n"); 432 pr_debug("snd_mfld_driver_init called\n");
435 return platform_driver_register(&snd_mfld_mc_driver); 433 return platform_driver_register(&snd_mfld_mc_driver);
436 } 434 }
437 module_init(snd_mfld_driver_init); 435 module_init(snd_mfld_driver_init);
438 436
439 static void __exit snd_mfld_driver_exit(void) 437 static void __exit snd_mfld_driver_exit(void)
440 { 438 {
441 pr_debug("snd_mfld_driver_exit called\n"); 439 pr_debug("snd_mfld_driver_exit called\n");
442 platform_driver_unregister(&snd_mfld_mc_driver); 440 platform_driver_unregister(&snd_mfld_mc_driver);
443 } 441 }
444 module_exit(snd_mfld_driver_exit); 442 module_exit(snd_mfld_driver_exit);
445 443
446 MODULE_DESCRIPTION("ASoC Intel(R) MID Machine driver"); 444 MODULE_DESCRIPTION("ASoC Intel(R) MID Machine driver");
447 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); 445 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
448 MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); 446 MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
449 MODULE_LICENSE("GPL v2"); 447 MODULE_LICENSE("GPL v2");
450 MODULE_ALIAS("platform:msic-audio"); 448 MODULE_ALIAS("platform:msic-audio");
451 449
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 26
27 #include <asm/mach-types.h> 27 #include <asm/mach-types.h>
28 #include <mach/corgi.h> 28 #include <mach/corgi.h>
29 #include <mach/audio.h> 29 #include <mach/audio.h>
30 30
31 #include "../codecs/wm8731.h" 31 #include "../codecs/wm8731.h"
32 #include "pxa2xx-i2s.h" 32 #include "pxa2xx-i2s.h"
33 33
34 #define CORGI_HP 0 34 #define CORGI_HP 0
35 #define CORGI_MIC 1 35 #define CORGI_MIC 1
36 #define CORGI_LINE 2 36 #define CORGI_LINE 2
37 #define CORGI_HEADSET 3 37 #define CORGI_HEADSET 3
38 #define CORGI_HP_OFF 4 38 #define CORGI_HP_OFF 4
39 #define CORGI_SPK_ON 0 39 #define CORGI_SPK_ON 0
40 #define CORGI_SPK_OFF 1 40 #define CORGI_SPK_OFF 1
41 41
42 /* audio clock in Hz - rounded from 12.235MHz */ 42 /* audio clock in Hz - rounded from 12.235MHz */
43 #define CORGI_AUDIO_CLOCK 12288000 43 #define CORGI_AUDIO_CLOCK 12288000
44 44
45 static int corgi_jack_func; 45 static int corgi_jack_func;
46 static int corgi_spk_func; 46 static int corgi_spk_func;
47 47
48 static void corgi_ext_control(struct snd_soc_codec *codec) 48 static void corgi_ext_control(struct snd_soc_codec *codec)
49 { 49 {
50 struct snd_soc_dapm_context *dapm = &codec->dapm; 50 struct snd_soc_dapm_context *dapm = &codec->dapm;
51 51
52 /* set up jack connection */ 52 /* set up jack connection */
53 switch (corgi_jack_func) { 53 switch (corgi_jack_func) {
54 case CORGI_HP: 54 case CORGI_HP:
55 /* set = unmute headphone */ 55 /* set = unmute headphone */
56 gpio_set_value(CORGI_GPIO_MUTE_L, 1); 56 gpio_set_value(CORGI_GPIO_MUTE_L, 1);
57 gpio_set_value(CORGI_GPIO_MUTE_R, 1); 57 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
58 snd_soc_dapm_disable_pin(dapm, "Mic Jack"); 58 snd_soc_dapm_disable_pin(dapm, "Mic Jack");
59 snd_soc_dapm_disable_pin(dapm, "Line Jack"); 59 snd_soc_dapm_disable_pin(dapm, "Line Jack");
60 snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); 60 snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
61 snd_soc_dapm_disable_pin(dapm, "Headset Jack"); 61 snd_soc_dapm_disable_pin(dapm, "Headset Jack");
62 break; 62 break;
63 case CORGI_MIC: 63 case CORGI_MIC:
64 /* reset = mute headphone */ 64 /* reset = mute headphone */
65 gpio_set_value(CORGI_GPIO_MUTE_L, 0); 65 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
66 gpio_set_value(CORGI_GPIO_MUTE_R, 0); 66 gpio_set_value(CORGI_GPIO_MUTE_R, 0);
67 snd_soc_dapm_enable_pin(dapm, "Mic Jack"); 67 snd_soc_dapm_enable_pin(dapm, "Mic Jack");
68 snd_soc_dapm_disable_pin(dapm, "Line Jack"); 68 snd_soc_dapm_disable_pin(dapm, "Line Jack");
69 snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); 69 snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
70 snd_soc_dapm_disable_pin(dapm, "Headset Jack"); 70 snd_soc_dapm_disable_pin(dapm, "Headset Jack");
71 break; 71 break;
72 case CORGI_LINE: 72 case CORGI_LINE:
73 gpio_set_value(CORGI_GPIO_MUTE_L, 0); 73 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
74 gpio_set_value(CORGI_GPIO_MUTE_R, 0); 74 gpio_set_value(CORGI_GPIO_MUTE_R, 0);
75 snd_soc_dapm_disable_pin(dapm, "Mic Jack"); 75 snd_soc_dapm_disable_pin(dapm, "Mic Jack");
76 snd_soc_dapm_enable_pin(dapm, "Line Jack"); 76 snd_soc_dapm_enable_pin(dapm, "Line Jack");
77 snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); 77 snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
78 snd_soc_dapm_disable_pin(dapm, "Headset Jack"); 78 snd_soc_dapm_disable_pin(dapm, "Headset Jack");
79 break; 79 break;
80 case CORGI_HEADSET: 80 case CORGI_HEADSET:
81 gpio_set_value(CORGI_GPIO_MUTE_L, 0); 81 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
82 gpio_set_value(CORGI_GPIO_MUTE_R, 1); 82 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
83 snd_soc_dapm_enable_pin(dapm, "Mic Jack"); 83 snd_soc_dapm_enable_pin(dapm, "Mic Jack");
84 snd_soc_dapm_disable_pin(dapm, "Line Jack"); 84 snd_soc_dapm_disable_pin(dapm, "Line Jack");
85 snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); 85 snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
86 snd_soc_dapm_enable_pin(dapm, "Headset Jack"); 86 snd_soc_dapm_enable_pin(dapm, "Headset Jack");
87 break; 87 break;
88 } 88 }
89 89
90 if (corgi_spk_func == CORGI_SPK_ON) 90 if (corgi_spk_func == CORGI_SPK_ON)
91 snd_soc_dapm_enable_pin(dapm, "Ext Spk"); 91 snd_soc_dapm_enable_pin(dapm, "Ext Spk");
92 else 92 else
93 snd_soc_dapm_disable_pin(dapm, "Ext Spk"); 93 snd_soc_dapm_disable_pin(dapm, "Ext Spk");
94 94
95 /* signal a DAPM event */ 95 /* signal a DAPM event */
96 snd_soc_dapm_sync(dapm); 96 snd_soc_dapm_sync(dapm);
97 } 97 }
98 98
99 static int corgi_startup(struct snd_pcm_substream *substream) 99 static int corgi_startup(struct snd_pcm_substream *substream)
100 { 100 {
101 struct snd_soc_pcm_runtime *rtd = substream->private_data; 101 struct snd_soc_pcm_runtime *rtd = substream->private_data;
102 struct snd_soc_codec *codec = rtd->codec; 102 struct snd_soc_codec *codec = rtd->codec;
103 103
104 mutex_lock(&codec->mutex); 104 mutex_lock(&codec->mutex);
105 105
106 /* check the jack status at stream startup */ 106 /* check the jack status at stream startup */
107 corgi_ext_control(codec); 107 corgi_ext_control(codec);
108 108
109 mutex_unlock(&codec->mutex); 109 mutex_unlock(&codec->mutex);
110 110
111 return 0; 111 return 0;
112 } 112 }
113 113
114 /* we need to unmute the HP at shutdown as the mute burns power on corgi */ 114 /* we need to unmute the HP at shutdown as the mute burns power on corgi */
115 static void corgi_shutdown(struct snd_pcm_substream *substream) 115 static void corgi_shutdown(struct snd_pcm_substream *substream)
116 { 116 {
117 /* set = unmute headphone */ 117 /* set = unmute headphone */
118 gpio_set_value(CORGI_GPIO_MUTE_L, 1); 118 gpio_set_value(CORGI_GPIO_MUTE_L, 1);
119 gpio_set_value(CORGI_GPIO_MUTE_R, 1); 119 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
120 } 120 }
121 121
122 static int corgi_hw_params(struct snd_pcm_substream *substream, 122 static int corgi_hw_params(struct snd_pcm_substream *substream,
123 struct snd_pcm_hw_params *params) 123 struct snd_pcm_hw_params *params)
124 { 124 {
125 struct snd_soc_pcm_runtime *rtd = substream->private_data; 125 struct snd_soc_pcm_runtime *rtd = substream->private_data;
126 struct snd_soc_dai *codec_dai = rtd->codec_dai; 126 struct snd_soc_dai *codec_dai = rtd->codec_dai;
127 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 127 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
128 unsigned int clk = 0; 128 unsigned int clk = 0;
129 int ret = 0; 129 int ret = 0;
130 130
131 switch (params_rate(params)) { 131 switch (params_rate(params)) {
132 case 8000: 132 case 8000:
133 case 16000: 133 case 16000:
134 case 48000: 134 case 48000:
135 case 96000: 135 case 96000:
136 clk = 12288000; 136 clk = 12288000;
137 break; 137 break;
138 case 11025: 138 case 11025:
139 case 22050: 139 case 22050:
140 case 44100: 140 case 44100:
141 clk = 11289600; 141 clk = 11289600;
142 break; 142 break;
143 } 143 }
144 144
145 /* set codec DAI configuration */ 145 /* set codec DAI configuration */
146 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 146 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
147 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 147 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
148 if (ret < 0) 148 if (ret < 0)
149 return ret; 149 return ret;
150 150
151 /* set cpu DAI configuration */ 151 /* set cpu DAI configuration */
152 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 152 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
153 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 153 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
154 if (ret < 0) 154 if (ret < 0)
155 return ret; 155 return ret;
156 156
157 /* set the codec system clock for DAC and ADC */ 157 /* set the codec system clock for DAC and ADC */
158 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk, 158 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk,
159 SND_SOC_CLOCK_IN); 159 SND_SOC_CLOCK_IN);
160 if (ret < 0) 160 if (ret < 0)
161 return ret; 161 return ret;
162 162
163 /* set the I2S system clock as input (unused) */ 163 /* set the I2S system clock as input (unused) */
164 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0, 164 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
165 SND_SOC_CLOCK_IN); 165 SND_SOC_CLOCK_IN);
166 if (ret < 0) 166 if (ret < 0)
167 return ret; 167 return ret;
168 168
169 return 0; 169 return 0;
170 } 170 }
171 171
172 static struct snd_soc_ops corgi_ops = { 172 static struct snd_soc_ops corgi_ops = {
173 .startup = corgi_startup, 173 .startup = corgi_startup,
174 .hw_params = corgi_hw_params, 174 .hw_params = corgi_hw_params,
175 .shutdown = corgi_shutdown, 175 .shutdown = corgi_shutdown,
176 }; 176 };
177 177
178 static int corgi_get_jack(struct snd_kcontrol *kcontrol, 178 static int corgi_get_jack(struct snd_kcontrol *kcontrol,
179 struct snd_ctl_elem_value *ucontrol) 179 struct snd_ctl_elem_value *ucontrol)
180 { 180 {
181 ucontrol->value.integer.value[0] = corgi_jack_func; 181 ucontrol->value.integer.value[0] = corgi_jack_func;
182 return 0; 182 return 0;
183 } 183 }
184 184
185 static int corgi_set_jack(struct snd_kcontrol *kcontrol, 185 static int corgi_set_jack(struct snd_kcontrol *kcontrol,
186 struct snd_ctl_elem_value *ucontrol) 186 struct snd_ctl_elem_value *ucontrol)
187 { 187 {
188 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 188 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
189 189
190 if (corgi_jack_func == ucontrol->value.integer.value[0]) 190 if (corgi_jack_func == ucontrol->value.integer.value[0])
191 return 0; 191 return 0;
192 192
193 corgi_jack_func = ucontrol->value.integer.value[0]; 193 corgi_jack_func = ucontrol->value.integer.value[0];
194 corgi_ext_control(codec); 194 corgi_ext_control(codec);
195 return 1; 195 return 1;
196 } 196 }
197 197
198 static int corgi_get_spk(struct snd_kcontrol *kcontrol, 198 static int corgi_get_spk(struct snd_kcontrol *kcontrol,
199 struct snd_ctl_elem_value *ucontrol) 199 struct snd_ctl_elem_value *ucontrol)
200 { 200 {
201 ucontrol->value.integer.value[0] = corgi_spk_func; 201 ucontrol->value.integer.value[0] = corgi_spk_func;
202 return 0; 202 return 0;
203 } 203 }
204 204
205 static int corgi_set_spk(struct snd_kcontrol *kcontrol, 205 static int corgi_set_spk(struct snd_kcontrol *kcontrol,
206 struct snd_ctl_elem_value *ucontrol) 206 struct snd_ctl_elem_value *ucontrol)
207 { 207 {
208 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 208 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
209 209
210 if (corgi_spk_func == ucontrol->value.integer.value[0]) 210 if (corgi_spk_func == ucontrol->value.integer.value[0])
211 return 0; 211 return 0;
212 212
213 corgi_spk_func = ucontrol->value.integer.value[0]; 213 corgi_spk_func = ucontrol->value.integer.value[0];
214 corgi_ext_control(codec); 214 corgi_ext_control(codec);
215 return 1; 215 return 1;
216 } 216 }
217 217
218 static int corgi_amp_event(struct snd_soc_dapm_widget *w, 218 static int corgi_amp_event(struct snd_soc_dapm_widget *w,
219 struct snd_kcontrol *k, int event) 219 struct snd_kcontrol *k, int event)
220 { 220 {
221 gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event)); 221 gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event));
222 return 0; 222 return 0;
223 } 223 }
224 224
225 static int corgi_mic_event(struct snd_soc_dapm_widget *w, 225 static int corgi_mic_event(struct snd_soc_dapm_widget *w,
226 struct snd_kcontrol *k, int event) 226 struct snd_kcontrol *k, int event)
227 { 227 {
228 gpio_set_value(CORGI_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event)); 228 gpio_set_value(CORGI_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event));
229 return 0; 229 return 0;
230 } 230 }
231 231
232 /* corgi machine dapm widgets */ 232 /* corgi machine dapm widgets */
233 static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { 233 static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
234 SND_SOC_DAPM_HP("Headphone Jack", NULL), 234 SND_SOC_DAPM_HP("Headphone Jack", NULL),
235 SND_SOC_DAPM_MIC("Mic Jack", corgi_mic_event), 235 SND_SOC_DAPM_MIC("Mic Jack", corgi_mic_event),
236 SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event), 236 SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event),
237 SND_SOC_DAPM_LINE("Line Jack", NULL), 237 SND_SOC_DAPM_LINE("Line Jack", NULL),
238 SND_SOC_DAPM_HP("Headset Jack", NULL), 238 SND_SOC_DAPM_HP("Headset Jack", NULL),
239 }; 239 };
240 240
241 /* Corgi machine audio map (connections to the codec pins) */ 241 /* Corgi machine audio map (connections to the codec pins) */
242 static const struct snd_soc_dapm_route audio_map[] = { 242 static const struct snd_soc_dapm_route audio_map[] = {
243 243
244 /* headset Jack - in = micin, out = LHPOUT*/ 244 /* headset Jack - in = micin, out = LHPOUT*/
245 {"Headset Jack", NULL, "LHPOUT"}, 245 {"Headset Jack", NULL, "LHPOUT"},
246 246
247 /* headphone connected to LHPOUT1, RHPOUT1 */ 247 /* headphone connected to LHPOUT1, RHPOUT1 */
248 {"Headphone Jack", NULL, "LHPOUT"}, 248 {"Headphone Jack", NULL, "LHPOUT"},
249 {"Headphone Jack", NULL, "RHPOUT"}, 249 {"Headphone Jack", NULL, "RHPOUT"},
250 250
251 /* speaker connected to LOUT, ROUT */ 251 /* speaker connected to LOUT, ROUT */
252 {"Ext Spk", NULL, "ROUT"}, 252 {"Ext Spk", NULL, "ROUT"},
253 {"Ext Spk", NULL, "LOUT"}, 253 {"Ext Spk", NULL, "LOUT"},
254 254
255 /* mic is connected to MICIN (via right channel of headphone jack) */ 255 /* mic is connected to MICIN (via right channel of headphone jack) */
256 {"MICIN", NULL, "Mic Jack"}, 256 {"MICIN", NULL, "Mic Jack"},
257 257
258 /* Same as the above but no mic bias for line signals */ 258 /* Same as the above but no mic bias for line signals */
259 {"MICIN", NULL, "Line Jack"}, 259 {"MICIN", NULL, "Line Jack"},
260 }; 260 };
261 261
262 static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", 262 static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
263 "Off"}; 263 "Off"};
264 static const char *spk_function[] = {"On", "Off"}; 264 static const char *spk_function[] = {"On", "Off"};
265 static const struct soc_enum corgi_enum[] = { 265 static const struct soc_enum corgi_enum[] = {
266 SOC_ENUM_SINGLE_EXT(5, jack_function), 266 SOC_ENUM_SINGLE_EXT(5, jack_function),
267 SOC_ENUM_SINGLE_EXT(2, spk_function), 267 SOC_ENUM_SINGLE_EXT(2, spk_function),
268 }; 268 };
269 269
270 static const struct snd_kcontrol_new wm8731_corgi_controls[] = { 270 static const struct snd_kcontrol_new wm8731_corgi_controls[] = {
271 SOC_ENUM_EXT("Jack Function", corgi_enum[0], corgi_get_jack, 271 SOC_ENUM_EXT("Jack Function", corgi_enum[0], corgi_get_jack,
272 corgi_set_jack), 272 corgi_set_jack),
273 SOC_ENUM_EXT("Speaker Function", corgi_enum[1], corgi_get_spk, 273 SOC_ENUM_EXT("Speaker Function", corgi_enum[1], corgi_get_spk,
274 corgi_set_spk), 274 corgi_set_spk),
275 }; 275 };
276 276
277 /* 277 /*
278 * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device 278 * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
279 */ 279 */
280 static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd) 280 static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd)
281 { 281 {
282 struct snd_soc_codec *codec = rtd->codec; 282 struct snd_soc_codec *codec = rtd->codec;
283 struct snd_soc_dapm_context *dapm = &codec->dapm; 283 struct snd_soc_dapm_context *dapm = &codec->dapm;
284 int err; 284 int err;
285 285
286 snd_soc_dapm_nc_pin(dapm, "LLINEIN"); 286 snd_soc_dapm_nc_pin(dapm, "LLINEIN");
287 snd_soc_dapm_nc_pin(dapm, "RLINEIN"); 287 snd_soc_dapm_nc_pin(dapm, "RLINEIN");
288 288
289 /* Add corgi specific controls */ 289 /* Add corgi specific controls */
290 err = snd_soc_add_controls(codec, wm8731_corgi_controls, 290 err = snd_soc_add_controls(codec, wm8731_corgi_controls,
291 ARRAY_SIZE(wm8731_corgi_controls)); 291 ARRAY_SIZE(wm8731_corgi_controls));
292 if (err < 0) 292 if (err < 0)
293 return err; 293 return err;
294 294
295 /* Add corgi specific widgets */ 295 /* Add corgi specific widgets */
296 snd_soc_dapm_new_controls(dapm, wm8731_dapm_widgets, 296 snd_soc_dapm_new_controls(dapm, wm8731_dapm_widgets,
297 ARRAY_SIZE(wm8731_dapm_widgets)); 297 ARRAY_SIZE(wm8731_dapm_widgets));
298 298
299 /* Set up corgi specific audio path audio_map */ 299 /* Set up corgi specific audio path audio_map */
300 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 300 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
301 301
302 snd_soc_dapm_sync(dapm);
303 return 0; 302 return 0;
304 } 303 }
305 304
306 /* corgi digital audio interface glue - connects codec <--> CPU */ 305 /* corgi digital audio interface glue - connects codec <--> CPU */
307 static struct snd_soc_dai_link corgi_dai = { 306 static struct snd_soc_dai_link corgi_dai = {
308 .name = "WM8731", 307 .name = "WM8731",
309 .stream_name = "WM8731", 308 .stream_name = "WM8731",
310 .cpu_dai_name = "pxa2xx-i2s", 309 .cpu_dai_name = "pxa2xx-i2s",
311 .codec_dai_name = "wm8731-hifi", 310 .codec_dai_name = "wm8731-hifi",
312 .platform_name = "pxa-pcm-audio", 311 .platform_name = "pxa-pcm-audio",
313 .codec_name = "wm8731.0-001b", 312 .codec_name = "wm8731.0-001b",
314 .init = corgi_wm8731_init, 313 .init = corgi_wm8731_init,
315 .ops = &corgi_ops, 314 .ops = &corgi_ops,
316 }; 315 };
317 316
318 /* corgi audio machine driver */ 317 /* corgi audio machine driver */
319 static struct snd_soc_card snd_soc_corgi = { 318 static struct snd_soc_card snd_soc_corgi = {
320 .name = "Corgi", 319 .name = "Corgi",
321 .dai_link = &corgi_dai, 320 .dai_link = &corgi_dai,
322 .num_links = 1, 321 .num_links = 1,
323 }; 322 };
324 323
325 static struct platform_device *corgi_snd_device; 324 static struct platform_device *corgi_snd_device;
326 325
327 static int __init corgi_init(void) 326 static int __init corgi_init(void)
328 { 327 {
329 int ret; 328 int ret;
330 329
331 if (!(machine_is_corgi() || machine_is_shepherd() || 330 if (!(machine_is_corgi() || machine_is_shepherd() ||
332 machine_is_husky())) 331 machine_is_husky()))
333 return -ENODEV; 332 return -ENODEV;
334 333
335 corgi_snd_device = platform_device_alloc("soc-audio", -1); 334 corgi_snd_device = platform_device_alloc("soc-audio", -1);
336 if (!corgi_snd_device) 335 if (!corgi_snd_device)
337 return -ENOMEM; 336 return -ENOMEM;
338 337
339 platform_set_drvdata(corgi_snd_device, &snd_soc_corgi); 338 platform_set_drvdata(corgi_snd_device, &snd_soc_corgi);
340 ret = platform_device_add(corgi_snd_device); 339 ret = platform_device_add(corgi_snd_device);
341 340
342 if (ret) 341 if (ret)
343 platform_device_put(corgi_snd_device); 342 platform_device_put(corgi_snd_device);
344 343
345 return ret; 344 return ret;
346 } 345 }
347 346
348 static void __exit corgi_exit(void) 347 static void __exit corgi_exit(void)
349 { 348 {
350 platform_device_unregister(corgi_snd_device); 349 platform_device_unregister(corgi_snd_device);
351 } 350 }
352 351
353 module_init(corgi_init); 352 module_init(corgi_init);
354 module_exit(corgi_exit); 353 module_exit(corgi_exit);
355 354
356 /* Module information */ 355 /* Module information */
357 MODULE_AUTHOR("Richard Purdie"); 356 MODULE_AUTHOR("Richard Purdie");
358 MODULE_DESCRIPTION("ALSA SoC Corgi"); 357 MODULE_DESCRIPTION("ALSA SoC Corgi");
359 MODULE_LICENSE("GPL"); 358 MODULE_LICENSE("GPL");
360 359
sound/soc/pxa/e740_wm9705.c
1 /* 1 /*
2 * e740-wm9705.c -- SoC audio for e740 2 * e740-wm9705.c -- SoC audio for e740
3 * 3 *
4 * Copyright 2007 (c) Ian Molton <spyro@f2s.com> 4 * Copyright 2007 (c) Ian Molton <spyro@f2s.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; version 2 ONLY. 8 * Free Software Foundation; version 2 ONLY.
9 * 9 *
10 */ 10 */
11 11
12 #include <linux/module.h> 12 #include <linux/module.h>
13 #include <linux/moduleparam.h> 13 #include <linux/moduleparam.h>
14 #include <linux/gpio.h> 14 #include <linux/gpio.h>
15 15
16 #include <sound/core.h> 16 #include <sound/core.h>
17 #include <sound/pcm.h> 17 #include <sound/pcm.h>
18 #include <sound/soc.h> 18 #include <sound/soc.h>
19 19
20 #include <mach/audio.h> 20 #include <mach/audio.h>
21 #include <mach/eseries-gpio.h> 21 #include <mach/eseries-gpio.h>
22 22
23 #include <asm/mach-types.h> 23 #include <asm/mach-types.h>
24 24
25 #include "../codecs/wm9705.h" 25 #include "../codecs/wm9705.h"
26 #include "pxa2xx-ac97.h" 26 #include "pxa2xx-ac97.h"
27 27
28 28
29 #define E740_AUDIO_OUT 1 29 #define E740_AUDIO_OUT 1
30 #define E740_AUDIO_IN 2 30 #define E740_AUDIO_IN 2
31 31
32 static int e740_audio_power; 32 static int e740_audio_power;
33 33
34 static void e740_sync_audio_power(int status) 34 static void e740_sync_audio_power(int status)
35 { 35 {
36 gpio_set_value(GPIO_E740_WM9705_nAVDD2, !status); 36 gpio_set_value(GPIO_E740_WM9705_nAVDD2, !status);
37 gpio_set_value(GPIO_E740_AMP_ON, (status & E740_AUDIO_OUT) ? 1 : 0); 37 gpio_set_value(GPIO_E740_AMP_ON, (status & E740_AUDIO_OUT) ? 1 : 0);
38 gpio_set_value(GPIO_E740_MIC_ON, (status & E740_AUDIO_IN) ? 1 : 0); 38 gpio_set_value(GPIO_E740_MIC_ON, (status & E740_AUDIO_IN) ? 1 : 0);
39 } 39 }
40 40
41 static int e740_mic_amp_event(struct snd_soc_dapm_widget *w, 41 static int e740_mic_amp_event(struct snd_soc_dapm_widget *w,
42 struct snd_kcontrol *kcontrol, int event) 42 struct snd_kcontrol *kcontrol, int event)
43 { 43 {
44 if (event & SND_SOC_DAPM_PRE_PMU) 44 if (event & SND_SOC_DAPM_PRE_PMU)
45 e740_audio_power |= E740_AUDIO_IN; 45 e740_audio_power |= E740_AUDIO_IN;
46 else if (event & SND_SOC_DAPM_POST_PMD) 46 else if (event & SND_SOC_DAPM_POST_PMD)
47 e740_audio_power &= ~E740_AUDIO_IN; 47 e740_audio_power &= ~E740_AUDIO_IN;
48 48
49 e740_sync_audio_power(e740_audio_power); 49 e740_sync_audio_power(e740_audio_power);
50 50
51 return 0; 51 return 0;
52 } 52 }
53 53
54 static int e740_output_amp_event(struct snd_soc_dapm_widget *w, 54 static int e740_output_amp_event(struct snd_soc_dapm_widget *w,
55 struct snd_kcontrol *kcontrol, int event) 55 struct snd_kcontrol *kcontrol, int event)
56 { 56 {
57 if (event & SND_SOC_DAPM_PRE_PMU) 57 if (event & SND_SOC_DAPM_PRE_PMU)
58 e740_audio_power |= E740_AUDIO_OUT; 58 e740_audio_power |= E740_AUDIO_OUT;
59 else if (event & SND_SOC_DAPM_POST_PMD) 59 else if (event & SND_SOC_DAPM_POST_PMD)
60 e740_audio_power &= ~E740_AUDIO_OUT; 60 e740_audio_power &= ~E740_AUDIO_OUT;
61 61
62 e740_sync_audio_power(e740_audio_power); 62 e740_sync_audio_power(e740_audio_power);
63 63
64 return 0; 64 return 0;
65 } 65 }
66 66
67 static const struct snd_soc_dapm_widget e740_dapm_widgets[] = { 67 static const struct snd_soc_dapm_widget e740_dapm_widgets[] = {
68 SND_SOC_DAPM_HP("Headphone Jack", NULL), 68 SND_SOC_DAPM_HP("Headphone Jack", NULL),
69 SND_SOC_DAPM_SPK("Speaker", NULL), 69 SND_SOC_DAPM_SPK("Speaker", NULL),
70 SND_SOC_DAPM_MIC("Mic (Internal)", NULL), 70 SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
71 SND_SOC_DAPM_PGA_E("Output Amp", SND_SOC_NOPM, 0, 0, NULL, 0, 71 SND_SOC_DAPM_PGA_E("Output Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
72 e740_output_amp_event, SND_SOC_DAPM_PRE_PMU | 72 e740_output_amp_event, SND_SOC_DAPM_PRE_PMU |
73 SND_SOC_DAPM_POST_PMD), 73 SND_SOC_DAPM_POST_PMD),
74 SND_SOC_DAPM_PGA_E("Mic Amp", SND_SOC_NOPM, 0, 0, NULL, 0, 74 SND_SOC_DAPM_PGA_E("Mic Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
75 e740_mic_amp_event, SND_SOC_DAPM_PRE_PMU | 75 e740_mic_amp_event, SND_SOC_DAPM_PRE_PMU |
76 SND_SOC_DAPM_POST_PMD), 76 SND_SOC_DAPM_POST_PMD),
77 }; 77 };
78 78
79 static const struct snd_soc_dapm_route audio_map[] = { 79 static const struct snd_soc_dapm_route audio_map[] = {
80 {"Output Amp", NULL, "LOUT"}, 80 {"Output Amp", NULL, "LOUT"},
81 {"Output Amp", NULL, "ROUT"}, 81 {"Output Amp", NULL, "ROUT"},
82 {"Output Amp", NULL, "MONOOUT"}, 82 {"Output Amp", NULL, "MONOOUT"},
83 83
84 {"Speaker", NULL, "Output Amp"}, 84 {"Speaker", NULL, "Output Amp"},
85 {"Headphone Jack", NULL, "Output Amp"}, 85 {"Headphone Jack", NULL, "Output Amp"},
86 86
87 {"MIC1", NULL, "Mic Amp"}, 87 {"MIC1", NULL, "Mic Amp"},
88 {"Mic Amp", NULL, "Mic (Internal)"}, 88 {"Mic Amp", NULL, "Mic (Internal)"},
89 }; 89 };
90 90
91 static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd) 91 static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd)
92 { 92 {
93 struct snd_soc_codec *codec = rtd->codec; 93 struct snd_soc_codec *codec = rtd->codec;
94 struct snd_soc_dapm_context *dapm = &codec->dapm; 94 struct snd_soc_dapm_context *dapm = &codec->dapm;
95 95
96 snd_soc_dapm_nc_pin(dapm, "HPOUTL"); 96 snd_soc_dapm_nc_pin(dapm, "HPOUTL");
97 snd_soc_dapm_nc_pin(dapm, "HPOUTR"); 97 snd_soc_dapm_nc_pin(dapm, "HPOUTR");
98 snd_soc_dapm_nc_pin(dapm, "PHONE"); 98 snd_soc_dapm_nc_pin(dapm, "PHONE");
99 snd_soc_dapm_nc_pin(dapm, "LINEINL"); 99 snd_soc_dapm_nc_pin(dapm, "LINEINL");
100 snd_soc_dapm_nc_pin(dapm, "LINEINR"); 100 snd_soc_dapm_nc_pin(dapm, "LINEINR");
101 snd_soc_dapm_nc_pin(dapm, "CDINL"); 101 snd_soc_dapm_nc_pin(dapm, "CDINL");
102 snd_soc_dapm_nc_pin(dapm, "CDINR"); 102 snd_soc_dapm_nc_pin(dapm, "CDINR");
103 snd_soc_dapm_nc_pin(dapm, "PCBEEP"); 103 snd_soc_dapm_nc_pin(dapm, "PCBEEP");
104 snd_soc_dapm_nc_pin(dapm, "MIC2"); 104 snd_soc_dapm_nc_pin(dapm, "MIC2");
105 105
106 snd_soc_dapm_new_controls(dapm, e740_dapm_widgets, 106 snd_soc_dapm_new_controls(dapm, e740_dapm_widgets,
107 ARRAY_SIZE(e740_dapm_widgets)); 107 ARRAY_SIZE(e740_dapm_widgets));
108 108
109 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 109 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
110 110
111 snd_soc_dapm_sync(dapm);
112
113 return 0; 111 return 0;
114 } 112 }
115 113
116 static struct snd_soc_dai_link e740_dai[] = { 114 static struct snd_soc_dai_link e740_dai[] = {
117 { 115 {
118 .name = "AC97", 116 .name = "AC97",
119 .stream_name = "AC97 HiFi", 117 .stream_name = "AC97 HiFi",
120 .cpu_dai_name = "pxa2xx-ac97", 118 .cpu_dai_name = "pxa2xx-ac97",
121 .codec_dai_name = "wm9705-hifi", 119 .codec_dai_name = "wm9705-hifi",
122 .platform_name = "pxa-pcm-audio", 120 .platform_name = "pxa-pcm-audio",
123 .codec_name = "wm9705-codec", 121 .codec_name = "wm9705-codec",
124 .init = e740_ac97_init, 122 .init = e740_ac97_init,
125 }, 123 },
126 { 124 {
127 .name = "AC97 Aux", 125 .name = "AC97 Aux",
128 .stream_name = "AC97 Aux", 126 .stream_name = "AC97 Aux",
129 .cpu_dai_name = "pxa2xx-ac97-aux", 127 .cpu_dai_name = "pxa2xx-ac97-aux",
130 .codec_dai_name = "wm9705-aux", 128 .codec_dai_name = "wm9705-aux",
131 .platform_name = "pxa-pcm-audio", 129 .platform_name = "pxa-pcm-audio",
132 .codec_name = "wm9705-codec", 130 .codec_name = "wm9705-codec",
133 }, 131 },
134 }; 132 };
135 133
136 static struct snd_soc_card e740 = { 134 static struct snd_soc_card e740 = {
137 .name = "Toshiba e740", 135 .name = "Toshiba e740",
138 .dai_link = e740_dai, 136 .dai_link = e740_dai,
139 .num_links = ARRAY_SIZE(e740_dai), 137 .num_links = ARRAY_SIZE(e740_dai),
140 }; 138 };
141 139
142 static struct platform_device *e740_snd_device; 140 static struct platform_device *e740_snd_device;
143 141
144 static int __init e740_init(void) 142 static int __init e740_init(void)
145 { 143 {
146 int ret; 144 int ret;
147 145
148 if (!machine_is_e740()) 146 if (!machine_is_e740())
149 return -ENODEV; 147 return -ENODEV;
150 148
151 ret = gpio_request(GPIO_E740_MIC_ON, "Mic amp"); 149 ret = gpio_request(GPIO_E740_MIC_ON, "Mic amp");
152 if (ret) 150 if (ret)
153 return ret; 151 return ret;
154 152
155 ret = gpio_request(GPIO_E740_AMP_ON, "Output amp"); 153 ret = gpio_request(GPIO_E740_AMP_ON, "Output amp");
156 if (ret) 154 if (ret)
157 goto free_mic_amp_gpio; 155 goto free_mic_amp_gpio;
158 156
159 ret = gpio_request(GPIO_E740_WM9705_nAVDD2, "Audio power"); 157 ret = gpio_request(GPIO_E740_WM9705_nAVDD2, "Audio power");
160 if (ret) 158 if (ret)
161 goto free_op_amp_gpio; 159 goto free_op_amp_gpio;
162 160
163 /* Disable audio */ 161 /* Disable audio */
164 ret = gpio_direction_output(GPIO_E740_MIC_ON, 0); 162 ret = gpio_direction_output(GPIO_E740_MIC_ON, 0);
165 if (ret) 163 if (ret)
166 goto free_apwr_gpio; 164 goto free_apwr_gpio;
167 ret = gpio_direction_output(GPIO_E740_AMP_ON, 0); 165 ret = gpio_direction_output(GPIO_E740_AMP_ON, 0);
168 if (ret) 166 if (ret)
169 goto free_apwr_gpio; 167 goto free_apwr_gpio;
170 ret = gpio_direction_output(GPIO_E740_WM9705_nAVDD2, 1); 168 ret = gpio_direction_output(GPIO_E740_WM9705_nAVDD2, 1);
171 if (ret) 169 if (ret)
172 goto free_apwr_gpio; 170 goto free_apwr_gpio;
173 171
174 e740_snd_device = platform_device_alloc("soc-audio", -1); 172 e740_snd_device = platform_device_alloc("soc-audio", -1);
175 if (!e740_snd_device) { 173 if (!e740_snd_device) {
176 ret = -ENOMEM; 174 ret = -ENOMEM;
177 goto free_apwr_gpio; 175 goto free_apwr_gpio;
178 } 176 }
179 177
180 platform_set_drvdata(e740_snd_device, &e740); 178 platform_set_drvdata(e740_snd_device, &e740);
181 ret = platform_device_add(e740_snd_device); 179 ret = platform_device_add(e740_snd_device);
182 180
183 if (!ret) 181 if (!ret)
184 return 0; 182 return 0;
185 183
186 /* Fail gracefully */ 184 /* Fail gracefully */
187 platform_device_put(e740_snd_device); 185 platform_device_put(e740_snd_device);
188 free_apwr_gpio: 186 free_apwr_gpio:
189 gpio_free(GPIO_E740_WM9705_nAVDD2); 187 gpio_free(GPIO_E740_WM9705_nAVDD2);
190 free_op_amp_gpio: 188 free_op_amp_gpio:
191 gpio_free(GPIO_E740_AMP_ON); 189 gpio_free(GPIO_E740_AMP_ON);
192 free_mic_amp_gpio: 190 free_mic_amp_gpio:
193 gpio_free(GPIO_E740_MIC_ON); 191 gpio_free(GPIO_E740_MIC_ON);
194 192
195 return ret; 193 return ret;
196 } 194 }
197 195
198 static void __exit e740_exit(void) 196 static void __exit e740_exit(void)
199 { 197 {
200 platform_device_unregister(e740_snd_device); 198 platform_device_unregister(e740_snd_device);
201 gpio_free(GPIO_E740_WM9705_nAVDD2); 199 gpio_free(GPIO_E740_WM9705_nAVDD2);
202 gpio_free(GPIO_E740_AMP_ON); 200 gpio_free(GPIO_E740_AMP_ON);
203 gpio_free(GPIO_E740_MIC_ON); 201 gpio_free(GPIO_E740_MIC_ON);
204 } 202 }
205 203
206 module_init(e740_init); 204 module_init(e740_init);
207 module_exit(e740_exit); 205 module_exit(e740_exit);
208 206
209 /* Module information */ 207 /* Module information */
210 MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); 208 MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
211 MODULE_DESCRIPTION("ALSA SoC driver for e740"); 209 MODULE_DESCRIPTION("ALSA SoC driver for e740");
212 MODULE_LICENSE("GPL v2"); 210 MODULE_LICENSE("GPL v2");
213 211
sound/soc/pxa/e750_wm9705.c
1 /* 1 /*
2 * e750-wm9705.c -- SoC audio for e750 2 * e750-wm9705.c -- SoC audio for e750
3 * 3 *
4 * Copyright 2007 (c) Ian Molton <spyro@f2s.com> 4 * Copyright 2007 (c) Ian Molton <spyro@f2s.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; version 2 ONLY. 8 * Free Software Foundation; version 2 ONLY.
9 * 9 *
10 */ 10 */
11 11
12 #include <linux/module.h> 12 #include <linux/module.h>
13 #include <linux/moduleparam.h> 13 #include <linux/moduleparam.h>
14 #include <linux/gpio.h> 14 #include <linux/gpio.h>
15 15
16 #include <sound/core.h> 16 #include <sound/core.h>
17 #include <sound/pcm.h> 17 #include <sound/pcm.h>
18 #include <sound/soc.h> 18 #include <sound/soc.h>
19 19
20 #include <mach/audio.h> 20 #include <mach/audio.h>
21 #include <mach/eseries-gpio.h> 21 #include <mach/eseries-gpio.h>
22 22
23 #include <asm/mach-types.h> 23 #include <asm/mach-types.h>
24 24
25 #include "../codecs/wm9705.h" 25 #include "../codecs/wm9705.h"
26 #include "pxa2xx-ac97.h" 26 #include "pxa2xx-ac97.h"
27 27
28 static int e750_spk_amp_event(struct snd_soc_dapm_widget *w, 28 static int e750_spk_amp_event(struct snd_soc_dapm_widget *w,
29 struct snd_kcontrol *kcontrol, int event) 29 struct snd_kcontrol *kcontrol, int event)
30 { 30 {
31 if (event & SND_SOC_DAPM_PRE_PMU) 31 if (event & SND_SOC_DAPM_PRE_PMU)
32 gpio_set_value(GPIO_E750_SPK_AMP_OFF, 0); 32 gpio_set_value(GPIO_E750_SPK_AMP_OFF, 0);
33 else if (event & SND_SOC_DAPM_POST_PMD) 33 else if (event & SND_SOC_DAPM_POST_PMD)
34 gpio_set_value(GPIO_E750_SPK_AMP_OFF, 1); 34 gpio_set_value(GPIO_E750_SPK_AMP_OFF, 1);
35 35
36 return 0; 36 return 0;
37 } 37 }
38 38
39 static int e750_hp_amp_event(struct snd_soc_dapm_widget *w, 39 static int e750_hp_amp_event(struct snd_soc_dapm_widget *w,
40 struct snd_kcontrol *kcontrol, int event) 40 struct snd_kcontrol *kcontrol, int event)
41 { 41 {
42 if (event & SND_SOC_DAPM_PRE_PMU) 42 if (event & SND_SOC_DAPM_PRE_PMU)
43 gpio_set_value(GPIO_E750_HP_AMP_OFF, 0); 43 gpio_set_value(GPIO_E750_HP_AMP_OFF, 0);
44 else if (event & SND_SOC_DAPM_POST_PMD) 44 else if (event & SND_SOC_DAPM_POST_PMD)
45 gpio_set_value(GPIO_E750_HP_AMP_OFF, 1); 45 gpio_set_value(GPIO_E750_HP_AMP_OFF, 1);
46 46
47 return 0; 47 return 0;
48 } 48 }
49 49
50 static const struct snd_soc_dapm_widget e750_dapm_widgets[] = { 50 static const struct snd_soc_dapm_widget e750_dapm_widgets[] = {
51 SND_SOC_DAPM_HP("Headphone Jack", NULL), 51 SND_SOC_DAPM_HP("Headphone Jack", NULL),
52 SND_SOC_DAPM_SPK("Speaker", NULL), 52 SND_SOC_DAPM_SPK("Speaker", NULL),
53 SND_SOC_DAPM_MIC("Mic (Internal)", NULL), 53 SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
54 SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0, 54 SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
55 e750_hp_amp_event, SND_SOC_DAPM_PRE_PMU | 55 e750_hp_amp_event, SND_SOC_DAPM_PRE_PMU |
56 SND_SOC_DAPM_POST_PMD), 56 SND_SOC_DAPM_POST_PMD),
57 SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0, 57 SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
58 e750_spk_amp_event, SND_SOC_DAPM_PRE_PMU | 58 e750_spk_amp_event, SND_SOC_DAPM_PRE_PMU |
59 SND_SOC_DAPM_POST_PMD), 59 SND_SOC_DAPM_POST_PMD),
60 }; 60 };
61 61
62 static const struct snd_soc_dapm_route audio_map[] = { 62 static const struct snd_soc_dapm_route audio_map[] = {
63 {"Headphone Amp", NULL, "HPOUTL"}, 63 {"Headphone Amp", NULL, "HPOUTL"},
64 {"Headphone Amp", NULL, "HPOUTR"}, 64 {"Headphone Amp", NULL, "HPOUTR"},
65 {"Headphone Jack", NULL, "Headphone Amp"}, 65 {"Headphone Jack", NULL, "Headphone Amp"},
66 66
67 {"Speaker Amp", NULL, "MONOOUT"}, 67 {"Speaker Amp", NULL, "MONOOUT"},
68 {"Speaker", NULL, "Speaker Amp"}, 68 {"Speaker", NULL, "Speaker Amp"},
69 69
70 {"MIC1", NULL, "Mic (Internal)"}, 70 {"MIC1", NULL, "Mic (Internal)"},
71 }; 71 };
72 72
73 static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd) 73 static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd)
74 { 74 {
75 struct snd_soc_codec *codec = rtd->codec; 75 struct snd_soc_codec *codec = rtd->codec;
76 struct snd_soc_dapm_context *dapm = &codec->dapm; 76 struct snd_soc_dapm_context *dapm = &codec->dapm;
77 77
78 snd_soc_dapm_nc_pin(dapm, "LOUT"); 78 snd_soc_dapm_nc_pin(dapm, "LOUT");
79 snd_soc_dapm_nc_pin(dapm, "ROUT"); 79 snd_soc_dapm_nc_pin(dapm, "ROUT");
80 snd_soc_dapm_nc_pin(dapm, "PHONE"); 80 snd_soc_dapm_nc_pin(dapm, "PHONE");
81 snd_soc_dapm_nc_pin(dapm, "LINEINL"); 81 snd_soc_dapm_nc_pin(dapm, "LINEINL");
82 snd_soc_dapm_nc_pin(dapm, "LINEINR"); 82 snd_soc_dapm_nc_pin(dapm, "LINEINR");
83 snd_soc_dapm_nc_pin(dapm, "CDINL"); 83 snd_soc_dapm_nc_pin(dapm, "CDINL");
84 snd_soc_dapm_nc_pin(dapm, "CDINR"); 84 snd_soc_dapm_nc_pin(dapm, "CDINR");
85 snd_soc_dapm_nc_pin(dapm, "PCBEEP"); 85 snd_soc_dapm_nc_pin(dapm, "PCBEEP");
86 snd_soc_dapm_nc_pin(dapm, "MIC2"); 86 snd_soc_dapm_nc_pin(dapm, "MIC2");
87 87
88 snd_soc_dapm_new_controls(dapm, e750_dapm_widgets, 88 snd_soc_dapm_new_controls(dapm, e750_dapm_widgets,
89 ARRAY_SIZE(e750_dapm_widgets)); 89 ARRAY_SIZE(e750_dapm_widgets));
90 90
91 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 91 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
92 92
93 snd_soc_dapm_sync(dapm);
94
95 return 0; 93 return 0;
96 } 94 }
97 95
98 static struct snd_soc_dai_link e750_dai[] = { 96 static struct snd_soc_dai_link e750_dai[] = {
99 { 97 {
100 .name = "AC97", 98 .name = "AC97",
101 .stream_name = "AC97 HiFi", 99 .stream_name = "AC97 HiFi",
102 .cpu_dai_name = "pxa2xx-ac97", 100 .cpu_dai_name = "pxa2xx-ac97",
103 .codec_dai_name = "wm9705-hifi", 101 .codec_dai_name = "wm9705-hifi",
104 .platform_name = "pxa-pcm-audio", 102 .platform_name = "pxa-pcm-audio",
105 .codec_name = "wm9705-codec", 103 .codec_name = "wm9705-codec",
106 .init = e750_ac97_init, 104 .init = e750_ac97_init,
107 /* use ops to check startup state */ 105 /* use ops to check startup state */
108 }, 106 },
109 { 107 {
110 .name = "AC97 Aux", 108 .name = "AC97 Aux",
111 .stream_name = "AC97 Aux", 109 .stream_name = "AC97 Aux",
112 .cpu_dai_name = "pxa2xx-ac97-aux", 110 .cpu_dai_name = "pxa2xx-ac97-aux",
113 .codec_dai_name ="wm9705-aux", 111 .codec_dai_name ="wm9705-aux",
114 .platform_name = "pxa-pcm-audio", 112 .platform_name = "pxa-pcm-audio",
115 .codec_name = "wm9705-codec", 113 .codec_name = "wm9705-codec",
116 }, 114 },
117 }; 115 };
118 116
119 static struct snd_soc_card e750 = { 117 static struct snd_soc_card e750 = {
120 .name = "Toshiba e750", 118 .name = "Toshiba e750",
121 .dai_link = e750_dai, 119 .dai_link = e750_dai,
122 .num_links = ARRAY_SIZE(e750_dai), 120 .num_links = ARRAY_SIZE(e750_dai),
123 }; 121 };
124 122
125 static struct platform_device *e750_snd_device; 123 static struct platform_device *e750_snd_device;
126 124
127 static int __init e750_init(void) 125 static int __init e750_init(void)
128 { 126 {
129 int ret; 127 int ret;
130 128
131 if (!machine_is_e750()) 129 if (!machine_is_e750())
132 return -ENODEV; 130 return -ENODEV;
133 131
134 ret = gpio_request(GPIO_E750_HP_AMP_OFF, "Headphone amp"); 132 ret = gpio_request(GPIO_E750_HP_AMP_OFF, "Headphone amp");
135 if (ret) 133 if (ret)
136 return ret; 134 return ret;
137 135
138 ret = gpio_request(GPIO_E750_SPK_AMP_OFF, "Speaker amp"); 136 ret = gpio_request(GPIO_E750_SPK_AMP_OFF, "Speaker amp");
139 if (ret) 137 if (ret)
140 goto free_hp_amp_gpio; 138 goto free_hp_amp_gpio;
141 139
142 ret = gpio_direction_output(GPIO_E750_HP_AMP_OFF, 1); 140 ret = gpio_direction_output(GPIO_E750_HP_AMP_OFF, 1);
143 if (ret) 141 if (ret)
144 goto free_spk_amp_gpio; 142 goto free_spk_amp_gpio;
145 143
146 ret = gpio_direction_output(GPIO_E750_SPK_AMP_OFF, 1); 144 ret = gpio_direction_output(GPIO_E750_SPK_AMP_OFF, 1);
147 if (ret) 145 if (ret)
148 goto free_spk_amp_gpio; 146 goto free_spk_amp_gpio;
149 147
150 e750_snd_device = platform_device_alloc("soc-audio", -1); 148 e750_snd_device = platform_device_alloc("soc-audio", -1);
151 if (!e750_snd_device) { 149 if (!e750_snd_device) {
152 ret = -ENOMEM; 150 ret = -ENOMEM;
153 goto free_spk_amp_gpio; 151 goto free_spk_amp_gpio;
154 } 152 }
155 153
156 platform_set_drvdata(e750_snd_device, &e750); 154 platform_set_drvdata(e750_snd_device, &e750);
157 ret = platform_device_add(e750_snd_device); 155 ret = platform_device_add(e750_snd_device);
158 156
159 if (!ret) 157 if (!ret)
160 return 0; 158 return 0;
161 159
162 /* Fail gracefully */ 160 /* Fail gracefully */
163 platform_device_put(e750_snd_device); 161 platform_device_put(e750_snd_device);
164 free_spk_amp_gpio: 162 free_spk_amp_gpio:
165 gpio_free(GPIO_E750_SPK_AMP_OFF); 163 gpio_free(GPIO_E750_SPK_AMP_OFF);
166 free_hp_amp_gpio: 164 free_hp_amp_gpio:
167 gpio_free(GPIO_E750_HP_AMP_OFF); 165 gpio_free(GPIO_E750_HP_AMP_OFF);
168 166
169 return ret; 167 return ret;
170 } 168 }
171 169
172 static void __exit e750_exit(void) 170 static void __exit e750_exit(void)
173 { 171 {
174 platform_device_unregister(e750_snd_device); 172 platform_device_unregister(e750_snd_device);
175 gpio_free(GPIO_E750_SPK_AMP_OFF); 173 gpio_free(GPIO_E750_SPK_AMP_OFF);
176 gpio_free(GPIO_E750_HP_AMP_OFF); 174 gpio_free(GPIO_E750_HP_AMP_OFF);
177 } 175 }
178 176
179 module_init(e750_init); 177 module_init(e750_init);
180 module_exit(e750_exit); 178 module_exit(e750_exit);
181 179
182 /* Module information */ 180 /* Module information */
183 MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); 181 MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
184 MODULE_DESCRIPTION("ALSA SoC driver for e750"); 182 MODULE_DESCRIPTION("ALSA SoC driver for e750");
185 MODULE_LICENSE("GPL v2"); 183 MODULE_LICENSE("GPL v2");
186 184
sound/soc/pxa/e800_wm9712.c
1 /* 1 /*
2 * e800-wm9712.c -- SoC audio for e800 2 * e800-wm9712.c -- SoC audio for e800
3 * 3 *
4 * Copyright 2007 (c) Ian Molton <spyro@f2s.com> 4 * Copyright 2007 (c) Ian Molton <spyro@f2s.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; version 2 ONLY. 8 * Free Software Foundation; version 2 ONLY.
9 * 9 *
10 */ 10 */
11 11
12 #include <linux/module.h> 12 #include <linux/module.h>
13 #include <linux/moduleparam.h> 13 #include <linux/moduleparam.h>
14 #include <linux/gpio.h> 14 #include <linux/gpio.h>
15 15
16 #include <sound/core.h> 16 #include <sound/core.h>
17 #include <sound/pcm.h> 17 #include <sound/pcm.h>
18 #include <sound/soc.h> 18 #include <sound/soc.h>
19 19
20 #include <asm/mach-types.h> 20 #include <asm/mach-types.h>
21 #include <mach/audio.h> 21 #include <mach/audio.h>
22 #include <mach/eseries-gpio.h> 22 #include <mach/eseries-gpio.h>
23 23
24 #include "../codecs/wm9712.h" 24 #include "../codecs/wm9712.h"
25 #include "pxa2xx-ac97.h" 25 #include "pxa2xx-ac97.h"
26 26
27 static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, 27 static int e800_spk_amp_event(struct snd_soc_dapm_widget *w,
28 struct snd_kcontrol *kcontrol, int event) 28 struct snd_kcontrol *kcontrol, int event)
29 { 29 {
30 if (event & SND_SOC_DAPM_PRE_PMU) 30 if (event & SND_SOC_DAPM_PRE_PMU)
31 gpio_set_value(GPIO_E800_SPK_AMP_ON, 1); 31 gpio_set_value(GPIO_E800_SPK_AMP_ON, 1);
32 else if (event & SND_SOC_DAPM_POST_PMD) 32 else if (event & SND_SOC_DAPM_POST_PMD)
33 gpio_set_value(GPIO_E800_SPK_AMP_ON, 0); 33 gpio_set_value(GPIO_E800_SPK_AMP_ON, 0);
34 34
35 return 0; 35 return 0;
36 } 36 }
37 37
38 static int e800_hp_amp_event(struct snd_soc_dapm_widget *w, 38 static int e800_hp_amp_event(struct snd_soc_dapm_widget *w,
39 struct snd_kcontrol *kcontrol, int event) 39 struct snd_kcontrol *kcontrol, int event)
40 { 40 {
41 if (event & SND_SOC_DAPM_PRE_PMU) 41 if (event & SND_SOC_DAPM_PRE_PMU)
42 gpio_set_value(GPIO_E800_HP_AMP_OFF, 0); 42 gpio_set_value(GPIO_E800_HP_AMP_OFF, 0);
43 else if (event & SND_SOC_DAPM_POST_PMD) 43 else if (event & SND_SOC_DAPM_POST_PMD)
44 gpio_set_value(GPIO_E800_HP_AMP_OFF, 1); 44 gpio_set_value(GPIO_E800_HP_AMP_OFF, 1);
45 45
46 return 0; 46 return 0;
47 } 47 }
48 48
49 static const struct snd_soc_dapm_widget e800_dapm_widgets[] = { 49 static const struct snd_soc_dapm_widget e800_dapm_widgets[] = {
50 SND_SOC_DAPM_HP("Headphone Jack", NULL), 50 SND_SOC_DAPM_HP("Headphone Jack", NULL),
51 SND_SOC_DAPM_MIC("Mic (Internal1)", NULL), 51 SND_SOC_DAPM_MIC("Mic (Internal1)", NULL),
52 SND_SOC_DAPM_MIC("Mic (Internal2)", NULL), 52 SND_SOC_DAPM_MIC("Mic (Internal2)", NULL),
53 SND_SOC_DAPM_SPK("Speaker", NULL), 53 SND_SOC_DAPM_SPK("Speaker", NULL),
54 SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0, 54 SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
55 e800_hp_amp_event, SND_SOC_DAPM_PRE_PMU | 55 e800_hp_amp_event, SND_SOC_DAPM_PRE_PMU |
56 SND_SOC_DAPM_POST_PMD), 56 SND_SOC_DAPM_POST_PMD),
57 SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0, 57 SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
58 e800_spk_amp_event, SND_SOC_DAPM_PRE_PMU | 58 e800_spk_amp_event, SND_SOC_DAPM_PRE_PMU |
59 SND_SOC_DAPM_POST_PMD), 59 SND_SOC_DAPM_POST_PMD),
60 }; 60 };
61 61
62 static const struct snd_soc_dapm_route audio_map[] = { 62 static const struct snd_soc_dapm_route audio_map[] = {
63 {"Headphone Jack", NULL, "HPOUTL"}, 63 {"Headphone Jack", NULL, "HPOUTL"},
64 {"Headphone Jack", NULL, "HPOUTR"}, 64 {"Headphone Jack", NULL, "HPOUTR"},
65 {"Headphone Jack", NULL, "Headphone Amp"}, 65 {"Headphone Jack", NULL, "Headphone Amp"},
66 66
67 {"Speaker Amp", NULL, "MONOOUT"}, 67 {"Speaker Amp", NULL, "MONOOUT"},
68 {"Speaker", NULL, "Speaker Amp"}, 68 {"Speaker", NULL, "Speaker Amp"},
69 69
70 {"MIC1", NULL, "Mic (Internal1)"}, 70 {"MIC1", NULL, "Mic (Internal1)"},
71 {"MIC2", NULL, "Mic (Internal2)"}, 71 {"MIC2", NULL, "Mic (Internal2)"},
72 }; 72 };
73 73
74 static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd) 74 static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd)
75 { 75 {
76 struct snd_soc_codec *codec = rtd->codec; 76 struct snd_soc_codec *codec = rtd->codec;
77 struct snd_soc_dapm_context *dapm = &codec->dapm; 77 struct snd_soc_dapm_context *dapm = &codec->dapm;
78 78
79 snd_soc_dapm_new_controls(dapm, e800_dapm_widgets, 79 snd_soc_dapm_new_controls(dapm, e800_dapm_widgets,
80 ARRAY_SIZE(e800_dapm_widgets)); 80 ARRAY_SIZE(e800_dapm_widgets));
81 81
82 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 82 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
83 snd_soc_dapm_sync(dapm);
84 83
85 return 0; 84 return 0;
86 } 85 }
87 86
88 static struct snd_soc_dai_link e800_dai[] = { 87 static struct snd_soc_dai_link e800_dai[] = {
89 { 88 {
90 .name = "AC97", 89 .name = "AC97",
91 .stream_name = "AC97 HiFi", 90 .stream_name = "AC97 HiFi",
92 .cpu_dai_name = "pxa2xx-ac97", 91 .cpu_dai_name = "pxa2xx-ac97",
93 .codec_dai_name = "wm9712-hifi", 92 .codec_dai_name = "wm9712-hifi",
94 .platform_name = "pxa-pcm-audio", 93 .platform_name = "pxa-pcm-audio",
95 .codec_name = "wm9712-codec", 94 .codec_name = "wm9712-codec",
96 .init = e800_ac97_init, 95 .init = e800_ac97_init,
97 }, 96 },
98 { 97 {
99 .name = "AC97 Aux", 98 .name = "AC97 Aux",
100 .stream_name = "AC97 Aux", 99 .stream_name = "AC97 Aux",
101 .cpu_dai_name = "pxa2xx-ac97-aux", 100 .cpu_dai_name = "pxa2xx-ac97-aux",
102 .codec_dai_name ="wm9712-aux", 101 .codec_dai_name ="wm9712-aux",
103 .platform_name = "pxa-pcm-audio", 102 .platform_name = "pxa-pcm-audio",
104 .codec_name = "wm9712-codec", 103 .codec_name = "wm9712-codec",
105 }, 104 },
106 }; 105 };
107 106
108 static struct snd_soc_card e800 = { 107 static struct snd_soc_card e800 = {
109 .name = "Toshiba e800", 108 .name = "Toshiba e800",
110 .dai_link = e800_dai, 109 .dai_link = e800_dai,
111 .num_links = ARRAY_SIZE(e800_dai), 110 .num_links = ARRAY_SIZE(e800_dai),
112 }; 111 };
113 112
114 static struct platform_device *e800_snd_device; 113 static struct platform_device *e800_snd_device;
115 114
116 static int __init e800_init(void) 115 static int __init e800_init(void)
117 { 116 {
118 int ret; 117 int ret;
119 118
120 if (!machine_is_e800()) 119 if (!machine_is_e800())
121 return -ENODEV; 120 return -ENODEV;
122 121
123 ret = gpio_request(GPIO_E800_HP_AMP_OFF, "Headphone amp"); 122 ret = gpio_request(GPIO_E800_HP_AMP_OFF, "Headphone amp");
124 if (ret) 123 if (ret)
125 return ret; 124 return ret;
126 125
127 ret = gpio_request(GPIO_E800_SPK_AMP_ON, "Speaker amp"); 126 ret = gpio_request(GPIO_E800_SPK_AMP_ON, "Speaker amp");
128 if (ret) 127 if (ret)
129 goto free_hp_amp_gpio; 128 goto free_hp_amp_gpio;
130 129
131 ret = gpio_direction_output(GPIO_E800_HP_AMP_OFF, 1); 130 ret = gpio_direction_output(GPIO_E800_HP_AMP_OFF, 1);
132 if (ret) 131 if (ret)
133 goto free_spk_amp_gpio; 132 goto free_spk_amp_gpio;
134 133
135 ret = gpio_direction_output(GPIO_E800_SPK_AMP_ON, 1); 134 ret = gpio_direction_output(GPIO_E800_SPK_AMP_ON, 1);
136 if (ret) 135 if (ret)
137 goto free_spk_amp_gpio; 136 goto free_spk_amp_gpio;
138 137
139 e800_snd_device = platform_device_alloc("soc-audio", -1); 138 e800_snd_device = platform_device_alloc("soc-audio", -1);
140 if (!e800_snd_device) 139 if (!e800_snd_device)
141 return -ENOMEM; 140 return -ENOMEM;
142 141
143 platform_set_drvdata(e800_snd_device, &e800); 142 platform_set_drvdata(e800_snd_device, &e800);
144 ret = platform_device_add(e800_snd_device); 143 ret = platform_device_add(e800_snd_device);
145 144
146 if (!ret) 145 if (!ret)
147 return 0; 146 return 0;
148 147
149 /* Fail gracefully */ 148 /* Fail gracefully */
150 platform_device_put(e800_snd_device); 149 platform_device_put(e800_snd_device);
151 free_spk_amp_gpio: 150 free_spk_amp_gpio:
152 gpio_free(GPIO_E800_SPK_AMP_ON); 151 gpio_free(GPIO_E800_SPK_AMP_ON);
153 free_hp_amp_gpio: 152 free_hp_amp_gpio:
154 gpio_free(GPIO_E800_HP_AMP_OFF); 153 gpio_free(GPIO_E800_HP_AMP_OFF);
155 154
156 return ret; 155 return ret;
157 } 156 }
158 157
159 static void __exit e800_exit(void) 158 static void __exit e800_exit(void)
160 { 159 {
161 platform_device_unregister(e800_snd_device); 160 platform_device_unregister(e800_snd_device);
162 gpio_free(GPIO_E800_SPK_AMP_ON); 161 gpio_free(GPIO_E800_SPK_AMP_ON);
163 gpio_free(GPIO_E800_HP_AMP_OFF); 162 gpio_free(GPIO_E800_HP_AMP_OFF);
164 } 163 }
165 164
166 module_init(e800_init); 165 module_init(e800_init);
167 module_exit(e800_exit); 166 module_exit(e800_exit);
168 167
169 /* Module information */ 168 /* Module information */
170 MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); 169 MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
171 MODULE_DESCRIPTION("ALSA SoC driver for e800"); 170 MODULE_DESCRIPTION("ALSA SoC driver for e800");
172 MODULE_LICENSE("GPL v2"); 171 MODULE_LICENSE("GPL v2");
173 172
sound/soc/pxa/magician.c
1 /* 1 /*
2 * SoC audio for HTC Magician 2 * SoC audio for HTC Magician
3 * 3 *
4 * Copyright (c) 2006 Philipp Zabel <philipp.zabel@gmail.com> 4 * Copyright (c) 2006 Philipp Zabel <philipp.zabel@gmail.com>
5 * 5 *
6 * based on spitz.c, 6 * based on spitz.c,
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/timer.h> 18 #include <linux/timer.h>
19 #include <linux/interrupt.h> 19 #include <linux/interrupt.h>
20 #include <linux/platform_device.h> 20 #include <linux/platform_device.h>
21 #include <linux/delay.h> 21 #include <linux/delay.h>
22 #include <linux/gpio.h> 22 #include <linux/gpio.h>
23 #include <linux/i2c.h> 23 #include <linux/i2c.h>
24 24
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/uda1380.h> 29 #include <sound/uda1380.h>
30 30
31 #include <mach/magician.h> 31 #include <mach/magician.h>
32 #include <asm/mach-types.h> 32 #include <asm/mach-types.h>
33 #include "../codecs/uda1380.h" 33 #include "../codecs/uda1380.h"
34 #include "pxa2xx-i2s.h" 34 #include "pxa2xx-i2s.h"
35 #include "pxa-ssp.h" 35 #include "pxa-ssp.h"
36 36
37 #define MAGICIAN_MIC 0 37 #define MAGICIAN_MIC 0
38 #define MAGICIAN_MIC_EXT 1 38 #define MAGICIAN_MIC_EXT 1
39 39
40 static int magician_hp_switch; 40 static int magician_hp_switch;
41 static int magician_spk_switch = 1; 41 static int magician_spk_switch = 1;
42 static int magician_in_sel = MAGICIAN_MIC; 42 static int magician_in_sel = MAGICIAN_MIC;
43 43
44 static void magician_ext_control(struct snd_soc_codec *codec) 44 static void magician_ext_control(struct snd_soc_codec *codec)
45 { 45 {
46 struct snd_soc_dapm_context *dapm = &codec->dapm; 46 struct snd_soc_dapm_context *dapm = &codec->dapm;
47 47
48 if (magician_spk_switch) 48 if (magician_spk_switch)
49 snd_soc_dapm_enable_pin(dapm, "Speaker"); 49 snd_soc_dapm_enable_pin(dapm, "Speaker");
50 else 50 else
51 snd_soc_dapm_disable_pin(dapm, "Speaker"); 51 snd_soc_dapm_disable_pin(dapm, "Speaker");
52 if (magician_hp_switch) 52 if (magician_hp_switch)
53 snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); 53 snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
54 else 54 else
55 snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); 55 snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
56 56
57 switch (magician_in_sel) { 57 switch (magician_in_sel) {
58 case MAGICIAN_MIC: 58 case MAGICIAN_MIC:
59 snd_soc_dapm_disable_pin(dapm, "Headset Mic"); 59 snd_soc_dapm_disable_pin(dapm, "Headset Mic");
60 snd_soc_dapm_enable_pin(dapm, "Call Mic"); 60 snd_soc_dapm_enable_pin(dapm, "Call Mic");
61 break; 61 break;
62 case MAGICIAN_MIC_EXT: 62 case MAGICIAN_MIC_EXT:
63 snd_soc_dapm_disable_pin(dapm, "Call Mic"); 63 snd_soc_dapm_disable_pin(dapm, "Call Mic");
64 snd_soc_dapm_enable_pin(dapm, "Headset Mic"); 64 snd_soc_dapm_enable_pin(dapm, "Headset Mic");
65 break; 65 break;
66 } 66 }
67 67
68 snd_soc_dapm_sync(dapm); 68 snd_soc_dapm_sync(dapm);
69 } 69 }
70 70
71 static int magician_startup(struct snd_pcm_substream *substream) 71 static int magician_startup(struct snd_pcm_substream *substream)
72 { 72 {
73 struct snd_soc_pcm_runtime *rtd = substream->private_data; 73 struct snd_soc_pcm_runtime *rtd = substream->private_data;
74 struct snd_soc_codec *codec = rtd->codec; 74 struct snd_soc_codec *codec = rtd->codec;
75 75
76 mutex_lock(&codec->mutex); 76 mutex_lock(&codec->mutex);
77 77
78 /* check the jack status at stream startup */ 78 /* check the jack status at stream startup */
79 magician_ext_control(codec); 79 magician_ext_control(codec);
80 80
81 mutex_unlock(&codec->mutex); 81 mutex_unlock(&codec->mutex);
82 82
83 return 0; 83 return 0;
84 } 84 }
85 85
86 /* 86 /*
87 * Magician uses SSP port for playback. 87 * Magician uses SSP port for playback.
88 */ 88 */
89 static int magician_playback_hw_params(struct snd_pcm_substream *substream, 89 static int magician_playback_hw_params(struct snd_pcm_substream *substream,
90 struct snd_pcm_hw_params *params) 90 struct snd_pcm_hw_params *params)
91 { 91 {
92 struct snd_soc_pcm_runtime *rtd = substream->private_data; 92 struct snd_soc_pcm_runtime *rtd = substream->private_data;
93 struct snd_soc_dai *codec_dai = rtd->codec_dai; 93 struct snd_soc_dai *codec_dai = rtd->codec_dai;
94 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 94 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
95 unsigned int acps, acds, width; 95 unsigned int acps, acds, width;
96 unsigned int div4 = PXA_SSP_CLK_SCDB_4; 96 unsigned int div4 = PXA_SSP_CLK_SCDB_4;
97 int ret = 0; 97 int ret = 0;
98 98
99 width = snd_pcm_format_physical_width(params_format(params)); 99 width = snd_pcm_format_physical_width(params_format(params));
100 100
101 /* 101 /*
102 * rate = SSPSCLK / (2 * width(16 or 32)) 102 * rate = SSPSCLK / (2 * width(16 or 32))
103 * SSPSCLK = (ACPS / ACDS) / SSPSCLKDIV(div4 or div1) 103 * SSPSCLK = (ACPS / ACDS) / SSPSCLKDIV(div4 or div1)
104 */ 104 */
105 switch (params_rate(params)) { 105 switch (params_rate(params)) {
106 case 8000: 106 case 8000:
107 /* off by a factor of 2: bug in the PXA27x audio clock? */ 107 /* off by a factor of 2: bug in the PXA27x audio clock? */
108 acps = 32842000; 108 acps = 32842000;
109 switch (width) { 109 switch (width) {
110 case 16: 110 case 16:
111 /* 513156 Hz ~= _2_ * 8000 Hz * 32 (+0.23%) */ 111 /* 513156 Hz ~= _2_ * 8000 Hz * 32 (+0.23%) */
112 acds = PXA_SSP_CLK_AUDIO_DIV_16; 112 acds = PXA_SSP_CLK_AUDIO_DIV_16;
113 break; 113 break;
114 default: /* 32 */ 114 default: /* 32 */
115 /* 1026312 Hz ~= _2_ * 8000 Hz * 64 (+0.23%) */ 115 /* 1026312 Hz ~= _2_ * 8000 Hz * 64 (+0.23%) */
116 acds = PXA_SSP_CLK_AUDIO_DIV_8; 116 acds = PXA_SSP_CLK_AUDIO_DIV_8;
117 } 117 }
118 break; 118 break;
119 case 11025: 119 case 11025:
120 acps = 5622000; 120 acps = 5622000;
121 switch (width) { 121 switch (width) {
122 case 16: 122 case 16:
123 /* 351375 Hz ~= 11025 Hz * 32 (-0.41%) */ 123 /* 351375 Hz ~= 11025 Hz * 32 (-0.41%) */
124 acds = PXA_SSP_CLK_AUDIO_DIV_4; 124 acds = PXA_SSP_CLK_AUDIO_DIV_4;
125 break; 125 break;
126 default: /* 32 */ 126 default: /* 32 */
127 /* 702750 Hz ~= 11025 Hz * 64 (-0.41%) */ 127 /* 702750 Hz ~= 11025 Hz * 64 (-0.41%) */
128 acds = PXA_SSP_CLK_AUDIO_DIV_2; 128 acds = PXA_SSP_CLK_AUDIO_DIV_2;
129 } 129 }
130 break; 130 break;
131 case 22050: 131 case 22050:
132 acps = 5622000; 132 acps = 5622000;
133 switch (width) { 133 switch (width) {
134 case 16: 134 case 16:
135 /* 702750 Hz ~= 22050 Hz * 32 (-0.41%) */ 135 /* 702750 Hz ~= 22050 Hz * 32 (-0.41%) */
136 acds = PXA_SSP_CLK_AUDIO_DIV_2; 136 acds = PXA_SSP_CLK_AUDIO_DIV_2;
137 break; 137 break;
138 default: /* 32 */ 138 default: /* 32 */
139 /* 1405500 Hz ~= 22050 Hz * 64 (-0.41%) */ 139 /* 1405500 Hz ~= 22050 Hz * 64 (-0.41%) */
140 acds = PXA_SSP_CLK_AUDIO_DIV_1; 140 acds = PXA_SSP_CLK_AUDIO_DIV_1;
141 } 141 }
142 break; 142 break;
143 case 44100: 143 case 44100:
144 acps = 5622000; 144 acps = 5622000;
145 switch (width) { 145 switch (width) {
146 case 16: 146 case 16:
147 /* 1405500 Hz ~= 44100 Hz * 32 (-0.41%) */ 147 /* 1405500 Hz ~= 44100 Hz * 32 (-0.41%) */
148 acds = PXA_SSP_CLK_AUDIO_DIV_2; 148 acds = PXA_SSP_CLK_AUDIO_DIV_2;
149 break; 149 break;
150 default: /* 32 */ 150 default: /* 32 */
151 /* 2811000 Hz ~= 44100 Hz * 64 (-0.41%) */ 151 /* 2811000 Hz ~= 44100 Hz * 64 (-0.41%) */
152 acds = PXA_SSP_CLK_AUDIO_DIV_1; 152 acds = PXA_SSP_CLK_AUDIO_DIV_1;
153 } 153 }
154 break; 154 break;
155 case 48000: 155 case 48000:
156 acps = 12235000; 156 acps = 12235000;
157 switch (width) { 157 switch (width) {
158 case 16: 158 case 16:
159 /* 1529375 Hz ~= 48000 Hz * 32 (-0.44%) */ 159 /* 1529375 Hz ~= 48000 Hz * 32 (-0.44%) */
160 acds = PXA_SSP_CLK_AUDIO_DIV_2; 160 acds = PXA_SSP_CLK_AUDIO_DIV_2;
161 break; 161 break;
162 default: /* 32 */ 162 default: /* 32 */
163 /* 3058750 Hz ~= 48000 Hz * 64 (-0.44%) */ 163 /* 3058750 Hz ~= 48000 Hz * 64 (-0.44%) */
164 acds = PXA_SSP_CLK_AUDIO_DIV_1; 164 acds = PXA_SSP_CLK_AUDIO_DIV_1;
165 } 165 }
166 break; 166 break;
167 case 96000: 167 case 96000:
168 default: 168 default:
169 acps = 12235000; 169 acps = 12235000;
170 switch (width) { 170 switch (width) {
171 case 16: 171 case 16:
172 /* 3058750 Hz ~= 96000 Hz * 32 (-0.44%) */ 172 /* 3058750 Hz ~= 96000 Hz * 32 (-0.44%) */
173 acds = PXA_SSP_CLK_AUDIO_DIV_1; 173 acds = PXA_SSP_CLK_AUDIO_DIV_1;
174 break; 174 break;
175 default: /* 32 */ 175 default: /* 32 */
176 /* 6117500 Hz ~= 96000 Hz * 64 (-0.44%) */ 176 /* 6117500 Hz ~= 96000 Hz * 64 (-0.44%) */
177 acds = PXA_SSP_CLK_AUDIO_DIV_2; 177 acds = PXA_SSP_CLK_AUDIO_DIV_2;
178 div4 = PXA_SSP_CLK_SCDB_1; 178 div4 = PXA_SSP_CLK_SCDB_1;
179 break; 179 break;
180 } 180 }
181 break; 181 break;
182 } 182 }
183 183
184 /* set codec DAI configuration */ 184 /* set codec DAI configuration */
185 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_MSB | 185 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_MSB |
186 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 186 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
187 if (ret < 0) 187 if (ret < 0)
188 return ret; 188 return ret;
189 189
190 /* set cpu DAI configuration */ 190 /* set cpu DAI configuration */
191 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | 191 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
192 SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBS_CFS); 192 SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBS_CFS);
193 if (ret < 0) 193 if (ret < 0)
194 return ret; 194 return ret;
195 195
196 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 0, 1, width); 196 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 0, 1, width);
197 if (ret < 0) 197 if (ret < 0)
198 return ret; 198 return ret;
199 199
200 /* set audio clock as clock source */ 200 /* set audio clock as clock source */
201 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 201 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0,
202 SND_SOC_CLOCK_OUT); 202 SND_SOC_CLOCK_OUT);
203 if (ret < 0) 203 if (ret < 0)
204 return ret; 204 return ret;
205 205
206 /* set the SSP audio system clock ACDS divider */ 206 /* set the SSP audio system clock ACDS divider */
207 ret = snd_soc_dai_set_clkdiv(cpu_dai, 207 ret = snd_soc_dai_set_clkdiv(cpu_dai,
208 PXA_SSP_AUDIO_DIV_ACDS, acds); 208 PXA_SSP_AUDIO_DIV_ACDS, acds);
209 if (ret < 0) 209 if (ret < 0)
210 return ret; 210 return ret;
211 211
212 /* set the SSP audio system clock SCDB divider4 */ 212 /* set the SSP audio system clock SCDB divider4 */
213 ret = snd_soc_dai_set_clkdiv(cpu_dai, 213 ret = snd_soc_dai_set_clkdiv(cpu_dai,
214 PXA_SSP_AUDIO_DIV_SCDB, div4); 214 PXA_SSP_AUDIO_DIV_SCDB, div4);
215 if (ret < 0) 215 if (ret < 0)
216 return ret; 216 return ret;
217 217
218 /* set SSP audio pll clock */ 218 /* set SSP audio pll clock */
219 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, acps); 219 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, acps);
220 if (ret < 0) 220 if (ret < 0)
221 return ret; 221 return ret;
222 222
223 return 0; 223 return 0;
224 } 224 }
225 225
226 /* 226 /*
227 * Magician uses I2S for capture. 227 * Magician uses I2S for capture.
228 */ 228 */
229 static int magician_capture_hw_params(struct snd_pcm_substream *substream, 229 static int magician_capture_hw_params(struct snd_pcm_substream *substream,
230 struct snd_pcm_hw_params *params) 230 struct snd_pcm_hw_params *params)
231 { 231 {
232 struct snd_soc_pcm_runtime *rtd = substream->private_data; 232 struct snd_soc_pcm_runtime *rtd = substream->private_data;
233 struct snd_soc_dai *codec_dai = rtd->codec_dai; 233 struct snd_soc_dai *codec_dai = rtd->codec_dai;
234 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 234 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
235 int ret = 0; 235 int ret = 0;
236 236
237 /* set codec DAI configuration */ 237 /* set codec DAI configuration */
238 ret = snd_soc_dai_set_fmt(codec_dai, 238 ret = snd_soc_dai_set_fmt(codec_dai,
239 SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF | 239 SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF |
240 SND_SOC_DAIFMT_CBS_CFS); 240 SND_SOC_DAIFMT_CBS_CFS);
241 if (ret < 0) 241 if (ret < 0)
242 return ret; 242 return ret;
243 243
244 /* set cpu DAI configuration */ 244 /* set cpu DAI configuration */
245 ret = snd_soc_dai_set_fmt(cpu_dai, 245 ret = snd_soc_dai_set_fmt(cpu_dai,
246 SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF | 246 SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF |
247 SND_SOC_DAIFMT_CBS_CFS); 247 SND_SOC_DAIFMT_CBS_CFS);
248 if (ret < 0) 248 if (ret < 0)
249 return ret; 249 return ret;
250 250
251 /* set the I2S system clock as output */ 251 /* set the I2S system clock as output */
252 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0, 252 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
253 SND_SOC_CLOCK_OUT); 253 SND_SOC_CLOCK_OUT);
254 if (ret < 0) 254 if (ret < 0)
255 return ret; 255 return ret;
256 256
257 return 0; 257 return 0;
258 } 258 }
259 259
260 static struct snd_soc_ops magician_capture_ops = { 260 static struct snd_soc_ops magician_capture_ops = {
261 .startup = magician_startup, 261 .startup = magician_startup,
262 .hw_params = magician_capture_hw_params, 262 .hw_params = magician_capture_hw_params,
263 }; 263 };
264 264
265 static struct snd_soc_ops magician_playback_ops = { 265 static struct snd_soc_ops magician_playback_ops = {
266 .startup = magician_startup, 266 .startup = magician_startup,
267 .hw_params = magician_playback_hw_params, 267 .hw_params = magician_playback_hw_params,
268 }; 268 };
269 269
270 static int magician_get_hp(struct snd_kcontrol *kcontrol, 270 static int magician_get_hp(struct snd_kcontrol *kcontrol,
271 struct snd_ctl_elem_value *ucontrol) 271 struct snd_ctl_elem_value *ucontrol)
272 { 272 {
273 ucontrol->value.integer.value[0] = magician_hp_switch; 273 ucontrol->value.integer.value[0] = magician_hp_switch;
274 return 0; 274 return 0;
275 } 275 }
276 276
277 static int magician_set_hp(struct snd_kcontrol *kcontrol, 277 static int magician_set_hp(struct snd_kcontrol *kcontrol,
278 struct snd_ctl_elem_value *ucontrol) 278 struct snd_ctl_elem_value *ucontrol)
279 { 279 {
280 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 280 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
281 281
282 if (magician_hp_switch == ucontrol->value.integer.value[0]) 282 if (magician_hp_switch == ucontrol->value.integer.value[0])
283 return 0; 283 return 0;
284 284
285 magician_hp_switch = ucontrol->value.integer.value[0]; 285 magician_hp_switch = ucontrol->value.integer.value[0];
286 magician_ext_control(codec); 286 magician_ext_control(codec);
287 return 1; 287 return 1;
288 } 288 }
289 289
290 static int magician_get_spk(struct snd_kcontrol *kcontrol, 290 static int magician_get_spk(struct snd_kcontrol *kcontrol,
291 struct snd_ctl_elem_value *ucontrol) 291 struct snd_ctl_elem_value *ucontrol)
292 { 292 {
293 ucontrol->value.integer.value[0] = magician_spk_switch; 293 ucontrol->value.integer.value[0] = magician_spk_switch;
294 return 0; 294 return 0;
295 } 295 }
296 296
297 static int magician_set_spk(struct snd_kcontrol *kcontrol, 297 static int magician_set_spk(struct snd_kcontrol *kcontrol,
298 struct snd_ctl_elem_value *ucontrol) 298 struct snd_ctl_elem_value *ucontrol)
299 { 299 {
300 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 300 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
301 301
302 if (magician_spk_switch == ucontrol->value.integer.value[0]) 302 if (magician_spk_switch == ucontrol->value.integer.value[0])
303 return 0; 303 return 0;
304 304
305 magician_spk_switch = ucontrol->value.integer.value[0]; 305 magician_spk_switch = ucontrol->value.integer.value[0];
306 magician_ext_control(codec); 306 magician_ext_control(codec);
307 return 1; 307 return 1;
308 } 308 }
309 309
310 static int magician_get_input(struct snd_kcontrol *kcontrol, 310 static int magician_get_input(struct snd_kcontrol *kcontrol,
311 struct snd_ctl_elem_value *ucontrol) 311 struct snd_ctl_elem_value *ucontrol)
312 { 312 {
313 ucontrol->value.integer.value[0] = magician_in_sel; 313 ucontrol->value.integer.value[0] = magician_in_sel;
314 return 0; 314 return 0;
315 } 315 }
316 316
317 static int magician_set_input(struct snd_kcontrol *kcontrol, 317 static int magician_set_input(struct snd_kcontrol *kcontrol,
318 struct snd_ctl_elem_value *ucontrol) 318 struct snd_ctl_elem_value *ucontrol)
319 { 319 {
320 if (magician_in_sel == ucontrol->value.integer.value[0]) 320 if (magician_in_sel == ucontrol->value.integer.value[0])
321 return 0; 321 return 0;
322 322
323 magician_in_sel = ucontrol->value.integer.value[0]; 323 magician_in_sel = ucontrol->value.integer.value[0];
324 324
325 switch (magician_in_sel) { 325 switch (magician_in_sel) {
326 case MAGICIAN_MIC: 326 case MAGICIAN_MIC:
327 gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 1); 327 gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 1);
328 break; 328 break;
329 case MAGICIAN_MIC_EXT: 329 case MAGICIAN_MIC_EXT:
330 gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 0); 330 gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 0);
331 } 331 }
332 332
333 return 1; 333 return 1;
334 } 334 }
335 335
336 static int magician_spk_power(struct snd_soc_dapm_widget *w, 336 static int magician_spk_power(struct snd_soc_dapm_widget *w,
337 struct snd_kcontrol *k, int event) 337 struct snd_kcontrol *k, int event)
338 { 338 {
339 gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, SND_SOC_DAPM_EVENT_ON(event)); 339 gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, SND_SOC_DAPM_EVENT_ON(event));
340 return 0; 340 return 0;
341 } 341 }
342 342
343 static int magician_hp_power(struct snd_soc_dapm_widget *w, 343 static int magician_hp_power(struct snd_soc_dapm_widget *w,
344 struct snd_kcontrol *k, int event) 344 struct snd_kcontrol *k, int event)
345 { 345 {
346 gpio_set_value(EGPIO_MAGICIAN_EP_POWER, SND_SOC_DAPM_EVENT_ON(event)); 346 gpio_set_value(EGPIO_MAGICIAN_EP_POWER, SND_SOC_DAPM_EVENT_ON(event));
347 return 0; 347 return 0;
348 } 348 }
349 349
350 static int magician_mic_bias(struct snd_soc_dapm_widget *w, 350 static int magician_mic_bias(struct snd_soc_dapm_widget *w,
351 struct snd_kcontrol *k, int event) 351 struct snd_kcontrol *k, int event)
352 { 352 {
353 gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, SND_SOC_DAPM_EVENT_ON(event)); 353 gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, SND_SOC_DAPM_EVENT_ON(event));
354 return 0; 354 return 0;
355 } 355 }
356 356
357 /* magician machine dapm widgets */ 357 /* magician machine dapm widgets */
358 static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = { 358 static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
359 SND_SOC_DAPM_HP("Headphone Jack", magician_hp_power), 359 SND_SOC_DAPM_HP("Headphone Jack", magician_hp_power),
360 SND_SOC_DAPM_SPK("Speaker", magician_spk_power), 360 SND_SOC_DAPM_SPK("Speaker", magician_spk_power),
361 SND_SOC_DAPM_MIC("Call Mic", magician_mic_bias), 361 SND_SOC_DAPM_MIC("Call Mic", magician_mic_bias),
362 SND_SOC_DAPM_MIC("Headset Mic", magician_mic_bias), 362 SND_SOC_DAPM_MIC("Headset Mic", magician_mic_bias),
363 }; 363 };
364 364
365 /* magician machine audio_map */ 365 /* magician machine audio_map */
366 static const struct snd_soc_dapm_route audio_map[] = { 366 static const struct snd_soc_dapm_route audio_map[] = {
367 367
368 /* Headphone connected to VOUTL, VOUTR */ 368 /* Headphone connected to VOUTL, VOUTR */
369 {"Headphone Jack", NULL, "VOUTL"}, 369 {"Headphone Jack", NULL, "VOUTL"},
370 {"Headphone Jack", NULL, "VOUTR"}, 370 {"Headphone Jack", NULL, "VOUTR"},
371 371
372 /* Speaker connected to VOUTL, VOUTR */ 372 /* Speaker connected to VOUTL, VOUTR */
373 {"Speaker", NULL, "VOUTL"}, 373 {"Speaker", NULL, "VOUTL"},
374 {"Speaker", NULL, "VOUTR"}, 374 {"Speaker", NULL, "VOUTR"},
375 375
376 /* Mics are connected to VINM */ 376 /* Mics are connected to VINM */
377 {"VINM", NULL, "Headset Mic"}, 377 {"VINM", NULL, "Headset Mic"},
378 {"VINM", NULL, "Call Mic"}, 378 {"VINM", NULL, "Call Mic"},
379 }; 379 };
380 380
381 static const char *input_select[] = {"Call Mic", "Headset Mic"}; 381 static const char *input_select[] = {"Call Mic", "Headset Mic"};
382 static const struct soc_enum magician_in_sel_enum = 382 static const struct soc_enum magician_in_sel_enum =
383 SOC_ENUM_SINGLE_EXT(2, input_select); 383 SOC_ENUM_SINGLE_EXT(2, input_select);
384 384
385 static const struct snd_kcontrol_new uda1380_magician_controls[] = { 385 static const struct snd_kcontrol_new uda1380_magician_controls[] = {
386 SOC_SINGLE_BOOL_EXT("Headphone Switch", 386 SOC_SINGLE_BOOL_EXT("Headphone Switch",
387 (unsigned long)&magician_hp_switch, 387 (unsigned long)&magician_hp_switch,
388 magician_get_hp, magician_set_hp), 388 magician_get_hp, magician_set_hp),
389 SOC_SINGLE_BOOL_EXT("Speaker Switch", 389 SOC_SINGLE_BOOL_EXT("Speaker Switch",
390 (unsigned long)&magician_spk_switch, 390 (unsigned long)&magician_spk_switch,
391 magician_get_spk, magician_set_spk), 391 magician_get_spk, magician_set_spk),
392 SOC_ENUM_EXT("Input Select", magician_in_sel_enum, 392 SOC_ENUM_EXT("Input Select", magician_in_sel_enum,
393 magician_get_input, magician_set_input), 393 magician_get_input, magician_set_input),
394 }; 394 };
395 395
396 /* 396 /*
397 * Logic for a uda1380 as connected on a HTC Magician 397 * Logic for a uda1380 as connected on a HTC Magician
398 */ 398 */
399 static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd) 399 static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd)
400 { 400 {
401 struct snd_soc_codec *codec = rtd->codec; 401 struct snd_soc_codec *codec = rtd->codec;
402 struct snd_soc_dapm_context *dapm = &codec->dapm; 402 struct snd_soc_dapm_context *dapm = &codec->dapm;
403 int err; 403 int err;
404 404
405 /* NC codec pins */ 405 /* NC codec pins */
406 snd_soc_dapm_nc_pin(dapm, "VOUTLHP"); 406 snd_soc_dapm_nc_pin(dapm, "VOUTLHP");
407 snd_soc_dapm_nc_pin(dapm, "VOUTRHP"); 407 snd_soc_dapm_nc_pin(dapm, "VOUTRHP");
408 408
409 /* FIXME: is anything connected here? */ 409 /* FIXME: is anything connected here? */
410 snd_soc_dapm_nc_pin(dapm, "VINL"); 410 snd_soc_dapm_nc_pin(dapm, "VINL");
411 snd_soc_dapm_nc_pin(dapm, "VINR"); 411 snd_soc_dapm_nc_pin(dapm, "VINR");
412 412
413 /* Add magician specific controls */ 413 /* Add magician specific controls */
414 err = snd_soc_add_controls(codec, uda1380_magician_controls, 414 err = snd_soc_add_controls(codec, uda1380_magician_controls,
415 ARRAY_SIZE(uda1380_magician_controls)); 415 ARRAY_SIZE(uda1380_magician_controls));
416 if (err < 0) 416 if (err < 0)
417 return err; 417 return err;
418 418
419 /* Add magician specific widgets */ 419 /* Add magician specific widgets */
420 snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets, 420 snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets,
421 ARRAY_SIZE(uda1380_dapm_widgets)); 421 ARRAY_SIZE(uda1380_dapm_widgets));
422 422
423 /* Set up magician specific audio path interconnects */ 423 /* Set up magician specific audio path interconnects */
424 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 424 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
425 425
426 snd_soc_dapm_sync(dapm);
427 return 0; 426 return 0;
428 } 427 }
429 428
430 /* magician digital audio interface glue - connects codec <--> CPU */ 429 /* magician digital audio interface glue - connects codec <--> CPU */
431 static struct snd_soc_dai_link magician_dai[] = { 430 static struct snd_soc_dai_link magician_dai[] = {
432 { 431 {
433 .name = "uda1380", 432 .name = "uda1380",
434 .stream_name = "UDA1380 Playback", 433 .stream_name = "UDA1380 Playback",
435 .cpu_dai_name = "pxa-ssp-dai.0", 434 .cpu_dai_name = "pxa-ssp-dai.0",
436 .codec_dai_name = "uda1380-hifi-playback", 435 .codec_dai_name = "uda1380-hifi-playback",
437 .platform_name = "pxa-pcm-audio", 436 .platform_name = "pxa-pcm-audio",
438 .codec_name = "uda1380-codec.0-0018", 437 .codec_name = "uda1380-codec.0-0018",
439 .init = magician_uda1380_init, 438 .init = magician_uda1380_init,
440 .ops = &magician_playback_ops, 439 .ops = &magician_playback_ops,
441 }, 440 },
442 { 441 {
443 .name = "uda1380", 442 .name = "uda1380",
444 .stream_name = "UDA1380 Capture", 443 .stream_name = "UDA1380 Capture",
445 .cpu_dai_name = "pxa2xx-i2s", 444 .cpu_dai_name = "pxa2xx-i2s",
446 .codec_dai_name = "uda1380-hifi-capture", 445 .codec_dai_name = "uda1380-hifi-capture",
447 .platform_name = "pxa-pcm-audio", 446 .platform_name = "pxa-pcm-audio",
448 .codec_name = "uda1380-codec.0-0018", 447 .codec_name = "uda1380-codec.0-0018",
449 .ops = &magician_capture_ops, 448 .ops = &magician_capture_ops,
450 } 449 }
451 }; 450 };
452 451
453 /* magician audio machine driver */ 452 /* magician audio machine driver */
454 static struct snd_soc_card snd_soc_card_magician = { 453 static struct snd_soc_card snd_soc_card_magician = {
455 .name = "Magician", 454 .name = "Magician",
456 .dai_link = magician_dai, 455 .dai_link = magician_dai,
457 .num_links = ARRAY_SIZE(magician_dai), 456 .num_links = ARRAY_SIZE(magician_dai),
458 457
459 }; 458 };
460 459
461 static struct platform_device *magician_snd_device; 460 static struct platform_device *magician_snd_device;
462 461
463 /* 462 /*
464 * FIXME: move into magician board file once merged into the pxa tree 463 * FIXME: move into magician board file once merged into the pxa tree
465 */ 464 */
466 static struct uda1380_platform_data uda1380_info = { 465 static struct uda1380_platform_data uda1380_info = {
467 .gpio_power = EGPIO_MAGICIAN_CODEC_POWER, 466 .gpio_power = EGPIO_MAGICIAN_CODEC_POWER,
468 .gpio_reset = EGPIO_MAGICIAN_CODEC_RESET, 467 .gpio_reset = EGPIO_MAGICIAN_CODEC_RESET,
469 .dac_clk = UDA1380_DAC_CLK_WSPLL, 468 .dac_clk = UDA1380_DAC_CLK_WSPLL,
470 }; 469 };
471 470
472 static struct i2c_board_info i2c_board_info[] = { 471 static struct i2c_board_info i2c_board_info[] = {
473 { 472 {
474 I2C_BOARD_INFO("uda1380", 0x18), 473 I2C_BOARD_INFO("uda1380", 0x18),
475 .platform_data = &uda1380_info, 474 .platform_data = &uda1380_info,
476 }, 475 },
477 }; 476 };
478 477
479 static int __init magician_init(void) 478 static int __init magician_init(void)
480 { 479 {
481 int ret; 480 int ret;
482 struct i2c_adapter *adapter; 481 struct i2c_adapter *adapter;
483 struct i2c_client *client; 482 struct i2c_client *client;
484 483
485 if (!machine_is_magician()) 484 if (!machine_is_magician())
486 return -ENODEV; 485 return -ENODEV;
487 486
488 adapter = i2c_get_adapter(0); 487 adapter = i2c_get_adapter(0);
489 if (!adapter) 488 if (!adapter)
490 return -ENODEV; 489 return -ENODEV;
491 client = i2c_new_device(adapter, i2c_board_info); 490 client = i2c_new_device(adapter, i2c_board_info);
492 i2c_put_adapter(adapter); 491 i2c_put_adapter(adapter);
493 if (!client) 492 if (!client)
494 return -ENODEV; 493 return -ENODEV;
495 494
496 ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER"); 495 ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER");
497 if (ret) 496 if (ret)
498 goto err_request_spk; 497 goto err_request_spk;
499 ret = gpio_request(EGPIO_MAGICIAN_EP_POWER, "EP_POWER"); 498 ret = gpio_request(EGPIO_MAGICIAN_EP_POWER, "EP_POWER");
500 if (ret) 499 if (ret)
501 goto err_request_ep; 500 goto err_request_ep;
502 ret = gpio_request(EGPIO_MAGICIAN_MIC_POWER, "MIC_POWER"); 501 ret = gpio_request(EGPIO_MAGICIAN_MIC_POWER, "MIC_POWER");
503 if (ret) 502 if (ret)
504 goto err_request_mic; 503 goto err_request_mic;
505 ret = gpio_request(EGPIO_MAGICIAN_IN_SEL0, "IN_SEL0"); 504 ret = gpio_request(EGPIO_MAGICIAN_IN_SEL0, "IN_SEL0");
506 if (ret) 505 if (ret)
507 goto err_request_in_sel0; 506 goto err_request_in_sel0;
508 ret = gpio_request(EGPIO_MAGICIAN_IN_SEL1, "IN_SEL1"); 507 ret = gpio_request(EGPIO_MAGICIAN_IN_SEL1, "IN_SEL1");
509 if (ret) 508 if (ret)
510 goto err_request_in_sel1; 509 goto err_request_in_sel1;
511 510
512 gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0); 511 gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0);
513 512
514 magician_snd_device = platform_device_alloc("soc-audio", -1); 513 magician_snd_device = platform_device_alloc("soc-audio", -1);
515 if (!magician_snd_device) { 514 if (!magician_snd_device) {
516 ret = -ENOMEM; 515 ret = -ENOMEM;
517 goto err_pdev; 516 goto err_pdev;
518 } 517 }
519 518
520 platform_set_drvdata(magician_snd_device, &snd_soc_card_magician); 519 platform_set_drvdata(magician_snd_device, &snd_soc_card_magician);
521 ret = platform_device_add(magician_snd_device); 520 ret = platform_device_add(magician_snd_device);
522 if (ret) { 521 if (ret) {
523 platform_device_put(magician_snd_device); 522 platform_device_put(magician_snd_device);
524 goto err_pdev; 523 goto err_pdev;
525 } 524 }
526 525
527 return 0; 526 return 0;
528 527
529 err_pdev: 528 err_pdev:
530 gpio_free(EGPIO_MAGICIAN_IN_SEL1); 529 gpio_free(EGPIO_MAGICIAN_IN_SEL1);
531 err_request_in_sel1: 530 err_request_in_sel1:
532 gpio_free(EGPIO_MAGICIAN_IN_SEL0); 531 gpio_free(EGPIO_MAGICIAN_IN_SEL0);
533 err_request_in_sel0: 532 err_request_in_sel0:
534 gpio_free(EGPIO_MAGICIAN_MIC_POWER); 533 gpio_free(EGPIO_MAGICIAN_MIC_POWER);
535 err_request_mic: 534 err_request_mic:
536 gpio_free(EGPIO_MAGICIAN_EP_POWER); 535 gpio_free(EGPIO_MAGICIAN_EP_POWER);
537 err_request_ep: 536 err_request_ep:
538 gpio_free(EGPIO_MAGICIAN_SPK_POWER); 537 gpio_free(EGPIO_MAGICIAN_SPK_POWER);
539 err_request_spk: 538 err_request_spk:
540 return ret; 539 return ret;
541 } 540 }
542 541
543 static void __exit magician_exit(void) 542 static void __exit magician_exit(void)
544 { 543 {
545 platform_device_unregister(magician_snd_device); 544 platform_device_unregister(magician_snd_device);
546 545
547 gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0); 546 gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0);
548 gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0); 547 gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0);
549 gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0); 548 gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0);
550 549
551 gpio_free(EGPIO_MAGICIAN_IN_SEL1); 550 gpio_free(EGPIO_MAGICIAN_IN_SEL1);
552 gpio_free(EGPIO_MAGICIAN_IN_SEL0); 551 gpio_free(EGPIO_MAGICIAN_IN_SEL0);
553 gpio_free(EGPIO_MAGICIAN_MIC_POWER); 552 gpio_free(EGPIO_MAGICIAN_MIC_POWER);
554 gpio_free(EGPIO_MAGICIAN_EP_POWER); 553 gpio_free(EGPIO_MAGICIAN_EP_POWER);
555 gpio_free(EGPIO_MAGICIAN_SPK_POWER); 554 gpio_free(EGPIO_MAGICIAN_SPK_POWER);
556 } 555 }
557 556
558 module_init(magician_init); 557 module_init(magician_init);
559 module_exit(magician_exit); 558 module_exit(magician_exit);
560 559
561 MODULE_AUTHOR("Philipp Zabel"); 560 MODULE_AUTHOR("Philipp Zabel");
562 MODULE_DESCRIPTION("ALSA SoC Magician"); 561 MODULE_DESCRIPTION("ALSA SoC Magician");
563 MODULE_LICENSE("GPL"); 562 MODULE_LICENSE("GPL");
564 563
sound/soc/pxa/mioa701_wm9713.c
1 /* 1 /*
2 * Handles the Mitac mioa701 SoC system 2 * Handles the Mitac mioa701 SoC system
3 * 3 *
4 * Copyright (C) 2008 Robert Jarzmik 4 * Copyright (C) 2008 Robert Jarzmik
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation in version 2 of the License. 8 * the Free Software Foundation in version 2 of the License.
9 * 9 *
10 * This program is distributed in the hope that it will be useful, 10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details. 13 * GNU General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU General Public License 15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software 16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * 18 *
19 * This is a little schema of the sound interconnections : 19 * This is a little schema of the sound interconnections :
20 * 20 *
21 * Sagem X200 Wolfson WM9713 21 * Sagem X200 Wolfson WM9713
22 * +--------+ +-------------------+ Rear Speaker 22 * +--------+ +-------------------+ Rear Speaker
23 * | | | | /-+ 23 * | | | | /-+
24 * | +--->----->---+MONOIN SPKL+--->----+-+ | 24 * | +--->----->---+MONOIN SPKL+--->----+-+ |
25 * | GSM | | | | | | 25 * | GSM | | | | | |
26 * | +--->----->---+PCBEEP SPKR+--->----+-+ | 26 * | +--->----->---+PCBEEP SPKR+--->----+-+ |
27 * | CHIP | | | \-+ 27 * | CHIP | | | \-+
28 * | +---<-----<---+MONO | 28 * | +---<-----<---+MONO |
29 * | | | | Front Speaker 29 * | | | | Front Speaker
30 * +--------+ | | /-+ 30 * +--------+ | | /-+
31 * | HPL+--->----+-+ | 31 * | HPL+--->----+-+ |
32 * | | | | | 32 * | | | | |
33 * | OUT3+--->----+-+ | 33 * | OUT3+--->----+-+ |
34 * | | \-+ 34 * | | \-+
35 * | | 35 * | |
36 * | | Front Micro 36 * | | Front Micro
37 * | | + 37 * | | +
38 * | MIC1+-----<--+o+ 38 * | MIC1+-----<--+o+
39 * | | + 39 * | | +
40 * +-------------------+ --- 40 * +-------------------+ ---
41 */ 41 */
42 42
43 #include <linux/module.h> 43 #include <linux/module.h>
44 #include <linux/moduleparam.h> 44 #include <linux/moduleparam.h>
45 #include <linux/platform_device.h> 45 #include <linux/platform_device.h>
46 46
47 #include <asm/mach-types.h> 47 #include <asm/mach-types.h>
48 #include <mach/audio.h> 48 #include <mach/audio.h>
49 49
50 #include <sound/core.h> 50 #include <sound/core.h>
51 #include <sound/pcm.h> 51 #include <sound/pcm.h>
52 #include <sound/soc.h> 52 #include <sound/soc.h>
53 #include <sound/initval.h> 53 #include <sound/initval.h>
54 #include <sound/ac97_codec.h> 54 #include <sound/ac97_codec.h>
55 55
56 #include "pxa2xx-ac97.h" 56 #include "pxa2xx-ac97.h"
57 #include "../codecs/wm9713.h" 57 #include "../codecs/wm9713.h"
58 58
59 #define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) 59 #define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
60 60
61 #define AC97_GPIO_PULL 0x58 61 #define AC97_GPIO_PULL 0x58
62 62
63 /* Use GPIO8 for rear speaker amplifier */ 63 /* Use GPIO8 for rear speaker amplifier */
64 static int rear_amp_power(struct snd_soc_codec *codec, int power) 64 static int rear_amp_power(struct snd_soc_codec *codec, int power)
65 { 65 {
66 unsigned short reg; 66 unsigned short reg;
67 67
68 if (power) { 68 if (power) {
69 reg = snd_soc_read(codec, AC97_GPIO_CFG); 69 reg = snd_soc_read(codec, AC97_GPIO_CFG);
70 snd_soc_write(codec, AC97_GPIO_CFG, reg | 0x0100); 70 snd_soc_write(codec, AC97_GPIO_CFG, reg | 0x0100);
71 reg = snd_soc_read(codec, AC97_GPIO_PULL); 71 reg = snd_soc_read(codec, AC97_GPIO_PULL);
72 snd_soc_write(codec, AC97_GPIO_PULL, reg | (1<<15)); 72 snd_soc_write(codec, AC97_GPIO_PULL, reg | (1<<15));
73 } else { 73 } else {
74 reg = snd_soc_read(codec, AC97_GPIO_CFG); 74 reg = snd_soc_read(codec, AC97_GPIO_CFG);
75 snd_soc_write(codec, AC97_GPIO_CFG, reg & ~0x0100); 75 snd_soc_write(codec, AC97_GPIO_CFG, reg & ~0x0100);
76 reg = snd_soc_read(codec, AC97_GPIO_PULL); 76 reg = snd_soc_read(codec, AC97_GPIO_PULL);
77 snd_soc_write(codec, AC97_GPIO_PULL, reg & ~(1<<15)); 77 snd_soc_write(codec, AC97_GPIO_PULL, reg & ~(1<<15));
78 } 78 }
79 79
80 return 0; 80 return 0;
81 } 81 }
82 82
83 static int rear_amp_event(struct snd_soc_dapm_widget *widget, 83 static int rear_amp_event(struct snd_soc_dapm_widget *widget,
84 struct snd_kcontrol *kctl, int event) 84 struct snd_kcontrol *kctl, int event)
85 { 85 {
86 struct snd_soc_codec *codec = widget->codec; 86 struct snd_soc_codec *codec = widget->codec;
87 87
88 return rear_amp_power(codec, SND_SOC_DAPM_EVENT_ON(event)); 88 return rear_amp_power(codec, SND_SOC_DAPM_EVENT_ON(event));
89 } 89 }
90 90
91 /* mioa701 machine dapm widgets */ 91 /* mioa701 machine dapm widgets */
92 static const struct snd_soc_dapm_widget mioa701_dapm_widgets[] = { 92 static const struct snd_soc_dapm_widget mioa701_dapm_widgets[] = {
93 SND_SOC_DAPM_SPK("Front Speaker", NULL), 93 SND_SOC_DAPM_SPK("Front Speaker", NULL),
94 SND_SOC_DAPM_SPK("Rear Speaker", rear_amp_event), 94 SND_SOC_DAPM_SPK("Rear Speaker", rear_amp_event),
95 SND_SOC_DAPM_MIC("Headset", NULL), 95 SND_SOC_DAPM_MIC("Headset", NULL),
96 SND_SOC_DAPM_LINE("GSM Line Out", NULL), 96 SND_SOC_DAPM_LINE("GSM Line Out", NULL),
97 SND_SOC_DAPM_LINE("GSM Line In", NULL), 97 SND_SOC_DAPM_LINE("GSM Line In", NULL),
98 SND_SOC_DAPM_MIC("Headset Mic", NULL), 98 SND_SOC_DAPM_MIC("Headset Mic", NULL),
99 SND_SOC_DAPM_MIC("Front Mic", NULL), 99 SND_SOC_DAPM_MIC("Front Mic", NULL),
100 }; 100 };
101 101
102 static const struct snd_soc_dapm_route audio_map[] = { 102 static const struct snd_soc_dapm_route audio_map[] = {
103 /* Call Mic */ 103 /* Call Mic */
104 {"Mic Bias", NULL, "Front Mic"}, 104 {"Mic Bias", NULL, "Front Mic"},
105 {"MIC1", NULL, "Mic Bias"}, 105 {"MIC1", NULL, "Mic Bias"},
106 106
107 /* Headset Mic */ 107 /* Headset Mic */
108 {"LINEL", NULL, "Headset Mic"}, 108 {"LINEL", NULL, "Headset Mic"},
109 {"LINER", NULL, "Headset Mic"}, 109 {"LINER", NULL, "Headset Mic"},
110 110
111 /* GSM Module */ 111 /* GSM Module */
112 {"MONOIN", NULL, "GSM Line Out"}, 112 {"MONOIN", NULL, "GSM Line Out"},
113 {"PCBEEP", NULL, "GSM Line Out"}, 113 {"PCBEEP", NULL, "GSM Line Out"},
114 {"GSM Line In", NULL, "MONO"}, 114 {"GSM Line In", NULL, "MONO"},
115 115
116 /* headphone connected to HPL, HPR */ 116 /* headphone connected to HPL, HPR */
117 {"Headset", NULL, "HPL"}, 117 {"Headset", NULL, "HPL"},
118 {"Headset", NULL, "HPR"}, 118 {"Headset", NULL, "HPR"},
119 119
120 /* front speaker connected to HPL, OUT3 */ 120 /* front speaker connected to HPL, OUT3 */
121 {"Front Speaker", NULL, "HPL"}, 121 {"Front Speaker", NULL, "HPL"},
122 {"Front Speaker", NULL, "OUT3"}, 122 {"Front Speaker", NULL, "OUT3"},
123 123
124 /* rear speaker connected to SPKL, SPKR */ 124 /* rear speaker connected to SPKL, SPKR */
125 {"Rear Speaker", NULL, "SPKL"}, 125 {"Rear Speaker", NULL, "SPKL"},
126 {"Rear Speaker", NULL, "SPKR"}, 126 {"Rear Speaker", NULL, "SPKR"},
127 }; 127 };
128 128
129 static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) 129 static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd)
130 { 130 {
131 struct snd_soc_codec *codec = rtd->codec; 131 struct snd_soc_codec *codec = rtd->codec;
132 struct snd_soc_dapm_context *dapm = &codec->dapm; 132 struct snd_soc_dapm_context *dapm = &codec->dapm;
133 unsigned short reg; 133 unsigned short reg;
134 134
135 /* Add mioa701 specific widgets */ 135 /* Add mioa701 specific widgets */
136 snd_soc_dapm_new_controls(dapm, ARRAY_AND_SIZE(mioa701_dapm_widgets)); 136 snd_soc_dapm_new_controls(dapm, ARRAY_AND_SIZE(mioa701_dapm_widgets));
137 137
138 /* Set up mioa701 specific audio path audio_mapnects */ 138 /* Set up mioa701 specific audio path audio_mapnects */
139 snd_soc_dapm_add_routes(dapm, ARRAY_AND_SIZE(audio_map)); 139 snd_soc_dapm_add_routes(dapm, ARRAY_AND_SIZE(audio_map));
140 140
141 /* Prepare GPIO8 for rear speaker amplifier */ 141 /* Prepare GPIO8 for rear speaker amplifier */
142 reg = codec->driver->read(codec, AC97_GPIO_CFG); 142 reg = codec->driver->read(codec, AC97_GPIO_CFG);
143 codec->driver->write(codec, AC97_GPIO_CFG, reg | 0x0100); 143 codec->driver->write(codec, AC97_GPIO_CFG, reg | 0x0100);
144 144
145 /* Prepare MIC input */ 145 /* Prepare MIC input */
146 reg = codec->driver->read(codec, AC97_3D_CONTROL); 146 reg = codec->driver->read(codec, AC97_3D_CONTROL);
147 codec->driver->write(codec, AC97_3D_CONTROL, reg | 0xc000); 147 codec->driver->write(codec, AC97_3D_CONTROL, reg | 0xc000);
148 148
149 snd_soc_dapm_enable_pin(dapm, "Front Speaker"); 149 snd_soc_dapm_enable_pin(dapm, "Front Speaker");
150 snd_soc_dapm_enable_pin(dapm, "Rear Speaker"); 150 snd_soc_dapm_enable_pin(dapm, "Rear Speaker");
151 snd_soc_dapm_enable_pin(dapm, "Front Mic"); 151 snd_soc_dapm_enable_pin(dapm, "Front Mic");
152 snd_soc_dapm_enable_pin(dapm, "GSM Line In"); 152 snd_soc_dapm_enable_pin(dapm, "GSM Line In");
153 snd_soc_dapm_enable_pin(dapm, "GSM Line Out"); 153 snd_soc_dapm_enable_pin(dapm, "GSM Line Out");
154 snd_soc_dapm_sync(dapm);
155 154
156 return 0; 155 return 0;
157 } 156 }
158 157
159 static struct snd_soc_ops mioa701_ops; 158 static struct snd_soc_ops mioa701_ops;
160 159
161 static struct snd_soc_dai_link mioa701_dai[] = { 160 static struct snd_soc_dai_link mioa701_dai[] = {
162 { 161 {
163 .name = "AC97", 162 .name = "AC97",
164 .stream_name = "AC97 HiFi", 163 .stream_name = "AC97 HiFi",
165 .cpu_dai_name = "pxa2xx-ac97", 164 .cpu_dai_name = "pxa2xx-ac97",
166 .codec_dai_name = "wm9713-hifi", 165 .codec_dai_name = "wm9713-hifi",
167 .codec_name = "wm9713-codec", 166 .codec_name = "wm9713-codec",
168 .init = mioa701_wm9713_init, 167 .init = mioa701_wm9713_init,
169 .platform_name = "pxa-pcm-audio", 168 .platform_name = "pxa-pcm-audio",
170 .ops = &mioa701_ops, 169 .ops = &mioa701_ops,
171 }, 170 },
172 { 171 {
173 .name = "AC97 Aux", 172 .name = "AC97 Aux",
174 .stream_name = "AC97 Aux", 173 .stream_name = "AC97 Aux",
175 .cpu_dai_name = "pxa2xx-ac97-aux", 174 .cpu_dai_name = "pxa2xx-ac97-aux",
176 .codec_dai_name ="wm9713-aux", 175 .codec_dai_name ="wm9713-aux",
177 .codec_name = "wm9713-codec", 176 .codec_name = "wm9713-codec",
178 .platform_name = "pxa-pcm-audio", 177 .platform_name = "pxa-pcm-audio",
179 .ops = &mioa701_ops, 178 .ops = &mioa701_ops,
180 }, 179 },
181 }; 180 };
182 181
183 static struct snd_soc_card mioa701 = { 182 static struct snd_soc_card mioa701 = {
184 .name = "MioA701", 183 .name = "MioA701",
185 .dai_link = mioa701_dai, 184 .dai_link = mioa701_dai,
186 .num_links = ARRAY_SIZE(mioa701_dai), 185 .num_links = ARRAY_SIZE(mioa701_dai),
187 }; 186 };
188 187
189 static struct platform_device *mioa701_snd_device; 188 static struct platform_device *mioa701_snd_device;
190 189
191 static int mioa701_wm9713_probe(struct platform_device *pdev) 190 static int mioa701_wm9713_probe(struct platform_device *pdev)
192 { 191 {
193 int ret; 192 int ret;
194 193
195 if (!machine_is_mioa701()) 194 if (!machine_is_mioa701())
196 return -ENODEV; 195 return -ENODEV;
197 196
198 dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will" 197 dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will"
199 "lead to overheating and possible destruction of your device." 198 "lead to overheating and possible destruction of your device."
200 "Do not use without a good knowledge of mio's board design!\n"); 199 "Do not use without a good knowledge of mio's board design!\n");
201 200
202 mioa701_snd_device = platform_device_alloc("soc-audio", -1); 201 mioa701_snd_device = platform_device_alloc("soc-audio", -1);
203 if (!mioa701_snd_device) 202 if (!mioa701_snd_device)
204 return -ENOMEM; 203 return -ENOMEM;
205 204
206 platform_set_drvdata(mioa701_snd_device, &mioa701); 205 platform_set_drvdata(mioa701_snd_device, &mioa701);
207 206
208 ret = platform_device_add(mioa701_snd_device); 207 ret = platform_device_add(mioa701_snd_device);
209 if (!ret) 208 if (!ret)
210 return 0; 209 return 0;
211 210
212 platform_device_put(mioa701_snd_device); 211 platform_device_put(mioa701_snd_device);
213 return ret; 212 return ret;
214 } 213 }
215 214
216 static int __devexit mioa701_wm9713_remove(struct platform_device *pdev) 215 static int __devexit mioa701_wm9713_remove(struct platform_device *pdev)
217 { 216 {
218 platform_device_unregister(mioa701_snd_device); 217 platform_device_unregister(mioa701_snd_device);
219 return 0; 218 return 0;
220 } 219 }
221 220
222 static struct platform_driver mioa701_wm9713_driver = { 221 static struct platform_driver mioa701_wm9713_driver = {
223 .probe = mioa701_wm9713_probe, 222 .probe = mioa701_wm9713_probe,
224 .remove = __devexit_p(mioa701_wm9713_remove), 223 .remove = __devexit_p(mioa701_wm9713_remove),
225 .driver = { 224 .driver = {
226 .name = "mioa701-wm9713", 225 .name = "mioa701-wm9713",
227 .owner = THIS_MODULE, 226 .owner = THIS_MODULE,
228 }, 227 },
229 }; 228 };
230 229
231 static int __init mioa701_asoc_init(void) 230 static int __init mioa701_asoc_init(void)
232 { 231 {
233 return platform_driver_register(&mioa701_wm9713_driver); 232 return platform_driver_register(&mioa701_wm9713_driver);
234 } 233 }
235 234
236 static void __exit mioa701_asoc_exit(void) 235 static void __exit mioa701_asoc_exit(void)
237 { 236 {
238 platform_driver_unregister(&mioa701_wm9713_driver); 237 platform_driver_unregister(&mioa701_wm9713_driver);
239 } 238 }
240 239
241 module_init(mioa701_asoc_init); 240 module_init(mioa701_asoc_init);
242 module_exit(mioa701_asoc_exit); 241 module_exit(mioa701_asoc_exit);
243 242
244 /* Module information */ 243 /* Module information */
245 MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)"); 244 MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)");
246 MODULE_DESCRIPTION("ALSA SoC WM9713 MIO A701"); 245 MODULE_DESCRIPTION("ALSA SoC WM9713 MIO A701");
247 MODULE_LICENSE("GPL"); 246 MODULE_LICENSE("GPL");
248 247
sound/soc/pxa/palm27x.c
1 /* 1 /*
2 * linux/sound/soc/pxa/palm27x.c 2 * linux/sound/soc/pxa/palm27x.c
3 * 3 *
4 * SoC Audio driver for Palm T|X, T5 and LifeDrive 4 * SoC Audio driver for Palm T|X, T5 and LifeDrive
5 * 5 *
6 * based on tosa.c 6 * based on tosa.c
7 * 7 *
8 * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com> 8 * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com>
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 15
16 #include <linux/module.h> 16 #include <linux/module.h>
17 #include <linux/moduleparam.h> 17 #include <linux/moduleparam.h>
18 #include <linux/device.h> 18 #include <linux/device.h>
19 #include <linux/gpio.h> 19 #include <linux/gpio.h>
20 20
21 #include <sound/core.h> 21 #include <sound/core.h>
22 #include <sound/pcm.h> 22 #include <sound/pcm.h>
23 #include <sound/soc.h> 23 #include <sound/soc.h>
24 #include <sound/jack.h> 24 #include <sound/jack.h>
25 25
26 #include <asm/mach-types.h> 26 #include <asm/mach-types.h>
27 #include <mach/audio.h> 27 #include <mach/audio.h>
28 #include <mach/palmasoc.h> 28 #include <mach/palmasoc.h>
29 29
30 #include "../codecs/wm9712.h" 30 #include "../codecs/wm9712.h"
31 #include "pxa2xx-ac97.h" 31 #include "pxa2xx-ac97.h"
32 32
33 static struct snd_soc_jack hs_jack; 33 static struct snd_soc_jack hs_jack;
34 34
35 /* Headphones jack detection DAPM pins */ 35 /* Headphones jack detection DAPM pins */
36 static struct snd_soc_jack_pin hs_jack_pins[] = { 36 static struct snd_soc_jack_pin hs_jack_pins[] = {
37 { 37 {
38 .pin = "Headphone Jack", 38 .pin = "Headphone Jack",
39 .mask = SND_JACK_HEADPHONE, 39 .mask = SND_JACK_HEADPHONE,
40 }, 40 },
41 }; 41 };
42 42
43 /* Headphones jack detection gpios */ 43 /* Headphones jack detection gpios */
44 static struct snd_soc_jack_gpio hs_jack_gpios[] = { 44 static struct snd_soc_jack_gpio hs_jack_gpios[] = {
45 [0] = { 45 [0] = {
46 /* gpio is set on per-platform basis */ 46 /* gpio is set on per-platform basis */
47 .name = "hp-gpio", 47 .name = "hp-gpio",
48 .report = SND_JACK_HEADPHONE, 48 .report = SND_JACK_HEADPHONE,
49 .debounce_time = 200, 49 .debounce_time = 200,
50 }, 50 },
51 }; 51 };
52 52
53 /* Palm27x machine dapm widgets */ 53 /* Palm27x machine dapm widgets */
54 static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = { 54 static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = {
55 SND_SOC_DAPM_HP("Headphone Jack", NULL), 55 SND_SOC_DAPM_HP("Headphone Jack", NULL),
56 SND_SOC_DAPM_SPK("Ext. Speaker", NULL), 56 SND_SOC_DAPM_SPK("Ext. Speaker", NULL),
57 SND_SOC_DAPM_MIC("Ext. Microphone", NULL), 57 SND_SOC_DAPM_MIC("Ext. Microphone", NULL),
58 }; 58 };
59 59
60 /* PalmTX audio map */ 60 /* PalmTX audio map */
61 static const struct snd_soc_dapm_route audio_map[] = { 61 static const struct snd_soc_dapm_route audio_map[] = {
62 /* headphone connected to HPOUTL, HPOUTR */ 62 /* headphone connected to HPOUTL, HPOUTR */
63 {"Headphone Jack", NULL, "HPOUTL"}, 63 {"Headphone Jack", NULL, "HPOUTL"},
64 {"Headphone Jack", NULL, "HPOUTR"}, 64 {"Headphone Jack", NULL, "HPOUTR"},
65 65
66 /* ext speaker connected to ROUT2, LOUT2 */ 66 /* ext speaker connected to ROUT2, LOUT2 */
67 {"Ext. Speaker", NULL, "LOUT2"}, 67 {"Ext. Speaker", NULL, "LOUT2"},
68 {"Ext. Speaker", NULL, "ROUT2"}, 68 {"Ext. Speaker", NULL, "ROUT2"},
69 69
70 /* mic connected to MIC1 */ 70 /* mic connected to MIC1 */
71 {"Ext. Microphone", NULL, "MIC1"}, 71 {"Ext. Microphone", NULL, "MIC1"},
72 }; 72 };
73 73
74 static struct snd_soc_card palm27x_asoc; 74 static struct snd_soc_card palm27x_asoc;
75 75
76 static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd) 76 static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd)
77 { 77 {
78 struct snd_soc_codec *codec = rtd->codec; 78 struct snd_soc_codec *codec = rtd->codec;
79 struct snd_soc_dapm_context *dapm = &codec->dapm; 79 struct snd_soc_dapm_context *dapm = &codec->dapm;
80 int err; 80 int err;
81 81
82 /* add palm27x specific widgets */ 82 /* add palm27x specific widgets */
83 err = snd_soc_dapm_new_controls(dapm, palm27x_dapm_widgets, 83 err = snd_soc_dapm_new_controls(dapm, palm27x_dapm_widgets,
84 ARRAY_SIZE(palm27x_dapm_widgets)); 84 ARRAY_SIZE(palm27x_dapm_widgets));
85 if (err) 85 if (err)
86 return err; 86 return err;
87 87
88 /* set up palm27x specific audio path audio_map */ 88 /* set up palm27x specific audio path audio_map */
89 err = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 89 err = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
90 if (err) 90 if (err)
91 return err; 91 return err;
92 92
93 /* connected pins */ 93 /* connected pins */
94 if (machine_is_palmld()) 94 if (machine_is_palmld())
95 snd_soc_dapm_enable_pin(dapm, "MIC1"); 95 snd_soc_dapm_enable_pin(dapm, "MIC1");
96 snd_soc_dapm_enable_pin(dapm, "HPOUTL"); 96 snd_soc_dapm_enable_pin(dapm, "HPOUTL");
97 snd_soc_dapm_enable_pin(dapm, "HPOUTR"); 97 snd_soc_dapm_enable_pin(dapm, "HPOUTR");
98 snd_soc_dapm_enable_pin(dapm, "LOUT2"); 98 snd_soc_dapm_enable_pin(dapm, "LOUT2");
99 snd_soc_dapm_enable_pin(dapm, "ROUT2"); 99 snd_soc_dapm_enable_pin(dapm, "ROUT2");
100 100
101 /* not connected pins */ 101 /* not connected pins */
102 snd_soc_dapm_nc_pin(dapm, "OUT3"); 102 snd_soc_dapm_nc_pin(dapm, "OUT3");
103 snd_soc_dapm_nc_pin(dapm, "MONOOUT"); 103 snd_soc_dapm_nc_pin(dapm, "MONOOUT");
104 snd_soc_dapm_nc_pin(dapm, "LINEINL"); 104 snd_soc_dapm_nc_pin(dapm, "LINEINL");
105 snd_soc_dapm_nc_pin(dapm, "LINEINR"); 105 snd_soc_dapm_nc_pin(dapm, "LINEINR");
106 snd_soc_dapm_nc_pin(dapm, "PCBEEP"); 106 snd_soc_dapm_nc_pin(dapm, "PCBEEP");
107 snd_soc_dapm_nc_pin(dapm, "PHONE"); 107 snd_soc_dapm_nc_pin(dapm, "PHONE");
108 snd_soc_dapm_nc_pin(dapm, "MIC2"); 108 snd_soc_dapm_nc_pin(dapm, "MIC2");
109 109
110 err = snd_soc_dapm_sync(dapm);
111 if (err)
112 return err;
113
114 /* Jack detection API stuff */ 110 /* Jack detection API stuff */
115 err = snd_soc_jack_new(codec, "Headphone Jack", 111 err = snd_soc_jack_new(codec, "Headphone Jack",
116 SND_JACK_HEADPHONE, &hs_jack); 112 SND_JACK_HEADPHONE, &hs_jack);
117 if (err) 113 if (err)
118 return err; 114 return err;
119 115
120 err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), 116 err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
121 hs_jack_pins); 117 hs_jack_pins);
122 if (err) 118 if (err)
123 return err; 119 return err;
124 120
125 err = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), 121 err = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios),
126 hs_jack_gpios); 122 hs_jack_gpios);
127 123
128 return err; 124 return err;
129 } 125 }
130 126
131 static struct snd_soc_dai_link palm27x_dai[] = { 127 static struct snd_soc_dai_link palm27x_dai[] = {
132 { 128 {
133 .name = "AC97 HiFi", 129 .name = "AC97 HiFi",
134 .stream_name = "AC97 HiFi", 130 .stream_name = "AC97 HiFi",
135 .cpu_dai_name = "pxa2xx-ac97", 131 .cpu_dai_name = "pxa2xx-ac97",
136 .codec_dai_name = "wm9712-hifi", 132 .codec_dai_name = "wm9712-hifi",
137 .codec_name = "wm9712-codec", 133 .codec_name = "wm9712-codec",
138 .platform_name = "pxa-pcm-audio", 134 .platform_name = "pxa-pcm-audio",
139 .init = palm27x_ac97_init, 135 .init = palm27x_ac97_init,
140 }, 136 },
141 { 137 {
142 .name = "AC97 Aux", 138 .name = "AC97 Aux",
143 .stream_name = "AC97 Aux", 139 .stream_name = "AC97 Aux",
144 .cpu_dai_name = "pxa2xx-ac97-aux", 140 .cpu_dai_name = "pxa2xx-ac97-aux",
145 .codec_dai_name = "wm9712-aux", 141 .codec_dai_name = "wm9712-aux",
146 .codec_name = "wm9712-codec", 142 .codec_name = "wm9712-codec",
147 .platform_name = "pxa-pcm-audio", 143 .platform_name = "pxa-pcm-audio",
148 }, 144 },
149 }; 145 };
150 146
151 static struct snd_soc_card palm27x_asoc = { 147 static struct snd_soc_card palm27x_asoc = {
152 .name = "Palm/PXA27x", 148 .name = "Palm/PXA27x",
153 .dai_link = palm27x_dai, 149 .dai_link = palm27x_dai,
154 .num_links = ARRAY_SIZE(palm27x_dai), 150 .num_links = ARRAY_SIZE(palm27x_dai),
155 }; 151 };
156 152
157 static struct platform_device *palm27x_snd_device; 153 static struct platform_device *palm27x_snd_device;
158 154
159 static int palm27x_asoc_probe(struct platform_device *pdev) 155 static int palm27x_asoc_probe(struct platform_device *pdev)
160 { 156 {
161 int ret; 157 int ret;
162 158
163 if (!(machine_is_palmtx() || machine_is_palmt5() || 159 if (!(machine_is_palmtx() || machine_is_palmt5() ||
164 machine_is_palmld() || machine_is_palmte2())) 160 machine_is_palmld() || machine_is_palmte2()))
165 return -ENODEV; 161 return -ENODEV;
166 162
167 if (!pdev->dev.platform_data) { 163 if (!pdev->dev.platform_data) {
168 dev_err(&pdev->dev, "please supply platform_data\n"); 164 dev_err(&pdev->dev, "please supply platform_data\n");
169 return -ENODEV; 165 return -ENODEV;
170 } 166 }
171 167
172 hs_jack_gpios[0].gpio = ((struct palm27x_asoc_info *) 168 hs_jack_gpios[0].gpio = ((struct palm27x_asoc_info *)
173 (pdev->dev.platform_data))->jack_gpio; 169 (pdev->dev.platform_data))->jack_gpio;
174 170
175 palm27x_snd_device = platform_device_alloc("soc-audio", -1); 171 palm27x_snd_device = platform_device_alloc("soc-audio", -1);
176 if (!palm27x_snd_device) 172 if (!palm27x_snd_device)
177 return -ENOMEM; 173 return -ENOMEM;
178 174
179 platform_set_drvdata(palm27x_snd_device, &palm27x_asoc); 175 platform_set_drvdata(palm27x_snd_device, &palm27x_asoc);
180 ret = platform_device_add(palm27x_snd_device); 176 ret = platform_device_add(palm27x_snd_device);
181 177
182 if (ret != 0) 178 if (ret != 0)
183 goto put_device; 179 goto put_device;
184 180
185 return 0; 181 return 0;
186 182
187 put_device: 183 put_device:
188 platform_device_put(palm27x_snd_device); 184 platform_device_put(palm27x_snd_device);
189 185
190 return ret; 186 return ret;
191 } 187 }
192 188
193 static int __devexit palm27x_asoc_remove(struct platform_device *pdev) 189 static int __devexit palm27x_asoc_remove(struct platform_device *pdev)
194 { 190 {
195 platform_device_unregister(palm27x_snd_device); 191 platform_device_unregister(palm27x_snd_device);
196 return 0; 192 return 0;
197 } 193 }
198 194
199 static struct platform_driver palm27x_wm9712_driver = { 195 static struct platform_driver palm27x_wm9712_driver = {
200 .probe = palm27x_asoc_probe, 196 .probe = palm27x_asoc_probe,
201 .remove = __devexit_p(palm27x_asoc_remove), 197 .remove = __devexit_p(palm27x_asoc_remove),
202 .driver = { 198 .driver = {
203 .name = "palm27x-asoc", 199 .name = "palm27x-asoc",
204 .owner = THIS_MODULE, 200 .owner = THIS_MODULE,
205 }, 201 },
206 }; 202 };
207 203
208 static int __init palm27x_asoc_init(void) 204 static int __init palm27x_asoc_init(void)
209 { 205 {
210 return platform_driver_register(&palm27x_wm9712_driver); 206 return platform_driver_register(&palm27x_wm9712_driver);
211 } 207 }
212 208
213 static void __exit palm27x_asoc_exit(void) 209 static void __exit palm27x_asoc_exit(void)
214 { 210 {
215 platform_driver_unregister(&palm27x_wm9712_driver); 211 platform_driver_unregister(&palm27x_wm9712_driver);
216 } 212 }
217 213
218 module_init(palm27x_asoc_init); 214 module_init(palm27x_asoc_init);
219 module_exit(palm27x_asoc_exit); 215 module_exit(palm27x_asoc_exit);
220 216
221 /* Module information */ 217 /* Module information */
222 MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); 218 MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
223 MODULE_DESCRIPTION("ALSA SoC Palm T|X, T5 and LifeDrive"); 219 MODULE_DESCRIPTION("ALSA SoC Palm T|X, T5 and LifeDrive");
224 MODULE_LICENSE("GPL"); 220 MODULE_LICENSE("GPL");
225 221
sound/soc/pxa/saarb.c
1 /* 1 /*
2 * saarb.c -- SoC audio for saarb 2 * saarb.c -- SoC audio for saarb
3 * 3 *
4 * Copyright (C) 2010 Marvell International Ltd. 4 * Copyright (C) 2010 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com> 5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 */ 10 */
11 11
12 #include <linux/module.h> 12 #include <linux/module.h>
13 #include <linux/moduleparam.h> 13 #include <linux/moduleparam.h>
14 #include <linux/device.h> 14 #include <linux/device.h>
15 #include <linux/clk.h> 15 #include <linux/clk.h>
16 #include <linux/i2c.h> 16 #include <linux/i2c.h>
17 #include <sound/core.h> 17 #include <sound/core.h>
18 #include <sound/pcm.h> 18 #include <sound/pcm.h>
19 #include <sound/pcm_params.h> 19 #include <sound/pcm_params.h>
20 #include <sound/soc.h> 20 #include <sound/soc.h>
21 #include <sound/jack.h> 21 #include <sound/jack.h>
22 22
23 #include <asm/mach-types.h> 23 #include <asm/mach-types.h>
24 24
25 #include "../codecs/88pm860x-codec.h" 25 #include "../codecs/88pm860x-codec.h"
26 #include "pxa-ssp.h" 26 #include "pxa-ssp.h"
27 27
28 static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd); 28 static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd);
29 29
30 static struct platform_device *saarb_snd_device; 30 static struct platform_device *saarb_snd_device;
31 31
32 static struct snd_soc_jack hs_jack, mic_jack; 32 static struct snd_soc_jack hs_jack, mic_jack;
33 33
34 static struct snd_soc_jack_pin hs_jack_pins[] = { 34 static struct snd_soc_jack_pin hs_jack_pins[] = {
35 { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, }, 35 { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, },
36 }; 36 };
37 37
38 static struct snd_soc_jack_pin mic_jack_pins[] = { 38 static struct snd_soc_jack_pin mic_jack_pins[] = {
39 { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, }, 39 { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, },
40 }; 40 };
41 41
42 /* saarb machine dapm widgets */ 42 /* saarb machine dapm widgets */
43 static const struct snd_soc_dapm_widget saarb_dapm_widgets[] = { 43 static const struct snd_soc_dapm_widget saarb_dapm_widgets[] = {
44 SND_SOC_DAPM_HP("Headphone Stereophone", NULL), 44 SND_SOC_DAPM_HP("Headphone Stereophone", NULL),
45 SND_SOC_DAPM_LINE("Lineout Out 1", NULL), 45 SND_SOC_DAPM_LINE("Lineout Out 1", NULL),
46 SND_SOC_DAPM_LINE("Lineout Out 2", NULL), 46 SND_SOC_DAPM_LINE("Lineout Out 2", NULL),
47 SND_SOC_DAPM_SPK("Ext Speaker", NULL), 47 SND_SOC_DAPM_SPK("Ext Speaker", NULL),
48 SND_SOC_DAPM_MIC("Ext Mic 1", NULL), 48 SND_SOC_DAPM_MIC("Ext Mic 1", NULL),
49 SND_SOC_DAPM_MIC("Headset Mic", NULL), 49 SND_SOC_DAPM_MIC("Headset Mic", NULL),
50 SND_SOC_DAPM_MIC("Ext Mic 3", NULL), 50 SND_SOC_DAPM_MIC("Ext Mic 3", NULL),
51 }; 51 };
52 52
53 /* saarb machine audio map */ 53 /* saarb machine audio map */
54 static const struct snd_soc_dapm_route audio_map[] = { 54 static const struct snd_soc_dapm_route audio_map[] = {
55 {"Headset Stereophone", NULL, "HS1"}, 55 {"Headset Stereophone", NULL, "HS1"},
56 {"Headset Stereophone", NULL, "HS2"}, 56 {"Headset Stereophone", NULL, "HS2"},
57 57
58 {"Ext Speaker", NULL, "LSP"}, 58 {"Ext Speaker", NULL, "LSP"},
59 {"Ext Speaker", NULL, "LSN"}, 59 {"Ext Speaker", NULL, "LSN"},
60 60
61 {"Lineout Out 1", NULL, "LINEOUT1"}, 61 {"Lineout Out 1", NULL, "LINEOUT1"},
62 {"Lineout Out 2", NULL, "LINEOUT2"}, 62 {"Lineout Out 2", NULL, "LINEOUT2"},
63 63
64 {"MIC1P", NULL, "Mic1 Bias"}, 64 {"MIC1P", NULL, "Mic1 Bias"},
65 {"MIC1N", NULL, "Mic1 Bias"}, 65 {"MIC1N", NULL, "Mic1 Bias"},
66 {"Mic1 Bias", NULL, "Ext Mic 1"}, 66 {"Mic1 Bias", NULL, "Ext Mic 1"},
67 67
68 {"MIC2P", NULL, "Mic1 Bias"}, 68 {"MIC2P", NULL, "Mic1 Bias"},
69 {"MIC2N", NULL, "Mic1 Bias"}, 69 {"MIC2N", NULL, "Mic1 Bias"},
70 {"Mic1 Bias", NULL, "Headset Mic 2"}, 70 {"Mic1 Bias", NULL, "Headset Mic 2"},
71 71
72 {"MIC3P", NULL, "Mic3 Bias"}, 72 {"MIC3P", NULL, "Mic3 Bias"},
73 {"MIC3N", NULL, "Mic3 Bias"}, 73 {"MIC3N", NULL, "Mic3 Bias"},
74 {"Mic3 Bias", NULL, "Ext Mic 3"}, 74 {"Mic3 Bias", NULL, "Ext Mic 3"},
75 }; 75 };
76 76
77 static int saarb_i2s_hw_params(struct snd_pcm_substream *substream, 77 static int saarb_i2s_hw_params(struct snd_pcm_substream *substream,
78 struct snd_pcm_hw_params *params) 78 struct snd_pcm_hw_params *params)
79 { 79 {
80 struct snd_soc_pcm_runtime *rtd = substream->private_data; 80 struct snd_soc_pcm_runtime *rtd = substream->private_data;
81 struct snd_soc_dai *codec_dai = rtd->codec_dai; 81 struct snd_soc_dai *codec_dai = rtd->codec_dai;
82 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 82 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
83 int width = snd_pcm_format_physical_width(params_format(params)); 83 int width = snd_pcm_format_physical_width(params_format(params));
84 int ret; 84 int ret;
85 85
86 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0, 86 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0,
87 PM860X_CLK_DIR_OUT); 87 PM860X_CLK_DIR_OUT);
88 if (ret < 0) 88 if (ret < 0)
89 return ret; 89 return ret;
90 90
91 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT); 91 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT);
92 if (ret < 0) 92 if (ret < 0)
93 return ret; 93 return ret;
94 94
95 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 95 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
96 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 96 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
97 if (ret < 0) 97 if (ret < 0)
98 return ret; 98 return ret;
99 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 99 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
100 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 100 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
101 if (ret < 0) 101 if (ret < 0)
102 return ret; 102 return ret;
103 103
104 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width); 104 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width);
105 105
106 return ret; 106 return ret;
107 } 107 }
108 108
109 static struct snd_soc_ops saarb_i2s_ops = { 109 static struct snd_soc_ops saarb_i2s_ops = {
110 .hw_params = saarb_i2s_hw_params, 110 .hw_params = saarb_i2s_hw_params,
111 }; 111 };
112 112
113 static struct snd_soc_dai_link saarb_dai[] = { 113 static struct snd_soc_dai_link saarb_dai[] = {
114 { 114 {
115 .name = "88PM860x I2S", 115 .name = "88PM860x I2S",
116 .stream_name = "I2S Audio", 116 .stream_name = "I2S Audio",
117 .cpu_dai_name = "pxa-ssp-dai.1", 117 .cpu_dai_name = "pxa-ssp-dai.1",
118 .codec_dai_name = "88pm860x-i2s", 118 .codec_dai_name = "88pm860x-i2s",
119 .platform_name = "pxa-pcm-audio", 119 .platform_name = "pxa-pcm-audio",
120 .codec_name = "88pm860x-codec", 120 .codec_name = "88pm860x-codec",
121 .init = saarb_pm860x_init, 121 .init = saarb_pm860x_init,
122 .ops = &saarb_i2s_ops, 122 .ops = &saarb_i2s_ops,
123 }, 123 },
124 }; 124 };
125 125
126 static struct snd_soc_card snd_soc_card_saarb = { 126 static struct snd_soc_card snd_soc_card_saarb = {
127 .name = "Saarb", 127 .name = "Saarb",
128 .dai_link = saarb_dai, 128 .dai_link = saarb_dai,
129 .num_links = ARRAY_SIZE(saarb_dai), 129 .num_links = ARRAY_SIZE(saarb_dai),
130 }; 130 };
131 131
132 static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd) 132 static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd)
133 { 133 {
134 struct snd_soc_codec *codec = rtd->codec; 134 struct snd_soc_codec *codec = rtd->codec;
135 struct snd_soc_dapm_context *dapm = &codec->dapm; 135 struct snd_soc_dapm_context *dapm = &codec->dapm;
136 int ret; 136 int ret;
137 137
138 snd_soc_dapm_new_controls(dapm, saarb_dapm_widgets, 138 snd_soc_dapm_new_controls(dapm, saarb_dapm_widgets,
139 ARRAY_SIZE(saarb_dapm_widgets)); 139 ARRAY_SIZE(saarb_dapm_widgets));
140 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 140 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
141 141
142 /* connected pins */ 142 /* connected pins */
143 snd_soc_dapm_enable_pin(dapm, "Ext Speaker"); 143 snd_soc_dapm_enable_pin(dapm, "Ext Speaker");
144 snd_soc_dapm_enable_pin(dapm, "Ext Mic 1"); 144 snd_soc_dapm_enable_pin(dapm, "Ext Mic 1");
145 snd_soc_dapm_enable_pin(dapm, "Ext Mic 3"); 145 snd_soc_dapm_enable_pin(dapm, "Ext Mic 3");
146 snd_soc_dapm_disable_pin(dapm, "Headset Mic 2"); 146 snd_soc_dapm_disable_pin(dapm, "Headset Mic 2");
147 snd_soc_dapm_disable_pin(dapm, "Headset Stereophone"); 147 snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
148 148
149 ret = snd_soc_dapm_sync(dapm);
150 if (ret)
151 return ret;
152
153 /* Headset jack detection */ 149 /* Headset jack detection */
154 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE 150 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
155 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2, 151 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
156 &hs_jack); 152 &hs_jack);
157 snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), 153 snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
158 hs_jack_pins); 154 hs_jack_pins);
159 snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE, 155 snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE,
160 &mic_jack); 156 &mic_jack);
161 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), 157 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
162 mic_jack_pins); 158 mic_jack_pins);
163 159
164 /* headphone, microphone detection & headset short detection */ 160 /* headphone, microphone detection & headset short detection */
165 pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE, 161 pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE,
166 SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2); 162 SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2);
167 pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE); 163 pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE);
168 return 0; 164 return 0;
169 } 165 }
170 166
171 static int __init saarb_init(void) 167 static int __init saarb_init(void)
172 { 168 {
173 int ret; 169 int ret;
174 170
175 if (!machine_is_saarb()) 171 if (!machine_is_saarb())
176 return -ENODEV; 172 return -ENODEV;
177 saarb_snd_device = platform_device_alloc("soc-audio", -1); 173 saarb_snd_device = platform_device_alloc("soc-audio", -1);
178 if (!saarb_snd_device) 174 if (!saarb_snd_device)
179 return -ENOMEM; 175 return -ENOMEM;
180 176
181 platform_set_drvdata(saarb_snd_device, &snd_soc_card_saarb); 177 platform_set_drvdata(saarb_snd_device, &snd_soc_card_saarb);
182 178
183 ret = platform_device_add(saarb_snd_device); 179 ret = platform_device_add(saarb_snd_device);
184 if (ret) 180 if (ret)
185 platform_device_put(saarb_snd_device); 181 platform_device_put(saarb_snd_device);
186 182
187 return ret; 183 return ret;
188 } 184 }
189 185
190 static void __exit saarb_exit(void) 186 static void __exit saarb_exit(void)
191 { 187 {
192 platform_device_unregister(saarb_snd_device); 188 platform_device_unregister(saarb_snd_device);
193 } 189 }
194 190
195 module_init(saarb_init); 191 module_init(saarb_init);
196 module_exit(saarb_exit); 192 module_exit(saarb_exit);
197 193
198 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 194 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
199 MODULE_DESCRIPTION("ALSA SoC 88PM860x Saarb"); 195 MODULE_DESCRIPTION("ALSA SoC 88PM860x Saarb");
200 MODULE_LICENSE("GPL"); 196 MODULE_LICENSE("GPL");
201 197
sound/soc/pxa/tavorevb3.c
1 /* 1 /*
2 * tavorevb3.c -- SoC audio for Tavor EVB3 2 * tavorevb3.c -- SoC audio for Tavor EVB3
3 * 3 *
4 * Copyright (C) 2010 Marvell International Ltd. 4 * Copyright (C) 2010 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com> 5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 */ 10 */
11 11
12 #include <linux/module.h> 12 #include <linux/module.h>
13 #include <linux/moduleparam.h> 13 #include <linux/moduleparam.h>
14 #include <linux/device.h> 14 #include <linux/device.h>
15 #include <linux/clk.h> 15 #include <linux/clk.h>
16 #include <linux/i2c.h> 16 #include <linux/i2c.h>
17 #include <sound/core.h> 17 #include <sound/core.h>
18 #include <sound/pcm.h> 18 #include <sound/pcm.h>
19 #include <sound/pcm_params.h> 19 #include <sound/pcm_params.h>
20 #include <sound/soc.h> 20 #include <sound/soc.h>
21 #include <sound/jack.h> 21 #include <sound/jack.h>
22 22
23 #include <asm/mach-types.h> 23 #include <asm/mach-types.h>
24 24
25 #include "../codecs/88pm860x-codec.h" 25 #include "../codecs/88pm860x-codec.h"
26 #include "pxa-ssp.h" 26 #include "pxa-ssp.h"
27 27
28 static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd); 28 static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd);
29 29
30 static struct platform_device *evb3_snd_device; 30 static struct platform_device *evb3_snd_device;
31 31
32 static struct snd_soc_jack hs_jack, mic_jack; 32 static struct snd_soc_jack hs_jack, mic_jack;
33 33
34 static struct snd_soc_jack_pin hs_jack_pins[] = { 34 static struct snd_soc_jack_pin hs_jack_pins[] = {
35 { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, }, 35 { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, },
36 }; 36 };
37 37
38 static struct snd_soc_jack_pin mic_jack_pins[] = { 38 static struct snd_soc_jack_pin mic_jack_pins[] = {
39 { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, }, 39 { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, },
40 }; 40 };
41 41
42 /* tavorevb3 machine dapm widgets */ 42 /* tavorevb3 machine dapm widgets */
43 static const struct snd_soc_dapm_widget evb3_dapm_widgets[] = { 43 static const struct snd_soc_dapm_widget evb3_dapm_widgets[] = {
44 SND_SOC_DAPM_HP("Headset Stereophone", NULL), 44 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
45 SND_SOC_DAPM_LINE("Lineout Out 1", NULL), 45 SND_SOC_DAPM_LINE("Lineout Out 1", NULL),
46 SND_SOC_DAPM_LINE("Lineout Out 2", NULL), 46 SND_SOC_DAPM_LINE("Lineout Out 2", NULL),
47 SND_SOC_DAPM_SPK("Ext Speaker", NULL), 47 SND_SOC_DAPM_SPK("Ext Speaker", NULL),
48 SND_SOC_DAPM_MIC("Ext Mic 1", NULL), 48 SND_SOC_DAPM_MIC("Ext Mic 1", NULL),
49 SND_SOC_DAPM_MIC("Headset Mic 2", NULL), 49 SND_SOC_DAPM_MIC("Headset Mic 2", NULL),
50 SND_SOC_DAPM_MIC("Ext Mic 3", NULL), 50 SND_SOC_DAPM_MIC("Ext Mic 3", NULL),
51 }; 51 };
52 52
53 /* tavorevb3 machine audio map */ 53 /* tavorevb3 machine audio map */
54 static const struct snd_soc_dapm_route audio_map[] = { 54 static const struct snd_soc_dapm_route audio_map[] = {
55 {"Headset Stereophone", NULL, "HS1"}, 55 {"Headset Stereophone", NULL, "HS1"},
56 {"Headset Stereophone", NULL, "HS2"}, 56 {"Headset Stereophone", NULL, "HS2"},
57 57
58 {"Ext Speaker", NULL, "LSP"}, 58 {"Ext Speaker", NULL, "LSP"},
59 {"Ext Speaker", NULL, "LSN"}, 59 {"Ext Speaker", NULL, "LSN"},
60 60
61 {"Lineout Out 1", NULL, "LINEOUT1"}, 61 {"Lineout Out 1", NULL, "LINEOUT1"},
62 {"Lineout Out 2", NULL, "LINEOUT2"}, 62 {"Lineout Out 2", NULL, "LINEOUT2"},
63 63
64 {"MIC1P", NULL, "Mic1 Bias"}, 64 {"MIC1P", NULL, "Mic1 Bias"},
65 {"MIC1N", NULL, "Mic1 Bias"}, 65 {"MIC1N", NULL, "Mic1 Bias"},
66 {"Mic1 Bias", NULL, "Ext Mic 1"}, 66 {"Mic1 Bias", NULL, "Ext Mic 1"},
67 67
68 {"MIC2P", NULL, "Mic1 Bias"}, 68 {"MIC2P", NULL, "Mic1 Bias"},
69 {"MIC2N", NULL, "Mic1 Bias"}, 69 {"MIC2N", NULL, "Mic1 Bias"},
70 {"Mic1 Bias", NULL, "Headset Mic 2"}, 70 {"Mic1 Bias", NULL, "Headset Mic 2"},
71 71
72 {"MIC3P", NULL, "Mic3 Bias"}, 72 {"MIC3P", NULL, "Mic3 Bias"},
73 {"MIC3N", NULL, "Mic3 Bias"}, 73 {"MIC3N", NULL, "Mic3 Bias"},
74 {"Mic3 Bias", NULL, "Ext Mic 3"}, 74 {"Mic3 Bias", NULL, "Ext Mic 3"},
75 }; 75 };
76 76
77 static int evb3_i2s_hw_params(struct snd_pcm_substream *substream, 77 static int evb3_i2s_hw_params(struct snd_pcm_substream *substream,
78 struct snd_pcm_hw_params *params) 78 struct snd_pcm_hw_params *params)
79 { 79 {
80 struct snd_soc_pcm_runtime *rtd = substream->private_data; 80 struct snd_soc_pcm_runtime *rtd = substream->private_data;
81 struct snd_soc_dai *codec_dai = rtd->codec_dai; 81 struct snd_soc_dai *codec_dai = rtd->codec_dai;
82 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 82 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
83 int width = snd_pcm_format_physical_width(params_format(params)); 83 int width = snd_pcm_format_physical_width(params_format(params));
84 int ret; 84 int ret;
85 85
86 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0, 86 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0,
87 PM860X_CLK_DIR_OUT); 87 PM860X_CLK_DIR_OUT);
88 if (ret < 0) 88 if (ret < 0)
89 return ret; 89 return ret;
90 90
91 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT); 91 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT);
92 if (ret < 0) 92 if (ret < 0)
93 return ret; 93 return ret;
94 94
95 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 95 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
96 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 96 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
97 if (ret < 0) 97 if (ret < 0)
98 return ret; 98 return ret;
99 99
100 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 100 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
101 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 101 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
102 if (ret < 0) 102 if (ret < 0)
103 return ret; 103 return ret;
104 104
105 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width); 105 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width);
106 return ret; 106 return ret;
107 } 107 }
108 108
109 static struct snd_soc_ops evb3_i2s_ops = { 109 static struct snd_soc_ops evb3_i2s_ops = {
110 .hw_params = evb3_i2s_hw_params, 110 .hw_params = evb3_i2s_hw_params,
111 }; 111 };
112 112
113 static struct snd_soc_dai_link evb3_dai[] = { 113 static struct snd_soc_dai_link evb3_dai[] = {
114 { 114 {
115 .name = "88PM860x I2S", 115 .name = "88PM860x I2S",
116 .stream_name = "I2S Audio", 116 .stream_name = "I2S Audio",
117 .cpu_dai_name = "pxa-ssp-dai.1", 117 .cpu_dai_name = "pxa-ssp-dai.1",
118 .codec_dai_name = "88pm860x-i2s", 118 .codec_dai_name = "88pm860x-i2s",
119 .platform_name = "pxa-pcm-audio", 119 .platform_name = "pxa-pcm-audio",
120 .codec_name = "88pm860x-codec", 120 .codec_name = "88pm860x-codec",
121 .init = evb3_pm860x_init, 121 .init = evb3_pm860x_init,
122 .ops = &evb3_i2s_ops, 122 .ops = &evb3_i2s_ops,
123 }, 123 },
124 }; 124 };
125 125
126 static struct snd_soc_card snd_soc_card_evb3 = { 126 static struct snd_soc_card snd_soc_card_evb3 = {
127 .name = "Tavor EVB3", 127 .name = "Tavor EVB3",
128 .dai_link = evb3_dai, 128 .dai_link = evb3_dai,
129 .num_links = ARRAY_SIZE(evb3_dai), 129 .num_links = ARRAY_SIZE(evb3_dai),
130 }; 130 };
131 131
132 static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd) 132 static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd)
133 { 133 {
134 struct snd_soc_codec *codec = rtd->codec; 134 struct snd_soc_codec *codec = rtd->codec;
135 struct snd_soc_dapm_context *dapm = &codec->dapm; 135 struct snd_soc_dapm_context *dapm = &codec->dapm;
136 int ret; 136 int ret;
137 137
138 snd_soc_dapm_new_controls(dapm, evb3_dapm_widgets, 138 snd_soc_dapm_new_controls(dapm, evb3_dapm_widgets,
139 ARRAY_SIZE(evb3_dapm_widgets)); 139 ARRAY_SIZE(evb3_dapm_widgets));
140 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 140 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
141 141
142 /* connected pins */ 142 /* connected pins */
143 snd_soc_dapm_enable_pin(dapm, "Ext Speaker"); 143 snd_soc_dapm_enable_pin(dapm, "Ext Speaker");
144 snd_soc_dapm_enable_pin(dapm, "Ext Mic 1"); 144 snd_soc_dapm_enable_pin(dapm, "Ext Mic 1");
145 snd_soc_dapm_enable_pin(dapm, "Ext Mic 3"); 145 snd_soc_dapm_enable_pin(dapm, "Ext Mic 3");
146 snd_soc_dapm_disable_pin(dapm, "Headset Mic 2"); 146 snd_soc_dapm_disable_pin(dapm, "Headset Mic 2");
147 snd_soc_dapm_disable_pin(dapm, "Headset Stereophone"); 147 snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
148 148
149 ret = snd_soc_dapm_sync(dapm);
150 if (ret)
151 return ret;
152
153 /* Headset jack detection */ 149 /* Headset jack detection */
154 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE 150 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
155 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2, 151 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
156 &hs_jack); 152 &hs_jack);
157 snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), 153 snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
158 hs_jack_pins); 154 hs_jack_pins);
159 snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE, 155 snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE,
160 &mic_jack); 156 &mic_jack);
161 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), 157 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
162 mic_jack_pins); 158 mic_jack_pins);
163 159
164 /* headphone, microphone detection & headset short detection */ 160 /* headphone, microphone detection & headset short detection */
165 pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE, 161 pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE,
166 SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2); 162 SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2);
167 pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE); 163 pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE);
168 return 0; 164 return 0;
169 } 165 }
170 166
171 static int __init tavorevb3_init(void) 167 static int __init tavorevb3_init(void)
172 { 168 {
173 int ret; 169 int ret;
174 170
175 if (!machine_is_tavorevb3()) 171 if (!machine_is_tavorevb3())
176 return -ENODEV; 172 return -ENODEV;
177 evb3_snd_device = platform_device_alloc("soc-audio", -1); 173 evb3_snd_device = platform_device_alloc("soc-audio", -1);
178 if (!evb3_snd_device) 174 if (!evb3_snd_device)
179 return -ENOMEM; 175 return -ENOMEM;
180 176
181 platform_set_drvdata(evb3_snd_device, &snd_soc_card_evb3); 177 platform_set_drvdata(evb3_snd_device, &snd_soc_card_evb3);
182 178
183 ret = platform_device_add(evb3_snd_device); 179 ret = platform_device_add(evb3_snd_device);
184 if (ret) 180 if (ret)
185 platform_device_put(evb3_snd_device); 181 platform_device_put(evb3_snd_device);
186 182
187 return ret; 183 return ret;
188 } 184 }
189 185
190 static void __exit tavorevb3_exit(void) 186 static void __exit tavorevb3_exit(void)
191 { 187 {
192 platform_device_unregister(evb3_snd_device); 188 platform_device_unregister(evb3_snd_device);
193 } 189 }
194 190
195 module_init(tavorevb3_init); 191 module_init(tavorevb3_init);
196 module_exit(tavorevb3_exit); 192 module_exit(tavorevb3_exit);
197 193
198 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 194 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
199 MODULE_DESCRIPTION("ALSA SoC 88PM860x Tavor EVB3"); 195 MODULE_DESCRIPTION("ALSA SoC 88PM860x Tavor EVB3");
200 MODULE_LICENSE("GPL"); 196 MODULE_LICENSE("GPL");
201 197
sound/soc/pxa/tosa.c
1 /* 1 /*
2 * tosa.c -- SoC audio for Tosa 2 * tosa.c -- SoC audio for Tosa
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 * GPIO's 15 * GPIO's
16 * 1 - Jack Insertion 16 * 1 - Jack Insertion
17 * 5 - Hookswitch (headset answer/hang up switch) 17 * 5 - Hookswitch (headset answer/hang up switch)
18 * 18 *
19 */ 19 */
20 20
21 #include <linux/module.h> 21 #include <linux/module.h>
22 #include <linux/moduleparam.h> 22 #include <linux/moduleparam.h>
23 #include <linux/device.h> 23 #include <linux/device.h>
24 #include <linux/gpio.h> 24 #include <linux/gpio.h>
25 25
26 #include <sound/core.h> 26 #include <sound/core.h>
27 #include <sound/pcm.h> 27 #include <sound/pcm.h>
28 #include <sound/soc.h> 28 #include <sound/soc.h>
29 29
30 #include <asm/mach-types.h> 30 #include <asm/mach-types.h>
31 #include <mach/tosa.h> 31 #include <mach/tosa.h>
32 #include <mach/audio.h> 32 #include <mach/audio.h>
33 33
34 #include "../codecs/wm9712.h" 34 #include "../codecs/wm9712.h"
35 #include "pxa2xx-ac97.h" 35 #include "pxa2xx-ac97.h"
36 36
37 static struct snd_soc_card tosa; 37 static struct snd_soc_card tosa;
38 38
39 #define TOSA_HP 0 39 #define TOSA_HP 0
40 #define TOSA_MIC_INT 1 40 #define TOSA_MIC_INT 1
41 #define TOSA_HEADSET 2 41 #define TOSA_HEADSET 2
42 #define TOSA_HP_OFF 3 42 #define TOSA_HP_OFF 3
43 #define TOSA_SPK_ON 0 43 #define TOSA_SPK_ON 0
44 #define TOSA_SPK_OFF 1 44 #define TOSA_SPK_OFF 1
45 45
46 static int tosa_jack_func; 46 static int tosa_jack_func;
47 static int tosa_spk_func; 47 static int tosa_spk_func;
48 48
49 static void tosa_ext_control(struct snd_soc_codec *codec) 49 static void tosa_ext_control(struct snd_soc_codec *codec)
50 { 50 {
51 struct snd_soc_dapm_context *dapm = &codec->dapm; 51 struct snd_soc_dapm_context *dapm = &codec->dapm;
52 52
53 /* set up jack connection */ 53 /* set up jack connection */
54 switch (tosa_jack_func) { 54 switch (tosa_jack_func) {
55 case TOSA_HP: 55 case TOSA_HP:
56 snd_soc_dapm_disable_pin(dapm, "Mic (Internal)"); 56 snd_soc_dapm_disable_pin(dapm, "Mic (Internal)");
57 snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); 57 snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
58 snd_soc_dapm_disable_pin(dapm, "Headset Jack"); 58 snd_soc_dapm_disable_pin(dapm, "Headset Jack");
59 break; 59 break;
60 case TOSA_MIC_INT: 60 case TOSA_MIC_INT:
61 snd_soc_dapm_enable_pin(dapm, "Mic (Internal)"); 61 snd_soc_dapm_enable_pin(dapm, "Mic (Internal)");
62 snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); 62 snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
63 snd_soc_dapm_disable_pin(dapm, "Headset Jack"); 63 snd_soc_dapm_disable_pin(dapm, "Headset Jack");
64 break; 64 break;
65 case TOSA_HEADSET: 65 case TOSA_HEADSET:
66 snd_soc_dapm_disable_pin(dapm, "Mic (Internal)"); 66 snd_soc_dapm_disable_pin(dapm, "Mic (Internal)");
67 snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); 67 snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
68 snd_soc_dapm_enable_pin(dapm, "Headset Jack"); 68 snd_soc_dapm_enable_pin(dapm, "Headset Jack");
69 break; 69 break;
70 } 70 }
71 71
72 if (tosa_spk_func == TOSA_SPK_ON) 72 if (tosa_spk_func == TOSA_SPK_ON)
73 snd_soc_dapm_enable_pin(dapm, "Speaker"); 73 snd_soc_dapm_enable_pin(dapm, "Speaker");
74 else 74 else
75 snd_soc_dapm_disable_pin(dapm, "Speaker"); 75 snd_soc_dapm_disable_pin(dapm, "Speaker");
76 76
77 snd_soc_dapm_sync(dapm); 77 snd_soc_dapm_sync(dapm);
78 } 78 }
79 79
80 static int tosa_startup(struct snd_pcm_substream *substream) 80 static int tosa_startup(struct snd_pcm_substream *substream)
81 { 81 {
82 struct snd_soc_pcm_runtime *rtd = substream->private_data; 82 struct snd_soc_pcm_runtime *rtd = substream->private_data;
83 struct snd_soc_codec *codec = rtd->codec; 83 struct snd_soc_codec *codec = rtd->codec;
84 84
85 mutex_lock(&codec->mutex); 85 mutex_lock(&codec->mutex);
86 86
87 /* check the jack status at stream startup */ 87 /* check the jack status at stream startup */
88 tosa_ext_control(codec); 88 tosa_ext_control(codec);
89 89
90 mutex_unlock(&codec->mutex); 90 mutex_unlock(&codec->mutex);
91 91
92 return 0; 92 return 0;
93 } 93 }
94 94
95 static struct snd_soc_ops tosa_ops = { 95 static struct snd_soc_ops tosa_ops = {
96 .startup = tosa_startup, 96 .startup = tosa_startup,
97 }; 97 };
98 98
99 static int tosa_get_jack(struct snd_kcontrol *kcontrol, 99 static int tosa_get_jack(struct snd_kcontrol *kcontrol,
100 struct snd_ctl_elem_value *ucontrol) 100 struct snd_ctl_elem_value *ucontrol)
101 { 101 {
102 ucontrol->value.integer.value[0] = tosa_jack_func; 102 ucontrol->value.integer.value[0] = tosa_jack_func;
103 return 0; 103 return 0;
104 } 104 }
105 105
106 static int tosa_set_jack(struct snd_kcontrol *kcontrol, 106 static int tosa_set_jack(struct snd_kcontrol *kcontrol,
107 struct snd_ctl_elem_value *ucontrol) 107 struct snd_ctl_elem_value *ucontrol)
108 { 108 {
109 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 109 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
110 110
111 if (tosa_jack_func == ucontrol->value.integer.value[0]) 111 if (tosa_jack_func == ucontrol->value.integer.value[0])
112 return 0; 112 return 0;
113 113
114 tosa_jack_func = ucontrol->value.integer.value[0]; 114 tosa_jack_func = ucontrol->value.integer.value[0];
115 tosa_ext_control(codec); 115 tosa_ext_control(codec);
116 return 1; 116 return 1;
117 } 117 }
118 118
119 static int tosa_get_spk(struct snd_kcontrol *kcontrol, 119 static int tosa_get_spk(struct snd_kcontrol *kcontrol,
120 struct snd_ctl_elem_value *ucontrol) 120 struct snd_ctl_elem_value *ucontrol)
121 { 121 {
122 ucontrol->value.integer.value[0] = tosa_spk_func; 122 ucontrol->value.integer.value[0] = tosa_spk_func;
123 return 0; 123 return 0;
124 } 124 }
125 125
126 static int tosa_set_spk(struct snd_kcontrol *kcontrol, 126 static int tosa_set_spk(struct snd_kcontrol *kcontrol,
127 struct snd_ctl_elem_value *ucontrol) 127 struct snd_ctl_elem_value *ucontrol)
128 { 128 {
129 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 129 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
130 130
131 if (tosa_spk_func == ucontrol->value.integer.value[0]) 131 if (tosa_spk_func == ucontrol->value.integer.value[0])
132 return 0; 132 return 0;
133 133
134 tosa_spk_func = ucontrol->value.integer.value[0]; 134 tosa_spk_func = ucontrol->value.integer.value[0];
135 tosa_ext_control(codec); 135 tosa_ext_control(codec);
136 return 1; 136 return 1;
137 } 137 }
138 138
139 /* tosa dapm event handlers */ 139 /* tosa dapm event handlers */
140 static int tosa_hp_event(struct snd_soc_dapm_widget *w, 140 static int tosa_hp_event(struct snd_soc_dapm_widget *w,
141 struct snd_kcontrol *k, int event) 141 struct snd_kcontrol *k, int event)
142 { 142 {
143 gpio_set_value(TOSA_GPIO_L_MUTE, SND_SOC_DAPM_EVENT_ON(event) ? 1 :0); 143 gpio_set_value(TOSA_GPIO_L_MUTE, SND_SOC_DAPM_EVENT_ON(event) ? 1 :0);
144 return 0; 144 return 0;
145 } 145 }
146 146
147 /* tosa machine dapm widgets */ 147 /* tosa machine dapm widgets */
148 static const struct snd_soc_dapm_widget tosa_dapm_widgets[] = { 148 static const struct snd_soc_dapm_widget tosa_dapm_widgets[] = {
149 SND_SOC_DAPM_HP("Headphone Jack", tosa_hp_event), 149 SND_SOC_DAPM_HP("Headphone Jack", tosa_hp_event),
150 SND_SOC_DAPM_HP("Headset Jack", NULL), 150 SND_SOC_DAPM_HP("Headset Jack", NULL),
151 SND_SOC_DAPM_MIC("Mic (Internal)", NULL), 151 SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
152 SND_SOC_DAPM_SPK("Speaker", NULL), 152 SND_SOC_DAPM_SPK("Speaker", NULL),
153 }; 153 };
154 154
155 /* tosa audio map */ 155 /* tosa audio map */
156 static const struct snd_soc_dapm_route audio_map[] = { 156 static const struct snd_soc_dapm_route audio_map[] = {
157 157
158 /* headphone connected to HPOUTL, HPOUTR */ 158 /* headphone connected to HPOUTL, HPOUTR */
159 {"Headphone Jack", NULL, "HPOUTL"}, 159 {"Headphone Jack", NULL, "HPOUTL"},
160 {"Headphone Jack", NULL, "HPOUTR"}, 160 {"Headphone Jack", NULL, "HPOUTR"},
161 161
162 /* ext speaker connected to LOUT2, ROUT2 */ 162 /* ext speaker connected to LOUT2, ROUT2 */
163 {"Speaker", NULL, "LOUT2"}, 163 {"Speaker", NULL, "LOUT2"},
164 {"Speaker", NULL, "ROUT2"}, 164 {"Speaker", NULL, "ROUT2"},
165 165
166 /* internal mic is connected to mic1, mic2 differential - with bias */ 166 /* internal mic is connected to mic1, mic2 differential - with bias */
167 {"MIC1", NULL, "Mic Bias"}, 167 {"MIC1", NULL, "Mic Bias"},
168 {"MIC2", NULL, "Mic Bias"}, 168 {"MIC2", NULL, "Mic Bias"},
169 {"Mic Bias", NULL, "Mic (Internal)"}, 169 {"Mic Bias", NULL, "Mic (Internal)"},
170 170
171 /* headset is connected to HPOUTR, and LINEINR with bias */ 171 /* headset is connected to HPOUTR, and LINEINR with bias */
172 {"Headset Jack", NULL, "HPOUTR"}, 172 {"Headset Jack", NULL, "HPOUTR"},
173 {"LINEINR", NULL, "Mic Bias"}, 173 {"LINEINR", NULL, "Mic Bias"},
174 {"Mic Bias", NULL, "Headset Jack"}, 174 {"Mic Bias", NULL, "Headset Jack"},
175 }; 175 };
176 176
177 static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", 177 static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
178 "Off"}; 178 "Off"};
179 static const char *spk_function[] = {"On", "Off"}; 179 static const char *spk_function[] = {"On", "Off"};
180 static const struct soc_enum tosa_enum[] = { 180 static const struct soc_enum tosa_enum[] = {
181 SOC_ENUM_SINGLE_EXT(5, jack_function), 181 SOC_ENUM_SINGLE_EXT(5, jack_function),
182 SOC_ENUM_SINGLE_EXT(2, spk_function), 182 SOC_ENUM_SINGLE_EXT(2, spk_function),
183 }; 183 };
184 184
185 static const struct snd_kcontrol_new tosa_controls[] = { 185 static const struct snd_kcontrol_new tosa_controls[] = {
186 SOC_ENUM_EXT("Jack Function", tosa_enum[0], tosa_get_jack, 186 SOC_ENUM_EXT("Jack Function", tosa_enum[0], tosa_get_jack,
187 tosa_set_jack), 187 tosa_set_jack),
188 SOC_ENUM_EXT("Speaker Function", tosa_enum[1], tosa_get_spk, 188 SOC_ENUM_EXT("Speaker Function", tosa_enum[1], tosa_get_spk,
189 tosa_set_spk), 189 tosa_set_spk),
190 }; 190 };
191 191
192 static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd) 192 static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd)
193 { 193 {
194 struct snd_soc_codec *codec = rtd->codec; 194 struct snd_soc_codec *codec = rtd->codec;
195 struct snd_soc_dapm_context *dapm = &codec->dapm; 195 struct snd_soc_dapm_context *dapm = &codec->dapm;
196 int err; 196 int err;
197 197
198 snd_soc_dapm_nc_pin(dapm, "OUT3"); 198 snd_soc_dapm_nc_pin(dapm, "OUT3");
199 snd_soc_dapm_nc_pin(dapm, "MONOOUT"); 199 snd_soc_dapm_nc_pin(dapm, "MONOOUT");
200 200
201 /* add tosa specific controls */ 201 /* add tosa specific controls */
202 err = snd_soc_add_controls(codec, tosa_controls, 202 err = snd_soc_add_controls(codec, tosa_controls,
203 ARRAY_SIZE(tosa_controls)); 203 ARRAY_SIZE(tosa_controls));
204 if (err < 0) 204 if (err < 0)
205 return err; 205 return err;
206 206
207 /* add tosa specific widgets */ 207 /* add tosa specific widgets */
208 snd_soc_dapm_new_controls(dapm, tosa_dapm_widgets, 208 snd_soc_dapm_new_controls(dapm, tosa_dapm_widgets,
209 ARRAY_SIZE(tosa_dapm_widgets)); 209 ARRAY_SIZE(tosa_dapm_widgets));
210 210
211 /* set up tosa specific audio path audio_map */ 211 /* set up tosa specific audio path audio_map */
212 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 212 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
213 213
214 snd_soc_dapm_sync(dapm);
215 return 0; 214 return 0;
216 } 215 }
217 216
218 static struct snd_soc_dai_link tosa_dai[] = { 217 static struct snd_soc_dai_link tosa_dai[] = {
219 { 218 {
220 .name = "AC97", 219 .name = "AC97",
221 .stream_name = "AC97 HiFi", 220 .stream_name = "AC97 HiFi",
222 .cpu_dai_name = "pxa2xx-ac97", 221 .cpu_dai_name = "pxa2xx-ac97",
223 .codec_dai_name = "wm9712-hifi", 222 .codec_dai_name = "wm9712-hifi",
224 .platform_name = "pxa-pcm-audio", 223 .platform_name = "pxa-pcm-audio",
225 .codec_name = "wm9712-codec", 224 .codec_name = "wm9712-codec",
226 .init = tosa_ac97_init, 225 .init = tosa_ac97_init,
227 .ops = &tosa_ops, 226 .ops = &tosa_ops,
228 }, 227 },
229 { 228 {
230 .name = "AC97 Aux", 229 .name = "AC97 Aux",
231 .stream_name = "AC97 Aux", 230 .stream_name = "AC97 Aux",
232 .cpu_dai_name = "pxa2xx-ac97-aux", 231 .cpu_dai_name = "pxa2xx-ac97-aux",
233 .codec_dai_name = "wm9712-aux", 232 .codec_dai_name = "wm9712-aux",
234 .platform_name = "pxa-pcm-audio", 233 .platform_name = "pxa-pcm-audio",
235 .codec_name = "wm9712-codec", 234 .codec_name = "wm9712-codec",
236 .ops = &tosa_ops, 235 .ops = &tosa_ops,
237 }, 236 },
238 }; 237 };
239 238
240 static int tosa_probe(struct snd_soc_card *card) 239 static int tosa_probe(struct snd_soc_card *card)
241 { 240 {
242 int ret; 241 int ret;
243 242
244 ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack"); 243 ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack");
245 if (ret) 244 if (ret)
246 return ret; 245 return ret;
247 ret = gpio_direction_output(TOSA_GPIO_L_MUTE, 0); 246 ret = gpio_direction_output(TOSA_GPIO_L_MUTE, 0);
248 if (ret) 247 if (ret)
249 gpio_free(TOSA_GPIO_L_MUTE); 248 gpio_free(TOSA_GPIO_L_MUTE);
250 249
251 return ret; 250 return ret;
252 } 251 }
253 252
254 static int tosa_remove(struct snd_soc_card *card) 253 static int tosa_remove(struct snd_soc_card *card)
255 { 254 {
256 gpio_free(TOSA_GPIO_L_MUTE); 255 gpio_free(TOSA_GPIO_L_MUTE);
257 return 0; 256 return 0;
258 } 257 }
259 258
260 static struct snd_soc_card tosa = { 259 static struct snd_soc_card tosa = {
261 .name = "Tosa", 260 .name = "Tosa",
262 .dai_link = tosa_dai, 261 .dai_link = tosa_dai,
263 .num_links = ARRAY_SIZE(tosa_dai), 262 .num_links = ARRAY_SIZE(tosa_dai),
264 .probe = tosa_probe, 263 .probe = tosa_probe,
265 .remove = tosa_remove, 264 .remove = tosa_remove,
266 }; 265 };
267 266
268 static struct platform_device *tosa_snd_device; 267 static struct platform_device *tosa_snd_device;
269 268
270 static int __init tosa_init(void) 269 static int __init tosa_init(void)
271 { 270 {
272 int ret; 271 int ret;
273 272
274 if (!machine_is_tosa()) 273 if (!machine_is_tosa())
275 return -ENODEV; 274 return -ENODEV;
276 275
277 tosa_snd_device = platform_device_alloc("soc-audio", -1); 276 tosa_snd_device = platform_device_alloc("soc-audio", -1);
278 if (!tosa_snd_device) { 277 if (!tosa_snd_device) {
279 ret = -ENOMEM; 278 ret = -ENOMEM;
280 goto err_alloc; 279 goto err_alloc;
281 } 280 }
282 281
283 platform_set_drvdata(tosa_snd_device, &tosa); 282 platform_set_drvdata(tosa_snd_device, &tosa);
284 ret = platform_device_add(tosa_snd_device); 283 ret = platform_device_add(tosa_snd_device);
285 284
286 if (!ret) 285 if (!ret)
287 return 0; 286 return 0;
288 287
289 platform_device_put(tosa_snd_device); 288 platform_device_put(tosa_snd_device);
290 289
291 err_alloc: 290 err_alloc:
292 return ret; 291 return ret;
293 } 292 }
294 293
295 static void __exit tosa_exit(void) 294 static void __exit tosa_exit(void)
296 { 295 {
297 platform_device_unregister(tosa_snd_device); 296 platform_device_unregister(tosa_snd_device);
298 } 297 }
299 298
300 module_init(tosa_init); 299 module_init(tosa_init);
301 module_exit(tosa_exit); 300 module_exit(tosa_exit);
302 301
303 /* Module information */ 302 /* Module information */
304 MODULE_AUTHOR("Richard Purdie"); 303 MODULE_AUTHOR("Richard Purdie");
305 MODULE_DESCRIPTION("ALSA SoC Tosa"); 304 MODULE_DESCRIPTION("ALSA SoC Tosa");
306 MODULE_LICENSE("GPL"); 305 MODULE_LICENSE("GPL");
307 306
1 /* 1 /*
2 * linux/sound/soc/pxa/z2.c 2 * linux/sound/soc/pxa/z2.c
3 * 3 *
4 * SoC Audio driver for Aeronix Zipit Z2 4 * SoC Audio driver for Aeronix Zipit Z2
5 * 5 *
6 * Copyright (C) 2009 Ken McGuire <kenm@desertweyr.com> 6 * Copyright (C) 2009 Ken McGuire <kenm@desertweyr.com>
7 * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com> 7 * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12 */ 12 */
13 13
14 #include <linux/module.h> 14 #include <linux/module.h>
15 #include <linux/moduleparam.h> 15 #include <linux/moduleparam.h>
16 #include <linux/timer.h> 16 #include <linux/timer.h>
17 #include <linux/interrupt.h> 17 #include <linux/interrupt.h>
18 #include <linux/platform_device.h> 18 #include <linux/platform_device.h>
19 #include <linux/gpio.h> 19 #include <linux/gpio.h>
20 20
21 #include <sound/core.h> 21 #include <sound/core.h>
22 #include <sound/pcm.h> 22 #include <sound/pcm.h>
23 #include <sound/soc.h> 23 #include <sound/soc.h>
24 #include <sound/jack.h> 24 #include <sound/jack.h>
25 25
26 #include <asm/mach-types.h> 26 #include <asm/mach-types.h>
27 #include <mach/hardware.h> 27 #include <mach/hardware.h>
28 #include <mach/audio.h> 28 #include <mach/audio.h>
29 #include <mach/z2.h> 29 #include <mach/z2.h>
30 30
31 #include "../codecs/wm8750.h" 31 #include "../codecs/wm8750.h"
32 #include "pxa2xx-i2s.h" 32 #include "pxa2xx-i2s.h"
33 33
34 static struct snd_soc_card snd_soc_z2; 34 static struct snd_soc_card snd_soc_z2;
35 35
36 static int z2_hw_params(struct snd_pcm_substream *substream, 36 static int z2_hw_params(struct snd_pcm_substream *substream,
37 struct snd_pcm_hw_params *params) 37 struct snd_pcm_hw_params *params)
38 { 38 {
39 struct snd_soc_pcm_runtime *rtd = substream->private_data; 39 struct snd_soc_pcm_runtime *rtd = substream->private_data;
40 struct snd_soc_dai *codec_dai = rtd->codec_dai; 40 struct snd_soc_dai *codec_dai = rtd->codec_dai;
41 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 41 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
42 unsigned int clk = 0; 42 unsigned int clk = 0;
43 int ret = 0; 43 int ret = 0;
44 44
45 switch (params_rate(params)) { 45 switch (params_rate(params)) {
46 case 8000: 46 case 8000:
47 case 16000: 47 case 16000:
48 case 48000: 48 case 48000:
49 case 96000: 49 case 96000:
50 clk = 12288000; 50 clk = 12288000;
51 break; 51 break;
52 case 11025: 52 case 11025:
53 case 22050: 53 case 22050:
54 case 44100: 54 case 44100:
55 clk = 11289600; 55 clk = 11289600;
56 break; 56 break;
57 } 57 }
58 58
59 /* set codec DAI configuration */ 59 /* set codec DAI configuration */
60 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 60 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
61 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 61 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
62 if (ret < 0) 62 if (ret < 0)
63 return ret; 63 return ret;
64 64
65 /* set cpu DAI configuration */ 65 /* set cpu DAI configuration */
66 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 66 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
67 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 67 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
68 if (ret < 0) 68 if (ret < 0)
69 return ret; 69 return ret;
70 70
71 /* set the codec system clock for DAC and ADC */ 71 /* set the codec system clock for DAC and ADC */
72 ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk, 72 ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
73 SND_SOC_CLOCK_IN); 73 SND_SOC_CLOCK_IN);
74 if (ret < 0) 74 if (ret < 0)
75 return ret; 75 return ret;
76 76
77 /* set the I2S system clock as input (unused) */ 77 /* set the I2S system clock as input (unused) */
78 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0, 78 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
79 SND_SOC_CLOCK_IN); 79 SND_SOC_CLOCK_IN);
80 if (ret < 0) 80 if (ret < 0)
81 return ret; 81 return ret;
82 82
83 return 0; 83 return 0;
84 } 84 }
85 85
86 static struct snd_soc_jack hs_jack; 86 static struct snd_soc_jack hs_jack;
87 87
88 /* Headset jack detection DAPM pins */ 88 /* Headset jack detection DAPM pins */
89 static struct snd_soc_jack_pin hs_jack_pins[] = { 89 static struct snd_soc_jack_pin hs_jack_pins[] = {
90 { 90 {
91 .pin = "Mic Jack", 91 .pin = "Mic Jack",
92 .mask = SND_JACK_MICROPHONE, 92 .mask = SND_JACK_MICROPHONE,
93 }, 93 },
94 { 94 {
95 .pin = "Headphone Jack", 95 .pin = "Headphone Jack",
96 .mask = SND_JACK_HEADPHONE, 96 .mask = SND_JACK_HEADPHONE,
97 }, 97 },
98 { 98 {
99 .pin = "Ext Spk", 99 .pin = "Ext Spk",
100 .mask = SND_JACK_HEADPHONE, 100 .mask = SND_JACK_HEADPHONE,
101 .invert = 1 101 .invert = 1
102 }, 102 },
103 }; 103 };
104 104
105 /* Headset jack detection gpios */ 105 /* Headset jack detection gpios */
106 static struct snd_soc_jack_gpio hs_jack_gpios[] = { 106 static struct snd_soc_jack_gpio hs_jack_gpios[] = {
107 { 107 {
108 .gpio = GPIO37_ZIPITZ2_HEADSET_DETECT, 108 .gpio = GPIO37_ZIPITZ2_HEADSET_DETECT,
109 .name = "hsdet-gpio", 109 .name = "hsdet-gpio",
110 .report = SND_JACK_HEADSET, 110 .report = SND_JACK_HEADSET,
111 .debounce_time = 200, 111 .debounce_time = 200,
112 .invert = 1, 112 .invert = 1,
113 }, 113 },
114 }; 114 };
115 115
116 /* z2 machine dapm widgets */ 116 /* z2 machine dapm widgets */
117 static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = { 117 static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
118 SND_SOC_DAPM_HP("Headphone Jack", NULL), 118 SND_SOC_DAPM_HP("Headphone Jack", NULL),
119 SND_SOC_DAPM_MIC("Mic Jack", NULL), 119 SND_SOC_DAPM_MIC("Mic Jack", NULL),
120 SND_SOC_DAPM_SPK("Ext Spk", NULL), 120 SND_SOC_DAPM_SPK("Ext Spk", NULL),
121 121
122 /* headset is a mic and mono headphone */ 122 /* headset is a mic and mono headphone */
123 SND_SOC_DAPM_HP("Headset Jack", NULL), 123 SND_SOC_DAPM_HP("Headset Jack", NULL),
124 }; 124 };
125 125
126 /* Z2 machine audio_map */ 126 /* Z2 machine audio_map */
127 static const struct snd_soc_dapm_route audio_map[] = { 127 static const struct snd_soc_dapm_route audio_map[] = {
128 128
129 /* headphone connected to LOUT1, ROUT1 */ 129 /* headphone connected to LOUT1, ROUT1 */
130 {"Headphone Jack", NULL, "LOUT1"}, 130 {"Headphone Jack", NULL, "LOUT1"},
131 {"Headphone Jack", NULL, "ROUT1"}, 131 {"Headphone Jack", NULL, "ROUT1"},
132 132
133 /* ext speaker connected to LOUT2, ROUT2 */ 133 /* ext speaker connected to LOUT2, ROUT2 */
134 {"Ext Spk", NULL , "ROUT2"}, 134 {"Ext Spk", NULL , "ROUT2"},
135 {"Ext Spk", NULL , "LOUT2"}, 135 {"Ext Spk", NULL , "LOUT2"},
136 136
137 /* mic is connected to R input 2 - with bias */ 137 /* mic is connected to R input 2 - with bias */
138 {"RINPUT2", NULL, "Mic Bias"}, 138 {"RINPUT2", NULL, "Mic Bias"},
139 {"Mic Bias", NULL, "Mic Jack"}, 139 {"Mic Bias", NULL, "Mic Jack"},
140 }; 140 };
141 141
142 /* 142 /*
143 * Logic for a wm8750 as connected on a Z2 Device 143 * Logic for a wm8750 as connected on a Z2 Device
144 */ 144 */
145 static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd) 145 static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd)
146 { 146 {
147 struct snd_soc_codec *codec = rtd->codec; 147 struct snd_soc_codec *codec = rtd->codec;
148 struct snd_soc_dapm_context *dapm = &codec->dapm; 148 struct snd_soc_dapm_context *dapm = &codec->dapm;
149 int ret; 149 int ret;
150 150
151 /* NC codec pins */ 151 /* NC codec pins */
152 snd_soc_dapm_disable_pin(dapm, "LINPUT3"); 152 snd_soc_dapm_disable_pin(dapm, "LINPUT3");
153 snd_soc_dapm_disable_pin(dapm, "RINPUT3"); 153 snd_soc_dapm_disable_pin(dapm, "RINPUT3");
154 snd_soc_dapm_disable_pin(dapm, "OUT3"); 154 snd_soc_dapm_disable_pin(dapm, "OUT3");
155 snd_soc_dapm_disable_pin(dapm, "MONO1"); 155 snd_soc_dapm_disable_pin(dapm, "MONO1");
156 156
157 /* Add z2 specific widgets */ 157 /* Add z2 specific widgets */
158 snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets, 158 snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets,
159 ARRAY_SIZE(wm8750_dapm_widgets)); 159 ARRAY_SIZE(wm8750_dapm_widgets));
160 160
161 /* Set up z2 specific audio paths */ 161 /* Set up z2 specific audio paths */
162 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 162 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
163 163
164 ret = snd_soc_dapm_sync(dapm);
165 if (ret)
166 goto err;
167
168 /* Jack detection API stuff */ 164 /* Jack detection API stuff */
169 ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, 165 ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
170 &hs_jack); 166 &hs_jack);
171 if (ret) 167 if (ret)
172 goto err; 168 goto err;
173 169
174 ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), 170 ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
175 hs_jack_pins); 171 hs_jack_pins);
176 if (ret) 172 if (ret)
177 goto err; 173 goto err;
178 174
179 ret = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), 175 ret = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios),
180 hs_jack_gpios); 176 hs_jack_gpios);
181 if (ret) 177 if (ret)
182 goto err; 178 goto err;
183 179
184 return 0; 180 return 0;
185 181
186 err: 182 err:
187 return ret; 183 return ret;
188 } 184 }
189 185
190 static struct snd_soc_ops z2_ops = { 186 static struct snd_soc_ops z2_ops = {
191 .hw_params = z2_hw_params, 187 .hw_params = z2_hw_params,
192 }; 188 };
193 189
194 /* z2 digital audio interface glue - connects codec <--> CPU */ 190 /* z2 digital audio interface glue - connects codec <--> CPU */
195 static struct snd_soc_dai_link z2_dai = { 191 static struct snd_soc_dai_link z2_dai = {
196 .name = "wm8750", 192 .name = "wm8750",
197 .stream_name = "WM8750", 193 .stream_name = "WM8750",
198 .cpu_dai_name = "pxa2xx-i2s", 194 .cpu_dai_name = "pxa2xx-i2s",
199 .codec_dai_name = "wm8750-hifi", 195 .codec_dai_name = "wm8750-hifi",
200 .platform_name = "pxa-pcm-audio", 196 .platform_name = "pxa-pcm-audio",
201 .codec_name = "wm8750.0-001b", 197 .codec_name = "wm8750.0-001b",
202 .init = z2_wm8750_init, 198 .init = z2_wm8750_init,
203 .ops = &z2_ops, 199 .ops = &z2_ops,
204 }; 200 };
205 201
206 /* z2 audio machine driver */ 202 /* z2 audio machine driver */
207 static struct snd_soc_card snd_soc_z2 = { 203 static struct snd_soc_card snd_soc_z2 = {
208 .name = "Z2", 204 .name = "Z2",
209 .dai_link = &z2_dai, 205 .dai_link = &z2_dai,
210 .num_links = 1, 206 .num_links = 1,
211 }; 207 };
212 208
213 static struct platform_device *z2_snd_device; 209 static struct platform_device *z2_snd_device;
214 210
215 static int __init z2_init(void) 211 static int __init z2_init(void)
216 { 212 {
217 int ret; 213 int ret;
218 214
219 if (!machine_is_zipit2()) 215 if (!machine_is_zipit2())
220 return -ENODEV; 216 return -ENODEV;
221 217
222 z2_snd_device = platform_device_alloc("soc-audio", -1); 218 z2_snd_device = platform_device_alloc("soc-audio", -1);
223 if (!z2_snd_device) 219 if (!z2_snd_device)
224 return -ENOMEM; 220 return -ENOMEM;
225 221
226 platform_set_drvdata(z2_snd_device, &snd_soc_z2); 222 platform_set_drvdata(z2_snd_device, &snd_soc_z2);
227 ret = platform_device_add(z2_snd_device); 223 ret = platform_device_add(z2_snd_device);
228 224
229 if (ret) 225 if (ret)
230 platform_device_put(z2_snd_device); 226 platform_device_put(z2_snd_device);
231 227
232 return ret; 228 return ret;
233 } 229 }
234 230
235 static void __exit z2_exit(void) 231 static void __exit z2_exit(void)
236 { 232 {
237 platform_device_unregister(z2_snd_device); 233 platform_device_unregister(z2_snd_device);
238 } 234 }
239 235
240 module_init(z2_init); 236 module_init(z2_init);
241 module_exit(z2_exit); 237 module_exit(z2_exit);
242 238
243 MODULE_AUTHOR("Ken McGuire <kenm@desertweyr.com>, " 239 MODULE_AUTHOR("Ken McGuire <kenm@desertweyr.com>, "
244 "Marek Vasut <marek.vasut@gmail.com>"); 240 "Marek Vasut <marek.vasut@gmail.com>");
245 MODULE_DESCRIPTION("ALSA SoC ZipitZ2"); 241 MODULE_DESCRIPTION("ALSA SoC ZipitZ2");
246 MODULE_LICENSE("GPL"); 242 MODULE_LICENSE("GPL");
247 243
sound/soc/pxa/zylonite.c
1 /* 1 /*
2 * zylonite.c -- SoC audio for Zylonite 2 * zylonite.c -- SoC audio for Zylonite
3 * 3 *
4 * Copyright 2008 Wolfson Microelectronics PLC. 4 * Copyright 2008 Wolfson Microelectronics PLC.
5 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 5 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as 8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the 9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version. 10 * License, or (at your option) any later version.
11 * 11 *
12 */ 12 */
13 13
14 #include <linux/module.h> 14 #include <linux/module.h>
15 #include <linux/moduleparam.h> 15 #include <linux/moduleparam.h>
16 #include <linux/device.h> 16 #include <linux/device.h>
17 #include <linux/clk.h> 17 #include <linux/clk.h>
18 #include <linux/i2c.h> 18 #include <linux/i2c.h>
19 #include <sound/core.h> 19 #include <sound/core.h>
20 #include <sound/pcm.h> 20 #include <sound/pcm.h>
21 #include <sound/pcm_params.h> 21 #include <sound/pcm_params.h>
22 #include <sound/soc.h> 22 #include <sound/soc.h>
23 23
24 #include "../codecs/wm9713.h" 24 #include "../codecs/wm9713.h"
25 #include "pxa2xx-ac97.h" 25 #include "pxa2xx-ac97.h"
26 #include "pxa-ssp.h" 26 #include "pxa-ssp.h"
27 27
28 /* 28 /*
29 * There is a physical switch SW15 on the board which changes the MCLK 29 * There is a physical switch SW15 on the board which changes the MCLK
30 * for the WM9713 between the standard AC97 master clock and the 30 * for the WM9713 between the standard AC97 master clock and the
31 * output of the CLK_POUT signal from the PXA. 31 * output of the CLK_POUT signal from the PXA.
32 */ 32 */
33 static int clk_pout; 33 static int clk_pout;
34 module_param(clk_pout, int, 0); 34 module_param(clk_pout, int, 0);
35 MODULE_PARM_DESC(clk_pout, "Use CLK_POUT as WM9713 MCLK (SW15 on board)."); 35 MODULE_PARM_DESC(clk_pout, "Use CLK_POUT as WM9713 MCLK (SW15 on board).");
36 36
37 static struct clk *pout; 37 static struct clk *pout;
38 38
39 static struct snd_soc_card zylonite; 39 static struct snd_soc_card zylonite;
40 40
41 static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = { 41 static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = {
42 SND_SOC_DAPM_HP("Headphone", NULL), 42 SND_SOC_DAPM_HP("Headphone", NULL),
43 SND_SOC_DAPM_MIC("Headset Microphone", NULL), 43 SND_SOC_DAPM_MIC("Headset Microphone", NULL),
44 SND_SOC_DAPM_MIC("Handset Microphone", NULL), 44 SND_SOC_DAPM_MIC("Handset Microphone", NULL),
45 SND_SOC_DAPM_SPK("Multiactor", NULL), 45 SND_SOC_DAPM_SPK("Multiactor", NULL),
46 SND_SOC_DAPM_SPK("Headset Earpiece", NULL), 46 SND_SOC_DAPM_SPK("Headset Earpiece", NULL),
47 }; 47 };
48 48
49 /* Currently supported audio map */ 49 /* Currently supported audio map */
50 static const struct snd_soc_dapm_route audio_map[] = { 50 static const struct snd_soc_dapm_route audio_map[] = {
51 51
52 /* Headphone output connected to HPL/HPR */ 52 /* Headphone output connected to HPL/HPR */
53 { "Headphone", NULL, "HPL" }, 53 { "Headphone", NULL, "HPL" },
54 { "Headphone", NULL, "HPR" }, 54 { "Headphone", NULL, "HPR" },
55 55
56 /* On-board earpiece */ 56 /* On-board earpiece */
57 { "Headset Earpiece", NULL, "OUT3" }, 57 { "Headset Earpiece", NULL, "OUT3" },
58 58
59 /* Headphone mic */ 59 /* Headphone mic */
60 { "MIC2A", NULL, "Mic Bias" }, 60 { "MIC2A", NULL, "Mic Bias" },
61 { "Mic Bias", NULL, "Headset Microphone" }, 61 { "Mic Bias", NULL, "Headset Microphone" },
62 62
63 /* On-board mic */ 63 /* On-board mic */
64 { "MIC1", NULL, "Mic Bias" }, 64 { "MIC1", NULL, "Mic Bias" },
65 { "Mic Bias", NULL, "Handset Microphone" }, 65 { "Mic Bias", NULL, "Handset Microphone" },
66 66
67 /* Multiactor differentially connected over SPKL/SPKR */ 67 /* Multiactor differentially connected over SPKL/SPKR */
68 { "Multiactor", NULL, "SPKL" }, 68 { "Multiactor", NULL, "SPKL" },
69 { "Multiactor", NULL, "SPKR" }, 69 { "Multiactor", NULL, "SPKR" },
70 }; 70 };
71 71
72 static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd) 72 static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd)
73 { 73 {
74 struct snd_soc_codec *codec = rtd->codec; 74 struct snd_soc_codec *codec = rtd->codec;
75 struct snd_soc_dapm_context *dapm = &codec->dapm; 75 struct snd_soc_dapm_context *dapm = &codec->dapm;
76 76
77 if (clk_pout) 77 if (clk_pout)
78 snd_soc_dai_set_pll(rtd->codec_dai, 0, 0, 78 snd_soc_dai_set_pll(rtd->codec_dai, 0, 0,
79 clk_get_rate(pout), 0); 79 clk_get_rate(pout), 0);
80 80
81 snd_soc_dapm_new_controls(dapm, zylonite_dapm_widgets, 81 snd_soc_dapm_new_controls(dapm, zylonite_dapm_widgets,
82 ARRAY_SIZE(zylonite_dapm_widgets)); 82 ARRAY_SIZE(zylonite_dapm_widgets));
83 83
84 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 84 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
85 85
86 /* Static setup for now */ 86 /* Static setup for now */
87 snd_soc_dapm_enable_pin(dapm, "Headphone"); 87 snd_soc_dapm_enable_pin(dapm, "Headphone");
88 snd_soc_dapm_enable_pin(dapm, "Headset Earpiece"); 88 snd_soc_dapm_enable_pin(dapm, "Headset Earpiece");
89 89
90 snd_soc_dapm_sync(dapm);
91 return 0; 90 return 0;
92 } 91 }
93 92
94 static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, 93 static int zylonite_voice_hw_params(struct snd_pcm_substream *substream,
95 struct snd_pcm_hw_params *params) 94 struct snd_pcm_hw_params *params)
96 { 95 {
97 struct snd_soc_pcm_runtime *rtd = substream->private_data; 96 struct snd_soc_pcm_runtime *rtd = substream->private_data;
98 struct snd_soc_dai *codec_dai = rtd->codec_dai; 97 struct snd_soc_dai *codec_dai = rtd->codec_dai;
99 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 98 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
100 unsigned int pll_out = 0; 99 unsigned int pll_out = 0;
101 unsigned int wm9713_div = 0; 100 unsigned int wm9713_div = 0;
102 int ret = 0; 101 int ret = 0;
103 int rate = params_rate(params); 102 int rate = params_rate(params);
104 int width = snd_pcm_format_physical_width(params_format(params)); 103 int width = snd_pcm_format_physical_width(params_format(params));
105 104
106 /* Only support ratios that we can generate neatly from the AC97 105 /* Only support ratios that we can generate neatly from the AC97
107 * based master clock - in particular, this excludes 44.1kHz. 106 * based master clock - in particular, this excludes 44.1kHz.
108 * In most applications the voice DAC will be used for telephony 107 * In most applications the voice DAC will be used for telephony
109 * data so multiples of 8kHz will be the common case. 108 * data so multiples of 8kHz will be the common case.
110 */ 109 */
111 switch (rate) { 110 switch (rate) {
112 case 8000: 111 case 8000:
113 wm9713_div = 12; 112 wm9713_div = 12;
114 break; 113 break;
115 case 16000: 114 case 16000:
116 wm9713_div = 6; 115 wm9713_div = 6;
117 break; 116 break;
118 case 48000: 117 case 48000:
119 wm9713_div = 2; 118 wm9713_div = 2;
120 break; 119 break;
121 default: 120 default:
122 /* Don't support OSS emulation */ 121 /* Don't support OSS emulation */
123 return -EINVAL; 122 return -EINVAL;
124 } 123 }
125 124
126 /* Add 1 to the width for the leading clock cycle */ 125 /* Add 1 to the width for the leading clock cycle */
127 pll_out = rate * (width + 1) * 8; 126 pll_out = rate * (width + 1) * 8;
128 127
129 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1); 128 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1);
130 if (ret < 0) 129 if (ret < 0)
131 return ret; 130 return ret;
132 131
133 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, pll_out); 132 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, pll_out);
134 if (ret < 0) 133 if (ret < 0)
135 return ret; 134 return ret;
136 135
137 if (clk_pout) 136 if (clk_pout)
138 ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV, 137 ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV,
139 WM9713_PCMDIV(wm9713_div)); 138 WM9713_PCMDIV(wm9713_div));
140 else 139 else
141 ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, 140 ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV,
142 WM9713_PCMDIV(wm9713_div)); 141 WM9713_PCMDIV(wm9713_div));
143 if (ret < 0) 142 if (ret < 0)
144 return ret; 143 return ret;
145 144
146 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 145 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
147 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 146 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
148 if (ret < 0) 147 if (ret < 0)
149 return ret; 148 return ret;
150 149
151 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 150 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
152 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 151 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
153 if (ret < 0) 152 if (ret < 0)
154 return ret; 153 return ret;
155 154
156 return 0; 155 return 0;
157 } 156 }
158 157
159 static struct snd_soc_ops zylonite_voice_ops = { 158 static struct snd_soc_ops zylonite_voice_ops = {
160 .hw_params = zylonite_voice_hw_params, 159 .hw_params = zylonite_voice_hw_params,
161 }; 160 };
162 161
163 static struct snd_soc_dai_link zylonite_dai[] = { 162 static struct snd_soc_dai_link zylonite_dai[] = {
164 { 163 {
165 .name = "AC97", 164 .name = "AC97",
166 .stream_name = "AC97 HiFi", 165 .stream_name = "AC97 HiFi",
167 .codec_name = "wm9713-codec", 166 .codec_name = "wm9713-codec",
168 .platform_name = "pxa-pcm-audio", 167 .platform_name = "pxa-pcm-audio",
169 .cpu_dai_name = "pxa2xx-ac97", 168 .cpu_dai_name = "pxa2xx-ac97",
170 .codec_dai_name = "wm9713-hifi", 169 .codec_dai_name = "wm9713-hifi",
171 .init = zylonite_wm9713_init, 170 .init = zylonite_wm9713_init,
172 }, 171 },
173 { 172 {
174 .name = "AC97 Aux", 173 .name = "AC97 Aux",
175 .stream_name = "AC97 Aux", 174 .stream_name = "AC97 Aux",
176 .codec_name = "wm9713-codec", 175 .codec_name = "wm9713-codec",
177 .platform_name = "pxa-pcm-audio", 176 .platform_name = "pxa-pcm-audio",
178 .cpu_dai_name = "pxa2xx-ac97-aux", 177 .cpu_dai_name = "pxa2xx-ac97-aux",
179 .codec_dai_name = "wm9713-aux", 178 .codec_dai_name = "wm9713-aux",
180 }, 179 },
181 { 180 {
182 .name = "WM9713 Voice", 181 .name = "WM9713 Voice",
183 .stream_name = "WM9713 Voice", 182 .stream_name = "WM9713 Voice",
184 .codec_name = "wm9713-codec", 183 .codec_name = "wm9713-codec",
185 .platform_name = "pxa-pcm-audio", 184 .platform_name = "pxa-pcm-audio",
186 .cpu_dai_name = "pxa-ssp-dai.2", 185 .cpu_dai_name = "pxa-ssp-dai.2",
187 .codec_dai_name = "wm9713-voice", 186 .codec_dai_name = "wm9713-voice",
188 .ops = &zylonite_voice_ops, 187 .ops = &zylonite_voice_ops,
189 }, 188 },
190 }; 189 };
191 190
192 static int zylonite_probe(struct snd_soc_card *card) 191 static int zylonite_probe(struct snd_soc_card *card)
193 { 192 {
194 int ret; 193 int ret;
195 194
196 if (clk_pout) { 195 if (clk_pout) {
197 pout = clk_get(NULL, "CLK_POUT"); 196 pout = clk_get(NULL, "CLK_POUT");
198 if (IS_ERR(pout)) { 197 if (IS_ERR(pout)) {
199 dev_err(card->dev, "Unable to obtain CLK_POUT: %ld\n", 198 dev_err(card->dev, "Unable to obtain CLK_POUT: %ld\n",
200 PTR_ERR(pout)); 199 PTR_ERR(pout));
201 return PTR_ERR(pout); 200 return PTR_ERR(pout);
202 } 201 }
203 202
204 ret = clk_enable(pout); 203 ret = clk_enable(pout);
205 if (ret != 0) { 204 if (ret != 0) {
206 dev_err(card->dev, "Unable to enable CLK_POUT: %d\n", 205 dev_err(card->dev, "Unable to enable CLK_POUT: %d\n",
207 ret); 206 ret);
208 clk_put(pout); 207 clk_put(pout);
209 return ret; 208 return ret;
210 } 209 }
211 210
212 dev_dbg(card->dev, "MCLK enabled at %luHz\n", 211 dev_dbg(card->dev, "MCLK enabled at %luHz\n",
213 clk_get_rate(pout)); 212 clk_get_rate(pout));
214 } 213 }
215 214
216 return 0; 215 return 0;
217 } 216 }
218 217
219 static int zylonite_remove(struct snd_soc_card *card) 218 static int zylonite_remove(struct snd_soc_card *card)
220 { 219 {
221 if (clk_pout) { 220 if (clk_pout) {
222 clk_disable(pout); 221 clk_disable(pout);
223 clk_put(pout); 222 clk_put(pout);
224 } 223 }
225 224
226 return 0; 225 return 0;
227 } 226 }
228 227
229 static int zylonite_suspend_post(struct snd_soc_card *card) 228 static int zylonite_suspend_post(struct snd_soc_card *card)
230 { 229 {
231 if (clk_pout) 230 if (clk_pout)
232 clk_disable(pout); 231 clk_disable(pout);
233 232
234 return 0; 233 return 0;
235 } 234 }
236 235
237 static int zylonite_resume_pre(struct snd_soc_card *card) 236 static int zylonite_resume_pre(struct snd_soc_card *card)
238 { 237 {
239 int ret = 0; 238 int ret = 0;
240 239
241 if (clk_pout) { 240 if (clk_pout) {
242 ret = clk_enable(pout); 241 ret = clk_enable(pout);
243 if (ret != 0) 242 if (ret != 0)
244 dev_err(card->dev, "Unable to enable CLK_POUT: %d\n", 243 dev_err(card->dev, "Unable to enable CLK_POUT: %d\n",
245 ret); 244 ret);
246 } 245 }
247 246
248 return ret; 247 return ret;
249 } 248 }
250 249
251 static struct snd_soc_card zylonite = { 250 static struct snd_soc_card zylonite = {
252 .name = "Zylonite", 251 .name = "Zylonite",
253 .probe = &zylonite_probe, 252 .probe = &zylonite_probe,
254 .remove = &zylonite_remove, 253 .remove = &zylonite_remove,
255 .suspend_post = &zylonite_suspend_post, 254 .suspend_post = &zylonite_suspend_post,
256 .resume_pre = &zylonite_resume_pre, 255 .resume_pre = &zylonite_resume_pre,
257 .dai_link = zylonite_dai, 256 .dai_link = zylonite_dai,
258 .num_links = ARRAY_SIZE(zylonite_dai), 257 .num_links = ARRAY_SIZE(zylonite_dai),
259 .owner = THIS_MODULE, 258 .owner = THIS_MODULE,
260 }; 259 };
261 260
262 static struct platform_device *zylonite_snd_ac97_device; 261 static struct platform_device *zylonite_snd_ac97_device;
263 262
264 static int __init zylonite_init(void) 263 static int __init zylonite_init(void)
265 { 264 {
266 int ret; 265 int ret;
267 266
268 zylonite_snd_ac97_device = platform_device_alloc("soc-audio", -1); 267 zylonite_snd_ac97_device = platform_device_alloc("soc-audio", -1);
269 if (!zylonite_snd_ac97_device) 268 if (!zylonite_snd_ac97_device)
270 return -ENOMEM; 269 return -ENOMEM;
271 270
272 platform_set_drvdata(zylonite_snd_ac97_device, &zylonite); 271 platform_set_drvdata(zylonite_snd_ac97_device, &zylonite);
273 272
274 ret = platform_device_add(zylonite_snd_ac97_device); 273 ret = platform_device_add(zylonite_snd_ac97_device);
275 if (ret != 0) 274 if (ret != 0)
276 platform_device_put(zylonite_snd_ac97_device); 275 platform_device_put(zylonite_snd_ac97_device);
277 276
278 return ret; 277 return ret;
279 } 278 }
280 279
281 static void __exit zylonite_exit(void) 280 static void __exit zylonite_exit(void)
282 { 281 {
283 platform_device_unregister(zylonite_snd_ac97_device); 282 platform_device_unregister(zylonite_snd_ac97_device);
284 } 283 }
285 284
286 module_init(zylonite_init); 285 module_init(zylonite_init);
287 module_exit(zylonite_exit); 286 module_exit(zylonite_exit);
288 287
289 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 288 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
290 MODULE_DESCRIPTION("ALSA SoC WM9713 Zylonite"); 289 MODULE_DESCRIPTION("ALSA SoC WM9713 Zylonite");
291 MODULE_LICENSE("GPL"); 290 MODULE_LICENSE("GPL");
292 291
sound/soc/samsung/goni_wm8994.c
1 /* 1 /*
2 * goni_wm8994.c 2 * goni_wm8994.c
3 * 3 *
4 * Copyright (C) 2010 Samsung Electronics Co.Ltd 4 * Copyright (C) 2010 Samsung Electronics Co.Ltd
5 * Author: Chanwoo Choi <cw00.choi@samsung.com> 5 * Author: Chanwoo Choi <cw00.choi@samsung.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your 9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. 10 * option) any later version.
11 * 11 *
12 */ 12 */
13 13
14 #include <sound/soc.h> 14 #include <sound/soc.h>
15 #include <sound/jack.h> 15 #include <sound/jack.h>
16 16
17 #include <asm/mach-types.h> 17 #include <asm/mach-types.h>
18 #include <mach/gpio.h> 18 #include <mach/gpio.h>
19 19
20 #include "../codecs/wm8994.h" 20 #include "../codecs/wm8994.h"
21 21
22 #define MACHINE_NAME 0 22 #define MACHINE_NAME 0
23 #define CPU_VOICE_DAI 1 23 #define CPU_VOICE_DAI 1
24 24
25 static const char *aquila_str[] = { 25 static const char *aquila_str[] = {
26 [MACHINE_NAME] = "aquila", 26 [MACHINE_NAME] = "aquila",
27 [CPU_VOICE_DAI] = "aquila-voice-dai", 27 [CPU_VOICE_DAI] = "aquila-voice-dai",
28 }; 28 };
29 29
30 static struct snd_soc_card goni; 30 static struct snd_soc_card goni;
31 static struct platform_device *goni_snd_device; 31 static struct platform_device *goni_snd_device;
32 32
33 /* 3.5 pie jack */ 33 /* 3.5 pie jack */
34 static struct snd_soc_jack jack; 34 static struct snd_soc_jack jack;
35 35
36 /* 3.5 pie jack detection DAPM pins */ 36 /* 3.5 pie jack detection DAPM pins */
37 static struct snd_soc_jack_pin jack_pins[] = { 37 static struct snd_soc_jack_pin jack_pins[] = {
38 { 38 {
39 .pin = "Headset Mic", 39 .pin = "Headset Mic",
40 .mask = SND_JACK_MICROPHONE, 40 .mask = SND_JACK_MICROPHONE,
41 }, { 41 }, {
42 .pin = "Headset Stereophone", 42 .pin = "Headset Stereophone",
43 .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL | 43 .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL |
44 SND_JACK_AVOUT, 44 SND_JACK_AVOUT,
45 }, 45 },
46 }; 46 };
47 47
48 /* 3.5 pie jack detection gpios */ 48 /* 3.5 pie jack detection gpios */
49 static struct snd_soc_jack_gpio jack_gpios[] = { 49 static struct snd_soc_jack_gpio jack_gpios[] = {
50 { 50 {
51 .gpio = S5PV210_GPH0(6), 51 .gpio = S5PV210_GPH0(6),
52 .name = "DET_3.5", 52 .name = "DET_3.5",
53 .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL | 53 .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL |
54 SND_JACK_AVOUT, 54 SND_JACK_AVOUT,
55 .debounce_time = 200, 55 .debounce_time = 200,
56 }, 56 },
57 }; 57 };
58 58
59 static const struct snd_soc_dapm_widget goni_dapm_widgets[] = { 59 static const struct snd_soc_dapm_widget goni_dapm_widgets[] = {
60 SND_SOC_DAPM_SPK("Ext Left Spk", NULL), 60 SND_SOC_DAPM_SPK("Ext Left Spk", NULL),
61 SND_SOC_DAPM_SPK("Ext Right Spk", NULL), 61 SND_SOC_DAPM_SPK("Ext Right Spk", NULL),
62 SND_SOC_DAPM_SPK("Ext Rcv", NULL), 62 SND_SOC_DAPM_SPK("Ext Rcv", NULL),
63 SND_SOC_DAPM_HP("Headset Stereophone", NULL), 63 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
64 SND_SOC_DAPM_MIC("Headset Mic", NULL), 64 SND_SOC_DAPM_MIC("Headset Mic", NULL),
65 SND_SOC_DAPM_MIC("Main Mic", NULL), 65 SND_SOC_DAPM_MIC("Main Mic", NULL),
66 SND_SOC_DAPM_MIC("2nd Mic", NULL), 66 SND_SOC_DAPM_MIC("2nd Mic", NULL),
67 SND_SOC_DAPM_LINE("Radio In", NULL), 67 SND_SOC_DAPM_LINE("Radio In", NULL),
68 }; 68 };
69 69
70 static const struct snd_soc_dapm_route goni_dapm_routes[] = { 70 static const struct snd_soc_dapm_route goni_dapm_routes[] = {
71 {"Ext Left Spk", NULL, "SPKOUTLP"}, 71 {"Ext Left Spk", NULL, "SPKOUTLP"},
72 {"Ext Left Spk", NULL, "SPKOUTLN"}, 72 {"Ext Left Spk", NULL, "SPKOUTLN"},
73 73
74 {"Ext Right Spk", NULL, "SPKOUTRP"}, 74 {"Ext Right Spk", NULL, "SPKOUTRP"},
75 {"Ext Right Spk", NULL, "SPKOUTRN"}, 75 {"Ext Right Spk", NULL, "SPKOUTRN"},
76 76
77 {"Ext Rcv", NULL, "HPOUT2N"}, 77 {"Ext Rcv", NULL, "HPOUT2N"},
78 {"Ext Rcv", NULL, "HPOUT2P"}, 78 {"Ext Rcv", NULL, "HPOUT2P"},
79 79
80 {"Headset Stereophone", NULL, "HPOUT1L"}, 80 {"Headset Stereophone", NULL, "HPOUT1L"},
81 {"Headset Stereophone", NULL, "HPOUT1R"}, 81 {"Headset Stereophone", NULL, "HPOUT1R"},
82 82
83 {"IN1RN", NULL, "Headset Mic"}, 83 {"IN1RN", NULL, "Headset Mic"},
84 {"IN1RP", NULL, "Headset Mic"}, 84 {"IN1RP", NULL, "Headset Mic"},
85 85
86 {"IN1RN", NULL, "2nd Mic"}, 86 {"IN1RN", NULL, "2nd Mic"},
87 {"IN1RP", NULL, "2nd Mic"}, 87 {"IN1RP", NULL, "2nd Mic"},
88 88
89 {"IN1LN", NULL, "Main Mic"}, 89 {"IN1LN", NULL, "Main Mic"},
90 {"IN1LP", NULL, "Main Mic"}, 90 {"IN1LP", NULL, "Main Mic"},
91 91
92 {"IN2LN", NULL, "Radio In"}, 92 {"IN2LN", NULL, "Radio In"},
93 {"IN2RN", NULL, "Radio In"}, 93 {"IN2RN", NULL, "Radio In"},
94 }; 94 };
95 95
96 static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd) 96 static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd)
97 { 97 {
98 struct snd_soc_codec *codec = rtd->codec; 98 struct snd_soc_codec *codec = rtd->codec;
99 struct snd_soc_dapm_context *dapm = &codec->dapm; 99 struct snd_soc_dapm_context *dapm = &codec->dapm;
100 int ret; 100 int ret;
101 101
102 /* add goni specific widgets */ 102 /* add goni specific widgets */
103 snd_soc_dapm_new_controls(dapm, goni_dapm_widgets, 103 snd_soc_dapm_new_controls(dapm, goni_dapm_widgets,
104 ARRAY_SIZE(goni_dapm_widgets)); 104 ARRAY_SIZE(goni_dapm_widgets));
105 105
106 /* set up goni specific audio routes */ 106 /* set up goni specific audio routes */
107 snd_soc_dapm_add_routes(dapm, goni_dapm_routes, 107 snd_soc_dapm_add_routes(dapm, goni_dapm_routes,
108 ARRAY_SIZE(goni_dapm_routes)); 108 ARRAY_SIZE(goni_dapm_routes));
109 109
110 /* set endpoints to not connected */ 110 /* set endpoints to not connected */
111 snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN"); 111 snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN");
112 snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP"); 112 snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP");
113 snd_soc_dapm_nc_pin(dapm, "LINEOUT1N"); 113 snd_soc_dapm_nc_pin(dapm, "LINEOUT1N");
114 snd_soc_dapm_nc_pin(dapm, "LINEOUT1P"); 114 snd_soc_dapm_nc_pin(dapm, "LINEOUT1P");
115 snd_soc_dapm_nc_pin(dapm, "LINEOUT2N"); 115 snd_soc_dapm_nc_pin(dapm, "LINEOUT2N");
116 snd_soc_dapm_nc_pin(dapm, "LINEOUT2P"); 116 snd_soc_dapm_nc_pin(dapm, "LINEOUT2P");
117 117
118 if (machine_is_aquila()) { 118 if (machine_is_aquila()) {
119 snd_soc_dapm_nc_pin(dapm, "SPKOUTRN"); 119 snd_soc_dapm_nc_pin(dapm, "SPKOUTRN");
120 snd_soc_dapm_nc_pin(dapm, "SPKOUTRP"); 120 snd_soc_dapm_nc_pin(dapm, "SPKOUTRP");
121 } 121 }
122 122
123 snd_soc_dapm_sync(dapm);
124
125 /* Headset jack detection */ 123 /* Headset jack detection */
126 ret = snd_soc_jack_new(codec, "Headset Jack", 124 ret = snd_soc_jack_new(codec, "Headset Jack",
127 SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT, 125 SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT,
128 &jack); 126 &jack);
129 if (ret) 127 if (ret)
130 return ret; 128 return ret;
131 129
132 ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins); 130 ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins);
133 if (ret) 131 if (ret)
134 return ret; 132 return ret;
135 133
136 ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios); 134 ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios);
137 if (ret) 135 if (ret)
138 return ret; 136 return ret;
139 137
140 return 0; 138 return 0;
141 } 139 }
142 140
143 static int goni_hifi_hw_params(struct snd_pcm_substream *substream, 141 static int goni_hifi_hw_params(struct snd_pcm_substream *substream,
144 struct snd_pcm_hw_params *params) 142 struct snd_pcm_hw_params *params)
145 { 143 {
146 struct snd_soc_pcm_runtime *rtd = substream->private_data; 144 struct snd_soc_pcm_runtime *rtd = substream->private_data;
147 struct snd_soc_dai *codec_dai = rtd->codec_dai; 145 struct snd_soc_dai *codec_dai = rtd->codec_dai;
148 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 146 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
149 unsigned int pll_out = 24000000; 147 unsigned int pll_out = 24000000;
150 int ret = 0; 148 int ret = 0;
151 149
152 /* set the cpu DAI configuration */ 150 /* set the cpu DAI configuration */
153 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 151 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
154 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 152 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
155 if (ret < 0) 153 if (ret < 0)
156 return ret; 154 return ret;
157 155
158 /* set codec DAI configuration */ 156 /* set codec DAI configuration */
159 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 157 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
160 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 158 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
161 if (ret < 0) 159 if (ret < 0)
162 return ret; 160 return ret;
163 161
164 /* set the codec FLL */ 162 /* set the codec FLL */
165 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out, 163 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out,
166 params_rate(params) * 256); 164 params_rate(params) * 256);
167 if (ret < 0) 165 if (ret < 0)
168 return ret; 166 return ret;
169 167
170 /* set the codec system clock */ 168 /* set the codec system clock */
171 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, 169 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
172 params_rate(params) * 256, SND_SOC_CLOCK_IN); 170 params_rate(params) * 256, SND_SOC_CLOCK_IN);
173 if (ret < 0) 171 if (ret < 0)
174 return ret; 172 return ret;
175 173
176 return 0; 174 return 0;
177 } 175 }
178 176
179 static struct snd_soc_ops goni_hifi_ops = { 177 static struct snd_soc_ops goni_hifi_ops = {
180 .hw_params = goni_hifi_hw_params, 178 .hw_params = goni_hifi_hw_params,
181 }; 179 };
182 180
183 static int goni_voice_hw_params(struct snd_pcm_substream *substream, 181 static int goni_voice_hw_params(struct snd_pcm_substream *substream,
184 struct snd_pcm_hw_params *params) 182 struct snd_pcm_hw_params *params)
185 { 183 {
186 struct snd_soc_pcm_runtime *rtd = substream->private_data; 184 struct snd_soc_pcm_runtime *rtd = substream->private_data;
187 struct snd_soc_dai *codec_dai = rtd->codec_dai; 185 struct snd_soc_dai *codec_dai = rtd->codec_dai;
188 unsigned int pll_out = 24000000; 186 unsigned int pll_out = 24000000;
189 int ret = 0; 187 int ret = 0;
190 188
191 if (params_rate(params) != 8000) 189 if (params_rate(params) != 8000)
192 return -EINVAL; 190 return -EINVAL;
193 191
194 /* set codec DAI configuration */ 192 /* set codec DAI configuration */
195 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | 193 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J |
196 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); 194 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
197 if (ret < 0) 195 if (ret < 0)
198 return ret; 196 return ret;
199 197
200 /* set the codec FLL */ 198 /* set the codec FLL */
201 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out, 199 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out,
202 params_rate(params) * 256); 200 params_rate(params) * 256);
203 if (ret < 0) 201 if (ret < 0)
204 return ret; 202 return ret;
205 203
206 /* set the codec system clock */ 204 /* set the codec system clock */
207 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, 205 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2,
208 params_rate(params) * 256, SND_SOC_CLOCK_IN); 206 params_rate(params) * 256, SND_SOC_CLOCK_IN);
209 if (ret < 0) 207 if (ret < 0)
210 return ret; 208 return ret;
211 209
212 return 0; 210 return 0;
213 } 211 }
214 212
215 static struct snd_soc_dai_driver voice_dai = { 213 static struct snd_soc_dai_driver voice_dai = {
216 .name = "goni-voice-dai", 214 .name = "goni-voice-dai",
217 .id = 0, 215 .id = 0,
218 .playback = { 216 .playback = {
219 .channels_min = 1, 217 .channels_min = 1,
220 .channels_max = 2, 218 .channels_max = 2,
221 .rates = SNDRV_PCM_RATE_8000, 219 .rates = SNDRV_PCM_RATE_8000,
222 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 220 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
223 .capture = { 221 .capture = {
224 .channels_min = 1, 222 .channels_min = 1,
225 .channels_max = 2, 223 .channels_max = 2,
226 .rates = SNDRV_PCM_RATE_8000, 224 .rates = SNDRV_PCM_RATE_8000,
227 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 225 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
228 }; 226 };
229 227
230 static struct snd_soc_ops goni_voice_ops = { 228 static struct snd_soc_ops goni_voice_ops = {
231 .hw_params = goni_voice_hw_params, 229 .hw_params = goni_voice_hw_params,
232 }; 230 };
233 231
234 static struct snd_soc_dai_link goni_dai[] = { 232 static struct snd_soc_dai_link goni_dai[] = {
235 { 233 {
236 .name = "WM8994", 234 .name = "WM8994",
237 .stream_name = "WM8994 HiFi", 235 .stream_name = "WM8994 HiFi",
238 .cpu_dai_name = "samsung-i2s.0", 236 .cpu_dai_name = "samsung-i2s.0",
239 .codec_dai_name = "wm8994-aif1", 237 .codec_dai_name = "wm8994-aif1",
240 .platform_name = "samsung-audio", 238 .platform_name = "samsung-audio",
241 .codec_name = "wm8994-codec.0-001a", 239 .codec_name = "wm8994-codec.0-001a",
242 .init = goni_wm8994_init, 240 .init = goni_wm8994_init,
243 .ops = &goni_hifi_ops, 241 .ops = &goni_hifi_ops,
244 }, { 242 }, {
245 .name = "WM8994 Voice", 243 .name = "WM8994 Voice",
246 .stream_name = "Voice", 244 .stream_name = "Voice",
247 .cpu_dai_name = "goni-voice-dai", 245 .cpu_dai_name = "goni-voice-dai",
248 .codec_dai_name = "wm8994-aif2", 246 .codec_dai_name = "wm8994-aif2",
249 .codec_name = "wm8994-codec.0-001a", 247 .codec_name = "wm8994-codec.0-001a",
250 .ops = &goni_voice_ops, 248 .ops = &goni_voice_ops,
251 }, 249 },
252 }; 250 };
253 251
254 static struct snd_soc_card goni = { 252 static struct snd_soc_card goni = {
255 .name = "goni", 253 .name = "goni",
256 .dai_link = goni_dai, 254 .dai_link = goni_dai,
257 .num_links = ARRAY_SIZE(goni_dai), 255 .num_links = ARRAY_SIZE(goni_dai),
258 }; 256 };
259 257
260 static int __init goni_init(void) 258 static int __init goni_init(void)
261 { 259 {
262 int ret; 260 int ret;
263 261
264 if (machine_is_aquila()) { 262 if (machine_is_aquila()) {
265 voice_dai.name = aquila_str[CPU_VOICE_DAI]; 263 voice_dai.name = aquila_str[CPU_VOICE_DAI];
266 goni_dai[1].cpu_dai_name = aquila_str[CPU_VOICE_DAI]; 264 goni_dai[1].cpu_dai_name = aquila_str[CPU_VOICE_DAI];
267 goni.name = aquila_str[MACHINE_NAME]; 265 goni.name = aquila_str[MACHINE_NAME];
268 } else if (!machine_is_goni()) 266 } else if (!machine_is_goni())
269 return -ENODEV; 267 return -ENODEV;
270 268
271 goni_snd_device = platform_device_alloc("soc-audio", -1); 269 goni_snd_device = platform_device_alloc("soc-audio", -1);
272 if (!goni_snd_device) 270 if (!goni_snd_device)
273 return -ENOMEM; 271 return -ENOMEM;
274 272
275 /* register voice DAI here */ 273 /* register voice DAI here */
276 ret = snd_soc_register_dai(&goni_snd_device->dev, &voice_dai); 274 ret = snd_soc_register_dai(&goni_snd_device->dev, &voice_dai);
277 if (ret) { 275 if (ret) {
278 platform_device_put(goni_snd_device); 276 platform_device_put(goni_snd_device);
279 return ret; 277 return ret;
280 } 278 }
281 279
282 platform_set_drvdata(goni_snd_device, &goni); 280 platform_set_drvdata(goni_snd_device, &goni);
283 ret = platform_device_add(goni_snd_device); 281 ret = platform_device_add(goni_snd_device);
284 282
285 if (ret) { 283 if (ret) {
286 snd_soc_unregister_dai(&goni_snd_device->dev); 284 snd_soc_unregister_dai(&goni_snd_device->dev);
287 platform_device_put(goni_snd_device); 285 platform_device_put(goni_snd_device);
288 } 286 }
289 287
290 return ret; 288 return ret;
291 } 289 }
292 290
293 static void __exit goni_exit(void) 291 static void __exit goni_exit(void)
294 { 292 {
295 snd_soc_unregister_dai(&goni_snd_device->dev); 293 snd_soc_unregister_dai(&goni_snd_device->dev);
296 platform_device_unregister(goni_snd_device); 294 platform_device_unregister(goni_snd_device);
297 } 295 }
298 296
299 module_init(goni_init); 297 module_init(goni_init);
300 module_exit(goni_exit); 298 module_exit(goni_exit);
301 299
302 /* Module information */ 300 /* Module information */
303 MODULE_DESCRIPTION("ALSA SoC WM8994 GONI(S5PV210)"); 301 MODULE_DESCRIPTION("ALSA SoC WM8994 GONI(S5PV210)");
304 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); 302 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
305 MODULE_LICENSE("GPL"); 303 MODULE_LICENSE("GPL");
306 304
sound/soc/samsung/h1940_uda1380.c
1 /* 1 /*
2 * h1940-uda1380.c -- ALSA Soc Audio Layer 2 * h1940-uda1380.c -- ALSA Soc Audio Layer
3 * 3 *
4 * Copyright (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org> 4 * Copyright (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
5 * Copyright (c) 2010 Vasily Khoruzhick <anarsoul@gmail.com> 5 * Copyright (c) 2010 Vasily Khoruzhick <anarsoul@gmail.com>
6 * 6 *
7 * Based on version from Arnaud Patard <arnaud.patard@rtp-net.org> 7 * Based on version from Arnaud Patard <arnaud.patard@rtp-net.org>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify it 9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the 10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your 11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. 12 * option) any later version.
13 * 13 *
14 */ 14 */
15 15
16 #include <linux/types.h> 16 #include <linux/types.h>
17 #include <linux/gpio.h> 17 #include <linux/gpio.h>
18 18
19 #include <sound/soc.h> 19 #include <sound/soc.h>
20 #include <sound/jack.h> 20 #include <sound/jack.h>
21 21
22 #include <plat/regs-iis.h> 22 #include <plat/regs-iis.h>
23 #include <mach/h1940-latch.h> 23 #include <mach/h1940-latch.h>
24 #include <asm/mach-types.h> 24 #include <asm/mach-types.h>
25 25
26 #include "s3c24xx-i2s.h" 26 #include "s3c24xx-i2s.h"
27 27
28 static unsigned int rates[] = { 28 static unsigned int rates[] = {
29 11025, 29 11025,
30 22050, 30 22050,
31 44100, 31 44100,
32 }; 32 };
33 33
34 static struct snd_pcm_hw_constraint_list hw_rates = { 34 static struct snd_pcm_hw_constraint_list hw_rates = {
35 .count = ARRAY_SIZE(rates), 35 .count = ARRAY_SIZE(rates),
36 .list = rates, 36 .list = rates,
37 .mask = 0, 37 .mask = 0,
38 }; 38 };
39 39
40 static struct snd_soc_jack hp_jack; 40 static struct snd_soc_jack hp_jack;
41 41
42 static struct snd_soc_jack_pin hp_jack_pins[] = { 42 static struct snd_soc_jack_pin hp_jack_pins[] = {
43 { 43 {
44 .pin = "Headphone Jack", 44 .pin = "Headphone Jack",
45 .mask = SND_JACK_HEADPHONE, 45 .mask = SND_JACK_HEADPHONE,
46 }, 46 },
47 { 47 {
48 .pin = "Speaker", 48 .pin = "Speaker",
49 .mask = SND_JACK_HEADPHONE, 49 .mask = SND_JACK_HEADPHONE,
50 .invert = 1, 50 .invert = 1,
51 }, 51 },
52 }; 52 };
53 53
54 static struct snd_soc_jack_gpio hp_jack_gpios[] = { 54 static struct snd_soc_jack_gpio hp_jack_gpios[] = {
55 { 55 {
56 .gpio = S3C2410_GPG(4), 56 .gpio = S3C2410_GPG(4),
57 .name = "hp-gpio", 57 .name = "hp-gpio",
58 .report = SND_JACK_HEADPHONE, 58 .report = SND_JACK_HEADPHONE,
59 .invert = 1, 59 .invert = 1,
60 .debounce_time = 200, 60 .debounce_time = 200,
61 }, 61 },
62 }; 62 };
63 63
64 static int h1940_startup(struct snd_pcm_substream *substream) 64 static int h1940_startup(struct snd_pcm_substream *substream)
65 { 65 {
66 struct snd_pcm_runtime *runtime = substream->runtime; 66 struct snd_pcm_runtime *runtime = substream->runtime;
67 67
68 runtime->hw.rate_min = hw_rates.list[0]; 68 runtime->hw.rate_min = hw_rates.list[0];
69 runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1]; 69 runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1];
70 runtime->hw.rates = SNDRV_PCM_RATE_KNOT; 70 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
71 71
72 return snd_pcm_hw_constraint_list(runtime, 0, 72 return snd_pcm_hw_constraint_list(runtime, 0,
73 SNDRV_PCM_HW_PARAM_RATE, 73 SNDRV_PCM_HW_PARAM_RATE,
74 &hw_rates); 74 &hw_rates);
75 } 75 }
76 76
77 static int h1940_hw_params(struct snd_pcm_substream *substream, 77 static int h1940_hw_params(struct snd_pcm_substream *substream,
78 struct snd_pcm_hw_params *params) 78 struct snd_pcm_hw_params *params)
79 { 79 {
80 struct snd_soc_pcm_runtime *rtd = substream->private_data; 80 struct snd_soc_pcm_runtime *rtd = substream->private_data;
81 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 81 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
82 struct snd_soc_dai *codec_dai = rtd->codec_dai; 82 struct snd_soc_dai *codec_dai = rtd->codec_dai;
83 int div; 83 int div;
84 int ret; 84 int ret;
85 unsigned int rate = params_rate(params); 85 unsigned int rate = params_rate(params);
86 86
87 switch (rate) { 87 switch (rate) {
88 case 11025: 88 case 11025:
89 case 22050: 89 case 22050:
90 case 44100: 90 case 44100:
91 div = s3c24xx_i2s_get_clockrate() / (384 * rate); 91 div = s3c24xx_i2s_get_clockrate() / (384 * rate);
92 if (s3c24xx_i2s_get_clockrate() % (384 * rate) > (192 * rate)) 92 if (s3c24xx_i2s_get_clockrate() % (384 * rate) > (192 * rate))
93 div++; 93 div++;
94 break; 94 break;
95 default: 95 default:
96 dev_err(&rtd->dev, "%s: rate %d is not supported\n", 96 dev_err(&rtd->dev, "%s: rate %d is not supported\n",
97 __func__, rate); 97 __func__, rate);
98 return -EINVAL; 98 return -EINVAL;
99 } 99 }
100 100
101 /* set codec DAI configuration */ 101 /* set codec DAI configuration */
102 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 102 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
103 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 103 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
104 if (ret < 0) 104 if (ret < 0)
105 return ret; 105 return ret;
106 106
107 /* set cpu DAI configuration */ 107 /* set cpu DAI configuration */
108 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 108 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
109 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 109 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
110 if (ret < 0) 110 if (ret < 0)
111 return ret; 111 return ret;
112 112
113 /* select clock source */ 113 /* select clock source */
114 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C24XX_CLKSRC_PCLK, rate, 114 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C24XX_CLKSRC_PCLK, rate,
115 SND_SOC_CLOCK_OUT); 115 SND_SOC_CLOCK_OUT);
116 if (ret < 0) 116 if (ret < 0)
117 return ret; 117 return ret;
118 118
119 /* set MCLK division for sample rate */ 119 /* set MCLK division for sample rate */
120 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, 120 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
121 S3C2410_IISMOD_384FS); 121 S3C2410_IISMOD_384FS);
122 if (ret < 0) 122 if (ret < 0)
123 return ret; 123 return ret;
124 124
125 /* set BCLK division for sample rate */ 125 /* set BCLK division for sample rate */
126 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK, 126 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
127 S3C2410_IISMOD_32FS); 127 S3C2410_IISMOD_32FS);
128 if (ret < 0) 128 if (ret < 0)
129 return ret; 129 return ret;
130 130
131 /* set prescaler division for sample rate */ 131 /* set prescaler division for sample rate */
132 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, 132 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
133 S3C24XX_PRESCALE(div, div)); 133 S3C24XX_PRESCALE(div, div));
134 if (ret < 0) 134 if (ret < 0)
135 return ret; 135 return ret;
136 136
137 return 0; 137 return 0;
138 } 138 }
139 139
140 static struct snd_soc_ops h1940_ops = { 140 static struct snd_soc_ops h1940_ops = {
141 .startup = h1940_startup, 141 .startup = h1940_startup,
142 .hw_params = h1940_hw_params, 142 .hw_params = h1940_hw_params,
143 }; 143 };
144 144
145 static int h1940_spk_power(struct snd_soc_dapm_widget *w, 145 static int h1940_spk_power(struct snd_soc_dapm_widget *w,
146 struct snd_kcontrol *kcontrol, int event) 146 struct snd_kcontrol *kcontrol, int event)
147 { 147 {
148 if (SND_SOC_DAPM_EVENT_ON(event)) 148 if (SND_SOC_DAPM_EVENT_ON(event))
149 gpio_set_value(H1940_LATCH_AUDIO_POWER, 1); 149 gpio_set_value(H1940_LATCH_AUDIO_POWER, 1);
150 else 150 else
151 gpio_set_value(H1940_LATCH_AUDIO_POWER, 0); 151 gpio_set_value(H1940_LATCH_AUDIO_POWER, 0);
152 152
153 return 0; 153 return 0;
154 } 154 }
155 155
156 /* h1940 machine dapm widgets */ 156 /* h1940 machine dapm widgets */
157 static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = { 157 static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
158 SND_SOC_DAPM_HP("Headphone Jack", NULL), 158 SND_SOC_DAPM_HP("Headphone Jack", NULL),
159 SND_SOC_DAPM_MIC("Mic Jack", NULL), 159 SND_SOC_DAPM_MIC("Mic Jack", NULL),
160 SND_SOC_DAPM_SPK("Speaker", h1940_spk_power), 160 SND_SOC_DAPM_SPK("Speaker", h1940_spk_power),
161 }; 161 };
162 162
163 /* h1940 machine audio_map */ 163 /* h1940 machine audio_map */
164 static const struct snd_soc_dapm_route audio_map[] = { 164 static const struct snd_soc_dapm_route audio_map[] = {
165 /* headphone connected to VOUTLHP, VOUTRHP */ 165 /* headphone connected to VOUTLHP, VOUTRHP */
166 {"Headphone Jack", NULL, "VOUTLHP"}, 166 {"Headphone Jack", NULL, "VOUTLHP"},
167 {"Headphone Jack", NULL, "VOUTRHP"}, 167 {"Headphone Jack", NULL, "VOUTRHP"},
168 168
169 /* ext speaker connected to VOUTL, VOUTR */ 169 /* ext speaker connected to VOUTL, VOUTR */
170 {"Speaker", NULL, "VOUTL"}, 170 {"Speaker", NULL, "VOUTL"},
171 {"Speaker", NULL, "VOUTR"}, 171 {"Speaker", NULL, "VOUTR"},
172 172
173 /* mic is connected to VINM */ 173 /* mic is connected to VINM */
174 {"VINM", NULL, "Mic Jack"}, 174 {"VINM", NULL, "Mic Jack"},
175 }; 175 };
176 176
177 static struct platform_device *s3c24xx_snd_device; 177 static struct platform_device *s3c24xx_snd_device;
178 178
179 static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd) 179 static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd)
180 { 180 {
181 struct snd_soc_codec *codec = rtd->codec; 181 struct snd_soc_codec *codec = rtd->codec;
182 struct snd_soc_dapm_context *dapm = &codec->dapm; 182 struct snd_soc_dapm_context *dapm = &codec->dapm;
183 int err; 183 int err;
184 184
185 /* Add h1940 specific widgets */ 185 /* Add h1940 specific widgets */
186 err = snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets, 186 err = snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets,
187 ARRAY_SIZE(uda1380_dapm_widgets)); 187 ARRAY_SIZE(uda1380_dapm_widgets));
188 if (err) 188 if (err)
189 return err; 189 return err;
190 190
191 /* Set up h1940 specific audio path audio_mapnects */ 191 /* Set up h1940 specific audio path audio_mapnects */
192 err = snd_soc_dapm_add_routes(dapm, audio_map, 192 err = snd_soc_dapm_add_routes(dapm, audio_map,
193 ARRAY_SIZE(audio_map)); 193 ARRAY_SIZE(audio_map));
194 if (err) 194 if (err)
195 return err; 195 return err;
196 196
197 snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); 197 snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
198 snd_soc_dapm_enable_pin(dapm, "Speaker"); 198 snd_soc_dapm_enable_pin(dapm, "Speaker");
199 snd_soc_dapm_enable_pin(dapm, "Mic Jack"); 199 snd_soc_dapm_enable_pin(dapm, "Mic Jack");
200 200
201 snd_soc_dapm_sync(dapm);
202
203 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, 201 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
204 &hp_jack); 202 &hp_jack);
205 203
206 snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), 204 snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
207 hp_jack_pins); 205 hp_jack_pins);
208 206
209 snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), 207 snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
210 hp_jack_gpios); 208 hp_jack_gpios);
211 209
212 return 0; 210 return 0;
213 } 211 }
214 212
215 /* s3c24xx digital audio interface glue - connects codec <--> CPU */ 213 /* s3c24xx digital audio interface glue - connects codec <--> CPU */
216 static struct snd_soc_dai_link h1940_uda1380_dai[] = { 214 static struct snd_soc_dai_link h1940_uda1380_dai[] = {
217 { 215 {
218 .name = "uda1380", 216 .name = "uda1380",
219 .stream_name = "UDA1380 Duplex", 217 .stream_name = "UDA1380 Duplex",
220 .cpu_dai_name = "s3c24xx-iis", 218 .cpu_dai_name = "s3c24xx-iis",
221 .codec_dai_name = "uda1380-hifi", 219 .codec_dai_name = "uda1380-hifi",
222 .init = h1940_uda1380_init, 220 .init = h1940_uda1380_init,
223 .platform_name = "samsung-audio", 221 .platform_name = "samsung-audio",
224 .codec_name = "uda1380-codec.0-001a", 222 .codec_name = "uda1380-codec.0-001a",
225 .ops = &h1940_ops, 223 .ops = &h1940_ops,
226 }, 224 },
227 }; 225 };
228 226
229 static struct snd_soc_card h1940_asoc = { 227 static struct snd_soc_card h1940_asoc = {
230 .name = "h1940", 228 .name = "h1940",
231 .dai_link = h1940_uda1380_dai, 229 .dai_link = h1940_uda1380_dai,
232 .num_links = ARRAY_SIZE(h1940_uda1380_dai), 230 .num_links = ARRAY_SIZE(h1940_uda1380_dai),
233 }; 231 };
234 232
235 static int __init h1940_init(void) 233 static int __init h1940_init(void)
236 { 234 {
237 int ret; 235 int ret;
238 236
239 if (!machine_is_h1940()) 237 if (!machine_is_h1940())
240 return -ENODEV; 238 return -ENODEV;
241 239
242 /* configure some gpios */ 240 /* configure some gpios */
243 ret = gpio_request(H1940_LATCH_AUDIO_POWER, "speaker-power"); 241 ret = gpio_request(H1940_LATCH_AUDIO_POWER, "speaker-power");
244 if (ret) 242 if (ret)
245 goto err_out; 243 goto err_out;
246 244
247 ret = gpio_direction_output(H1940_LATCH_AUDIO_POWER, 0); 245 ret = gpio_direction_output(H1940_LATCH_AUDIO_POWER, 0);
248 if (ret) 246 if (ret)
249 goto err_gpio; 247 goto err_gpio;
250 248
251 s3c24xx_snd_device = platform_device_alloc("soc-audio", -1); 249 s3c24xx_snd_device = platform_device_alloc("soc-audio", -1);
252 if (!s3c24xx_snd_device) { 250 if (!s3c24xx_snd_device) {
253 ret = -ENOMEM; 251 ret = -ENOMEM;
254 goto err_gpio; 252 goto err_gpio;
255 } 253 }
256 254
257 platform_set_drvdata(s3c24xx_snd_device, &h1940_asoc); 255 platform_set_drvdata(s3c24xx_snd_device, &h1940_asoc);
258 ret = platform_device_add(s3c24xx_snd_device); 256 ret = platform_device_add(s3c24xx_snd_device);
259 257
260 if (ret) 258 if (ret)
261 goto err_plat; 259 goto err_plat;
262 260
263 return 0; 261 return 0;
264 262
265 err_plat: 263 err_plat:
266 platform_device_put(s3c24xx_snd_device); 264 platform_device_put(s3c24xx_snd_device);
267 err_gpio: 265 err_gpio:
268 gpio_free(H1940_LATCH_AUDIO_POWER); 266 gpio_free(H1940_LATCH_AUDIO_POWER);
269 267
270 err_out: 268 err_out:
271 return ret; 269 return ret;
272 } 270 }
273 271
274 static void __exit h1940_exit(void) 272 static void __exit h1940_exit(void)
275 { 273 {
276 platform_device_unregister(s3c24xx_snd_device); 274 platform_device_unregister(s3c24xx_snd_device);
277 snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), 275 snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
278 hp_jack_gpios); 276 hp_jack_gpios);
279 gpio_free(H1940_LATCH_AUDIO_POWER); 277 gpio_free(H1940_LATCH_AUDIO_POWER);
280 } 278 }
281 279
282 module_init(h1940_init); 280 module_init(h1940_init);
283 module_exit(h1940_exit); 281 module_exit(h1940_exit);
284 282
285 /* Module information */ 283 /* Module information */
286 MODULE_AUTHOR("Arnaud Patard, Vasily Khoruzhick"); 284 MODULE_AUTHOR("Arnaud Patard, Vasily Khoruzhick");
287 MODULE_DESCRIPTION("ALSA SoC H1940"); 285 MODULE_DESCRIPTION("ALSA SoC H1940");
288 MODULE_LICENSE("GPL"); 286 MODULE_LICENSE("GPL");
289 287
sound/soc/samsung/jive_wm8750.c
1 /* sound/soc/samsung/jive_wm8750.c 1 /* sound/soc/samsung/jive_wm8750.c
2 * 2 *
3 * Copyright 2007,2008 Simtec Electronics 3 * Copyright 2007,2008 Simtec Electronics
4 * 4 *
5 * Based on sound/soc/pxa/spitz.c 5 * Based on sound/soc/pxa/spitz.c
6 * Copyright 2005 Wolfson Microelectronics PLC. 6 * Copyright 2005 Wolfson Microelectronics PLC.
7 * Copyright 2005 Openedhand Ltd. 7 * Copyright 2005 Openedhand Ltd.
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12 */ 12 */
13 13
14 #include <sound/soc.h> 14 #include <sound/soc.h>
15 15
16 #include <asm/mach-types.h> 16 #include <asm/mach-types.h>
17 17
18 #include "s3c2412-i2s.h" 18 #include "s3c2412-i2s.h"
19 #include "../codecs/wm8750.h" 19 #include "../codecs/wm8750.h"
20 20
21 static const struct snd_soc_dapm_route audio_map[] = { 21 static const struct snd_soc_dapm_route audio_map[] = {
22 { "Headphone Jack", NULL, "LOUT1" }, 22 { "Headphone Jack", NULL, "LOUT1" },
23 { "Headphone Jack", NULL, "ROUT1" }, 23 { "Headphone Jack", NULL, "ROUT1" },
24 { "Internal Speaker", NULL, "LOUT2" }, 24 { "Internal Speaker", NULL, "LOUT2" },
25 { "Internal Speaker", NULL, "ROUT2" }, 25 { "Internal Speaker", NULL, "ROUT2" },
26 { "LINPUT1", NULL, "Line Input" }, 26 { "LINPUT1", NULL, "Line Input" },
27 { "RINPUT1", NULL, "Line Input" }, 27 { "RINPUT1", NULL, "Line Input" },
28 }; 28 };
29 29
30 static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = { 30 static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
31 SND_SOC_DAPM_HP("Headphone Jack", NULL), 31 SND_SOC_DAPM_HP("Headphone Jack", NULL),
32 SND_SOC_DAPM_SPK("Internal Speaker", NULL), 32 SND_SOC_DAPM_SPK("Internal Speaker", NULL),
33 SND_SOC_DAPM_LINE("Line In", NULL), 33 SND_SOC_DAPM_LINE("Line In", NULL),
34 }; 34 };
35 35
36 static int jive_hw_params(struct snd_pcm_substream *substream, 36 static int jive_hw_params(struct snd_pcm_substream *substream,
37 struct snd_pcm_hw_params *params) 37 struct snd_pcm_hw_params *params)
38 { 38 {
39 struct snd_soc_pcm_runtime *rtd = substream->private_data; 39 struct snd_soc_pcm_runtime *rtd = substream->private_data;
40 struct snd_soc_dai *codec_dai = rtd->codec_dai; 40 struct snd_soc_dai *codec_dai = rtd->codec_dai;
41 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 41 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
42 struct s3c_i2sv2_rate_calc div; 42 struct s3c_i2sv2_rate_calc div;
43 unsigned int clk = 0; 43 unsigned int clk = 0;
44 int ret = 0; 44 int ret = 0;
45 45
46 switch (params_rate(params)) { 46 switch (params_rate(params)) {
47 case 8000: 47 case 8000:
48 case 16000: 48 case 16000:
49 case 48000: 49 case 48000:
50 case 96000: 50 case 96000:
51 clk = 12288000; 51 clk = 12288000;
52 break; 52 break;
53 case 11025: 53 case 11025:
54 case 22050: 54 case 22050:
55 case 44100: 55 case 44100:
56 clk = 11289600; 56 clk = 11289600;
57 break; 57 break;
58 } 58 }
59 59
60 s3c_i2sv2_iis_calc_rate(&div, NULL, params_rate(params), 60 s3c_i2sv2_iis_calc_rate(&div, NULL, params_rate(params),
61 s3c_i2sv2_get_clock(cpu_dai)); 61 s3c_i2sv2_get_clock(cpu_dai));
62 62
63 /* set codec DAI configuration */ 63 /* set codec DAI configuration */
64 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 64 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
65 SND_SOC_DAIFMT_NB_NF | 65 SND_SOC_DAIFMT_NB_NF |
66 SND_SOC_DAIFMT_CBS_CFS); 66 SND_SOC_DAIFMT_CBS_CFS);
67 if (ret < 0) 67 if (ret < 0)
68 return ret; 68 return ret;
69 69
70 /* set cpu DAI configuration */ 70 /* set cpu DAI configuration */
71 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 71 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
72 SND_SOC_DAIFMT_NB_NF | 72 SND_SOC_DAIFMT_NB_NF |
73 SND_SOC_DAIFMT_CBS_CFS); 73 SND_SOC_DAIFMT_CBS_CFS);
74 if (ret < 0) 74 if (ret < 0)
75 return ret; 75 return ret;
76 76
77 /* set the codec system clock for DAC and ADC */ 77 /* set the codec system clock for DAC and ADC */
78 ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk, 78 ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
79 SND_SOC_CLOCK_IN); 79 SND_SOC_CLOCK_IN);
80 if (ret < 0) 80 if (ret < 0)
81 return ret; 81 return ret;
82 82
83 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_RCLK, div.fs_div); 83 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_RCLK, div.fs_div);
84 if (ret < 0) 84 if (ret < 0)
85 return ret; 85 return ret;
86 86
87 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_PRESCALER, 87 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_PRESCALER,
88 div.clk_div - 1); 88 div.clk_div - 1);
89 if (ret < 0) 89 if (ret < 0)
90 return ret; 90 return ret;
91 91
92 return 0; 92 return 0;
93 } 93 }
94 94
95 static struct snd_soc_ops jive_ops = { 95 static struct snd_soc_ops jive_ops = {
96 .hw_params = jive_hw_params, 96 .hw_params = jive_hw_params,
97 }; 97 };
98 98
99 static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd) 99 static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd)
100 { 100 {
101 struct snd_soc_codec *codec = rtd->codec; 101 struct snd_soc_codec *codec = rtd->codec;
102 struct snd_soc_dapm_context *dapm = &codec->dapm; 102 struct snd_soc_dapm_context *dapm = &codec->dapm;
103 int err; 103 int err;
104 104
105 /* These endpoints are not being used. */ 105 /* These endpoints are not being used. */
106 snd_soc_dapm_nc_pin(dapm, "LINPUT2"); 106 snd_soc_dapm_nc_pin(dapm, "LINPUT2");
107 snd_soc_dapm_nc_pin(dapm, "RINPUT2"); 107 snd_soc_dapm_nc_pin(dapm, "RINPUT2");
108 snd_soc_dapm_nc_pin(dapm, "LINPUT3"); 108 snd_soc_dapm_nc_pin(dapm, "LINPUT3");
109 snd_soc_dapm_nc_pin(dapm, "RINPUT3"); 109 snd_soc_dapm_nc_pin(dapm, "RINPUT3");
110 snd_soc_dapm_nc_pin(dapm, "OUT3"); 110 snd_soc_dapm_nc_pin(dapm, "OUT3");
111 snd_soc_dapm_nc_pin(dapm, "MONO"); 111 snd_soc_dapm_nc_pin(dapm, "MONO");
112 112
113 /* Add jive specific widgets */ 113 /* Add jive specific widgets */
114 err = snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets, 114 err = snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets,
115 ARRAY_SIZE(wm8750_dapm_widgets)); 115 ARRAY_SIZE(wm8750_dapm_widgets));
116 if (err) { 116 if (err) {
117 printk(KERN_ERR "%s: failed to add widgets (%d)\n", 117 printk(KERN_ERR "%s: failed to add widgets (%d)\n",
118 __func__, err); 118 __func__, err);
119 return err; 119 return err;
120 } 120 }
121 121
122 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 122 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
123 snd_soc_dapm_sync(dapm);
124 123
125 return 0; 124 return 0;
126 } 125 }
127 126
128 static struct snd_soc_dai_link jive_dai = { 127 static struct snd_soc_dai_link jive_dai = {
129 .name = "wm8750", 128 .name = "wm8750",
130 .stream_name = "WM8750", 129 .stream_name = "WM8750",
131 .cpu_dai_name = "s3c2412-i2s", 130 .cpu_dai_name = "s3c2412-i2s",
132 .codec_dai_name = "wm8750-hifi", 131 .codec_dai_name = "wm8750-hifi",
133 .platform_name = "samsung-audio", 132 .platform_name = "samsung-audio",
134 .codec_name = "wm8750.0-001a", 133 .codec_name = "wm8750.0-001a",
135 .init = jive_wm8750_init, 134 .init = jive_wm8750_init,
136 .ops = &jive_ops, 135 .ops = &jive_ops,
137 }; 136 };
138 137
139 /* jive audio machine driver */ 138 /* jive audio machine driver */
140 static struct snd_soc_card snd_soc_machine_jive = { 139 static struct snd_soc_card snd_soc_machine_jive = {
141 .name = "Jive", 140 .name = "Jive",
142 .dai_link = &jive_dai, 141 .dai_link = &jive_dai,
143 .num_links = 1, 142 .num_links = 1,
144 }; 143 };
145 144
146 static struct platform_device *jive_snd_device; 145 static struct platform_device *jive_snd_device;
147 146
148 static int __init jive_init(void) 147 static int __init jive_init(void)
149 { 148 {
150 int ret; 149 int ret;
151 150
152 if (!machine_is_jive()) 151 if (!machine_is_jive())
153 return 0; 152 return 0;
154 153
155 printk("JIVE WM8750 Audio support\n"); 154 printk("JIVE WM8750 Audio support\n");
156 155
157 jive_snd_device = platform_device_alloc("soc-audio", -1); 156 jive_snd_device = platform_device_alloc("soc-audio", -1);
158 if (!jive_snd_device) 157 if (!jive_snd_device)
159 return -ENOMEM; 158 return -ENOMEM;
160 159
161 platform_set_drvdata(jive_snd_device, &snd_soc_machine_jive); 160 platform_set_drvdata(jive_snd_device, &snd_soc_machine_jive);
162 ret = platform_device_add(jive_snd_device); 161 ret = platform_device_add(jive_snd_device);
163 162
164 if (ret) 163 if (ret)
165 platform_device_put(jive_snd_device); 164 platform_device_put(jive_snd_device);
166 165
167 return ret; 166 return ret;
168 } 167 }
169 168
170 static void __exit jive_exit(void) 169 static void __exit jive_exit(void)
171 { 170 {
172 platform_device_unregister(jive_snd_device); 171 platform_device_unregister(jive_snd_device);
173 } 172 }
174 173
175 module_init(jive_init); 174 module_init(jive_init);
176 module_exit(jive_exit); 175 module_exit(jive_exit);
177 176
178 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 177 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
179 MODULE_DESCRIPTION("ALSA SoC Jive Audio support"); 178 MODULE_DESCRIPTION("ALSA SoC Jive Audio support");
180 MODULE_LICENSE("GPL"); 179 MODULE_LICENSE("GPL");
181 180
sound/soc/samsung/neo1973_wm8753.c
1 /* 1 /*
2 * neo1973_wm8753.c -- SoC audio for Openmoko Neo1973 and Freerunner devices 2 * neo1973_wm8753.c -- SoC audio for Openmoko Neo1973 and Freerunner devices
3 * 3 *
4 * Copyright 2007 Openmoko Inc 4 * Copyright 2007 Openmoko Inc
5 * Author: Graeme Gregory <graeme@openmoko.org> 5 * Author: Graeme Gregory <graeme@openmoko.org>
6 * Copyright 2007 Wolfson Microelectronics PLC. 6 * Copyright 2007 Wolfson Microelectronics PLC.
7 * Author: Graeme Gregory 7 * Author: Graeme Gregory
8 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com 8 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
9 * Copyright 2009 Wolfson Microelectronics 9 * Copyright 2009 Wolfson Microelectronics
10 * 10 *
11 * This program is free software; you can redistribute it and/or modify it 11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the 12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your 13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version. 14 * option) any later version.
15 */ 15 */
16 16
17 #include <linux/module.h> 17 #include <linux/module.h>
18 #include <linux/platform_device.h> 18 #include <linux/platform_device.h>
19 #include <linux/gpio.h> 19 #include <linux/gpio.h>
20 20
21 #include <sound/soc.h> 21 #include <sound/soc.h>
22 22
23 #include <asm/mach-types.h> 23 #include <asm/mach-types.h>
24 #include <plat/regs-iis.h> 24 #include <plat/regs-iis.h>
25 #include <mach/gta02.h> 25 #include <mach/gta02.h>
26 26
27 #include "../codecs/wm8753.h" 27 #include "../codecs/wm8753.h"
28 #include "s3c24xx-i2s.h" 28 #include "s3c24xx-i2s.h"
29 29
30 static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, 30 static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
31 struct snd_pcm_hw_params *params) 31 struct snd_pcm_hw_params *params)
32 { 32 {
33 struct snd_soc_pcm_runtime *rtd = substream->private_data; 33 struct snd_soc_pcm_runtime *rtd = substream->private_data;
34 struct snd_soc_dai *codec_dai = rtd->codec_dai; 34 struct snd_soc_dai *codec_dai = rtd->codec_dai;
35 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 35 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
36 unsigned int pll_out = 0, bclk = 0; 36 unsigned int pll_out = 0, bclk = 0;
37 int ret = 0; 37 int ret = 0;
38 unsigned long iis_clkrate; 38 unsigned long iis_clkrate;
39 39
40 iis_clkrate = s3c24xx_i2s_get_clockrate(); 40 iis_clkrate = s3c24xx_i2s_get_clockrate();
41 41
42 switch (params_rate(params)) { 42 switch (params_rate(params)) {
43 case 8000: 43 case 8000:
44 case 16000: 44 case 16000:
45 pll_out = 12288000; 45 pll_out = 12288000;
46 break; 46 break;
47 case 48000: 47 case 48000:
48 bclk = WM8753_BCLK_DIV_4; 48 bclk = WM8753_BCLK_DIV_4;
49 pll_out = 12288000; 49 pll_out = 12288000;
50 break; 50 break;
51 case 96000: 51 case 96000:
52 bclk = WM8753_BCLK_DIV_2; 52 bclk = WM8753_BCLK_DIV_2;
53 pll_out = 12288000; 53 pll_out = 12288000;
54 break; 54 break;
55 case 11025: 55 case 11025:
56 bclk = WM8753_BCLK_DIV_16; 56 bclk = WM8753_BCLK_DIV_16;
57 pll_out = 11289600; 57 pll_out = 11289600;
58 break; 58 break;
59 case 22050: 59 case 22050:
60 bclk = WM8753_BCLK_DIV_8; 60 bclk = WM8753_BCLK_DIV_8;
61 pll_out = 11289600; 61 pll_out = 11289600;
62 break; 62 break;
63 case 44100: 63 case 44100:
64 bclk = WM8753_BCLK_DIV_4; 64 bclk = WM8753_BCLK_DIV_4;
65 pll_out = 11289600; 65 pll_out = 11289600;
66 break; 66 break;
67 case 88200: 67 case 88200:
68 bclk = WM8753_BCLK_DIV_2; 68 bclk = WM8753_BCLK_DIV_2;
69 pll_out = 11289600; 69 pll_out = 11289600;
70 break; 70 break;
71 } 71 }
72 72
73 /* set codec DAI configuration */ 73 /* set codec DAI configuration */
74 ret = snd_soc_dai_set_fmt(codec_dai, 74 ret = snd_soc_dai_set_fmt(codec_dai,
75 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 75 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
76 SND_SOC_DAIFMT_CBM_CFM); 76 SND_SOC_DAIFMT_CBM_CFM);
77 if (ret < 0) 77 if (ret < 0)
78 return ret; 78 return ret;
79 79
80 /* set cpu DAI configuration */ 80 /* set cpu DAI configuration */
81 ret = snd_soc_dai_set_fmt(cpu_dai, 81 ret = snd_soc_dai_set_fmt(cpu_dai,
82 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 82 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
83 SND_SOC_DAIFMT_CBM_CFM); 83 SND_SOC_DAIFMT_CBM_CFM);
84 if (ret < 0) 84 if (ret < 0)
85 return ret; 85 return ret;
86 86
87 /* set the codec system clock for DAC and ADC */ 87 /* set the codec system clock for DAC and ADC */
88 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out, 88 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
89 SND_SOC_CLOCK_IN); 89 SND_SOC_CLOCK_IN);
90 if (ret < 0) 90 if (ret < 0)
91 return ret; 91 return ret;
92 92
93 /* set MCLK division for sample rate */ 93 /* set MCLK division for sample rate */
94 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, 94 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
95 S3C2410_IISMOD_32FS); 95 S3C2410_IISMOD_32FS);
96 if (ret < 0) 96 if (ret < 0)
97 return ret; 97 return ret;
98 98
99 /* set codec BCLK division for sample rate */ 99 /* set codec BCLK division for sample rate */
100 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk); 100 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);
101 if (ret < 0) 101 if (ret < 0)
102 return ret; 102 return ret;
103 103
104 /* set prescaler division for sample rate */ 104 /* set prescaler division for sample rate */
105 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, 105 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
106 S3C24XX_PRESCALE(4, 4)); 106 S3C24XX_PRESCALE(4, 4));
107 if (ret < 0) 107 if (ret < 0)
108 return ret; 108 return ret;
109 109
110 /* codec PLL input is PCLK/4 */ 110 /* codec PLL input is PCLK/4 */
111 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 111 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
112 iis_clkrate / 4, pll_out); 112 iis_clkrate / 4, pll_out);
113 if (ret < 0) 113 if (ret < 0)
114 return ret; 114 return ret;
115 115
116 return 0; 116 return 0;
117 } 117 }
118 118
119 static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) 119 static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
120 { 120 {
121 struct snd_soc_pcm_runtime *rtd = substream->private_data; 121 struct snd_soc_pcm_runtime *rtd = substream->private_data;
122 struct snd_soc_dai *codec_dai = rtd->codec_dai; 122 struct snd_soc_dai *codec_dai = rtd->codec_dai;
123 123
124 /* disable the PLL */ 124 /* disable the PLL */
125 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); 125 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
126 } 126 }
127 127
128 /* 128 /*
129 * Neo1973 WM8753 HiFi DAI opserations. 129 * Neo1973 WM8753 HiFi DAI opserations.
130 */ 130 */
131 static struct snd_soc_ops neo1973_hifi_ops = { 131 static struct snd_soc_ops neo1973_hifi_ops = {
132 .hw_params = neo1973_hifi_hw_params, 132 .hw_params = neo1973_hifi_hw_params,
133 .hw_free = neo1973_hifi_hw_free, 133 .hw_free = neo1973_hifi_hw_free,
134 }; 134 };
135 135
136 static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, 136 static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
137 struct snd_pcm_hw_params *params) 137 struct snd_pcm_hw_params *params)
138 { 138 {
139 struct snd_soc_pcm_runtime *rtd = substream->private_data; 139 struct snd_soc_pcm_runtime *rtd = substream->private_data;
140 struct snd_soc_dai *codec_dai = rtd->codec_dai; 140 struct snd_soc_dai *codec_dai = rtd->codec_dai;
141 unsigned int pcmdiv = 0; 141 unsigned int pcmdiv = 0;
142 int ret = 0; 142 int ret = 0;
143 unsigned long iis_clkrate; 143 unsigned long iis_clkrate;
144 144
145 iis_clkrate = s3c24xx_i2s_get_clockrate(); 145 iis_clkrate = s3c24xx_i2s_get_clockrate();
146 146
147 if (params_rate(params) != 8000) 147 if (params_rate(params) != 8000)
148 return -EINVAL; 148 return -EINVAL;
149 if (params_channels(params) != 1) 149 if (params_channels(params) != 1)
150 return -EINVAL; 150 return -EINVAL;
151 151
152 pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */ 152 pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
153 153
154 /* todo: gg check mode (DSP_B) against CSR datasheet */ 154 /* todo: gg check mode (DSP_B) against CSR datasheet */
155 /* set codec DAI configuration */ 155 /* set codec DAI configuration */
156 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | 156 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
157 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 157 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
158 if (ret < 0) 158 if (ret < 0)
159 return ret; 159 return ret;
160 160
161 /* set the codec system clock for DAC and ADC */ 161 /* set the codec system clock for DAC and ADC */
162 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, 12288000, 162 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, 12288000,
163 SND_SOC_CLOCK_IN); 163 SND_SOC_CLOCK_IN);
164 if (ret < 0) 164 if (ret < 0)
165 return ret; 165 return ret;
166 166
167 /* set codec PCM division for sample rate */ 167 /* set codec PCM division for sample rate */
168 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv); 168 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
169 if (ret < 0) 169 if (ret < 0)
170 return ret; 170 return ret;
171 171
172 /* configure and enable PLL for 12.288MHz output */ 172 /* configure and enable PLL for 12.288MHz output */
173 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 173 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
174 iis_clkrate / 4, 12288000); 174 iis_clkrate / 4, 12288000);
175 if (ret < 0) 175 if (ret < 0)
176 return ret; 176 return ret;
177 177
178 return 0; 178 return 0;
179 } 179 }
180 180
181 static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) 181 static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
182 { 182 {
183 struct snd_soc_pcm_runtime *rtd = substream->private_data; 183 struct snd_soc_pcm_runtime *rtd = substream->private_data;
184 struct snd_soc_dai *codec_dai = rtd->codec_dai; 184 struct snd_soc_dai *codec_dai = rtd->codec_dai;
185 185
186 /* disable the PLL */ 186 /* disable the PLL */
187 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); 187 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
188 } 188 }
189 189
190 static struct snd_soc_ops neo1973_voice_ops = { 190 static struct snd_soc_ops neo1973_voice_ops = {
191 .hw_params = neo1973_voice_hw_params, 191 .hw_params = neo1973_voice_hw_params,
192 .hw_free = neo1973_voice_hw_free, 192 .hw_free = neo1973_voice_hw_free,
193 }; 193 };
194 194
195 /* Shared routes and controls */ 195 /* Shared routes and controls */
196 196
197 static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = { 197 static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = {
198 SND_SOC_DAPM_LINE("GSM Line Out", NULL), 198 SND_SOC_DAPM_LINE("GSM Line Out", NULL),
199 SND_SOC_DAPM_LINE("GSM Line In", NULL), 199 SND_SOC_DAPM_LINE("GSM Line In", NULL),
200 SND_SOC_DAPM_MIC("Headset Mic", NULL), 200 SND_SOC_DAPM_MIC("Headset Mic", NULL),
201 SND_SOC_DAPM_MIC("Handset Mic", NULL), 201 SND_SOC_DAPM_MIC("Handset Mic", NULL),
202 }; 202 };
203 203
204 static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = { 204 static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = {
205 /* Connections to the GSM Module */ 205 /* Connections to the GSM Module */
206 {"GSM Line Out", NULL, "MONO1"}, 206 {"GSM Line Out", NULL, "MONO1"},
207 {"GSM Line Out", NULL, "MONO2"}, 207 {"GSM Line Out", NULL, "MONO2"},
208 {"RXP", NULL, "GSM Line In"}, 208 {"RXP", NULL, "GSM Line In"},
209 {"RXN", NULL, "GSM Line In"}, 209 {"RXN", NULL, "GSM Line In"},
210 210
211 /* Connections to Headset */ 211 /* Connections to Headset */
212 {"MIC1", NULL, "Mic Bias"}, 212 {"MIC1", NULL, "Mic Bias"},
213 {"Mic Bias", NULL, "Headset Mic"}, 213 {"Mic Bias", NULL, "Headset Mic"},
214 214
215 /* Call Mic */ 215 /* Call Mic */
216 {"MIC2", NULL, "Mic Bias"}, 216 {"MIC2", NULL, "Mic Bias"},
217 {"MIC2N", NULL, "Mic Bias"}, 217 {"MIC2N", NULL, "Mic Bias"},
218 {"Mic Bias", NULL, "Handset Mic"}, 218 {"Mic Bias", NULL, "Handset Mic"},
219 219
220 /* Connect the ALC pins */ 220 /* Connect the ALC pins */
221 {"ACIN", NULL, "ACOP"}, 221 {"ACIN", NULL, "ACOP"},
222 }; 222 };
223 223
224 static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { 224 static const struct snd_kcontrol_new neo1973_wm8753_controls[] = {
225 SOC_DAPM_PIN_SWITCH("GSM Line Out"), 225 SOC_DAPM_PIN_SWITCH("GSM Line Out"),
226 SOC_DAPM_PIN_SWITCH("GSM Line In"), 226 SOC_DAPM_PIN_SWITCH("GSM Line In"),
227 SOC_DAPM_PIN_SWITCH("Headset Mic"), 227 SOC_DAPM_PIN_SWITCH("Headset Mic"),
228 SOC_DAPM_PIN_SWITCH("Handset Mic"), 228 SOC_DAPM_PIN_SWITCH("Handset Mic"),
229 }; 229 };
230 230
231 /* GTA02 specific routes and controls */ 231 /* GTA02 specific routes and controls */
232 232
233 #ifdef CONFIG_MACH_NEO1973_GTA02 233 #ifdef CONFIG_MACH_NEO1973_GTA02
234 234
235 static int gta02_speaker_enabled; 235 static int gta02_speaker_enabled;
236 236
237 static int lm4853_set_spk(struct snd_kcontrol *kcontrol, 237 static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
238 struct snd_ctl_elem_value *ucontrol) 238 struct snd_ctl_elem_value *ucontrol)
239 { 239 {
240 gta02_speaker_enabled = ucontrol->value.integer.value[0]; 240 gta02_speaker_enabled = ucontrol->value.integer.value[0];
241 241
242 gpio_set_value(GTA02_GPIO_HP_IN, !gta02_speaker_enabled); 242 gpio_set_value(GTA02_GPIO_HP_IN, !gta02_speaker_enabled);
243 243
244 return 0; 244 return 0;
245 } 245 }
246 246
247 static int lm4853_get_spk(struct snd_kcontrol *kcontrol, 247 static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
248 struct snd_ctl_elem_value *ucontrol) 248 struct snd_ctl_elem_value *ucontrol)
249 { 249 {
250 ucontrol->value.integer.value[0] = gta02_speaker_enabled; 250 ucontrol->value.integer.value[0] = gta02_speaker_enabled;
251 return 0; 251 return 0;
252 } 252 }
253 253
254 static int lm4853_event(struct snd_soc_dapm_widget *w, 254 static int lm4853_event(struct snd_soc_dapm_widget *w,
255 struct snd_kcontrol *k, int event) 255 struct snd_kcontrol *k, int event)
256 { 256 {
257 gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event)); 257 gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event));
258 258
259 return 0; 259 return 0;
260 } 260 }
261 261
262 static const struct snd_soc_dapm_route neo1973_gta02_routes[] = { 262 static const struct snd_soc_dapm_route neo1973_gta02_routes[] = {
263 /* Connections to the amp */ 263 /* Connections to the amp */
264 {"Stereo Out", NULL, "LOUT1"}, 264 {"Stereo Out", NULL, "LOUT1"},
265 {"Stereo Out", NULL, "ROUT1"}, 265 {"Stereo Out", NULL, "ROUT1"},
266 266
267 /* Call Speaker */ 267 /* Call Speaker */
268 {"Handset Spk", NULL, "LOUT2"}, 268 {"Handset Spk", NULL, "LOUT2"},
269 {"Handset Spk", NULL, "ROUT2"}, 269 {"Handset Spk", NULL, "ROUT2"},
270 }; 270 };
271 271
272 static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = { 272 static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = {
273 SOC_DAPM_PIN_SWITCH("Handset Spk"), 273 SOC_DAPM_PIN_SWITCH("Handset Spk"),
274 SOC_DAPM_PIN_SWITCH("Stereo Out"), 274 SOC_DAPM_PIN_SWITCH("Stereo Out"),
275 275
276 SOC_SINGLE_BOOL_EXT("Amp Spk Switch", 0, 276 SOC_SINGLE_BOOL_EXT("Amp Spk Switch", 0,
277 lm4853_get_spk, 277 lm4853_get_spk,
278 lm4853_set_spk), 278 lm4853_set_spk),
279 }; 279 };
280 280
281 static const struct snd_soc_dapm_widget neo1973_gta02_wm8753_dapm_widgets[] = { 281 static const struct snd_soc_dapm_widget neo1973_gta02_wm8753_dapm_widgets[] = {
282 SND_SOC_DAPM_SPK("Handset Spk", NULL), 282 SND_SOC_DAPM_SPK("Handset Spk", NULL),
283 SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), 283 SND_SOC_DAPM_SPK("Stereo Out", lm4853_event),
284 }; 284 };
285 285
286 static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) 286 static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
287 { 287 {
288 struct snd_soc_dapm_context *dapm = &codec->dapm; 288 struct snd_soc_dapm_context *dapm = &codec->dapm;
289 int ret; 289 int ret;
290 290
291 ret = snd_soc_dapm_new_controls(dapm, neo1973_gta02_wm8753_dapm_widgets, 291 ret = snd_soc_dapm_new_controls(dapm, neo1973_gta02_wm8753_dapm_widgets,
292 ARRAY_SIZE(neo1973_gta02_wm8753_dapm_widgets)); 292 ARRAY_SIZE(neo1973_gta02_wm8753_dapm_widgets));
293 if (ret) 293 if (ret)
294 return ret; 294 return ret;
295 295
296 ret = snd_soc_dapm_add_routes(dapm, neo1973_gta02_routes, 296 ret = snd_soc_dapm_add_routes(dapm, neo1973_gta02_routes,
297 ARRAY_SIZE(neo1973_gta02_routes)); 297 ARRAY_SIZE(neo1973_gta02_routes));
298 if (ret) 298 if (ret)
299 return ret; 299 return ret;
300 300
301 ret = snd_soc_add_controls(codec, neo1973_gta02_wm8753_controls, 301 ret = snd_soc_add_controls(codec, neo1973_gta02_wm8753_controls,
302 ARRAY_SIZE(neo1973_gta02_wm8753_controls)); 302 ARRAY_SIZE(neo1973_gta02_wm8753_controls));
303 if (ret) 303 if (ret)
304 return ret; 304 return ret;
305 305
306 snd_soc_dapm_disable_pin(dapm, "Stereo Out"); 306 snd_soc_dapm_disable_pin(dapm, "Stereo Out");
307 snd_soc_dapm_disable_pin(dapm, "Handset Spk"); 307 snd_soc_dapm_disable_pin(dapm, "Handset Spk");
308 snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); 308 snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
309 snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); 309 snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
310 310
311 return 0; 311 return 0;
312 } 312 }
313 313
314 #else 314 #else
315 static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; } 315 static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; }
316 #endif 316 #endif
317 317
318 static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) 318 static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
319 { 319 {
320 struct snd_soc_codec *codec = rtd->codec; 320 struct snd_soc_codec *codec = rtd->codec;
321 struct snd_soc_dapm_context *dapm = &codec->dapm; 321 struct snd_soc_dapm_context *dapm = &codec->dapm;
322 int ret; 322 int ret;
323 323
324 /* set up NC codec pins */ 324 /* set up NC codec pins */
325 if (machine_is_neo1973_gta01()) { 325 if (machine_is_neo1973_gta01()) {
326 snd_soc_dapm_nc_pin(dapm, "LOUT2"); 326 snd_soc_dapm_nc_pin(dapm, "LOUT2");
327 snd_soc_dapm_nc_pin(dapm, "ROUT2"); 327 snd_soc_dapm_nc_pin(dapm, "ROUT2");
328 } 328 }
329 snd_soc_dapm_nc_pin(dapm, "OUT3"); 329 snd_soc_dapm_nc_pin(dapm, "OUT3");
330 snd_soc_dapm_nc_pin(dapm, "OUT4"); 330 snd_soc_dapm_nc_pin(dapm, "OUT4");
331 snd_soc_dapm_nc_pin(dapm, "LINE1"); 331 snd_soc_dapm_nc_pin(dapm, "LINE1");
332 snd_soc_dapm_nc_pin(dapm, "LINE2"); 332 snd_soc_dapm_nc_pin(dapm, "LINE2");
333 333
334 /* Add neo1973 specific widgets */ 334 /* Add neo1973 specific widgets */
335 ret = snd_soc_dapm_new_controls(dapm, neo1973_wm8753_dapm_widgets, 335 ret = snd_soc_dapm_new_controls(dapm, neo1973_wm8753_dapm_widgets,
336 ARRAY_SIZE(neo1973_wm8753_dapm_widgets)); 336 ARRAY_SIZE(neo1973_wm8753_dapm_widgets));
337 if (ret) 337 if (ret)
338 return ret; 338 return ret;
339 339
340 /* add neo1973 specific controls */ 340 /* add neo1973 specific controls */
341 ret = snd_soc_add_controls(codec, neo1973_wm8753_controls, 341 ret = snd_soc_add_controls(codec, neo1973_wm8753_controls,
342 ARRAY_SIZE(neo1973_wm8753_controls)); 342 ARRAY_SIZE(neo1973_wm8753_controls));
343 if (ret) 343 if (ret)
344 return ret; 344 return ret;
345 345
346 /* set up neo1973 specific audio routes */ 346 /* set up neo1973 specific audio routes */
347 ret = snd_soc_dapm_add_routes(dapm, neo1973_wm8753_routes, 347 ret = snd_soc_dapm_add_routes(dapm, neo1973_wm8753_routes,
348 ARRAY_SIZE(neo1973_wm8753_routes)); 348 ARRAY_SIZE(neo1973_wm8753_routes));
349 if (ret) 349 if (ret)
350 return ret; 350 return ret;
351 351
352 /* set endpoints to default off mode */ 352 /* set endpoints to default off mode */
353 snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); 353 snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
354 snd_soc_dapm_disable_pin(dapm, "GSM Line In"); 354 snd_soc_dapm_disable_pin(dapm, "GSM Line In");
355 snd_soc_dapm_disable_pin(dapm, "Headset Mic"); 355 snd_soc_dapm_disable_pin(dapm, "Headset Mic");
356 snd_soc_dapm_disable_pin(dapm, "Handset Mic"); 356 snd_soc_dapm_disable_pin(dapm, "Handset Mic");
357 357
358 /* allow audio paths from the GSM modem to run during suspend */ 358 /* allow audio paths from the GSM modem to run during suspend */
359 snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out"); 359 snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out");
360 snd_soc_dapm_ignore_suspend(dapm, "GSM Line In"); 360 snd_soc_dapm_ignore_suspend(dapm, "GSM Line In");
361 snd_soc_dapm_ignore_suspend(dapm, "Headset Mic"); 361 snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
362 snd_soc_dapm_ignore_suspend(dapm, "Handset Mic"); 362 snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
363 363
364 if (machine_is_neo1973_gta02()) { 364 if (machine_is_neo1973_gta02()) {
365 ret = neo1973_gta02_wm8753_init(codec); 365 ret = neo1973_gta02_wm8753_init(codec);
366 if (ret) 366 if (ret)
367 return ret; 367 return ret;
368 } 368 }
369 369
370 snd_soc_dapm_sync(dapm);
371
372 return 0; 370 return 0;
373 } 371 }
374 372
375 /* GTA01 specific controls */ 373 /* GTA01 specific controls */
376 374
377 #ifdef CONFIG_MACH_NEO1973_GTA01 375 #ifdef CONFIG_MACH_NEO1973_GTA01
378 376
379 static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = { 377 static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = {
380 {"Amp IN", NULL, "ROUT1"}, 378 {"Amp IN", NULL, "ROUT1"},
381 {"Amp IN", NULL, "LOUT1"}, 379 {"Amp IN", NULL, "LOUT1"},
382 380
383 {"Handset Spk", NULL, "Amp EP"}, 381 {"Handset Spk", NULL, "Amp EP"},
384 {"Stereo Out", NULL, "Amp LS"}, 382 {"Stereo Out", NULL, "Amp LS"},
385 {"Headphone", NULL, "Amp HP"}, 383 {"Headphone", NULL, "Amp HP"},
386 }; 384 };
387 385
388 static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = { 386 static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = {
389 SND_SOC_DAPM_SPK("Handset Spk", NULL), 387 SND_SOC_DAPM_SPK("Handset Spk", NULL),
390 SND_SOC_DAPM_SPK("Stereo Out", NULL), 388 SND_SOC_DAPM_SPK("Stereo Out", NULL),
391 SND_SOC_DAPM_HP("Headphone", NULL), 389 SND_SOC_DAPM_HP("Headphone", NULL),
392 }; 390 };
393 391
394 static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) 392 static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm)
395 { 393 {
396 int ret; 394 int ret;
397 395
398 ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets, 396 ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets,
399 ARRAY_SIZE(neo1973_lm4857_dapm_widgets)); 397 ARRAY_SIZE(neo1973_lm4857_dapm_widgets));
400 if (ret) 398 if (ret)
401 return ret; 399 return ret;
402 400
403 ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes, 401 ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes,
404 ARRAY_SIZE(neo1973_lm4857_routes)); 402 ARRAY_SIZE(neo1973_lm4857_routes));
405 if (ret) 403 if (ret)
406 return ret; 404 return ret;
407 405
408 snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); 406 snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
409 snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); 407 snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
410 snd_soc_dapm_ignore_suspend(dapm, "Headphone"); 408 snd_soc_dapm_ignore_suspend(dapm, "Headphone");
411
412 snd_soc_dapm_sync(dapm);
413 409
414 return 0; 410 return 0;
415 } 411 }
416 412
417 #else 413 #else
418 static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; }; 414 static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; };
419 #endif 415 #endif
420 416
421 static struct snd_soc_dai_link neo1973_dai[] = { 417 static struct snd_soc_dai_link neo1973_dai[] = {
422 { /* Hifi Playback - for similatious use with voice below */ 418 { /* Hifi Playback - for similatious use with voice below */
423 .name = "WM8753", 419 .name = "WM8753",
424 .stream_name = "WM8753 HiFi", 420 .stream_name = "WM8753 HiFi",
425 .platform_name = "samsung-audio", 421 .platform_name = "samsung-audio",
426 .cpu_dai_name = "s3c24xx-iis", 422 .cpu_dai_name = "s3c24xx-iis",
427 .codec_dai_name = "wm8753-hifi", 423 .codec_dai_name = "wm8753-hifi",
428 .codec_name = "wm8753-codec.0-001a", 424 .codec_name = "wm8753-codec.0-001a",
429 .init = neo1973_wm8753_init, 425 .init = neo1973_wm8753_init,
430 .ops = &neo1973_hifi_ops, 426 .ops = &neo1973_hifi_ops,
431 }, 427 },
432 { /* Voice via BT */ 428 { /* Voice via BT */
433 .name = "Bluetooth", 429 .name = "Bluetooth",
434 .stream_name = "Voice", 430 .stream_name = "Voice",
435 .cpu_dai_name = "dfbmcs320-pcm", 431 .cpu_dai_name = "dfbmcs320-pcm",
436 .codec_dai_name = "wm8753-voice", 432 .codec_dai_name = "wm8753-voice",
437 .codec_name = "wm8753-codec.0-001a", 433 .codec_name = "wm8753-codec.0-001a",
438 .ops = &neo1973_voice_ops, 434 .ops = &neo1973_voice_ops,
439 }, 435 },
440 }; 436 };
441 437
442 static struct snd_soc_aux_dev neo1973_aux_devs[] = { 438 static struct snd_soc_aux_dev neo1973_aux_devs[] = {
443 { 439 {
444 .name = "dfbmcs320", 440 .name = "dfbmcs320",
445 .codec_name = "dfbmcs320.0", 441 .codec_name = "dfbmcs320.0",
446 }, 442 },
447 { 443 {
448 .name = "lm4857", 444 .name = "lm4857",
449 .codec_name = "lm4857.0-007c", 445 .codec_name = "lm4857.0-007c",
450 .init = neo1973_lm4857_init, 446 .init = neo1973_lm4857_init,
451 }, 447 },
452 }; 448 };
453 449
454 static struct snd_soc_codec_conf neo1973_codec_conf[] = { 450 static struct snd_soc_codec_conf neo1973_codec_conf[] = {
455 { 451 {
456 .dev_name = "lm4857.0-007c", 452 .dev_name = "lm4857.0-007c",
457 .name_prefix = "Amp", 453 .name_prefix = "Amp",
458 }, 454 },
459 }; 455 };
460 456
461 #ifdef CONFIG_MACH_NEO1973_GTA02 457 #ifdef CONFIG_MACH_NEO1973_GTA02
462 static const struct gpio neo1973_gta02_gpios[] = { 458 static const struct gpio neo1973_gta02_gpios[] = {
463 { GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" }, 459 { GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" },
464 { GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" }, 460 { GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" },
465 }; 461 };
466 #else 462 #else
467 static const struct gpio neo1973_gta02_gpios[] = {}; 463 static const struct gpio neo1973_gta02_gpios[] = {};
468 #endif 464 #endif
469 465
470 static struct snd_soc_card neo1973 = { 466 static struct snd_soc_card neo1973 = {
471 .name = "neo1973", 467 .name = "neo1973",
472 .dai_link = neo1973_dai, 468 .dai_link = neo1973_dai,
473 .num_links = ARRAY_SIZE(neo1973_dai), 469 .num_links = ARRAY_SIZE(neo1973_dai),
474 .aux_dev = neo1973_aux_devs, 470 .aux_dev = neo1973_aux_devs,
475 .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs), 471 .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs),
476 .codec_conf = neo1973_codec_conf, 472 .codec_conf = neo1973_codec_conf,
477 .num_configs = ARRAY_SIZE(neo1973_codec_conf), 473 .num_configs = ARRAY_SIZE(neo1973_codec_conf),
478 }; 474 };
479 475
480 static struct platform_device *neo1973_snd_device; 476 static struct platform_device *neo1973_snd_device;
481 477
482 static int __init neo1973_init(void) 478 static int __init neo1973_init(void)
483 { 479 {
484 int ret; 480 int ret;
485 481
486 if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02()) 482 if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02())
487 return -ENODEV; 483 return -ENODEV;
488 484
489 if (machine_is_neo1973_gta02()) { 485 if (machine_is_neo1973_gta02()) {
490 neo1973.name = "neo1973gta02"; 486 neo1973.name = "neo1973gta02";
491 neo1973.num_aux_devs = 1; 487 neo1973.num_aux_devs = 1;
492 488
493 ret = gpio_request_array(neo1973_gta02_gpios, 489 ret = gpio_request_array(neo1973_gta02_gpios,
494 ARRAY_SIZE(neo1973_gta02_gpios)); 490 ARRAY_SIZE(neo1973_gta02_gpios));
495 if (ret) 491 if (ret)
496 return ret; 492 return ret;
497 } 493 }
498 494
499 neo1973_snd_device = platform_device_alloc("soc-audio", -1); 495 neo1973_snd_device = platform_device_alloc("soc-audio", -1);
500 if (!neo1973_snd_device) { 496 if (!neo1973_snd_device) {
501 ret = -ENOMEM; 497 ret = -ENOMEM;
502 goto err_gpio_free; 498 goto err_gpio_free;
503 } 499 }
504 500
505 platform_set_drvdata(neo1973_snd_device, &neo1973); 501 platform_set_drvdata(neo1973_snd_device, &neo1973);
506 ret = platform_device_add(neo1973_snd_device); 502 ret = platform_device_add(neo1973_snd_device);
507 503
508 if (ret) 504 if (ret)
509 goto err_put_device; 505 goto err_put_device;
510 506
511 return 0; 507 return 0;
512 508
513 err_put_device: 509 err_put_device:
514 platform_device_put(neo1973_snd_device); 510 platform_device_put(neo1973_snd_device);
515 err_gpio_free: 511 err_gpio_free:
516 if (machine_is_neo1973_gta02()) { 512 if (machine_is_neo1973_gta02()) {
517 gpio_free_array(neo1973_gta02_gpios, 513 gpio_free_array(neo1973_gta02_gpios,
518 ARRAY_SIZE(neo1973_gta02_gpios)); 514 ARRAY_SIZE(neo1973_gta02_gpios));
519 } 515 }
520 return ret; 516 return ret;
521 } 517 }
522 module_init(neo1973_init); 518 module_init(neo1973_init);
523 519
524 static void __exit neo1973_exit(void) 520 static void __exit neo1973_exit(void)
525 { 521 {
526 platform_device_unregister(neo1973_snd_device); 522 platform_device_unregister(neo1973_snd_device);
527 523
528 if (machine_is_neo1973_gta02()) { 524 if (machine_is_neo1973_gta02()) {
529 gpio_free_array(neo1973_gta02_gpios, 525 gpio_free_array(neo1973_gta02_gpios,
530 ARRAY_SIZE(neo1973_gta02_gpios)); 526 ARRAY_SIZE(neo1973_gta02_gpios));
531 } 527 }
532 } 528 }
533 module_exit(neo1973_exit); 529 module_exit(neo1973_exit);
534 530
535 /* Module information */ 531 /* Module information */
536 MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org"); 532 MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org");
537 MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 and Frerunner"); 533 MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 and Frerunner");
538 MODULE_LICENSE("GPL"); 534 MODULE_LICENSE("GPL");
539 535
sound/soc/samsung/rx1950_uda1380.c
1 /* 1 /*
2 * rx1950.c -- ALSA Soc Audio Layer 2 * rx1950.c -- ALSA Soc Audio Layer
3 * 3 *
4 * Copyright (c) 2010 Vasily Khoruzhick <anarsoul@gmail.com> 4 * Copyright (c) 2010 Vasily Khoruzhick <anarsoul@gmail.com>
5 * 5 *
6 * Based on smdk2440.c and magician.c 6 * Based on smdk2440.c and magician.c
7 * 7 *
8 * Authors: Graeme Gregory graeme.gregory@wolfsonmicro.com 8 * Authors: Graeme Gregory graeme.gregory@wolfsonmicro.com
9 * Philipp Zabel <philipp.zabel@gmail.com> 9 * Philipp Zabel <philipp.zabel@gmail.com>
10 * Denis Grigoriev <dgreenday@gmail.com> 10 * Denis Grigoriev <dgreenday@gmail.com>
11 * Vasily Khoruzhick <anarsoul@gmail.com> 11 * Vasily Khoruzhick <anarsoul@gmail.com>
12 * 12 *
13 * This program is free software; you can redistribute it and/or modify it 13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the 14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your 15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. 16 * option) any later version.
17 * 17 *
18 */ 18 */
19 19
20 #include <linux/types.h> 20 #include <linux/types.h>
21 #include <linux/gpio.h> 21 #include <linux/gpio.h>
22 22
23 #include <sound/soc.h> 23 #include <sound/soc.h>
24 #include <sound/jack.h> 24 #include <sound/jack.h>
25 25
26 #include <plat/regs-iis.h> 26 #include <plat/regs-iis.h>
27 #include <asm/mach-types.h> 27 #include <asm/mach-types.h>
28 28
29 #include "s3c24xx-i2s.h" 29 #include "s3c24xx-i2s.h"
30 30
31 static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd); 31 static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd);
32 static int rx1950_startup(struct snd_pcm_substream *substream); 32 static int rx1950_startup(struct snd_pcm_substream *substream);
33 static int rx1950_hw_params(struct snd_pcm_substream *substream, 33 static int rx1950_hw_params(struct snd_pcm_substream *substream,
34 struct snd_pcm_hw_params *params); 34 struct snd_pcm_hw_params *params);
35 static int rx1950_spk_power(struct snd_soc_dapm_widget *w, 35 static int rx1950_spk_power(struct snd_soc_dapm_widget *w,
36 struct snd_kcontrol *kcontrol, int event); 36 struct snd_kcontrol *kcontrol, int event);
37 37
38 static unsigned int rates[] = { 38 static unsigned int rates[] = {
39 16000, 39 16000,
40 44100, 40 44100,
41 48000, 41 48000,
42 }; 42 };
43 43
44 static struct snd_pcm_hw_constraint_list hw_rates = { 44 static struct snd_pcm_hw_constraint_list hw_rates = {
45 .count = ARRAY_SIZE(rates), 45 .count = ARRAY_SIZE(rates),
46 .list = rates, 46 .list = rates,
47 .mask = 0, 47 .mask = 0,
48 }; 48 };
49 49
50 static struct snd_soc_jack hp_jack; 50 static struct snd_soc_jack hp_jack;
51 51
52 static struct snd_soc_jack_pin hp_jack_pins[] = { 52 static struct snd_soc_jack_pin hp_jack_pins[] = {
53 { 53 {
54 .pin = "Headphone Jack", 54 .pin = "Headphone Jack",
55 .mask = SND_JACK_HEADPHONE, 55 .mask = SND_JACK_HEADPHONE,
56 }, 56 },
57 { 57 {
58 .pin = "Speaker", 58 .pin = "Speaker",
59 .mask = SND_JACK_HEADPHONE, 59 .mask = SND_JACK_HEADPHONE,
60 .invert = 1, 60 .invert = 1,
61 }, 61 },
62 }; 62 };
63 63
64 static struct snd_soc_jack_gpio hp_jack_gpios[] = { 64 static struct snd_soc_jack_gpio hp_jack_gpios[] = {
65 [0] = { 65 [0] = {
66 .gpio = S3C2410_GPG(12), 66 .gpio = S3C2410_GPG(12),
67 .name = "hp-gpio", 67 .name = "hp-gpio",
68 .report = SND_JACK_HEADPHONE, 68 .report = SND_JACK_HEADPHONE,
69 .invert = 1, 69 .invert = 1,
70 .debounce_time = 200, 70 .debounce_time = 200,
71 }, 71 },
72 }; 72 };
73 73
74 static struct snd_soc_ops rx1950_ops = { 74 static struct snd_soc_ops rx1950_ops = {
75 .startup = rx1950_startup, 75 .startup = rx1950_startup,
76 .hw_params = rx1950_hw_params, 76 .hw_params = rx1950_hw_params,
77 }; 77 };
78 78
79 /* s3c24xx digital audio interface glue - connects codec <--> CPU */ 79 /* s3c24xx digital audio interface glue - connects codec <--> CPU */
80 static struct snd_soc_dai_link rx1950_uda1380_dai[] = { 80 static struct snd_soc_dai_link rx1950_uda1380_dai[] = {
81 { 81 {
82 .name = "uda1380", 82 .name = "uda1380",
83 .stream_name = "UDA1380 Duplex", 83 .stream_name = "UDA1380 Duplex",
84 .cpu_dai_name = "s3c24xx-iis", 84 .cpu_dai_name = "s3c24xx-iis",
85 .codec_dai_name = "uda1380-hifi", 85 .codec_dai_name = "uda1380-hifi",
86 .init = rx1950_uda1380_init, 86 .init = rx1950_uda1380_init,
87 .platform_name = "samsung-audio", 87 .platform_name = "samsung-audio",
88 .codec_name = "uda1380-codec.0-001a", 88 .codec_name = "uda1380-codec.0-001a",
89 .ops = &rx1950_ops, 89 .ops = &rx1950_ops,
90 }, 90 },
91 }; 91 };
92 92
93 static struct snd_soc_card rx1950_asoc = { 93 static struct snd_soc_card rx1950_asoc = {
94 .name = "rx1950", 94 .name = "rx1950",
95 .dai_link = rx1950_uda1380_dai, 95 .dai_link = rx1950_uda1380_dai,
96 .num_links = ARRAY_SIZE(rx1950_uda1380_dai), 96 .num_links = ARRAY_SIZE(rx1950_uda1380_dai),
97 }; 97 };
98 98
99 /* rx1950 machine dapm widgets */ 99 /* rx1950 machine dapm widgets */
100 static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = { 100 static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
101 SND_SOC_DAPM_HP("Headphone Jack", NULL), 101 SND_SOC_DAPM_HP("Headphone Jack", NULL),
102 SND_SOC_DAPM_MIC("Mic Jack", NULL), 102 SND_SOC_DAPM_MIC("Mic Jack", NULL),
103 SND_SOC_DAPM_SPK("Speaker", rx1950_spk_power), 103 SND_SOC_DAPM_SPK("Speaker", rx1950_spk_power),
104 }; 104 };
105 105
106 /* rx1950 machine audio_map */ 106 /* rx1950 machine audio_map */
107 static const struct snd_soc_dapm_route audio_map[] = { 107 static const struct snd_soc_dapm_route audio_map[] = {
108 /* headphone connected to VOUTLHP, VOUTRHP */ 108 /* headphone connected to VOUTLHP, VOUTRHP */
109 {"Headphone Jack", NULL, "VOUTLHP"}, 109 {"Headphone Jack", NULL, "VOUTLHP"},
110 {"Headphone Jack", NULL, "VOUTRHP"}, 110 {"Headphone Jack", NULL, "VOUTRHP"},
111 111
112 /* ext speaker connected to VOUTL, VOUTR */ 112 /* ext speaker connected to VOUTL, VOUTR */
113 {"Speaker", NULL, "VOUTL"}, 113 {"Speaker", NULL, "VOUTL"},
114 {"Speaker", NULL, "VOUTR"}, 114 {"Speaker", NULL, "VOUTR"},
115 115
116 /* mic is connected to VINM */ 116 /* mic is connected to VINM */
117 {"VINM", NULL, "Mic Jack"}, 117 {"VINM", NULL, "Mic Jack"},
118 }; 118 };
119 119
120 static struct platform_device *s3c24xx_snd_device; 120 static struct platform_device *s3c24xx_snd_device;
121 121
122 static int rx1950_startup(struct snd_pcm_substream *substream) 122 static int rx1950_startup(struct snd_pcm_substream *substream)
123 { 123 {
124 struct snd_pcm_runtime *runtime = substream->runtime; 124 struct snd_pcm_runtime *runtime = substream->runtime;
125 125
126 runtime->hw.rate_min = hw_rates.list[0]; 126 runtime->hw.rate_min = hw_rates.list[0];
127 runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1]; 127 runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1];
128 runtime->hw.rates = SNDRV_PCM_RATE_KNOT; 128 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
129 129
130 return snd_pcm_hw_constraint_list(runtime, 0, 130 return snd_pcm_hw_constraint_list(runtime, 0,
131 SNDRV_PCM_HW_PARAM_RATE, 131 SNDRV_PCM_HW_PARAM_RATE,
132 &hw_rates); 132 &hw_rates);
133 } 133 }
134 134
135 static int rx1950_spk_power(struct snd_soc_dapm_widget *w, 135 static int rx1950_spk_power(struct snd_soc_dapm_widget *w,
136 struct snd_kcontrol *kcontrol, int event) 136 struct snd_kcontrol *kcontrol, int event)
137 { 137 {
138 if (SND_SOC_DAPM_EVENT_ON(event)) 138 if (SND_SOC_DAPM_EVENT_ON(event))
139 gpio_set_value(S3C2410_GPA(1), 1); 139 gpio_set_value(S3C2410_GPA(1), 1);
140 else 140 else
141 gpio_set_value(S3C2410_GPA(1), 0); 141 gpio_set_value(S3C2410_GPA(1), 0);
142 142
143 return 0; 143 return 0;
144 } 144 }
145 145
146 static int rx1950_hw_params(struct snd_pcm_substream *substream, 146 static int rx1950_hw_params(struct snd_pcm_substream *substream,
147 struct snd_pcm_hw_params *params) 147 struct snd_pcm_hw_params *params)
148 { 148 {
149 struct snd_soc_pcm_runtime *rtd = substream->private_data; 149 struct snd_soc_pcm_runtime *rtd = substream->private_data;
150 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 150 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
151 struct snd_soc_dai *codec_dai = rtd->codec_dai; 151 struct snd_soc_dai *codec_dai = rtd->codec_dai;
152 int div; 152 int div;
153 int ret; 153 int ret;
154 unsigned int rate = params_rate(params); 154 unsigned int rate = params_rate(params);
155 int clk_source, fs_mode; 155 int clk_source, fs_mode;
156 156
157 switch (rate) { 157 switch (rate) {
158 case 16000: 158 case 16000:
159 case 48000: 159 case 48000:
160 clk_source = S3C24XX_CLKSRC_PCLK; 160 clk_source = S3C24XX_CLKSRC_PCLK;
161 fs_mode = S3C2410_IISMOD_256FS; 161 fs_mode = S3C2410_IISMOD_256FS;
162 div = s3c24xx_i2s_get_clockrate() / (256 * rate); 162 div = s3c24xx_i2s_get_clockrate() / (256 * rate);
163 if (s3c24xx_i2s_get_clockrate() % (256 * rate) > (128 * rate)) 163 if (s3c24xx_i2s_get_clockrate() % (256 * rate) > (128 * rate))
164 div++; 164 div++;
165 break; 165 break;
166 case 44100: 166 case 44100:
167 case 88200: 167 case 88200:
168 clk_source = S3C24XX_CLKSRC_MPLL; 168 clk_source = S3C24XX_CLKSRC_MPLL;
169 fs_mode = S3C2410_IISMOD_384FS; 169 fs_mode = S3C2410_IISMOD_384FS;
170 div = 1; 170 div = 1;
171 break; 171 break;
172 default: 172 default:
173 printk(KERN_ERR "%s: rate %d is not supported\n", 173 printk(KERN_ERR "%s: rate %d is not supported\n",
174 __func__, rate); 174 __func__, rate);
175 return -EINVAL; 175 return -EINVAL;
176 } 176 }
177 177
178 /* set codec DAI configuration */ 178 /* set codec DAI configuration */
179 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 179 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
180 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 180 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
181 if (ret < 0) 181 if (ret < 0)
182 return ret; 182 return ret;
183 183
184 /* set cpu DAI configuration */ 184 /* set cpu DAI configuration */
185 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 185 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
186 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 186 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
187 if (ret < 0) 187 if (ret < 0)
188 return ret; 188 return ret;
189 189
190 /* select clock source */ 190 /* select clock source */
191 ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source, rate, 191 ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source, rate,
192 SND_SOC_CLOCK_OUT); 192 SND_SOC_CLOCK_OUT);
193 if (ret < 0) 193 if (ret < 0)
194 return ret; 194 return ret;
195 195
196 /* set MCLK division for sample rate */ 196 /* set MCLK division for sample rate */
197 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, 197 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
198 fs_mode); 198 fs_mode);
199 if (ret < 0) 199 if (ret < 0)
200 return ret; 200 return ret;
201 201
202 /* set BCLK division for sample rate */ 202 /* set BCLK division for sample rate */
203 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK, 203 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
204 S3C2410_IISMOD_32FS); 204 S3C2410_IISMOD_32FS);
205 if (ret < 0) 205 if (ret < 0)
206 return ret; 206 return ret;
207 207
208 /* set prescaler division for sample rate */ 208 /* set prescaler division for sample rate */
209 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, 209 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
210 S3C24XX_PRESCALE(div, div)); 210 S3C24XX_PRESCALE(div, div));
211 if (ret < 0) 211 if (ret < 0)
212 return ret; 212 return ret;
213 213
214 return 0; 214 return 0;
215 } 215 }
216 216
217 static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd) 217 static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd)
218 { 218 {
219 struct snd_soc_codec *codec = rtd->codec; 219 struct snd_soc_codec *codec = rtd->codec;
220 struct snd_soc_dapm_context *dapm = &codec->dapm; 220 struct snd_soc_dapm_context *dapm = &codec->dapm;
221 int err; 221 int err;
222 222
223 /* Add rx1950 specific widgets */ 223 /* Add rx1950 specific widgets */
224 err = snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets, 224 err = snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets,
225 ARRAY_SIZE(uda1380_dapm_widgets)); 225 ARRAY_SIZE(uda1380_dapm_widgets));
226 226
227 if (err) 227 if (err)
228 return err; 228 return err;
229 229
230 /* Set up rx1950 specific audio path audio_mapnects */ 230 /* Set up rx1950 specific audio path audio_mapnects */
231 err = snd_soc_dapm_add_routes(dapm, audio_map, 231 err = snd_soc_dapm_add_routes(dapm, audio_map,
232 ARRAY_SIZE(audio_map)); 232 ARRAY_SIZE(audio_map));
233 233
234 if (err) 234 if (err)
235 return err; 235 return err;
236 236
237 snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); 237 snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
238 snd_soc_dapm_enable_pin(dapm, "Speaker"); 238 snd_soc_dapm_enable_pin(dapm, "Speaker");
239 snd_soc_dapm_enable_pin(dapm, "Mic Jack"); 239 snd_soc_dapm_enable_pin(dapm, "Mic Jack");
240 240
241 snd_soc_dapm_sync(dapm);
242
243 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, 241 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
244 &hp_jack); 242 &hp_jack);
245 243
246 snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), 244 snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
247 hp_jack_pins); 245 hp_jack_pins);
248 246
249 snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), 247 snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
250 hp_jack_gpios); 248 hp_jack_gpios);
251 249
252 return 0; 250 return 0;
253 } 251 }
254 252
255 static int __init rx1950_init(void) 253 static int __init rx1950_init(void)
256 { 254 {
257 int ret; 255 int ret;
258 256
259 if (!machine_is_rx1950()) 257 if (!machine_is_rx1950())
260 return -ENODEV; 258 return -ENODEV;
261 259
262 /* configure some gpios */ 260 /* configure some gpios */
263 ret = gpio_request(S3C2410_GPA(1), "speaker-power"); 261 ret = gpio_request(S3C2410_GPA(1), "speaker-power");
264 if (ret) 262 if (ret)
265 goto err_gpio; 263 goto err_gpio;
266 264
267 ret = gpio_direction_output(S3C2410_GPA(1), 0); 265 ret = gpio_direction_output(S3C2410_GPA(1), 0);
268 if (ret) 266 if (ret)
269 goto err_gpio_conf; 267 goto err_gpio_conf;
270 268
271 s3c24xx_snd_device = platform_device_alloc("soc-audio", -1); 269 s3c24xx_snd_device = platform_device_alloc("soc-audio", -1);
272 if (!s3c24xx_snd_device) { 270 if (!s3c24xx_snd_device) {
273 ret = -ENOMEM; 271 ret = -ENOMEM;
274 goto err_plat_alloc; 272 goto err_plat_alloc;
275 } 273 }
276 274
277 platform_set_drvdata(s3c24xx_snd_device, &rx1950_asoc); 275 platform_set_drvdata(s3c24xx_snd_device, &rx1950_asoc);
278 ret = platform_device_add(s3c24xx_snd_device); 276 ret = platform_device_add(s3c24xx_snd_device);
279 277
280 if (ret) { 278 if (ret) {
281 platform_device_put(s3c24xx_snd_device); 279 platform_device_put(s3c24xx_snd_device);
282 goto err_plat_add; 280 goto err_plat_add;
283 } 281 }
284 282
285 return 0; 283 return 0;
286 284
287 err_plat_add: 285 err_plat_add:
288 err_plat_alloc: 286 err_plat_alloc:
289 err_gpio_conf: 287 err_gpio_conf:
290 gpio_free(S3C2410_GPA(1)); 288 gpio_free(S3C2410_GPA(1));
291 289
292 err_gpio: 290 err_gpio:
293 return ret; 291 return ret;
294 } 292 }
295 293
296 static void __exit rx1950_exit(void) 294 static void __exit rx1950_exit(void)
297 { 295 {
298 platform_device_unregister(s3c24xx_snd_device); 296 platform_device_unregister(s3c24xx_snd_device);
299 snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), 297 snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
300 hp_jack_gpios); 298 hp_jack_gpios);
301 gpio_free(S3C2410_GPA(1)); 299 gpio_free(S3C2410_GPA(1));
302 } 300 }
303 301
304 module_init(rx1950_init); 302 module_init(rx1950_init);
305 module_exit(rx1950_exit); 303 module_exit(rx1950_exit);
306 304
307 /* Module information */ 305 /* Module information */
308 MODULE_AUTHOR("Vasily Khoruzhick"); 306 MODULE_AUTHOR("Vasily Khoruzhick");
309 MODULE_DESCRIPTION("ALSA SoC RX1950"); 307 MODULE_DESCRIPTION("ALSA SoC RX1950");
310 MODULE_LICENSE("GPL"); 308 MODULE_LICENSE("GPL");
311 309
sound/soc/samsung/s3c24xx_simtec_hermes.c
1 /* sound/soc/samsung/s3c24xx_simtec_hermes.c 1 /* sound/soc/samsung/s3c24xx_simtec_hermes.c
2 * 2 *
3 * Copyright 2009 Simtec Electronics 3 * Copyright 2009 Simtec Electronics
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 */ 8 */
9 9
10 #include <sound/soc.h> 10 #include <sound/soc.h>
11 11
12 #include "s3c24xx_simtec.h" 12 #include "s3c24xx_simtec.h"
13 13
14 static const struct snd_soc_dapm_widget dapm_widgets[] = { 14 static const struct snd_soc_dapm_widget dapm_widgets[] = {
15 SND_SOC_DAPM_LINE("GSM Out", NULL), 15 SND_SOC_DAPM_LINE("GSM Out", NULL),
16 SND_SOC_DAPM_LINE("GSM In", NULL), 16 SND_SOC_DAPM_LINE("GSM In", NULL),
17 SND_SOC_DAPM_LINE("Line In", NULL), 17 SND_SOC_DAPM_LINE("Line In", NULL),
18 SND_SOC_DAPM_LINE("Line Out", NULL), 18 SND_SOC_DAPM_LINE("Line Out", NULL),
19 SND_SOC_DAPM_LINE("ZV", NULL), 19 SND_SOC_DAPM_LINE("ZV", NULL),
20 SND_SOC_DAPM_MIC("Mic Jack", NULL), 20 SND_SOC_DAPM_MIC("Mic Jack", NULL),
21 SND_SOC_DAPM_HP("Headphone Jack", NULL), 21 SND_SOC_DAPM_HP("Headphone Jack", NULL),
22 }; 22 };
23 23
24 static const struct snd_soc_dapm_route base_map[] = { 24 static const struct snd_soc_dapm_route base_map[] = {
25 /* Headphone connected to HP{L,R}OUT and HP{L,R}COM */ 25 /* Headphone connected to HP{L,R}OUT and HP{L,R}COM */
26 26
27 { "Headphone Jack", NULL, "HPLOUT" }, 27 { "Headphone Jack", NULL, "HPLOUT" },
28 { "Headphone Jack", NULL, "HPLCOM" }, 28 { "Headphone Jack", NULL, "HPLCOM" },
29 { "Headphone Jack", NULL, "HPROUT" }, 29 { "Headphone Jack", NULL, "HPROUT" },
30 { "Headphone Jack", NULL, "HPRCOM" }, 30 { "Headphone Jack", NULL, "HPRCOM" },
31 31
32 /* ZV connected to Line1 */ 32 /* ZV connected to Line1 */
33 33
34 { "LINE1L", NULL, "ZV" }, 34 { "LINE1L", NULL, "ZV" },
35 { "LINE1R", NULL, "ZV" }, 35 { "LINE1R", NULL, "ZV" },
36 36
37 /* Line In connected to Line2 */ 37 /* Line In connected to Line2 */
38 38
39 { "LINE2L", NULL, "Line In" }, 39 { "LINE2L", NULL, "Line In" },
40 { "LINE2R", NULL, "Line In" }, 40 { "LINE2R", NULL, "Line In" },
41 41
42 /* Microphone connected to MIC3R and MIC_BIAS */ 42 /* Microphone connected to MIC3R and MIC_BIAS */
43 43
44 { "MIC3L", NULL, "Mic Jack" }, 44 { "MIC3L", NULL, "Mic Jack" },
45 45
46 /* GSM connected to MONO_LOUT and MIC3L (in) */ 46 /* GSM connected to MONO_LOUT and MIC3L (in) */
47 47
48 { "GSM Out", NULL, "MONO_LOUT" }, 48 { "GSM Out", NULL, "MONO_LOUT" },
49 { "MIC3L", NULL, "GSM In" }, 49 { "MIC3L", NULL, "GSM In" },
50 50
51 /* Speaker is connected to LINEOUT{LN,LP,RN,RP}, however we are 51 /* Speaker is connected to LINEOUT{LN,LP,RN,RP}, however we are
52 * not using the DAPM to power it up and down as there it makes 52 * not using the DAPM to power it up and down as there it makes
53 * a click when powering up. */ 53 * a click when powering up. */
54 }; 54 };
55 55
56 /** 56 /**
57 * simtec_hermes_init - initialise and add controls 57 * simtec_hermes_init - initialise and add controls
58 * @codec; The codec instance to attach to. 58 * @codec; The codec instance to attach to.
59 * 59 *
60 * Attach our controls and configure the necessary codec 60 * Attach our controls and configure the necessary codec
61 * mappings for our sound card instance. 61 * mappings for our sound card instance.
62 */ 62 */
63 static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd) 63 static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd)
64 { 64 {
65 struct snd_soc_codec *codec = rtd->codec; 65 struct snd_soc_codec *codec = rtd->codec;
66 struct snd_soc_dapm_context *dapm = &codec->dapm; 66 struct snd_soc_dapm_context *dapm = &codec->dapm;
67 67
68 snd_soc_dapm_new_controls(dapm, dapm_widgets, 68 snd_soc_dapm_new_controls(dapm, dapm_widgets,
69 ARRAY_SIZE(dapm_widgets)); 69 ARRAY_SIZE(dapm_widgets));
70 70
71 snd_soc_dapm_add_routes(dapm, base_map, ARRAY_SIZE(base_map)); 71 snd_soc_dapm_add_routes(dapm, base_map, ARRAY_SIZE(base_map));
72 72
73 snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); 73 snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
74 snd_soc_dapm_enable_pin(dapm, "Line In"); 74 snd_soc_dapm_enable_pin(dapm, "Line In");
75 snd_soc_dapm_enable_pin(dapm, "Line Out"); 75 snd_soc_dapm_enable_pin(dapm, "Line Out");
76 snd_soc_dapm_enable_pin(dapm, "Mic Jack"); 76 snd_soc_dapm_enable_pin(dapm, "Mic Jack");
77 77
78 simtec_audio_init(rtd); 78 simtec_audio_init(rtd);
79 snd_soc_dapm_sync(dapm);
80 79
81 return 0; 80 return 0;
82 } 81 }
83 82
84 static struct snd_soc_dai_link simtec_dai_aic33 = { 83 static struct snd_soc_dai_link simtec_dai_aic33 = {
85 .name = "tlv320aic33", 84 .name = "tlv320aic33",
86 .stream_name = "TLV320AIC33", 85 .stream_name = "TLV320AIC33",
87 .codec_name = "tlv320aic3x-codec.0-001a", 86 .codec_name = "tlv320aic3x-codec.0-001a",
88 .cpu_dai_name = "s3c24xx-iis", 87 .cpu_dai_name = "s3c24xx-iis",
89 .codec_dai_name = "tlv320aic3x-hifi", 88 .codec_dai_name = "tlv320aic3x-hifi",
90 .platform_name = "samsung-audio", 89 .platform_name = "samsung-audio",
91 .init = simtec_hermes_init, 90 .init = simtec_hermes_init,
92 }; 91 };
93 92
94 /* simtec audio machine driver */ 93 /* simtec audio machine driver */
95 static struct snd_soc_card snd_soc_machine_simtec_aic33 = { 94 static struct snd_soc_card snd_soc_machine_simtec_aic33 = {
96 .name = "Simtec-Hermes", 95 .name = "Simtec-Hermes",
97 .dai_link = &simtec_dai_aic33, 96 .dai_link = &simtec_dai_aic33,
98 .num_links = 1, 97 .num_links = 1,
99 }; 98 };
100 99
101 static int __devinit simtec_audio_hermes_probe(struct platform_device *pd) 100 static int __devinit simtec_audio_hermes_probe(struct platform_device *pd)
102 { 101 {
103 dev_info(&pd->dev, "probing....\n"); 102 dev_info(&pd->dev, "probing....\n");
104 return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic33); 103 return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic33);
105 } 104 }
106 105
107 static struct platform_driver simtec_audio_hermes_platdrv = { 106 static struct platform_driver simtec_audio_hermes_platdrv = {
108 .driver = { 107 .driver = {
109 .owner = THIS_MODULE, 108 .owner = THIS_MODULE,
110 .name = "s3c24xx-simtec-hermes-snd", 109 .name = "s3c24xx-simtec-hermes-snd",
111 .pm = simtec_audio_pm, 110 .pm = simtec_audio_pm,
112 }, 111 },
113 .probe = simtec_audio_hermes_probe, 112 .probe = simtec_audio_hermes_probe,
114 .remove = __devexit_p(simtec_audio_remove), 113 .remove = __devexit_p(simtec_audio_remove),
115 }; 114 };
116 115
117 MODULE_ALIAS("platform:s3c24xx-simtec-hermes-snd"); 116 MODULE_ALIAS("platform:s3c24xx-simtec-hermes-snd");
118 117
119 static int __init simtec_hermes_modinit(void) 118 static int __init simtec_hermes_modinit(void)
120 { 119 {
121 return platform_driver_register(&simtec_audio_hermes_platdrv); 120 return platform_driver_register(&simtec_audio_hermes_platdrv);
122 } 121 }
123 122
124 static void __exit simtec_hermes_modexit(void) 123 static void __exit simtec_hermes_modexit(void)
125 { 124 {
126 platform_driver_unregister(&simtec_audio_hermes_platdrv); 125 platform_driver_unregister(&simtec_audio_hermes_platdrv);
127 } 126 }
128 127
129 module_init(simtec_hermes_modinit); 128 module_init(simtec_hermes_modinit);
130 module_exit(simtec_hermes_modexit); 129 module_exit(simtec_hermes_modexit);
131 130
132 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 131 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
133 MODULE_DESCRIPTION("ALSA SoC Simtec Audio support"); 132 MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
134 MODULE_LICENSE("GPL"); 133 MODULE_LICENSE("GPL");
135 134
sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
1 /* sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c 1 /* sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
2 * 2 *
3 * Copyright 2009 Simtec Electronics 3 * Copyright 2009 Simtec Electronics
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 */ 8 */
9 9
10 #include <sound/soc.h> 10 #include <sound/soc.h>
11 11
12 #include "s3c24xx_simtec.h" 12 #include "s3c24xx_simtec.h"
13 13
14 /* supported machines: 14 /* supported machines:
15 * 15 *
16 * Machine Connections AMP 16 * Machine Connections AMP
17 * ------- ----------- --- 17 * ------- ----------- ---
18 * BAST MIC, HPOUT, LOUT, LIN TPA2001D1 (HPOUTL,R) (gain hardwired) 18 * BAST MIC, HPOUT, LOUT, LIN TPA2001D1 (HPOUTL,R) (gain hardwired)
19 * VR1000 HPOUT, LIN None 19 * VR1000 HPOUT, LIN None
20 * VR2000 LIN, LOUT, MIC, HP LM4871 (HPOUTL,R) 20 * VR2000 LIN, LOUT, MIC, HP LM4871 (HPOUTL,R)
21 * DePicture LIN, LOUT, MIC, HP LM4871 (HPOUTL,R) 21 * DePicture LIN, LOUT, MIC, HP LM4871 (HPOUTL,R)
22 * Anubis LIN, LOUT, MIC, HP TPA2001D1 (HPOUTL,R) 22 * Anubis LIN, LOUT, MIC, HP TPA2001D1 (HPOUTL,R)
23 */ 23 */
24 24
25 static const struct snd_soc_dapm_widget dapm_widgets[] = { 25 static const struct snd_soc_dapm_widget dapm_widgets[] = {
26 SND_SOC_DAPM_HP("Headphone Jack", NULL), 26 SND_SOC_DAPM_HP("Headphone Jack", NULL),
27 SND_SOC_DAPM_LINE("Line In", NULL), 27 SND_SOC_DAPM_LINE("Line In", NULL),
28 SND_SOC_DAPM_LINE("Line Out", NULL), 28 SND_SOC_DAPM_LINE("Line Out", NULL),
29 SND_SOC_DAPM_MIC("Mic Jack", NULL), 29 SND_SOC_DAPM_MIC("Mic Jack", NULL),
30 }; 30 };
31 31
32 static const struct snd_soc_dapm_route base_map[] = { 32 static const struct snd_soc_dapm_route base_map[] = {
33 { "Headphone Jack", NULL, "LHPOUT"}, 33 { "Headphone Jack", NULL, "LHPOUT"},
34 { "Headphone Jack", NULL, "RHPOUT"}, 34 { "Headphone Jack", NULL, "RHPOUT"},
35 35
36 { "Line Out", NULL, "LOUT" }, 36 { "Line Out", NULL, "LOUT" },
37 { "Line Out", NULL, "ROUT" }, 37 { "Line Out", NULL, "ROUT" },
38 38
39 { "LLINEIN", NULL, "Line In"}, 39 { "LLINEIN", NULL, "Line In"},
40 { "RLINEIN", NULL, "Line In"}, 40 { "RLINEIN", NULL, "Line In"},
41 41
42 { "MICIN", NULL, "Mic Jack"}, 42 { "MICIN", NULL, "Mic Jack"},
43 }; 43 };
44 44
45 /** 45 /**
46 * simtec_tlv320aic23_init - initialise and add controls 46 * simtec_tlv320aic23_init - initialise and add controls
47 * @codec; The codec instance to attach to. 47 * @codec; The codec instance to attach to.
48 * 48 *
49 * Attach our controls and configure the necessary codec 49 * Attach our controls and configure the necessary codec
50 * mappings for our sound card instance. 50 * mappings for our sound card instance.
51 */ 51 */
52 static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) 52 static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
53 { 53 {
54 struct snd_soc_codec *codec = rtd->codec; 54 struct snd_soc_codec *codec = rtd->codec;
55 struct snd_soc_dapm_context *dapm = &codec->dapm; 55 struct snd_soc_dapm_context *dapm = &codec->dapm;
56 56
57 snd_soc_dapm_new_controls(dapm, dapm_widgets, 57 snd_soc_dapm_new_controls(dapm, dapm_widgets,
58 ARRAY_SIZE(dapm_widgets)); 58 ARRAY_SIZE(dapm_widgets));
59 59
60 snd_soc_dapm_add_routes(dapm, base_map, ARRAY_SIZE(base_map)); 60 snd_soc_dapm_add_routes(dapm, base_map, ARRAY_SIZE(base_map));
61 61
62 snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); 62 snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
63 snd_soc_dapm_enable_pin(dapm, "Line In"); 63 snd_soc_dapm_enable_pin(dapm, "Line In");
64 snd_soc_dapm_enable_pin(dapm, "Line Out"); 64 snd_soc_dapm_enable_pin(dapm, "Line Out");
65 snd_soc_dapm_enable_pin(dapm, "Mic Jack"); 65 snd_soc_dapm_enable_pin(dapm, "Mic Jack");
66 66
67 simtec_audio_init(rtd); 67 simtec_audio_init(rtd);
68 snd_soc_dapm_sync(dapm);
69 68
70 return 0; 69 return 0;
71 } 70 }
72 71
73 static struct snd_soc_dai_link simtec_dai_aic23 = { 72 static struct snd_soc_dai_link simtec_dai_aic23 = {
74 .name = "tlv320aic23", 73 .name = "tlv320aic23",
75 .stream_name = "TLV320AIC23", 74 .stream_name = "TLV320AIC23",
76 .codec_name = "tlv320aic3x-codec.0-001a", 75 .codec_name = "tlv320aic3x-codec.0-001a",
77 .cpu_dai_name = "s3c24xx-iis", 76 .cpu_dai_name = "s3c24xx-iis",
78 .codec_dai_name = "tlv320aic3x-hifi", 77 .codec_dai_name = "tlv320aic3x-hifi",
79 .platform_name = "samsung-audio", 78 .platform_name = "samsung-audio",
80 .init = simtec_tlv320aic23_init, 79 .init = simtec_tlv320aic23_init,
81 }; 80 };
82 81
83 /* simtec audio machine driver */ 82 /* simtec audio machine driver */
84 static struct snd_soc_card snd_soc_machine_simtec_aic23 = { 83 static struct snd_soc_card snd_soc_machine_simtec_aic23 = {
85 .name = "Simtec", 84 .name = "Simtec",
86 .dai_link = &simtec_dai_aic23, 85 .dai_link = &simtec_dai_aic23,
87 .num_links = 1, 86 .num_links = 1,
88 }; 87 };
89 88
90 static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd) 89 static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)
91 { 90 {
92 return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23); 91 return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23);
93 } 92 }
94 93
95 static struct platform_driver simtec_audio_tlv320aic23_platdrv = { 94 static struct platform_driver simtec_audio_tlv320aic23_platdrv = {
96 .driver = { 95 .driver = {
97 .owner = THIS_MODULE, 96 .owner = THIS_MODULE,
98 .name = "s3c24xx-simtec-tlv320aic23", 97 .name = "s3c24xx-simtec-tlv320aic23",
99 .pm = simtec_audio_pm, 98 .pm = simtec_audio_pm,
100 }, 99 },
101 .probe = simtec_audio_tlv320aic23_probe, 100 .probe = simtec_audio_tlv320aic23_probe,
102 .remove = __devexit_p(simtec_audio_remove), 101 .remove = __devexit_p(simtec_audio_remove),
103 }; 102 };
104 103
105 MODULE_ALIAS("platform:s3c24xx-simtec-tlv320aic23"); 104 MODULE_ALIAS("platform:s3c24xx-simtec-tlv320aic23");
106 105
107 static int __init simtec_tlv320aic23_modinit(void) 106 static int __init simtec_tlv320aic23_modinit(void)
108 { 107 {
109 return platform_driver_register(&simtec_audio_tlv320aic23_platdrv); 108 return platform_driver_register(&simtec_audio_tlv320aic23_platdrv);
110 } 109 }
111 110
112 static void __exit simtec_tlv320aic23_modexit(void) 111 static void __exit simtec_tlv320aic23_modexit(void)
113 { 112 {
114 platform_driver_unregister(&simtec_audio_tlv320aic23_platdrv); 113 platform_driver_unregister(&simtec_audio_tlv320aic23_platdrv);
115 } 114 }
116 115
117 module_init(simtec_tlv320aic23_modinit); 116 module_init(simtec_tlv320aic23_modinit);
118 module_exit(simtec_tlv320aic23_modexit); 117 module_exit(simtec_tlv320aic23_modexit);
119 118
120 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 119 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
121 MODULE_DESCRIPTION("ALSA SoC Simtec Audio support"); 120 MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
122 MODULE_LICENSE("GPL"); 121 MODULE_LICENSE("GPL");
123 122
sound/soc/samsung/smartq_wm8987.c
1 /* sound/soc/samsung/smartq_wm8987.c 1 /* sound/soc/samsung/smartq_wm8987.c
2 * 2 *
3 * Copyright 2010 Maurus Cuelenaere <mcuelenaere@gmail.com> 3 * Copyright 2010 Maurus Cuelenaere <mcuelenaere@gmail.com>
4 * 4 *
5 * Based on smdk6410_wm8987.c 5 * Based on smdk6410_wm8987.c
6 * Copyright 2007 Wolfson Microelectronics PLC. - linux@wolfsonmicro.com 6 * Copyright 2007 Wolfson Microelectronics PLC. - linux@wolfsonmicro.com
7 * Graeme Gregory - graeme.gregory@wolfsonmicro.com 7 * Graeme Gregory - graeme.gregory@wolfsonmicro.com
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify it 9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the 10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your 11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. 12 * option) any later version.
13 * 13 *
14 */ 14 */
15 15
16 #include <linux/gpio.h> 16 #include <linux/gpio.h>
17 17
18 #include <sound/soc.h> 18 #include <sound/soc.h>
19 #include <sound/jack.h> 19 #include <sound/jack.h>
20 20
21 #include <asm/mach-types.h> 21 #include <asm/mach-types.h>
22 22
23 #include "i2s.h" 23 #include "i2s.h"
24 #include "../codecs/wm8750.h" 24 #include "../codecs/wm8750.h"
25 25
26 /* 26 /*
27 * WM8987 is register compatible with WM8750, so using that as base driver. 27 * WM8987 is register compatible with WM8750, so using that as base driver.
28 */ 28 */
29 29
30 static struct snd_soc_card snd_soc_smartq; 30 static struct snd_soc_card snd_soc_smartq;
31 31
32 static int smartq_hifi_hw_params(struct snd_pcm_substream *substream, 32 static int smartq_hifi_hw_params(struct snd_pcm_substream *substream,
33 struct snd_pcm_hw_params *params) 33 struct snd_pcm_hw_params *params)
34 { 34 {
35 struct snd_soc_pcm_runtime *rtd = substream->private_data; 35 struct snd_soc_pcm_runtime *rtd = substream->private_data;
36 struct snd_soc_dai *codec_dai = rtd->codec_dai; 36 struct snd_soc_dai *codec_dai = rtd->codec_dai;
37 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 37 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
38 unsigned int clk = 0; 38 unsigned int clk = 0;
39 int ret; 39 int ret;
40 40
41 switch (params_rate(params)) { 41 switch (params_rate(params)) {
42 case 8000: 42 case 8000:
43 case 16000: 43 case 16000:
44 case 32000: 44 case 32000:
45 case 48000: 45 case 48000:
46 case 96000: 46 case 96000:
47 clk = 12288000; 47 clk = 12288000;
48 break; 48 break;
49 case 11025: 49 case 11025:
50 case 22050: 50 case 22050:
51 case 44100: 51 case 44100:
52 case 88200: 52 case 88200:
53 clk = 11289600; 53 clk = 11289600;
54 break; 54 break;
55 } 55 }
56 56
57 /* set codec DAI configuration */ 57 /* set codec DAI configuration */
58 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 58 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
59 SND_SOC_DAIFMT_NB_NF | 59 SND_SOC_DAIFMT_NB_NF |
60 SND_SOC_DAIFMT_CBS_CFS); 60 SND_SOC_DAIFMT_CBS_CFS);
61 if (ret < 0) 61 if (ret < 0)
62 return ret; 62 return ret;
63 63
64 /* set cpu DAI configuration */ 64 /* set cpu DAI configuration */
65 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 65 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
66 SND_SOC_DAIFMT_NB_NF | 66 SND_SOC_DAIFMT_NB_NF |
67 SND_SOC_DAIFMT_CBS_CFS); 67 SND_SOC_DAIFMT_CBS_CFS);
68 if (ret < 0) 68 if (ret < 0)
69 return ret; 69 return ret;
70 70
71 /* Use PCLK for I2S signal generation */ 71 /* Use PCLK for I2S signal generation */
72 ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_RCLKSRC_0, 72 ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_RCLKSRC_0,
73 0, SND_SOC_CLOCK_IN); 73 0, SND_SOC_CLOCK_IN);
74 if (ret < 0) 74 if (ret < 0)
75 return ret; 75 return ret;
76 76
77 /* Gate the RCLK output on PAD */ 77 /* Gate the RCLK output on PAD */
78 ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK, 78 ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK,
79 0, SND_SOC_CLOCK_IN); 79 0, SND_SOC_CLOCK_IN);
80 if (ret < 0) 80 if (ret < 0)
81 return ret; 81 return ret;
82 82
83 /* set the codec system clock for DAC and ADC */ 83 /* set the codec system clock for DAC and ADC */
84 ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk, 84 ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
85 SND_SOC_CLOCK_IN); 85 SND_SOC_CLOCK_IN);
86 if (ret < 0) 86 if (ret < 0)
87 return ret; 87 return ret;
88 88
89 return 0; 89 return 0;
90 } 90 }
91 91
92 /* 92 /*
93 * SmartQ WM8987 HiFi DAI operations. 93 * SmartQ WM8987 HiFi DAI operations.
94 */ 94 */
95 static struct snd_soc_ops smartq_hifi_ops = { 95 static struct snd_soc_ops smartq_hifi_ops = {
96 .hw_params = smartq_hifi_hw_params, 96 .hw_params = smartq_hifi_hw_params,
97 }; 97 };
98 98
99 static struct snd_soc_jack smartq_jack; 99 static struct snd_soc_jack smartq_jack;
100 100
101 static struct snd_soc_jack_pin smartq_jack_pins[] = { 101 static struct snd_soc_jack_pin smartq_jack_pins[] = {
102 /* Disable speaker when headphone is plugged in */ 102 /* Disable speaker when headphone is plugged in */
103 { 103 {
104 .pin = "Internal Speaker", 104 .pin = "Internal Speaker",
105 .mask = SND_JACK_HEADPHONE, 105 .mask = SND_JACK_HEADPHONE,
106 }, 106 },
107 }; 107 };
108 108
109 static struct snd_soc_jack_gpio smartq_jack_gpios[] = { 109 static struct snd_soc_jack_gpio smartq_jack_gpios[] = {
110 { 110 {
111 .gpio = S3C64XX_GPL(12), 111 .gpio = S3C64XX_GPL(12),
112 .name = "headphone detect", 112 .name = "headphone detect",
113 .report = SND_JACK_HEADPHONE, 113 .report = SND_JACK_HEADPHONE,
114 .debounce_time = 200, 114 .debounce_time = 200,
115 }, 115 },
116 }; 116 };
117 117
118 static const struct snd_kcontrol_new wm8987_smartq_controls[] = { 118 static const struct snd_kcontrol_new wm8987_smartq_controls[] = {
119 SOC_DAPM_PIN_SWITCH("Internal Speaker"), 119 SOC_DAPM_PIN_SWITCH("Internal Speaker"),
120 SOC_DAPM_PIN_SWITCH("Headphone Jack"), 120 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
121 SOC_DAPM_PIN_SWITCH("Internal Mic"), 121 SOC_DAPM_PIN_SWITCH("Internal Mic"),
122 }; 122 };
123 123
124 static int smartq_speaker_event(struct snd_soc_dapm_widget *w, 124 static int smartq_speaker_event(struct snd_soc_dapm_widget *w,
125 struct snd_kcontrol *k, 125 struct snd_kcontrol *k,
126 int event) 126 int event)
127 { 127 {
128 gpio_set_value(S3C64XX_GPK(12), SND_SOC_DAPM_EVENT_OFF(event)); 128 gpio_set_value(S3C64XX_GPK(12), SND_SOC_DAPM_EVENT_OFF(event));
129 129
130 return 0; 130 return 0;
131 } 131 }
132 132
133 static const struct snd_soc_dapm_widget wm8987_dapm_widgets[] = { 133 static const struct snd_soc_dapm_widget wm8987_dapm_widgets[] = {
134 SND_SOC_DAPM_SPK("Internal Speaker", smartq_speaker_event), 134 SND_SOC_DAPM_SPK("Internal Speaker", smartq_speaker_event),
135 SND_SOC_DAPM_HP("Headphone Jack", NULL), 135 SND_SOC_DAPM_HP("Headphone Jack", NULL),
136 SND_SOC_DAPM_MIC("Internal Mic", NULL), 136 SND_SOC_DAPM_MIC("Internal Mic", NULL),
137 }; 137 };
138 138
139 static const struct snd_soc_dapm_route audio_map[] = { 139 static const struct snd_soc_dapm_route audio_map[] = {
140 {"Headphone Jack", NULL, "LOUT2"}, 140 {"Headphone Jack", NULL, "LOUT2"},
141 {"Headphone Jack", NULL, "ROUT2"}, 141 {"Headphone Jack", NULL, "ROUT2"},
142 142
143 {"Internal Speaker", NULL, "LOUT2"}, 143 {"Internal Speaker", NULL, "LOUT2"},
144 {"Internal Speaker", NULL, "ROUT2"}, 144 {"Internal Speaker", NULL, "ROUT2"},
145 145
146 {"Mic Bias", NULL, "Internal Mic"}, 146 {"Mic Bias", NULL, "Internal Mic"},
147 {"LINPUT2", NULL, "Mic Bias"}, 147 {"LINPUT2", NULL, "Mic Bias"},
148 }; 148 };
149 149
150 static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd) 150 static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd)
151 { 151 {
152 struct snd_soc_codec *codec = rtd->codec; 152 struct snd_soc_codec *codec = rtd->codec;
153 struct snd_soc_dapm_context *dapm = &codec->dapm; 153 struct snd_soc_dapm_context *dapm = &codec->dapm;
154 int err = 0; 154 int err = 0;
155 155
156 /* Add SmartQ specific widgets */ 156 /* Add SmartQ specific widgets */
157 snd_soc_dapm_new_controls(dapm, wm8987_dapm_widgets, 157 snd_soc_dapm_new_controls(dapm, wm8987_dapm_widgets,
158 ARRAY_SIZE(wm8987_dapm_widgets)); 158 ARRAY_SIZE(wm8987_dapm_widgets));
159 159
160 /* add SmartQ specific controls */ 160 /* add SmartQ specific controls */
161 err = snd_soc_add_controls(codec, wm8987_smartq_controls, 161 err = snd_soc_add_controls(codec, wm8987_smartq_controls,
162 ARRAY_SIZE(wm8987_smartq_controls)); 162 ARRAY_SIZE(wm8987_smartq_controls));
163 163
164 if (err < 0) 164 if (err < 0)
165 return err; 165 return err;
166 166
167 /* setup SmartQ specific audio path */ 167 /* setup SmartQ specific audio path */
168 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); 168 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
169 169
170 /* set endpoints to not connected */ 170 /* set endpoints to not connected */
171 snd_soc_dapm_nc_pin(dapm, "LINPUT1"); 171 snd_soc_dapm_nc_pin(dapm, "LINPUT1");
172 snd_soc_dapm_nc_pin(dapm, "RINPUT1"); 172 snd_soc_dapm_nc_pin(dapm, "RINPUT1");
173 snd_soc_dapm_nc_pin(dapm, "OUT3"); 173 snd_soc_dapm_nc_pin(dapm, "OUT3");
174 snd_soc_dapm_nc_pin(dapm, "ROUT1"); 174 snd_soc_dapm_nc_pin(dapm, "ROUT1");
175 175
176 /* set endpoints to default off mode */ 176 /* set endpoints to default off mode */
177 snd_soc_dapm_enable_pin(dapm, "Internal Speaker"); 177 snd_soc_dapm_enable_pin(dapm, "Internal Speaker");
178 snd_soc_dapm_enable_pin(dapm, "Internal Mic"); 178 snd_soc_dapm_enable_pin(dapm, "Internal Mic");
179 snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); 179 snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
180 180
181 err = snd_soc_dapm_sync(dapm);
182 if (err)
183 return err;
184
185 /* Headphone jack detection */ 181 /* Headphone jack detection */
186 err = snd_soc_jack_new(codec, "Headphone Jack", 182 err = snd_soc_jack_new(codec, "Headphone Jack",
187 SND_JACK_HEADPHONE, &smartq_jack); 183 SND_JACK_HEADPHONE, &smartq_jack);
188 if (err) 184 if (err)
189 return err; 185 return err;
190 186
191 err = snd_soc_jack_add_pins(&smartq_jack, ARRAY_SIZE(smartq_jack_pins), 187 err = snd_soc_jack_add_pins(&smartq_jack, ARRAY_SIZE(smartq_jack_pins),
192 smartq_jack_pins); 188 smartq_jack_pins);
193 if (err) 189 if (err)
194 return err; 190 return err;
195 191
196 err = snd_soc_jack_add_gpios(&smartq_jack, 192 err = snd_soc_jack_add_gpios(&smartq_jack,
197 ARRAY_SIZE(smartq_jack_gpios), 193 ARRAY_SIZE(smartq_jack_gpios),
198 smartq_jack_gpios); 194 smartq_jack_gpios);
199 195
200 return err; 196 return err;
201 } 197 }
202 198
203 static struct snd_soc_dai_link smartq_dai[] = { 199 static struct snd_soc_dai_link smartq_dai[] = {
204 { 200 {
205 .name = "wm8987", 201 .name = "wm8987",
206 .stream_name = "SmartQ Hi-Fi", 202 .stream_name = "SmartQ Hi-Fi",
207 .cpu_dai_name = "samsung-i2s.0", 203 .cpu_dai_name = "samsung-i2s.0",
208 .codec_dai_name = "wm8750-hifi", 204 .codec_dai_name = "wm8750-hifi",
209 .platform_name = "samsung-audio", 205 .platform_name = "samsung-audio",
210 .codec_name = "wm8750.0-0x1a", 206 .codec_name = "wm8750.0-0x1a",
211 .init = smartq_wm8987_init, 207 .init = smartq_wm8987_init,
212 .ops = &smartq_hifi_ops, 208 .ops = &smartq_hifi_ops,
213 }, 209 },
214 }; 210 };
215 211
216 static struct snd_soc_card snd_soc_smartq = { 212 static struct snd_soc_card snd_soc_smartq = {
217 .name = "SmartQ", 213 .name = "SmartQ",
218 .dai_link = smartq_dai, 214 .dai_link = smartq_dai,
219 .num_links = ARRAY_SIZE(smartq_dai), 215 .num_links = ARRAY_SIZE(smartq_dai),
220 }; 216 };
221 217
222 static struct platform_device *smartq_snd_device; 218 static struct platform_device *smartq_snd_device;
223 219
224 static int __init smartq_init(void) 220 static int __init smartq_init(void)
225 { 221 {
226 int ret; 222 int ret;
227 223
228 if (!machine_is_smartq7() && !machine_is_smartq5()) { 224 if (!machine_is_smartq7() && !machine_is_smartq5()) {
229 pr_info("Only SmartQ is supported by this ASoC driver\n"); 225 pr_info("Only SmartQ is supported by this ASoC driver\n");
230 return -ENODEV; 226 return -ENODEV;
231 } 227 }
232 228
233 smartq_snd_device = platform_device_alloc("soc-audio", -1); 229 smartq_snd_device = platform_device_alloc("soc-audio", -1);
234 if (!smartq_snd_device) 230 if (!smartq_snd_device)
235 return -ENOMEM; 231 return -ENOMEM;
236 232
237 platform_set_drvdata(smartq_snd_device, &snd_soc_smartq); 233 platform_set_drvdata(smartq_snd_device, &snd_soc_smartq);
238 234
239 ret = platform_device_add(smartq_snd_device); 235 ret = platform_device_add(smartq_snd_device);
240 if (ret) { 236 if (ret) {
241 platform_device_put(smartq_snd_device); 237 platform_device_put(smartq_snd_device);
242 return ret; 238 return ret;
243 } 239 }
244 240
245 /* Initialise GPIOs used by amplifiers */ 241 /* Initialise GPIOs used by amplifiers */
246 ret = gpio_request(S3C64XX_GPK(12), "amplifiers shutdown"); 242 ret = gpio_request(S3C64XX_GPK(12), "amplifiers shutdown");
247 if (ret) { 243 if (ret) {
248 dev_err(&smartq_snd_device->dev, "Failed to register GPK12\n"); 244 dev_err(&smartq_snd_device->dev, "Failed to register GPK12\n");
249 goto err_unregister_device; 245 goto err_unregister_device;
250 } 246 }
251 247
252 /* Disable amplifiers */ 248 /* Disable amplifiers */
253 ret = gpio_direction_output(S3C64XX_GPK(12), 1); 249 ret = gpio_direction_output(S3C64XX_GPK(12), 1);
254 if (ret) { 250 if (ret) {
255 dev_err(&smartq_snd_device->dev, "Failed to configure GPK12\n"); 251 dev_err(&smartq_snd_device->dev, "Failed to configure GPK12\n");
256 goto err_free_gpio_amp_shut; 252 goto err_free_gpio_amp_shut;
257 } 253 }
258 254
259 return 0; 255 return 0;
260 256
261 err_free_gpio_amp_shut: 257 err_free_gpio_amp_shut:
262 gpio_free(S3C64XX_GPK(12)); 258 gpio_free(S3C64XX_GPK(12));
263 err_unregister_device: 259 err_unregister_device:
264 platform_device_unregister(smartq_snd_device); 260 platform_device_unregister(smartq_snd_device);
265 261
266 return ret; 262 return ret;
267 } 263 }
268 264
269 static void __exit smartq_exit(void) 265 static void __exit smartq_exit(void)
270 { 266 {
271 gpio_free(S3C64XX_GPK(12)); 267 gpio_free(S3C64XX_GPK(12));
272 snd_soc_jack_free_gpios(&smartq_jack, ARRAY_SIZE(smartq_jack_gpios), 268 snd_soc_jack_free_gpios(&smartq_jack, ARRAY_SIZE(smartq_jack_gpios),
273 smartq_jack_gpios); 269 smartq_jack_gpios);
274 270
275 platform_device_unregister(smartq_snd_device); 271 platform_device_unregister(smartq_snd_device);
276 } 272 }
277 273
278 module_init(smartq_init); 274 module_init(smartq_init);
279 module_exit(smartq_exit); 275 module_exit(smartq_exit);
280 276
281 /* Module information */ 277 /* Module information */
282 MODULE_AUTHOR("Maurus Cuelenaere <mcuelenaere@gmail.com>"); 278 MODULE_AUTHOR("Maurus Cuelenaere <mcuelenaere@gmail.com>");
283 MODULE_DESCRIPTION("ALSA SoC SmartQ WM8987"); 279 MODULE_DESCRIPTION("ALSA SoC SmartQ WM8987");
284 MODULE_LICENSE("GPL"); 280 MODULE_LICENSE("GPL");
285 281
sound/soc/samsung/smdk_wm8580.c
1 /* 1 /*
2 * smdk_wm8580.c 2 * smdk_wm8580.c
3 * 3 *
4 * Copyright (c) 2009 Samsung Electronics Co. Ltd 4 * Copyright (c) 2009 Samsung Electronics Co. Ltd
5 * Author: Jaswinder Singh <jassi.brar@samsung.com> 5 * Author: Jaswinder Singh <jassi.brar@samsung.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your 9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. 10 * option) any later version.
11 */ 11 */
12 12
13 #include <sound/soc.h> 13 #include <sound/soc.h>
14 #include <sound/pcm_params.h> 14 #include <sound/pcm_params.h>
15 15
16 #include <asm/mach-types.h> 16 #include <asm/mach-types.h>
17 17
18 #include "../codecs/wm8580.h" 18 #include "../codecs/wm8580.h"
19 #include "i2s.h" 19 #include "i2s.h"
20 20
21 /* 21 /*
22 * Default CFG switch settings to use this driver: 22 * Default CFG switch settings to use this driver:
23 * 23 *
24 * SMDK6410: Set CFG1 1-3 Off, CFG2 1-4 On 24 * SMDK6410: Set CFG1 1-3 Off, CFG2 1-4 On
25 */ 25 */
26 26
27 /* SMDK has a 12MHZ crystal attached to WM8580 */ 27 /* SMDK has a 12MHZ crystal attached to WM8580 */
28 #define SMDK_WM8580_FREQ 12000000 28 #define SMDK_WM8580_FREQ 12000000
29 29
30 static int smdk_hw_params(struct snd_pcm_substream *substream, 30 static int smdk_hw_params(struct snd_pcm_substream *substream,
31 struct snd_pcm_hw_params *params) 31 struct snd_pcm_hw_params *params)
32 { 32 {
33 struct snd_soc_pcm_runtime *rtd = substream->private_data; 33 struct snd_soc_pcm_runtime *rtd = substream->private_data;
34 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 34 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
35 struct snd_soc_dai *codec_dai = rtd->codec_dai; 35 struct snd_soc_dai *codec_dai = rtd->codec_dai;
36 unsigned int pll_out; 36 unsigned int pll_out;
37 int bfs, rfs, ret; 37 int bfs, rfs, ret;
38 38
39 switch (params_format(params)) { 39 switch (params_format(params)) {
40 case SNDRV_PCM_FORMAT_U8: 40 case SNDRV_PCM_FORMAT_U8:
41 case SNDRV_PCM_FORMAT_S8: 41 case SNDRV_PCM_FORMAT_S8:
42 bfs = 16; 42 bfs = 16;
43 break; 43 break;
44 case SNDRV_PCM_FORMAT_U16_LE: 44 case SNDRV_PCM_FORMAT_U16_LE:
45 case SNDRV_PCM_FORMAT_S16_LE: 45 case SNDRV_PCM_FORMAT_S16_LE:
46 bfs = 32; 46 bfs = 32;
47 break; 47 break;
48 default: 48 default:
49 return -EINVAL; 49 return -EINVAL;
50 } 50 }
51 51
52 /* The Fvco for WM8580 PLLs must fall within [90,100]MHz. 52 /* The Fvco for WM8580 PLLs must fall within [90,100]MHz.
53 * This criterion can't be met if we request PLL output 53 * This criterion can't be met if we request PLL output
54 * as {8000x256, 64000x256, 11025x256}Hz. 54 * as {8000x256, 64000x256, 11025x256}Hz.
55 * As a wayout, we rather change rfs to a minimum value that 55 * As a wayout, we rather change rfs to a minimum value that
56 * results in (params_rate(params) * rfs), and itself, acceptable 56 * results in (params_rate(params) * rfs), and itself, acceptable
57 * to both - the CODEC and the CPU. 57 * to both - the CODEC and the CPU.
58 */ 58 */
59 switch (params_rate(params)) { 59 switch (params_rate(params)) {
60 case 16000: 60 case 16000:
61 case 22050: 61 case 22050:
62 case 32000: 62 case 32000:
63 case 44100: 63 case 44100:
64 case 48000: 64 case 48000:
65 case 88200: 65 case 88200:
66 case 96000: 66 case 96000:
67 rfs = 256; 67 rfs = 256;
68 break; 68 break;
69 case 64000: 69 case 64000:
70 rfs = 384; 70 rfs = 384;
71 break; 71 break;
72 case 8000: 72 case 8000:
73 case 11025: 73 case 11025:
74 rfs = 512; 74 rfs = 512;
75 break; 75 break;
76 default: 76 default:
77 return -EINVAL; 77 return -EINVAL;
78 } 78 }
79 pll_out = params_rate(params) * rfs; 79 pll_out = params_rate(params) * rfs;
80 80
81 /* Set the Codec DAI configuration */ 81 /* Set the Codec DAI configuration */
82 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S 82 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
83 | SND_SOC_DAIFMT_NB_NF 83 | SND_SOC_DAIFMT_NB_NF
84 | SND_SOC_DAIFMT_CBM_CFM); 84 | SND_SOC_DAIFMT_CBM_CFM);
85 if (ret < 0) 85 if (ret < 0)
86 return ret; 86 return ret;
87 87
88 /* Set the AP DAI configuration */ 88 /* Set the AP DAI configuration */
89 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S 89 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
90 | SND_SOC_DAIFMT_NB_NF 90 | SND_SOC_DAIFMT_NB_NF
91 | SND_SOC_DAIFMT_CBM_CFM); 91 | SND_SOC_DAIFMT_CBM_CFM);
92 if (ret < 0) 92 if (ret < 0)
93 return ret; 93 return ret;
94 94
95 /* Set WM8580 to drive MCLK from its PLLA */ 95 /* Set WM8580 to drive MCLK from its PLLA */
96 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK, 96 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK,
97 WM8580_CLKSRC_PLLA); 97 WM8580_CLKSRC_PLLA);
98 if (ret < 0) 98 if (ret < 0)
99 return ret; 99 return ret;
100 100
101 ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0, 101 ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0,
102 SMDK_WM8580_FREQ, pll_out); 102 SMDK_WM8580_FREQ, pll_out);
103 if (ret < 0) 103 if (ret < 0)
104 return ret; 104 return ret;
105 105
106 ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA, 106 ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA,
107 pll_out, SND_SOC_CLOCK_IN); 107 pll_out, SND_SOC_CLOCK_IN);
108 if (ret < 0) 108 if (ret < 0)
109 return ret; 109 return ret;
110 110
111 return 0; 111 return 0;
112 } 112 }
113 113
114 /* 114 /*
115 * SMDK WM8580 DAI operations. 115 * SMDK WM8580 DAI operations.
116 */ 116 */
117 static struct snd_soc_ops smdk_ops = { 117 static struct snd_soc_ops smdk_ops = {
118 .hw_params = smdk_hw_params, 118 .hw_params = smdk_hw_params,
119 }; 119 };
120 120
121 /* SMDK Playback widgets */ 121 /* SMDK Playback widgets */
122 static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = { 122 static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = {
123 SND_SOC_DAPM_HP("Front", NULL), 123 SND_SOC_DAPM_HP("Front", NULL),
124 SND_SOC_DAPM_HP("Center+Sub", NULL), 124 SND_SOC_DAPM_HP("Center+Sub", NULL),
125 SND_SOC_DAPM_HP("Rear", NULL), 125 SND_SOC_DAPM_HP("Rear", NULL),
126 }; 126 };
127 127
128 /* SMDK Capture widgets */ 128 /* SMDK Capture widgets */
129 static const struct snd_soc_dapm_widget wm8580_dapm_widgets_cpt[] = { 129 static const struct snd_soc_dapm_widget wm8580_dapm_widgets_cpt[] = {
130 SND_SOC_DAPM_MIC("MicIn", NULL), 130 SND_SOC_DAPM_MIC("MicIn", NULL),
131 SND_SOC_DAPM_LINE("LineIn", NULL), 131 SND_SOC_DAPM_LINE("LineIn", NULL),
132 }; 132 };
133 133
134 /* SMDK-PAIFTX connections */ 134 /* SMDK-PAIFTX connections */
135 static const struct snd_soc_dapm_route audio_map_tx[] = { 135 static const struct snd_soc_dapm_route audio_map_tx[] = {
136 /* MicIn feeds AINL */ 136 /* MicIn feeds AINL */
137 {"AINL", NULL, "MicIn"}, 137 {"AINL", NULL, "MicIn"},
138 138
139 /* LineIn feeds AINL/R */ 139 /* LineIn feeds AINL/R */
140 {"AINL", NULL, "LineIn"}, 140 {"AINL", NULL, "LineIn"},
141 {"AINR", NULL, "LineIn"}, 141 {"AINR", NULL, "LineIn"},
142 }; 142 };
143 143
144 /* SMDK-PAIFRX connections */ 144 /* SMDK-PAIFRX connections */
145 static const struct snd_soc_dapm_route audio_map_rx[] = { 145 static const struct snd_soc_dapm_route audio_map_rx[] = {
146 /* Front Left/Right are fed VOUT1L/R */ 146 /* Front Left/Right are fed VOUT1L/R */
147 {"Front", NULL, "VOUT1L"}, 147 {"Front", NULL, "VOUT1L"},
148 {"Front", NULL, "VOUT1R"}, 148 {"Front", NULL, "VOUT1R"},
149 149
150 /* Center/Sub are fed VOUT2L/R */ 150 /* Center/Sub are fed VOUT2L/R */
151 {"Center+Sub", NULL, "VOUT2L"}, 151 {"Center+Sub", NULL, "VOUT2L"},
152 {"Center+Sub", NULL, "VOUT2R"}, 152 {"Center+Sub", NULL, "VOUT2R"},
153 153
154 /* Rear Left/Right are fed VOUT3L/R */ 154 /* Rear Left/Right are fed VOUT3L/R */
155 {"Rear", NULL, "VOUT3L"}, 155 {"Rear", NULL, "VOUT3L"},
156 {"Rear", NULL, "VOUT3R"}, 156 {"Rear", NULL, "VOUT3R"},
157 }; 157 };
158 158
159 static int smdk_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd) 159 static int smdk_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd)
160 { 160 {
161 struct snd_soc_codec *codec = rtd->codec; 161 struct snd_soc_codec *codec = rtd->codec;
162 struct snd_soc_dapm_context *dapm = &codec->dapm; 162 struct snd_soc_dapm_context *dapm = &codec->dapm;
163 163
164 /* Add smdk specific Capture widgets */ 164 /* Add smdk specific Capture widgets */
165 snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets_cpt, 165 snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets_cpt,
166 ARRAY_SIZE(wm8580_dapm_widgets_cpt)); 166 ARRAY_SIZE(wm8580_dapm_widgets_cpt));
167 167
168 /* Set up PAIFTX audio path */ 168 /* Set up PAIFTX audio path */
169 snd_soc_dapm_add_routes(dapm, audio_map_tx, ARRAY_SIZE(audio_map_tx)); 169 snd_soc_dapm_add_routes(dapm, audio_map_tx, ARRAY_SIZE(audio_map_tx));
170 170
171 /* Enabling the microphone requires the fitting of a 0R 171 /* Enabling the microphone requires the fitting of a 0R
172 * resistor to connect the line from the microphone jack. 172 * resistor to connect the line from the microphone jack.
173 */ 173 */
174 snd_soc_dapm_disable_pin(dapm, "MicIn"); 174 snd_soc_dapm_disable_pin(dapm, "MicIn");
175 175
176 /* signal a DAPM event */
177 snd_soc_dapm_sync(dapm);
178
179 return 0; 176 return 0;
180 } 177 }
181 178
182 static int smdk_wm8580_init_paifrx(struct snd_soc_pcm_runtime *rtd) 179 static int smdk_wm8580_init_paifrx(struct snd_soc_pcm_runtime *rtd)
183 { 180 {
184 struct snd_soc_codec *codec = rtd->codec; 181 struct snd_soc_codec *codec = rtd->codec;
185 struct snd_soc_dapm_context *dapm = &codec->dapm; 182 struct snd_soc_dapm_context *dapm = &codec->dapm;
186 183
187 /* Add smdk specific Playback widgets */ 184 /* Add smdk specific Playback widgets */
188 snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets_pbk, 185 snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets_pbk,
189 ARRAY_SIZE(wm8580_dapm_widgets_pbk)); 186 ARRAY_SIZE(wm8580_dapm_widgets_pbk));
190 187
191 /* Set up PAIFRX audio path */ 188 /* Set up PAIFRX audio path */
192 snd_soc_dapm_add_routes(dapm, audio_map_rx, ARRAY_SIZE(audio_map_rx)); 189 snd_soc_dapm_add_routes(dapm, audio_map_rx, ARRAY_SIZE(audio_map_rx));
193
194 /* signal a DAPM event */
195 snd_soc_dapm_sync(dapm);
196 190
197 return 0; 191 return 0;
198 } 192 }
199 193
200 enum { 194 enum {
201 PRI_PLAYBACK = 0, 195 PRI_PLAYBACK = 0,
202 PRI_CAPTURE, 196 PRI_CAPTURE,
203 SEC_PLAYBACK, 197 SEC_PLAYBACK,
204 }; 198 };
205 199
206 static struct snd_soc_dai_link smdk_dai[] = { 200 static struct snd_soc_dai_link smdk_dai[] = {
207 [PRI_PLAYBACK] = { /* Primary Playback i/f */ 201 [PRI_PLAYBACK] = { /* Primary Playback i/f */
208 .name = "WM8580 PAIF RX", 202 .name = "WM8580 PAIF RX",
209 .stream_name = "Playback", 203 .stream_name = "Playback",
210 .cpu_dai_name = "samsung-i2s.0", 204 .cpu_dai_name = "samsung-i2s.0",
211 .codec_dai_name = "wm8580-hifi-playback", 205 .codec_dai_name = "wm8580-hifi-playback",
212 .platform_name = "samsung-audio", 206 .platform_name = "samsung-audio",
213 .codec_name = "wm8580.0-001b", 207 .codec_name = "wm8580.0-001b",
214 .init = smdk_wm8580_init_paifrx, 208 .init = smdk_wm8580_init_paifrx,
215 .ops = &smdk_ops, 209 .ops = &smdk_ops,
216 }, 210 },
217 [PRI_CAPTURE] = { /* Primary Capture i/f */ 211 [PRI_CAPTURE] = { /* Primary Capture i/f */
218 .name = "WM8580 PAIF TX", 212 .name = "WM8580 PAIF TX",
219 .stream_name = "Capture", 213 .stream_name = "Capture",
220 .cpu_dai_name = "samsung-i2s.0", 214 .cpu_dai_name = "samsung-i2s.0",
221 .codec_dai_name = "wm8580-hifi-capture", 215 .codec_dai_name = "wm8580-hifi-capture",
222 .platform_name = "samsung-audio", 216 .platform_name = "samsung-audio",
223 .codec_name = "wm8580.0-001b", 217 .codec_name = "wm8580.0-001b",
224 .init = smdk_wm8580_init_paiftx, 218 .init = smdk_wm8580_init_paiftx,
225 .ops = &smdk_ops, 219 .ops = &smdk_ops,
226 }, 220 },
227 [SEC_PLAYBACK] = { /* Sec_Fifo Playback i/f */ 221 [SEC_PLAYBACK] = { /* Sec_Fifo Playback i/f */
228 .name = "Sec_FIFO TX", 222 .name = "Sec_FIFO TX",
229 .stream_name = "Playback", 223 .stream_name = "Playback",
230 .cpu_dai_name = "samsung-i2s.x", 224 .cpu_dai_name = "samsung-i2s.x",
231 .codec_dai_name = "wm8580-hifi-playback", 225 .codec_dai_name = "wm8580-hifi-playback",
232 .platform_name = "samsung-audio", 226 .platform_name = "samsung-audio",
233 .codec_name = "wm8580.0-001b", 227 .codec_name = "wm8580.0-001b",
234 .init = smdk_wm8580_init_paifrx, 228 .init = smdk_wm8580_init_paifrx,
235 .ops = &smdk_ops, 229 .ops = &smdk_ops,
236 }, 230 },
237 }; 231 };
238 232
239 static struct snd_soc_card smdk = { 233 static struct snd_soc_card smdk = {
240 .name = "SMDK-I2S", 234 .name = "SMDK-I2S",
241 .dai_link = smdk_dai, 235 .dai_link = smdk_dai,
242 .num_links = 2, 236 .num_links = 2,
243 }; 237 };
244 238
245 static struct platform_device *smdk_snd_device; 239 static struct platform_device *smdk_snd_device;
246 240
247 static int __init smdk_audio_init(void) 241 static int __init smdk_audio_init(void)
248 { 242 {
249 int ret; 243 int ret;
250 char *str; 244 char *str;
251 245
252 if (machine_is_smdkc100() 246 if (machine_is_smdkc100()
253 || machine_is_smdkv210() || machine_is_smdkc110()) { 247 || machine_is_smdkv210() || machine_is_smdkc110()) {
254 smdk.num_links = 3; 248 smdk.num_links = 3;
255 /* Secondary is at offset SAMSUNG_I2S_SECOFF from Primary */ 249 /* Secondary is at offset SAMSUNG_I2S_SECOFF from Primary */
256 str = (char *)smdk_dai[SEC_PLAYBACK].cpu_dai_name; 250 str = (char *)smdk_dai[SEC_PLAYBACK].cpu_dai_name;
257 str[strlen(str) - 1] = '0' + SAMSUNG_I2S_SECOFF; 251 str[strlen(str) - 1] = '0' + SAMSUNG_I2S_SECOFF;
258 } else if (machine_is_smdk6410()) { 252 } else if (machine_is_smdk6410()) {
259 str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name; 253 str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
260 str[strlen(str) - 1] = '2'; 254 str[strlen(str) - 1] = '2';
261 str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name; 255 str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
262 str[strlen(str) - 1] = '2'; 256 str[strlen(str) - 1] = '2';
263 } 257 }
264 258
265 smdk_snd_device = platform_device_alloc("soc-audio", -1); 259 smdk_snd_device = platform_device_alloc("soc-audio", -1);
266 if (!smdk_snd_device) 260 if (!smdk_snd_device)
267 return -ENOMEM; 261 return -ENOMEM;
268 262
269 platform_set_drvdata(smdk_snd_device, &smdk); 263 platform_set_drvdata(smdk_snd_device, &smdk);
270 ret = platform_device_add(smdk_snd_device); 264 ret = platform_device_add(smdk_snd_device);
271 265
272 if (ret) 266 if (ret)
273 platform_device_put(smdk_snd_device); 267 platform_device_put(smdk_snd_device);
274 268
275 return ret; 269 return ret;
276 } 270 }
277 module_init(smdk_audio_init); 271 module_init(smdk_audio_init);
278 272
279 static void __exit smdk_audio_exit(void) 273 static void __exit smdk_audio_exit(void)
280 { 274 {
281 platform_device_unregister(smdk_snd_device); 275 platform_device_unregister(smdk_snd_device);
282 } 276 }
283 module_exit(smdk_audio_exit); 277 module_exit(smdk_audio_exit);
284 278
285 MODULE_AUTHOR("Jaswinder Singh, jassi.brar@samsung.com"); 279 MODULE_AUTHOR("Jaswinder Singh, jassi.brar@samsung.com");
286 MODULE_DESCRIPTION("ALSA SoC SMDK WM8580"); 280 MODULE_DESCRIPTION("ALSA SoC SMDK WM8580");
287 MODULE_LICENSE("GPL"); 281 MODULE_LICENSE("GPL");
288 282
sound/soc/samsung/smdk_wm8994.c
1 /* 1 /*
2 * smdk_wm8994.c 2 * smdk_wm8994.c
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the 5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your 6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. 7 * option) any later version.
8 */ 8 */
9 9
10 #include "../codecs/wm8994.h" 10 #include "../codecs/wm8994.h"
11 #include <sound/pcm_params.h> 11 #include <sound/pcm_params.h>
12 12
13 /* 13 /*
14 * Default CFG switch settings to use this driver: 14 * Default CFG switch settings to use this driver:
15 * SMDKV310: CFG5-1000, CFG7-111111 15 * SMDKV310: CFG5-1000, CFG7-111111
16 */ 16 */
17 17
18 /* 18 /*
19 * Configure audio route as :- 19 * Configure audio route as :-
20 * $ amixer sset 'DAC1' on,on 20 * $ amixer sset 'DAC1' on,on
21 * $ amixer sset 'Right Headphone Mux' 'DAC' 21 * $ amixer sset 'Right Headphone Mux' 'DAC'
22 * $ amixer sset 'Left Headphone Mux' 'DAC' 22 * $ amixer sset 'Left Headphone Mux' 'DAC'
23 * $ amixer sset 'DAC1R Mixer AIF1.1' on 23 * $ amixer sset 'DAC1R Mixer AIF1.1' on
24 * $ amixer sset 'DAC1L Mixer AIF1.1' on 24 * $ amixer sset 'DAC1L Mixer AIF1.1' on
25 * $ amixer sset 'IN2L' on 25 * $ amixer sset 'IN2L' on
26 * $ amixer sset 'IN2L PGA IN2LN' on 26 * $ amixer sset 'IN2L PGA IN2LN' on
27 * $ amixer sset 'MIXINL IN2L' on 27 * $ amixer sset 'MIXINL IN2L' on
28 * $ amixer sset 'AIF1ADC1L Mixer ADC/DMIC' on 28 * $ amixer sset 'AIF1ADC1L Mixer ADC/DMIC' on
29 * $ amixer sset 'IN2R' on 29 * $ amixer sset 'IN2R' on
30 * $ amixer sset 'IN2R PGA IN2RN' on 30 * $ amixer sset 'IN2R PGA IN2RN' on
31 * $ amixer sset 'MIXINR IN2R' on 31 * $ amixer sset 'MIXINR IN2R' on
32 * $ amixer sset 'AIF1ADC1R Mixer ADC/DMIC' on 32 * $ amixer sset 'AIF1ADC1R Mixer ADC/DMIC' on
33 */ 33 */
34 34
35 /* SMDK has a 16.934MHZ crystal attached to WM8994 */ 35 /* SMDK has a 16.934MHZ crystal attached to WM8994 */
36 #define SMDK_WM8994_FREQ 16934000 36 #define SMDK_WM8994_FREQ 16934000
37 37
38 static int smdk_hw_params(struct snd_pcm_substream *substream, 38 static int smdk_hw_params(struct snd_pcm_substream *substream,
39 struct snd_pcm_hw_params *params) 39 struct snd_pcm_hw_params *params)
40 { 40 {
41 struct snd_soc_pcm_runtime *rtd = substream->private_data; 41 struct snd_soc_pcm_runtime *rtd = substream->private_data;
42 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 42 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
43 struct snd_soc_dai *codec_dai = rtd->codec_dai; 43 struct snd_soc_dai *codec_dai = rtd->codec_dai;
44 unsigned int pll_out; 44 unsigned int pll_out;
45 int ret; 45 int ret;
46 46
47 /* AIF1CLK should be >=3MHz for optimal performance */ 47 /* AIF1CLK should be >=3MHz for optimal performance */
48 if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE) 48 if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE)
49 pll_out = params_rate(params) * 384; 49 pll_out = params_rate(params) * 384;
50 else if (params_rate(params) == 8000 || params_rate(params) == 11025) 50 else if (params_rate(params) == 8000 || params_rate(params) == 11025)
51 pll_out = params_rate(params) * 512; 51 pll_out = params_rate(params) * 512;
52 else 52 else
53 pll_out = params_rate(params) * 256; 53 pll_out = params_rate(params) * 256;
54 54
55 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S 55 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
56 | SND_SOC_DAIFMT_NB_NF 56 | SND_SOC_DAIFMT_NB_NF
57 | SND_SOC_DAIFMT_CBM_CFM); 57 | SND_SOC_DAIFMT_CBM_CFM);
58 if (ret < 0) 58 if (ret < 0)
59 return ret; 59 return ret;
60 60
61 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S 61 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
62 | SND_SOC_DAIFMT_NB_NF 62 | SND_SOC_DAIFMT_NB_NF
63 | SND_SOC_DAIFMT_CBM_CFM); 63 | SND_SOC_DAIFMT_CBM_CFM);
64 if (ret < 0) 64 if (ret < 0)
65 return ret; 65 return ret;
66 66
67 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, 67 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1,
68 SMDK_WM8994_FREQ, pll_out); 68 SMDK_WM8994_FREQ, pll_out);
69 if (ret < 0) 69 if (ret < 0)
70 return ret; 70 return ret;
71 71
72 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, 72 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
73 pll_out, SND_SOC_CLOCK_IN); 73 pll_out, SND_SOC_CLOCK_IN);
74 if (ret < 0) 74 if (ret < 0)
75 return ret; 75 return ret;
76 76
77 return 0; 77 return 0;
78 } 78 }
79 79
80 /* 80 /*
81 * SMDK WM8994 DAI operations. 81 * SMDK WM8994 DAI operations.
82 */ 82 */
83 static struct snd_soc_ops smdk_ops = { 83 static struct snd_soc_ops smdk_ops = {
84 .hw_params = smdk_hw_params, 84 .hw_params = smdk_hw_params,
85 }; 85 };
86 86
87 static int smdk_wm8994_init_paiftx(struct snd_soc_pcm_runtime *rtd) 87 static int smdk_wm8994_init_paiftx(struct snd_soc_pcm_runtime *rtd)
88 { 88 {
89 struct snd_soc_codec *codec = rtd->codec; 89 struct snd_soc_codec *codec = rtd->codec;
90 struct snd_soc_dapm_context *dapm = &codec->dapm; 90 struct snd_soc_dapm_context *dapm = &codec->dapm;
91 91
92 /* HeadPhone */ 92 /* HeadPhone */
93 snd_soc_dapm_enable_pin(dapm, "HPOUT1R"); 93 snd_soc_dapm_enable_pin(dapm, "HPOUT1R");
94 snd_soc_dapm_enable_pin(dapm, "HPOUT1L"); 94 snd_soc_dapm_enable_pin(dapm, "HPOUT1L");
95 95
96 /* MicIn */ 96 /* MicIn */
97 snd_soc_dapm_enable_pin(dapm, "IN1LN"); 97 snd_soc_dapm_enable_pin(dapm, "IN1LN");
98 snd_soc_dapm_enable_pin(dapm, "IN1RN"); 98 snd_soc_dapm_enable_pin(dapm, "IN1RN");
99 99
100 /* LineIn */ 100 /* LineIn */
101 snd_soc_dapm_enable_pin(dapm, "IN2LN"); 101 snd_soc_dapm_enable_pin(dapm, "IN2LN");
102 snd_soc_dapm_enable_pin(dapm, "IN2RN"); 102 snd_soc_dapm_enable_pin(dapm, "IN2RN");
103 103
104 /* Other pins NC */ 104 /* Other pins NC */
105 snd_soc_dapm_nc_pin(dapm, "HPOUT2P"); 105 snd_soc_dapm_nc_pin(dapm, "HPOUT2P");
106 snd_soc_dapm_nc_pin(dapm, "HPOUT2N"); 106 snd_soc_dapm_nc_pin(dapm, "HPOUT2N");
107 snd_soc_dapm_nc_pin(dapm, "SPKOUTLN"); 107 snd_soc_dapm_nc_pin(dapm, "SPKOUTLN");
108 snd_soc_dapm_nc_pin(dapm, "SPKOUTLP"); 108 snd_soc_dapm_nc_pin(dapm, "SPKOUTLP");
109 snd_soc_dapm_nc_pin(dapm, "SPKOUTRP"); 109 snd_soc_dapm_nc_pin(dapm, "SPKOUTRP");
110 snd_soc_dapm_nc_pin(dapm, "SPKOUTRN"); 110 snd_soc_dapm_nc_pin(dapm, "SPKOUTRN");
111 snd_soc_dapm_nc_pin(dapm, "LINEOUT1N"); 111 snd_soc_dapm_nc_pin(dapm, "LINEOUT1N");
112 snd_soc_dapm_nc_pin(dapm, "LINEOUT1P"); 112 snd_soc_dapm_nc_pin(dapm, "LINEOUT1P");
113 snd_soc_dapm_nc_pin(dapm, "LINEOUT2N"); 113 snd_soc_dapm_nc_pin(dapm, "LINEOUT2N");
114 snd_soc_dapm_nc_pin(dapm, "LINEOUT2P"); 114 snd_soc_dapm_nc_pin(dapm, "LINEOUT2P");
115 snd_soc_dapm_nc_pin(dapm, "IN1LP"); 115 snd_soc_dapm_nc_pin(dapm, "IN1LP");
116 snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN"); 116 snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN");
117 snd_soc_dapm_nc_pin(dapm, "IN1RP"); 117 snd_soc_dapm_nc_pin(dapm, "IN1RP");
118 snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP"); 118 snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP");
119 119
120 snd_soc_dapm_sync(dapm);
121
122 return 0; 120 return 0;
123 } 121 }
124 122
125 static struct snd_soc_dai_link smdk_dai[] = { 123 static struct snd_soc_dai_link smdk_dai[] = {
126 { /* Primary DAI i/f */ 124 { /* Primary DAI i/f */
127 .name = "WM8994 AIF1", 125 .name = "WM8994 AIF1",
128 .stream_name = "Pri_Dai", 126 .stream_name = "Pri_Dai",
129 .cpu_dai_name = "samsung-i2s.0", 127 .cpu_dai_name = "samsung-i2s.0",
130 .codec_dai_name = "wm8994-aif1", 128 .codec_dai_name = "wm8994-aif1",
131 .platform_name = "samsung-audio", 129 .platform_name = "samsung-audio",
132 .codec_name = "wm8994-codec", 130 .codec_name = "wm8994-codec",
133 .init = smdk_wm8994_init_paiftx, 131 .init = smdk_wm8994_init_paiftx,
134 .ops = &smdk_ops, 132 .ops = &smdk_ops,
135 }, { /* Sec_Fifo Playback i/f */ 133 }, { /* Sec_Fifo Playback i/f */
136 .name = "Sec_FIFO TX", 134 .name = "Sec_FIFO TX",
137 .stream_name = "Sec_Dai", 135 .stream_name = "Sec_Dai",
138 .cpu_dai_name = "samsung-i2s.4", 136 .cpu_dai_name = "samsung-i2s.4",
139 .codec_dai_name = "wm8994-aif1", 137 .codec_dai_name = "wm8994-aif1",
140 .platform_name = "samsung-audio", 138 .platform_name = "samsung-audio",
141 .codec_name = "wm8994-codec", 139 .codec_name = "wm8994-codec",
142 .ops = &smdk_ops, 140 .ops = &smdk_ops,
143 }, 141 },
144 }; 142 };
145 143
146 static struct snd_soc_card smdk = { 144 static struct snd_soc_card smdk = {
147 .name = "SMDK-I2S", 145 .name = "SMDK-I2S",
148 .dai_link = smdk_dai, 146 .dai_link = smdk_dai,
149 .num_links = ARRAY_SIZE(smdk_dai), 147 .num_links = ARRAY_SIZE(smdk_dai),
150 }; 148 };
151 149
152 static struct platform_device *smdk_snd_device; 150 static struct platform_device *smdk_snd_device;
153 151
154 static int __init smdk_audio_init(void) 152 static int __init smdk_audio_init(void)
155 { 153 {
156 int ret; 154 int ret;
157 155
158 smdk_snd_device = platform_device_alloc("soc-audio", -1); 156 smdk_snd_device = platform_device_alloc("soc-audio", -1);
159 if (!smdk_snd_device) 157 if (!smdk_snd_device)
160 return -ENOMEM; 158 return -ENOMEM;
161 159
162 platform_set_drvdata(smdk_snd_device, &smdk); 160 platform_set_drvdata(smdk_snd_device, &smdk);
163 161
164 ret = platform_device_add(smdk_snd_device); 162 ret = platform_device_add(smdk_snd_device);
165 if (ret) 163 if (ret)
166 platform_device_put(smdk_snd_device); 164 platform_device_put(smdk_snd_device);
167 165
168 return ret; 166 return ret;
169 } 167 }
170 module_init(smdk_audio_init); 168 module_init(smdk_audio_init);
171 169
172 static void __exit smdk_audio_exit(void) 170 static void __exit smdk_audio_exit(void)
173 { 171 {
174 platform_device_unregister(smdk_snd_device); 172 platform_device_unregister(smdk_snd_device);
175 } 173 }
176 module_exit(smdk_audio_exit); 174 module_exit(smdk_audio_exit);
177 175
178 MODULE_DESCRIPTION("ALSA SoC SMDK WM8994"); 176 MODULE_DESCRIPTION("ALSA SoC SMDK WM8994");
179 MODULE_LICENSE("GPL"); 177 MODULE_LICENSE("GPL");
180 178
sound/soc/sh/sh7760-ac97.c
1 /* 1 /*
2 * Generic AC97 sound support for SH7760 2 * Generic AC97 sound support for SH7760
3 * 3 *
4 * (c) 2007 Manuel Lauss 4 * (c) 2007 Manuel Lauss
5 * 5 *
6 * Licensed under the GPLv2. 6 * Licensed under the GPLv2.
7 */ 7 */
8 8
9 #include <linux/module.h> 9 #include <linux/module.h>
10 #include <linux/moduleparam.h> 10 #include <linux/moduleparam.h>
11 #include <linux/platform_device.h> 11 #include <linux/platform_device.h>
12 #include <sound/core.h> 12 #include <sound/core.h>
13 #include <sound/pcm.h> 13 #include <sound/pcm.h>
14 #include <sound/soc.h> 14 #include <sound/soc.h>
15 #include <asm/io.h> 15 #include <asm/io.h>
16 16
17 #define IPSEL 0xFE400034 17 #define IPSEL 0xFE400034
18 18
19 /* platform specific structs can be declared here */ 19 /* platform specific structs can be declared here */
20 extern struct snd_soc_dai_driver sh4_hac_dai[2]; 20 extern struct snd_soc_dai_driver sh4_hac_dai[2];
21 extern struct snd_soc_platform_driver sh7760_soc_platform; 21 extern struct snd_soc_platform_driver sh7760_soc_platform;
22 22
23 static int machine_init(struct snd_soc_pcm_runtime *rtd)
24 {
25 snd_soc_dapm_sync(&rtd->codec->dapm);
26 return 0;
27 }
28
29 static struct snd_soc_dai_link sh7760_ac97_dai = { 23 static struct snd_soc_dai_link sh7760_ac97_dai = {
30 .name = "AC97", 24 .name = "AC97",
31 .stream_name = "AC97 HiFi", 25 .stream_name = "AC97 HiFi",
32 .cpu_dai_name = "hac-dai.0", /* HAC0 */ 26 .cpu_dai_name = "hac-dai.0", /* HAC0 */
33 .codec_dai_name = "ac97-hifi", 27 .codec_dai_name = "ac97-hifi",
34 .platform_name = "sh7760-pcm-audio", 28 .platform_name = "sh7760-pcm-audio",
35 .codec_name = "ac97-codec", 29 .codec_name = "ac97-codec",
36 .init = machine_init,
37 .ops = NULL, 30 .ops = NULL,
38 }; 31 };
39 32
40 static struct snd_soc_card sh7760_ac97_soc_machine = { 33 static struct snd_soc_card sh7760_ac97_soc_machine = {
41 .name = "SH7760 AC97", 34 .name = "SH7760 AC97",
42 .dai_link = &sh7760_ac97_dai, 35 .dai_link = &sh7760_ac97_dai,
43 .num_links = 1, 36 .num_links = 1,
44 }; 37 };
45 38
46 static struct platform_device *sh7760_ac97_snd_device; 39 static struct platform_device *sh7760_ac97_snd_device;
47 40
48 static int __init sh7760_ac97_init(void) 41 static int __init sh7760_ac97_init(void)
49 { 42 {
50 int ret; 43 int ret;
51 unsigned short ipsel; 44 unsigned short ipsel;
52 45
53 /* enable both AC97 controllers in pinmux reg */ 46 /* enable both AC97 controllers in pinmux reg */
54 ipsel = __raw_readw(IPSEL); 47 ipsel = __raw_readw(IPSEL);
55 __raw_writew(ipsel | (3 << 10), IPSEL); 48 __raw_writew(ipsel | (3 << 10), IPSEL);
56 49
57 ret = -ENOMEM; 50 ret = -ENOMEM;
58 sh7760_ac97_snd_device = platform_device_alloc("soc-audio", -1); 51 sh7760_ac97_snd_device = platform_device_alloc("soc-audio", -1);
59 if (!sh7760_ac97_snd_device) 52 if (!sh7760_ac97_snd_device)
60 goto out; 53 goto out;
61 54
62 platform_set_drvdata(sh7760_ac97_snd_device, 55 platform_set_drvdata(sh7760_ac97_snd_device,
63 &sh7760_ac97_soc_machine); 56 &sh7760_ac97_soc_machine);
64 ret = platform_device_add(sh7760_ac97_snd_device); 57 ret = platform_device_add(sh7760_ac97_snd_device);
65 58
66 if (ret) 59 if (ret)
67 platform_device_put(sh7760_ac97_snd_device); 60 platform_device_put(sh7760_ac97_snd_device);
68 61
69 out: 62 out:
70 return ret; 63 return ret;
71 } 64 }
72 65
73 static void __exit sh7760_ac97_exit(void) 66 static void __exit sh7760_ac97_exit(void)
74 { 67 {
75 platform_device_unregister(sh7760_ac97_snd_device); 68 platform_device_unregister(sh7760_ac97_snd_device);
76 } 69 }
77 70
78 module_init(sh7760_ac97_init); 71 module_init(sh7760_ac97_init);
79 module_exit(sh7760_ac97_exit); 72 module_exit(sh7760_ac97_exit);
80 73
81 MODULE_LICENSE("GPL"); 74 MODULE_LICENSE("GPL");
82 MODULE_DESCRIPTION("Generic SH7760 AC97 sound machine"); 75 MODULE_DESCRIPTION("Generic SH7760 AC97 sound machine");
83 MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); 76 MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
84 77
sound/soc/tegra/tegra_wm8903.c
1 /* 1 /*
2 * tegra_wm8903.c - Tegra machine ASoC driver for boards using WM8903 codec. 2 * tegra_wm8903.c - Tegra machine ASoC driver for boards using WM8903 codec.
3 * 3 *
4 * Author: Stephen Warren <swarren@nvidia.com> 4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010-2011 - NVIDIA, Inc. 5 * Copyright (C) 2010-2011 - NVIDIA, Inc.
6 * 6 *
7 * Based on code copyright/by: 7 * Based on code copyright/by:
8 * 8 *
9 * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd. 9 * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
10 * 10 *
11 * Copyright 2007 Wolfson Microelectronics PLC. 11 * Copyright 2007 Wolfson Microelectronics PLC.
12 * Author: Graeme Gregory 12 * Author: Graeme Gregory
13 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com 13 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
14 * 14 *
15 * This program is free software; you can redistribute it and/or 15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License 16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation. 17 * version 2 as published by the Free Software Foundation.
18 * 18 *
19 * This program is distributed in the hope that it will be useful, but 19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of 20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details. 22 * General Public License for more details.
23 * 23 *
24 * You should have received a copy of the GNU General Public License 24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software 25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA 27 * 02110-1301 USA
28 * 28 *
29 */ 29 */
30 30
31 #include <asm/mach-types.h> 31 #include <asm/mach-types.h>
32 32
33 #include <linux/module.h> 33 #include <linux/module.h>
34 #include <linux/platform_device.h> 34 #include <linux/platform_device.h>
35 #include <linux/slab.h> 35 #include <linux/slab.h>
36 #include <linux/gpio.h> 36 #include <linux/gpio.h>
37 37
38 #include <mach/tegra_wm8903_pdata.h> 38 #include <mach/tegra_wm8903_pdata.h>
39 39
40 #include <sound/core.h> 40 #include <sound/core.h>
41 #include <sound/jack.h> 41 #include <sound/jack.h>
42 #include <sound/pcm.h> 42 #include <sound/pcm.h>
43 #include <sound/pcm_params.h> 43 #include <sound/pcm_params.h>
44 #include <sound/soc.h> 44 #include <sound/soc.h>
45 45
46 #include "../codecs/wm8903.h" 46 #include "../codecs/wm8903.h"
47 47
48 #include "tegra_das.h" 48 #include "tegra_das.h"
49 #include "tegra_i2s.h" 49 #include "tegra_i2s.h"
50 #include "tegra_pcm.h" 50 #include "tegra_pcm.h"
51 #include "tegra_asoc_utils.h" 51 #include "tegra_asoc_utils.h"
52 52
53 #define DRV_NAME "tegra-snd-wm8903" 53 #define DRV_NAME "tegra-snd-wm8903"
54 54
55 #define GPIO_SPKR_EN BIT(0) 55 #define GPIO_SPKR_EN BIT(0)
56 #define GPIO_HP_MUTE BIT(1) 56 #define GPIO_HP_MUTE BIT(1)
57 #define GPIO_INT_MIC_EN BIT(2) 57 #define GPIO_INT_MIC_EN BIT(2)
58 #define GPIO_EXT_MIC_EN BIT(3) 58 #define GPIO_EXT_MIC_EN BIT(3)
59 #define GPIO_HP_DET BIT(4) 59 #define GPIO_HP_DET BIT(4)
60 60
61 struct tegra_wm8903 { 61 struct tegra_wm8903 {
62 struct tegra_asoc_utils_data util_data; 62 struct tegra_asoc_utils_data util_data;
63 struct tegra_wm8903_platform_data *pdata; 63 struct tegra_wm8903_platform_data *pdata;
64 int gpio_requested; 64 int gpio_requested;
65 }; 65 };
66 66
67 static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, 67 static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
68 struct snd_pcm_hw_params *params) 68 struct snd_pcm_hw_params *params)
69 { 69 {
70 struct snd_soc_pcm_runtime *rtd = substream->private_data; 70 struct snd_soc_pcm_runtime *rtd = substream->private_data;
71 struct snd_soc_dai *codec_dai = rtd->codec_dai; 71 struct snd_soc_dai *codec_dai = rtd->codec_dai;
72 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 72 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
73 struct snd_soc_codec *codec = rtd->codec; 73 struct snd_soc_codec *codec = rtd->codec;
74 struct snd_soc_card *card = codec->card; 74 struct snd_soc_card *card = codec->card;
75 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 75 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
76 int srate, mclk; 76 int srate, mclk;
77 int err; 77 int err;
78 78
79 srate = params_rate(params); 79 srate = params_rate(params);
80 switch (srate) { 80 switch (srate) {
81 case 64000: 81 case 64000:
82 case 88200: 82 case 88200:
83 case 96000: 83 case 96000:
84 mclk = 128 * srate; 84 mclk = 128 * srate;
85 break; 85 break;
86 default: 86 default:
87 mclk = 256 * srate; 87 mclk = 256 * srate;
88 break; 88 break;
89 } 89 }
90 /* FIXME: Codec only requires >= 3MHz if OSR==0 */ 90 /* FIXME: Codec only requires >= 3MHz if OSR==0 */
91 while (mclk < 6000000) 91 while (mclk < 6000000)
92 mclk *= 2; 92 mclk *= 2;
93 93
94 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); 94 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
95 if (err < 0) { 95 if (err < 0) {
96 dev_err(card->dev, "Can't configure clocks\n"); 96 dev_err(card->dev, "Can't configure clocks\n");
97 return err; 97 return err;
98 } 98 }
99 99
100 err = snd_soc_dai_set_fmt(codec_dai, 100 err = snd_soc_dai_set_fmt(codec_dai,
101 SND_SOC_DAIFMT_I2S | 101 SND_SOC_DAIFMT_I2S |
102 SND_SOC_DAIFMT_NB_NF | 102 SND_SOC_DAIFMT_NB_NF |
103 SND_SOC_DAIFMT_CBS_CFS); 103 SND_SOC_DAIFMT_CBS_CFS);
104 if (err < 0) { 104 if (err < 0) {
105 dev_err(card->dev, "codec_dai fmt not set\n"); 105 dev_err(card->dev, "codec_dai fmt not set\n");
106 return err; 106 return err;
107 } 107 }
108 108
109 err = snd_soc_dai_set_fmt(cpu_dai, 109 err = snd_soc_dai_set_fmt(cpu_dai,
110 SND_SOC_DAIFMT_I2S | 110 SND_SOC_DAIFMT_I2S |
111 SND_SOC_DAIFMT_NB_NF | 111 SND_SOC_DAIFMT_NB_NF |
112 SND_SOC_DAIFMT_CBS_CFS); 112 SND_SOC_DAIFMT_CBS_CFS);
113 if (err < 0) { 113 if (err < 0) {
114 dev_err(card->dev, "cpu_dai fmt not set\n"); 114 dev_err(card->dev, "cpu_dai fmt not set\n");
115 return err; 115 return err;
116 } 116 }
117 117
118 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, 118 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
119 SND_SOC_CLOCK_IN); 119 SND_SOC_CLOCK_IN);
120 if (err < 0) { 120 if (err < 0) {
121 dev_err(card->dev, "codec_dai clock not set\n"); 121 dev_err(card->dev, "codec_dai clock not set\n");
122 return err; 122 return err;
123 } 123 }
124 124
125 return 0; 125 return 0;
126 } 126 }
127 127
128 static struct snd_soc_ops tegra_wm8903_ops = { 128 static struct snd_soc_ops tegra_wm8903_ops = {
129 .hw_params = tegra_wm8903_hw_params, 129 .hw_params = tegra_wm8903_hw_params,
130 }; 130 };
131 131
132 static struct snd_soc_jack tegra_wm8903_hp_jack; 132 static struct snd_soc_jack tegra_wm8903_hp_jack;
133 133
134 static struct snd_soc_jack_pin tegra_wm8903_hp_jack_pins[] = { 134 static struct snd_soc_jack_pin tegra_wm8903_hp_jack_pins[] = {
135 { 135 {
136 .pin = "Headphone Jack", 136 .pin = "Headphone Jack",
137 .mask = SND_JACK_HEADPHONE, 137 .mask = SND_JACK_HEADPHONE,
138 }, 138 },
139 }; 139 };
140 140
141 static struct snd_soc_jack_gpio tegra_wm8903_hp_jack_gpio = { 141 static struct snd_soc_jack_gpio tegra_wm8903_hp_jack_gpio = {
142 .name = "headphone detect", 142 .name = "headphone detect",
143 .report = SND_JACK_HEADPHONE, 143 .report = SND_JACK_HEADPHONE,
144 .debounce_time = 150, 144 .debounce_time = 150,
145 .invert = 1, 145 .invert = 1,
146 }; 146 };
147 147
148 static struct snd_soc_jack tegra_wm8903_mic_jack; 148 static struct snd_soc_jack tegra_wm8903_mic_jack;
149 149
150 static struct snd_soc_jack_pin tegra_wm8903_mic_jack_pins[] = { 150 static struct snd_soc_jack_pin tegra_wm8903_mic_jack_pins[] = {
151 { 151 {
152 .pin = "Mic Jack", 152 .pin = "Mic Jack",
153 .mask = SND_JACK_MICROPHONE, 153 .mask = SND_JACK_MICROPHONE,
154 }, 154 },
155 }; 155 };
156 156
157 static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w, 157 static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w,
158 struct snd_kcontrol *k, int event) 158 struct snd_kcontrol *k, int event)
159 { 159 {
160 struct snd_soc_dapm_context *dapm = w->dapm; 160 struct snd_soc_dapm_context *dapm = w->dapm;
161 struct snd_soc_card *card = dapm->card; 161 struct snd_soc_card *card = dapm->card;
162 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 162 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
163 struct tegra_wm8903_platform_data *pdata = machine->pdata; 163 struct tegra_wm8903_platform_data *pdata = machine->pdata;
164 164
165 if (!(machine->gpio_requested & GPIO_SPKR_EN)) 165 if (!(machine->gpio_requested & GPIO_SPKR_EN))
166 return 0; 166 return 0;
167 167
168 gpio_set_value_cansleep(pdata->gpio_spkr_en, 168 gpio_set_value_cansleep(pdata->gpio_spkr_en,
169 SND_SOC_DAPM_EVENT_ON(event)); 169 SND_SOC_DAPM_EVENT_ON(event));
170 170
171 return 0; 171 return 0;
172 } 172 }
173 173
174 static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w, 174 static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w,
175 struct snd_kcontrol *k, int event) 175 struct snd_kcontrol *k, int event)
176 { 176 {
177 struct snd_soc_dapm_context *dapm = w->dapm; 177 struct snd_soc_dapm_context *dapm = w->dapm;
178 struct snd_soc_card *card = dapm->card; 178 struct snd_soc_card *card = dapm->card;
179 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 179 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
180 struct tegra_wm8903_platform_data *pdata = machine->pdata; 180 struct tegra_wm8903_platform_data *pdata = machine->pdata;
181 181
182 if (!(machine->gpio_requested & GPIO_HP_MUTE)) 182 if (!(machine->gpio_requested & GPIO_HP_MUTE))
183 return 0; 183 return 0;
184 184
185 gpio_set_value_cansleep(pdata->gpio_hp_mute, 185 gpio_set_value_cansleep(pdata->gpio_hp_mute,
186 !SND_SOC_DAPM_EVENT_ON(event)); 186 !SND_SOC_DAPM_EVENT_ON(event));
187 187
188 return 0; 188 return 0;
189 } 189 }
190 190
191 static const struct snd_soc_dapm_widget tegra_wm8903_dapm_widgets[] = { 191 static const struct snd_soc_dapm_widget tegra_wm8903_dapm_widgets[] = {
192 SND_SOC_DAPM_SPK("Int Spk", tegra_wm8903_event_int_spk), 192 SND_SOC_DAPM_SPK("Int Spk", tegra_wm8903_event_int_spk),
193 SND_SOC_DAPM_HP("Headphone Jack", tegra_wm8903_event_hp), 193 SND_SOC_DAPM_HP("Headphone Jack", tegra_wm8903_event_hp),
194 SND_SOC_DAPM_MIC("Mic Jack", NULL), 194 SND_SOC_DAPM_MIC("Mic Jack", NULL),
195 }; 195 };
196 196
197 static const struct snd_soc_dapm_route harmony_audio_map[] = { 197 static const struct snd_soc_dapm_route harmony_audio_map[] = {
198 {"Headphone Jack", NULL, "HPOUTR"}, 198 {"Headphone Jack", NULL, "HPOUTR"},
199 {"Headphone Jack", NULL, "HPOUTL"}, 199 {"Headphone Jack", NULL, "HPOUTL"},
200 {"Int Spk", NULL, "ROP"}, 200 {"Int Spk", NULL, "ROP"},
201 {"Int Spk", NULL, "RON"}, 201 {"Int Spk", NULL, "RON"},
202 {"Int Spk", NULL, "LOP"}, 202 {"Int Spk", NULL, "LOP"},
203 {"Int Spk", NULL, "LON"}, 203 {"Int Spk", NULL, "LON"},
204 {"Mic Bias", NULL, "Mic Jack"}, 204 {"Mic Bias", NULL, "Mic Jack"},
205 {"IN1L", NULL, "Mic Bias"}, 205 {"IN1L", NULL, "Mic Bias"},
206 }; 206 };
207 207
208 static const struct snd_soc_dapm_route seaboard_audio_map[] = { 208 static const struct snd_soc_dapm_route seaboard_audio_map[] = {
209 {"Headphone Jack", NULL, "HPOUTR"}, 209 {"Headphone Jack", NULL, "HPOUTR"},
210 {"Headphone Jack", NULL, "HPOUTL"}, 210 {"Headphone Jack", NULL, "HPOUTL"},
211 {"Int Spk", NULL, "ROP"}, 211 {"Int Spk", NULL, "ROP"},
212 {"Int Spk", NULL, "RON"}, 212 {"Int Spk", NULL, "RON"},
213 {"Int Spk", NULL, "LOP"}, 213 {"Int Spk", NULL, "LOP"},
214 {"Int Spk", NULL, "LON"}, 214 {"Int Spk", NULL, "LON"},
215 {"Mic Bias", NULL, "Mic Jack"}, 215 {"Mic Bias", NULL, "Mic Jack"},
216 {"IN1R", NULL, "Mic Bias"}, 216 {"IN1R", NULL, "Mic Bias"},
217 }; 217 };
218 218
219 static const struct snd_soc_dapm_route kaen_audio_map[] = { 219 static const struct snd_soc_dapm_route kaen_audio_map[] = {
220 {"Headphone Jack", NULL, "HPOUTR"}, 220 {"Headphone Jack", NULL, "HPOUTR"},
221 {"Headphone Jack", NULL, "HPOUTL"}, 221 {"Headphone Jack", NULL, "HPOUTL"},
222 {"Int Spk", NULL, "ROP"}, 222 {"Int Spk", NULL, "ROP"},
223 {"Int Spk", NULL, "RON"}, 223 {"Int Spk", NULL, "RON"},
224 {"Int Spk", NULL, "LOP"}, 224 {"Int Spk", NULL, "LOP"},
225 {"Int Spk", NULL, "LON"}, 225 {"Int Spk", NULL, "LON"},
226 {"Mic Bias", NULL, "Mic Jack"}, 226 {"Mic Bias", NULL, "Mic Jack"},
227 {"IN2R", NULL, "Mic Bias"}, 227 {"IN2R", NULL, "Mic Bias"},
228 }; 228 };
229 229
230 static const struct snd_soc_dapm_route aebl_audio_map[] = { 230 static const struct snd_soc_dapm_route aebl_audio_map[] = {
231 {"Headphone Jack", NULL, "HPOUTR"}, 231 {"Headphone Jack", NULL, "HPOUTR"},
232 {"Headphone Jack", NULL, "HPOUTL"}, 232 {"Headphone Jack", NULL, "HPOUTL"},
233 {"Int Spk", NULL, "LINEOUTR"}, 233 {"Int Spk", NULL, "LINEOUTR"},
234 {"Int Spk", NULL, "LINEOUTL"}, 234 {"Int Spk", NULL, "LINEOUTL"},
235 {"Mic Bias", NULL, "Mic Jack"}, 235 {"Mic Bias", NULL, "Mic Jack"},
236 {"IN1R", NULL, "Mic Bias"}, 236 {"IN1R", NULL, "Mic Bias"},
237 }; 237 };
238 238
239 static const struct snd_kcontrol_new tegra_wm8903_controls[] = { 239 static const struct snd_kcontrol_new tegra_wm8903_controls[] = {
240 SOC_DAPM_PIN_SWITCH("Int Spk"), 240 SOC_DAPM_PIN_SWITCH("Int Spk"),
241 }; 241 };
242 242
243 static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) 243 static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
244 { 244 {
245 struct snd_soc_codec *codec = rtd->codec; 245 struct snd_soc_codec *codec = rtd->codec;
246 struct snd_soc_dapm_context *dapm = &codec->dapm; 246 struct snd_soc_dapm_context *dapm = &codec->dapm;
247 struct snd_soc_card *card = codec->card; 247 struct snd_soc_card *card = codec->card;
248 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 248 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
249 struct tegra_wm8903_platform_data *pdata = machine->pdata; 249 struct tegra_wm8903_platform_data *pdata = machine->pdata;
250 int ret; 250 int ret;
251 251
252 if (gpio_is_valid(pdata->gpio_spkr_en)) { 252 if (gpio_is_valid(pdata->gpio_spkr_en)) {
253 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); 253 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
254 if (ret) { 254 if (ret) {
255 dev_err(card->dev, "cannot get spkr_en gpio\n"); 255 dev_err(card->dev, "cannot get spkr_en gpio\n");
256 return ret; 256 return ret;
257 } 257 }
258 machine->gpio_requested |= GPIO_SPKR_EN; 258 machine->gpio_requested |= GPIO_SPKR_EN;
259 259
260 gpio_direction_output(pdata->gpio_spkr_en, 0); 260 gpio_direction_output(pdata->gpio_spkr_en, 0);
261 } 261 }
262 262
263 if (gpio_is_valid(pdata->gpio_hp_mute)) { 263 if (gpio_is_valid(pdata->gpio_hp_mute)) {
264 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute"); 264 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
265 if (ret) { 265 if (ret) {
266 dev_err(card->dev, "cannot get hp_mute gpio\n"); 266 dev_err(card->dev, "cannot get hp_mute gpio\n");
267 return ret; 267 return ret;
268 } 268 }
269 machine->gpio_requested |= GPIO_HP_MUTE; 269 machine->gpio_requested |= GPIO_HP_MUTE;
270 270
271 gpio_direction_output(pdata->gpio_hp_mute, 1); 271 gpio_direction_output(pdata->gpio_hp_mute, 1);
272 } 272 }
273 273
274 if (gpio_is_valid(pdata->gpio_int_mic_en)) { 274 if (gpio_is_valid(pdata->gpio_int_mic_en)) {
275 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en"); 275 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
276 if (ret) { 276 if (ret) {
277 dev_err(card->dev, "cannot get int_mic_en gpio\n"); 277 dev_err(card->dev, "cannot get int_mic_en gpio\n");
278 return ret; 278 return ret;
279 } 279 }
280 machine->gpio_requested |= GPIO_INT_MIC_EN; 280 machine->gpio_requested |= GPIO_INT_MIC_EN;
281 281
282 /* Disable int mic; enable signal is active-high */ 282 /* Disable int mic; enable signal is active-high */
283 gpio_direction_output(pdata->gpio_int_mic_en, 0); 283 gpio_direction_output(pdata->gpio_int_mic_en, 0);
284 } 284 }
285 285
286 if (gpio_is_valid(pdata->gpio_ext_mic_en)) { 286 if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
287 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en"); 287 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
288 if (ret) { 288 if (ret) {
289 dev_err(card->dev, "cannot get ext_mic_en gpio\n"); 289 dev_err(card->dev, "cannot get ext_mic_en gpio\n");
290 return ret; 290 return ret;
291 } 291 }
292 machine->gpio_requested |= GPIO_EXT_MIC_EN; 292 machine->gpio_requested |= GPIO_EXT_MIC_EN;
293 293
294 /* Enable ext mic; enable signal is active-low */ 294 /* Enable ext mic; enable signal is active-low */
295 gpio_direction_output(pdata->gpio_ext_mic_en, 0); 295 gpio_direction_output(pdata->gpio_ext_mic_en, 0);
296 } 296 }
297 297
298 if (gpio_is_valid(pdata->gpio_hp_det)) { 298 if (gpio_is_valid(pdata->gpio_hp_det)) {
299 tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det; 299 tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det;
300 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, 300 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
301 &tegra_wm8903_hp_jack); 301 &tegra_wm8903_hp_jack);
302 snd_soc_jack_add_pins(&tegra_wm8903_hp_jack, 302 snd_soc_jack_add_pins(&tegra_wm8903_hp_jack,
303 ARRAY_SIZE(tegra_wm8903_hp_jack_pins), 303 ARRAY_SIZE(tegra_wm8903_hp_jack_pins),
304 tegra_wm8903_hp_jack_pins); 304 tegra_wm8903_hp_jack_pins);
305 snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, 305 snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack,
306 1, 306 1,
307 &tegra_wm8903_hp_jack_gpio); 307 &tegra_wm8903_hp_jack_gpio);
308 machine->gpio_requested |= GPIO_HP_DET; 308 machine->gpio_requested |= GPIO_HP_DET;
309 } 309 }
310 310
311 snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, 311 snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE,
312 &tegra_wm8903_mic_jack); 312 &tegra_wm8903_mic_jack);
313 snd_soc_jack_add_pins(&tegra_wm8903_mic_jack, 313 snd_soc_jack_add_pins(&tegra_wm8903_mic_jack,
314 ARRAY_SIZE(tegra_wm8903_mic_jack_pins), 314 ARRAY_SIZE(tegra_wm8903_mic_jack_pins),
315 tegra_wm8903_mic_jack_pins); 315 tegra_wm8903_mic_jack_pins);
316 wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE, 316 wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE,
317 0); 317 0);
318 318
319 snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); 319 snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
320 320
321 /* FIXME: Calculate automatically based on DAPM routes? */ 321 /* FIXME: Calculate automatically based on DAPM routes? */
322 if (!machine_is_harmony()) 322 if (!machine_is_harmony())
323 snd_soc_dapm_nc_pin(dapm, "IN1L"); 323 snd_soc_dapm_nc_pin(dapm, "IN1L");
324 if (!machine_is_seaboard() && !machine_is_aebl()) 324 if (!machine_is_seaboard() && !machine_is_aebl())
325 snd_soc_dapm_nc_pin(dapm, "IN1R"); 325 snd_soc_dapm_nc_pin(dapm, "IN1R");
326 snd_soc_dapm_nc_pin(dapm, "IN2L"); 326 snd_soc_dapm_nc_pin(dapm, "IN2L");
327 if (!machine_is_kaen()) 327 if (!machine_is_kaen())
328 snd_soc_dapm_nc_pin(dapm, "IN2R"); 328 snd_soc_dapm_nc_pin(dapm, "IN2R");
329 snd_soc_dapm_nc_pin(dapm, "IN3L"); 329 snd_soc_dapm_nc_pin(dapm, "IN3L");
330 snd_soc_dapm_nc_pin(dapm, "IN3R"); 330 snd_soc_dapm_nc_pin(dapm, "IN3R");
331 331
332 if (machine_is_aebl()) { 332 if (machine_is_aebl()) {
333 snd_soc_dapm_nc_pin(dapm, "LON"); 333 snd_soc_dapm_nc_pin(dapm, "LON");
334 snd_soc_dapm_nc_pin(dapm, "RON"); 334 snd_soc_dapm_nc_pin(dapm, "RON");
335 snd_soc_dapm_nc_pin(dapm, "ROP"); 335 snd_soc_dapm_nc_pin(dapm, "ROP");
336 snd_soc_dapm_nc_pin(dapm, "LOP"); 336 snd_soc_dapm_nc_pin(dapm, "LOP");
337 } else { 337 } else {
338 snd_soc_dapm_nc_pin(dapm, "LINEOUTR"); 338 snd_soc_dapm_nc_pin(dapm, "LINEOUTR");
339 snd_soc_dapm_nc_pin(dapm, "LINEOUTL"); 339 snd_soc_dapm_nc_pin(dapm, "LINEOUTL");
340 } 340 }
341 341
342 snd_soc_dapm_sync(dapm);
343
344 return 0; 342 return 0;
345 } 343 }
346 344
347 static struct snd_soc_dai_link tegra_wm8903_dai = { 345 static struct snd_soc_dai_link tegra_wm8903_dai = {
348 .name = "WM8903", 346 .name = "WM8903",
349 .stream_name = "WM8903 PCM", 347 .stream_name = "WM8903 PCM",
350 .codec_name = "wm8903.0-001a", 348 .codec_name = "wm8903.0-001a",
351 .platform_name = "tegra-pcm-audio", 349 .platform_name = "tegra-pcm-audio",
352 .cpu_dai_name = "tegra-i2s.0", 350 .cpu_dai_name = "tegra-i2s.0",
353 .codec_dai_name = "wm8903-hifi", 351 .codec_dai_name = "wm8903-hifi",
354 .init = tegra_wm8903_init, 352 .init = tegra_wm8903_init,
355 .ops = &tegra_wm8903_ops, 353 .ops = &tegra_wm8903_ops,
356 }; 354 };
357 355
358 static struct snd_soc_card snd_soc_tegra_wm8903 = { 356 static struct snd_soc_card snd_soc_tegra_wm8903 = {
359 .name = "tegra-wm8903", 357 .name = "tegra-wm8903",
360 .dai_link = &tegra_wm8903_dai, 358 .dai_link = &tegra_wm8903_dai,
361 .num_links = 1, 359 .num_links = 1,
362 360
363 .controls = tegra_wm8903_controls, 361 .controls = tegra_wm8903_controls,
364 .num_controls = ARRAY_SIZE(tegra_wm8903_controls), 362 .num_controls = ARRAY_SIZE(tegra_wm8903_controls),
365 .dapm_widgets = tegra_wm8903_dapm_widgets, 363 .dapm_widgets = tegra_wm8903_dapm_widgets,
366 .num_dapm_widgets = ARRAY_SIZE(tegra_wm8903_dapm_widgets), 364 .num_dapm_widgets = ARRAY_SIZE(tegra_wm8903_dapm_widgets),
367 }; 365 };
368 366
369 static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) 367 static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
370 { 368 {
371 struct snd_soc_card *card = &snd_soc_tegra_wm8903; 369 struct snd_soc_card *card = &snd_soc_tegra_wm8903;
372 struct tegra_wm8903 *machine; 370 struct tegra_wm8903 *machine;
373 struct tegra_wm8903_platform_data *pdata; 371 struct tegra_wm8903_platform_data *pdata;
374 int ret; 372 int ret;
375 373
376 pdata = pdev->dev.platform_data; 374 pdata = pdev->dev.platform_data;
377 if (!pdata) { 375 if (!pdata) {
378 dev_err(&pdev->dev, "No platform data supplied\n"); 376 dev_err(&pdev->dev, "No platform data supplied\n");
379 return -EINVAL; 377 return -EINVAL;
380 } 378 }
381 379
382 machine = kzalloc(sizeof(struct tegra_wm8903), GFP_KERNEL); 380 machine = kzalloc(sizeof(struct tegra_wm8903), GFP_KERNEL);
383 if (!machine) { 381 if (!machine) {
384 dev_err(&pdev->dev, "Can't allocate tegra_wm8903 struct\n"); 382 dev_err(&pdev->dev, "Can't allocate tegra_wm8903 struct\n");
385 return -ENOMEM; 383 return -ENOMEM;
386 } 384 }
387 385
388 machine->pdata = pdata; 386 machine->pdata = pdata;
389 387
390 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); 388 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
391 if (ret) 389 if (ret)
392 goto err_free_machine; 390 goto err_free_machine;
393 391
394 card->dev = &pdev->dev; 392 card->dev = &pdev->dev;
395 platform_set_drvdata(pdev, card); 393 platform_set_drvdata(pdev, card);
396 snd_soc_card_set_drvdata(card, machine); 394 snd_soc_card_set_drvdata(card, machine);
397 395
398 if (machine_is_harmony()) { 396 if (machine_is_harmony()) {
399 card->dapm_routes = harmony_audio_map; 397 card->dapm_routes = harmony_audio_map;
400 card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); 398 card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map);
401 } else if (machine_is_seaboard()) { 399 } else if (machine_is_seaboard()) {
402 card->dapm_routes = seaboard_audio_map; 400 card->dapm_routes = seaboard_audio_map;
403 card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map); 401 card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map);
404 } else if (machine_is_kaen()) { 402 } else if (machine_is_kaen()) {
405 card->dapm_routes = kaen_audio_map; 403 card->dapm_routes = kaen_audio_map;
406 card->num_dapm_routes = ARRAY_SIZE(kaen_audio_map); 404 card->num_dapm_routes = ARRAY_SIZE(kaen_audio_map);
407 } else { 405 } else {
408 card->dapm_routes = aebl_audio_map; 406 card->dapm_routes = aebl_audio_map;
409 card->num_dapm_routes = ARRAY_SIZE(aebl_audio_map); 407 card->num_dapm_routes = ARRAY_SIZE(aebl_audio_map);
410 } 408 }
411 409
412 ret = snd_soc_register_card(card); 410 ret = snd_soc_register_card(card);
413 if (ret) { 411 if (ret) {
414 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", 412 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
415 ret); 413 ret);
416 goto err_fini_utils; 414 goto err_fini_utils;
417 } 415 }
418 416
419 return 0; 417 return 0;
420 418
421 err_fini_utils: 419 err_fini_utils:
422 tegra_asoc_utils_fini(&machine->util_data); 420 tegra_asoc_utils_fini(&machine->util_data);
423 err_free_machine: 421 err_free_machine:
424 kfree(machine); 422 kfree(machine);
425 return ret; 423 return ret;
426 } 424 }
427 425
428 static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev) 426 static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
429 { 427 {
430 struct snd_soc_card *card = platform_get_drvdata(pdev); 428 struct snd_soc_card *card = platform_get_drvdata(pdev);
431 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 429 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
432 struct tegra_wm8903_platform_data *pdata = machine->pdata; 430 struct tegra_wm8903_platform_data *pdata = machine->pdata;
433 431
434 if (machine->gpio_requested & GPIO_HP_DET) 432 if (machine->gpio_requested & GPIO_HP_DET)
435 snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, 433 snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack,
436 1, 434 1,
437 &tegra_wm8903_hp_jack_gpio); 435 &tegra_wm8903_hp_jack_gpio);
438 if (machine->gpio_requested & GPIO_EXT_MIC_EN) 436 if (machine->gpio_requested & GPIO_EXT_MIC_EN)
439 gpio_free(pdata->gpio_ext_mic_en); 437 gpio_free(pdata->gpio_ext_mic_en);
440 if (machine->gpio_requested & GPIO_INT_MIC_EN) 438 if (machine->gpio_requested & GPIO_INT_MIC_EN)
441 gpio_free(pdata->gpio_int_mic_en); 439 gpio_free(pdata->gpio_int_mic_en);
442 if (machine->gpio_requested & GPIO_HP_MUTE) 440 if (machine->gpio_requested & GPIO_HP_MUTE)
443 gpio_free(pdata->gpio_hp_mute); 441 gpio_free(pdata->gpio_hp_mute);
444 if (machine->gpio_requested & GPIO_SPKR_EN) 442 if (machine->gpio_requested & GPIO_SPKR_EN)
445 gpio_free(pdata->gpio_spkr_en); 443 gpio_free(pdata->gpio_spkr_en);
446 machine->gpio_requested = 0; 444 machine->gpio_requested = 0;
447 445
448 snd_soc_unregister_card(card); 446 snd_soc_unregister_card(card);
449 447
450 tegra_asoc_utils_fini(&machine->util_data); 448 tegra_asoc_utils_fini(&machine->util_data);
451 449
452 kfree(machine); 450 kfree(machine);
453 451
454 return 0; 452 return 0;
455 } 453 }
456 454
457 static struct platform_driver tegra_wm8903_driver = { 455 static struct platform_driver tegra_wm8903_driver = {
458 .driver = { 456 .driver = {
459 .name = DRV_NAME, 457 .name = DRV_NAME,
460 .owner = THIS_MODULE, 458 .owner = THIS_MODULE,
461 .pm = &snd_soc_pm_ops, 459 .pm = &snd_soc_pm_ops,
462 }, 460 },
463 .probe = tegra_wm8903_driver_probe, 461 .probe = tegra_wm8903_driver_probe,
464 .remove = __devexit_p(tegra_wm8903_driver_remove), 462 .remove = __devexit_p(tegra_wm8903_driver_remove),
465 }; 463 };
466 464
467 static int __init tegra_wm8903_modinit(void) 465 static int __init tegra_wm8903_modinit(void)
468 { 466 {
469 return platform_driver_register(&tegra_wm8903_driver); 467 return platform_driver_register(&tegra_wm8903_driver);
470 } 468 }
471 module_init(tegra_wm8903_modinit); 469 module_init(tegra_wm8903_modinit);
472 470
473 static void __exit tegra_wm8903_modexit(void) 471 static void __exit tegra_wm8903_modexit(void)
474 { 472 {
475 platform_driver_unregister(&tegra_wm8903_driver); 473 platform_driver_unregister(&tegra_wm8903_driver);
476 } 474 }
477 module_exit(tegra_wm8903_modexit); 475 module_exit(tegra_wm8903_modexit);
478 476
479 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); 477 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
480 MODULE_DESCRIPTION("Tegra+WM8903 machine ASoC driver"); 478 MODULE_DESCRIPTION("Tegra+WM8903 machine ASoC driver");
481 MODULE_LICENSE("GPL"); 479 MODULE_LICENSE("GPL");
482 MODULE_ALIAS("platform:" DRV_NAME); 480 MODULE_ALIAS("platform:" DRV_NAME);
483 481
sound/soc/tegra/trimslice.c
1 /* 1 /*
2 * trimslice.c - TrimSlice machine ASoC driver 2 * trimslice.c - TrimSlice machine ASoC driver
3 * 3 *
4 * Copyright (C) 2011 - CompuLab, Ltd. 4 * Copyright (C) 2011 - CompuLab, Ltd.
5 * Author: Mike Rapoport <mike@compulab.co.il> 5 * Author: Mike Rapoport <mike@compulab.co.il>
6 * 6 *
7 * Based on code copyright/by: 7 * Based on code copyright/by:
8 * Author: Stephen Warren <swarren@nvidia.com> 8 * Author: Stephen Warren <swarren@nvidia.com>
9 * Copyright (C) 2010-2011 - NVIDIA, Inc. 9 * Copyright (C) 2010-2011 - NVIDIA, Inc.
10 * 10 *
11 * This program is free software; you can redistribute it and/or 11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License 12 * modify it under the terms of the GNU General Public License
13 * version 2 as published by the Free Software Foundation. 13 * version 2 as published by the Free Software Foundation.
14 * 14 *
15 * This program is distributed in the hope that it will be useful, but 15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details. 18 * General Public License for more details.
19 * 19 *
20 * You should have received a copy of the GNU General Public License 20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software 21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 * 02110-1301 USA 23 * 02110-1301 USA
24 * 24 *
25 */ 25 */
26 26
27 #include <asm/mach-types.h> 27 #include <asm/mach-types.h>
28 28
29 #include <linux/module.h> 29 #include <linux/module.h>
30 #include <linux/platform_device.h> 30 #include <linux/platform_device.h>
31 #include <linux/slab.h> 31 #include <linux/slab.h>
32 32
33 #include <sound/core.h> 33 #include <sound/core.h>
34 #include <sound/jack.h> 34 #include <sound/jack.h>
35 #include <sound/pcm.h> 35 #include <sound/pcm.h>
36 #include <sound/pcm_params.h> 36 #include <sound/pcm_params.h>
37 #include <sound/soc.h> 37 #include <sound/soc.h>
38 38
39 #include "../codecs/tlv320aic23.h" 39 #include "../codecs/tlv320aic23.h"
40 40
41 #include "tegra_das.h" 41 #include "tegra_das.h"
42 #include "tegra_i2s.h" 42 #include "tegra_i2s.h"
43 #include "tegra_pcm.h" 43 #include "tegra_pcm.h"
44 #include "tegra_asoc_utils.h" 44 #include "tegra_asoc_utils.h"
45 45
46 #define DRV_NAME "tegra-snd-trimslice" 46 #define DRV_NAME "tegra-snd-trimslice"
47 47
48 struct tegra_trimslice { 48 struct tegra_trimslice {
49 struct tegra_asoc_utils_data util_data; 49 struct tegra_asoc_utils_data util_data;
50 }; 50 };
51 51
52 static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, 52 static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream,
53 struct snd_pcm_hw_params *params) 53 struct snd_pcm_hw_params *params)
54 { 54 {
55 struct snd_soc_pcm_runtime *rtd = substream->private_data; 55 struct snd_soc_pcm_runtime *rtd = substream->private_data;
56 struct snd_soc_dai *codec_dai = rtd->codec_dai; 56 struct snd_soc_dai *codec_dai = rtd->codec_dai;
57 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 57 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
58 struct snd_soc_codec *codec = rtd->codec; 58 struct snd_soc_codec *codec = rtd->codec;
59 struct snd_soc_card *card = codec->card; 59 struct snd_soc_card *card = codec->card;
60 struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); 60 struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card);
61 int srate, mclk; 61 int srate, mclk;
62 int err; 62 int err;
63 63
64 srate = params_rate(params); 64 srate = params_rate(params);
65 mclk = 128 * srate; 65 mclk = 128 * srate;
66 66
67 err = tegra_asoc_utils_set_rate(&trimslice->util_data, srate, mclk); 67 err = tegra_asoc_utils_set_rate(&trimslice->util_data, srate, mclk);
68 if (err < 0) { 68 if (err < 0) {
69 dev_err(card->dev, "Can't configure clocks\n"); 69 dev_err(card->dev, "Can't configure clocks\n");
70 return err; 70 return err;
71 } 71 }
72 72
73 err = snd_soc_dai_set_fmt(codec_dai, 73 err = snd_soc_dai_set_fmt(codec_dai,
74 SND_SOC_DAIFMT_I2S | 74 SND_SOC_DAIFMT_I2S |
75 SND_SOC_DAIFMT_NB_NF | 75 SND_SOC_DAIFMT_NB_NF |
76 SND_SOC_DAIFMT_CBS_CFS); 76 SND_SOC_DAIFMT_CBS_CFS);
77 if (err < 0) { 77 if (err < 0) {
78 dev_err(card->dev, "codec_dai fmt not set\n"); 78 dev_err(card->dev, "codec_dai fmt not set\n");
79 return err; 79 return err;
80 } 80 }
81 81
82 err = snd_soc_dai_set_fmt(cpu_dai, 82 err = snd_soc_dai_set_fmt(cpu_dai,
83 SND_SOC_DAIFMT_I2S | 83 SND_SOC_DAIFMT_I2S |
84 SND_SOC_DAIFMT_NB_NF | 84 SND_SOC_DAIFMT_NB_NF |
85 SND_SOC_DAIFMT_CBS_CFS); 85 SND_SOC_DAIFMT_CBS_CFS);
86 if (err < 0) { 86 if (err < 0) {
87 dev_err(card->dev, "cpu_dai fmt not set\n"); 87 dev_err(card->dev, "cpu_dai fmt not set\n");
88 return err; 88 return err;
89 } 89 }
90 90
91 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, 91 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
92 SND_SOC_CLOCK_IN); 92 SND_SOC_CLOCK_IN);
93 if (err < 0) { 93 if (err < 0) {
94 dev_err(card->dev, "codec_dai clock not set\n"); 94 dev_err(card->dev, "codec_dai clock not set\n");
95 return err; 95 return err;
96 } 96 }
97 97
98 return 0; 98 return 0;
99 } 99 }
100 100
101 static struct snd_soc_ops trimslice_asoc_ops = { 101 static struct snd_soc_ops trimslice_asoc_ops = {
102 .hw_params = trimslice_asoc_hw_params, 102 .hw_params = trimslice_asoc_hw_params,
103 }; 103 };
104 104
105 static const struct snd_soc_dapm_widget trimslice_dapm_widgets[] = { 105 static const struct snd_soc_dapm_widget trimslice_dapm_widgets[] = {
106 SND_SOC_DAPM_HP("Line Out", NULL), 106 SND_SOC_DAPM_HP("Line Out", NULL),
107 SND_SOC_DAPM_LINE("Line In", NULL), 107 SND_SOC_DAPM_LINE("Line In", NULL),
108 }; 108 };
109 109
110 static const struct snd_soc_dapm_route trimslice_audio_map[] = { 110 static const struct snd_soc_dapm_route trimslice_audio_map[] = {
111 {"Line Out", NULL, "LOUT"}, 111 {"Line Out", NULL, "LOUT"},
112 {"Line Out", NULL, "ROUT"}, 112 {"Line Out", NULL, "ROUT"},
113 113
114 {"LLINEIN", NULL, "Line In"}, 114 {"LLINEIN", NULL, "Line In"},
115 {"RLINEIN", NULL, "Line In"}, 115 {"RLINEIN", NULL, "Line In"},
116 }; 116 };
117 117
118 static int trimslice_asoc_init(struct snd_soc_pcm_runtime *rtd) 118 static int trimslice_asoc_init(struct snd_soc_pcm_runtime *rtd)
119 { 119 {
120 struct snd_soc_codec *codec = rtd->codec; 120 struct snd_soc_codec *codec = rtd->codec;
121 struct snd_soc_dapm_context *dapm = &codec->dapm; 121 struct snd_soc_dapm_context *dapm = &codec->dapm;
122 122
123 snd_soc_dapm_nc_pin(dapm, "LHPOUT"); 123 snd_soc_dapm_nc_pin(dapm, "LHPOUT");
124 snd_soc_dapm_nc_pin(dapm, "RHPOUT"); 124 snd_soc_dapm_nc_pin(dapm, "RHPOUT");
125 snd_soc_dapm_nc_pin(dapm, "MICIN"); 125 snd_soc_dapm_nc_pin(dapm, "MICIN");
126 126
127 snd_soc_dapm_sync(dapm);
128
129 return 0; 127 return 0;
130 } 128 }
131 129
132 static struct snd_soc_dai_link trimslice_tlv320aic23_dai = { 130 static struct snd_soc_dai_link trimslice_tlv320aic23_dai = {
133 .name = "TLV320AIC23", 131 .name = "TLV320AIC23",
134 .stream_name = "AIC23", 132 .stream_name = "AIC23",
135 .codec_name = "tlv320aic23-codec.2-001a", 133 .codec_name = "tlv320aic23-codec.2-001a",
136 .platform_name = "tegra-pcm-audio", 134 .platform_name = "tegra-pcm-audio",
137 .cpu_dai_name = "tegra-i2s.0", 135 .cpu_dai_name = "tegra-i2s.0",
138 .codec_dai_name = "tlv320aic23-hifi", 136 .codec_dai_name = "tlv320aic23-hifi",
139 .init = trimslice_asoc_init, 137 .init = trimslice_asoc_init,
140 .ops = &trimslice_asoc_ops, 138 .ops = &trimslice_asoc_ops,
141 }; 139 };
142 140
143 static struct snd_soc_card snd_soc_trimslice = { 141 static struct snd_soc_card snd_soc_trimslice = {
144 .name = "tegra-trimslice", 142 .name = "tegra-trimslice",
145 .dai_link = &trimslice_tlv320aic23_dai, 143 .dai_link = &trimslice_tlv320aic23_dai,
146 .num_links = 1, 144 .num_links = 1,
147 145
148 .dapm_widgets = trimslice_dapm_widgets, 146 .dapm_widgets = trimslice_dapm_widgets,
149 .num_dapm_widgets = ARRAY_SIZE(trimslice_dapm_widgets), 147 .num_dapm_widgets = ARRAY_SIZE(trimslice_dapm_widgets),
150 .dapm_routes = trimslice_audio_map, 148 .dapm_routes = trimslice_audio_map,
151 .num_dapm_routes = ARRAY_SIZE(trimslice_audio_map), 149 .num_dapm_routes = ARRAY_SIZE(trimslice_audio_map),
152 }; 150 };
153 151
154 static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev) 152 static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
155 { 153 {
156 struct snd_soc_card *card = &snd_soc_trimslice; 154 struct snd_soc_card *card = &snd_soc_trimslice;
157 struct tegra_trimslice *trimslice; 155 struct tegra_trimslice *trimslice;
158 int ret; 156 int ret;
159 157
160 trimslice = kzalloc(sizeof(struct tegra_trimslice), GFP_KERNEL); 158 trimslice = kzalloc(sizeof(struct tegra_trimslice), GFP_KERNEL);
161 if (!trimslice) { 159 if (!trimslice) {
162 dev_err(&pdev->dev, "Can't allocate tegra_trimslice\n"); 160 dev_err(&pdev->dev, "Can't allocate tegra_trimslice\n");
163 return -ENOMEM; 161 return -ENOMEM;
164 } 162 }
165 163
166 ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev); 164 ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev);
167 if (ret) 165 if (ret)
168 goto err_free_trimslice; 166 goto err_free_trimslice;
169 167
170 card->dev = &pdev->dev; 168 card->dev = &pdev->dev;
171 platform_set_drvdata(pdev, card); 169 platform_set_drvdata(pdev, card);
172 snd_soc_card_set_drvdata(card, trimslice); 170 snd_soc_card_set_drvdata(card, trimslice);
173 171
174 ret = snd_soc_register_card(card); 172 ret = snd_soc_register_card(card);
175 if (ret) { 173 if (ret) {
176 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", 174 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
177 ret); 175 ret);
178 goto err_fini_utils; 176 goto err_fini_utils;
179 } 177 }
180 178
181 return 0; 179 return 0;
182 180
183 err_fini_utils: 181 err_fini_utils:
184 tegra_asoc_utils_fini(&trimslice->util_data); 182 tegra_asoc_utils_fini(&trimslice->util_data);
185 err_free_trimslice: 183 err_free_trimslice:
186 kfree(trimslice); 184 kfree(trimslice);
187 return ret; 185 return ret;
188 } 186 }
189 187
190 static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev) 188 static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev)
191 { 189 {
192 struct snd_soc_card *card = platform_get_drvdata(pdev); 190 struct snd_soc_card *card = platform_get_drvdata(pdev);
193 struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); 191 struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card);
194 192
195 snd_soc_unregister_card(card); 193 snd_soc_unregister_card(card);
196 194
197 tegra_asoc_utils_fini(&trimslice->util_data); 195 tegra_asoc_utils_fini(&trimslice->util_data);
198 196
199 kfree(trimslice); 197 kfree(trimslice);
200 198
201 return 0; 199 return 0;
202 } 200 }
203 201
204 static struct platform_driver tegra_snd_trimslice_driver = { 202 static struct platform_driver tegra_snd_trimslice_driver = {
205 .driver = { 203 .driver = {
206 .name = DRV_NAME, 204 .name = DRV_NAME,
207 .owner = THIS_MODULE, 205 .owner = THIS_MODULE,
208 }, 206 },
209 .probe = tegra_snd_trimslice_probe, 207 .probe = tegra_snd_trimslice_probe,
210 .remove = __devexit_p(tegra_snd_trimslice_remove), 208 .remove = __devexit_p(tegra_snd_trimslice_remove),
211 }; 209 };
212 210
213 static int __init snd_tegra_trimslice_init(void) 211 static int __init snd_tegra_trimslice_init(void)
214 { 212 {
215 return platform_driver_register(&tegra_snd_trimslice_driver); 213 return platform_driver_register(&tegra_snd_trimslice_driver);
216 } 214 }
217 module_init(snd_tegra_trimslice_init); 215 module_init(snd_tegra_trimslice_init);
218 216
219 static void __exit snd_tegra_trimslice_exit(void) 217 static void __exit snd_tegra_trimslice_exit(void)
220 { 218 {
221 platform_driver_unregister(&tegra_snd_trimslice_driver); 219 platform_driver_unregister(&tegra_snd_trimslice_driver);
222 } 220 }
223 module_exit(snd_tegra_trimslice_exit); 221 module_exit(snd_tegra_trimslice_exit);
224 222
225 MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); 223 MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
226 MODULE_DESCRIPTION("Trimslice machine ASoC driver"); 224 MODULE_DESCRIPTION("Trimslice machine ASoC driver");
227 MODULE_LICENSE("GPL"); 225 MODULE_LICENSE("GPL");
228 MODULE_ALIAS("platform:" DRV_NAME); 226 MODULE_ALIAS("platform:" DRV_NAME);
229 227