aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/samsung/neo1973_wm8753.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/samsung/neo1973_wm8753.c')
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c635
1 files changed, 234 insertions, 401 deletions
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index d20815d5ab2..78bfdb3f5d7 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -1,57 +1,32 @@
1/* 1/*
2 * neo1973_wm8753.c -- SoC audio for Neo1973 2 * neo1973_wm8753.c -- SoC audio for Openmoko Neo1973 and Freerunner devices
3 * 3 *
4 * Copyright 2007 Openmoko Inc
5 * Author: Graeme Gregory <graeme@openmoko.org>
4 * Copyright 2007 Wolfson Microelectronics PLC. 6 * Copyright 2007 Wolfson Microelectronics PLC.
5 * Author: Graeme Gregory 7 * Author: Graeme Gregory
6 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com 8 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
9 * Copyright 2009 Wolfson Microelectronics
7 * 10 *
8 * 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
9 * 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
10 * 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
11 * option) any later version. 14 * option) any later version.
12 *
13 */ 15 */
14 16
15#include <linux/module.h> 17#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/timer.h>
18#include <linux/interrupt.h>
19#include <linux/platform_device.h> 18#include <linux/platform_device.h>
20#include <linux/i2c.h> 19#include <linux/gpio.h>
21#include <sound/core.h> 20
22#include <sound/pcm.h>
23#include <sound/soc.h> 21#include <sound/soc.h>
24#include <sound/tlv.h>
25 22
26#include <asm/mach-types.h> 23#include <asm/mach-types.h>
27#include <asm/hardware/scoop.h>
28#include <mach/regs-clock.h>
29#include <mach/regs-gpio.h>
30#include <mach/hardware.h>
31#include <linux/io.h>
32#include <mach/spi-gpio.h>
33
34#include <plat/regs-iis.h> 24#include <plat/regs-iis.h>
25#include <mach/gta02.h>
35 26
36#include "../codecs/wm8753.h" 27#include "../codecs/wm8753.h"
37#include "lm4857.h"
38#include "dma.h"
39#include "s3c24xx-i2s.h" 28#include "s3c24xx-i2s.h"
40 29
41/* define the scenarios */
42#define NEO_AUDIO_OFF 0
43#define NEO_GSM_CALL_AUDIO_HANDSET 1
44#define NEO_GSM_CALL_AUDIO_HEADSET 2
45#define NEO_GSM_CALL_AUDIO_BLUETOOTH 3
46#define NEO_STEREO_TO_SPEAKERS 4
47#define NEO_STEREO_TO_HEADPHONES 5
48#define NEO_CAPTURE_HANDSET 6
49#define NEO_CAPTURE_HEADSET 7
50#define NEO_CAPTURE_BLUETOOTH 8
51
52static struct snd_soc_card neo1973;
53static struct i2c_client *i2c;
54
55static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, 30static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
56 struct snd_pcm_hw_params *params) 31 struct snd_pcm_hw_params *params)
57{ 32{
@@ -62,8 +37,6 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
62 int ret = 0; 37 int ret = 0;
63 unsigned long iis_clkrate; 38 unsigned long iis_clkrate;
64 39
65 pr_debug("Entered %s\n", __func__);
66
67 iis_clkrate = s3c24xx_i2s_get_clockrate(); 40 iis_clkrate = s3c24xx_i2s_get_clockrate();
68 41
69 switch (params_rate(params)) { 42 switch (params_rate(params)) {
@@ -148,8 +121,6 @@ static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
148 struct snd_soc_pcm_runtime *rtd = substream->private_data; 121 struct snd_soc_pcm_runtime *rtd = substream->private_data;
149 struct snd_soc_dai *codec_dai = rtd->codec_dai; 122 struct snd_soc_dai *codec_dai = rtd->codec_dai;
150 123
151 pr_debug("Entered %s\n", __func__);
152
153 /* disable the PLL */ 124 /* disable the PLL */
154 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);
155} 126}
@@ -171,8 +142,6 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
171 int ret = 0; 142 int ret = 0;
172 unsigned long iis_clkrate; 143 unsigned long iis_clkrate;
173 144
174 pr_debug("Entered %s\n", __func__);
175
176 iis_clkrate = s3c24xx_i2s_get_clockrate(); 145 iis_clkrate = s3c24xx_i2s_get_clockrate();
177 146
178 if (params_rate(params) != 8000) 147 if (params_rate(params) != 8000)
@@ -214,8 +183,6 @@ static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
214 struct snd_soc_pcm_runtime *rtd = substream->private_data; 183 struct snd_soc_pcm_runtime *rtd = substream->private_data;
215 struct snd_soc_dai *codec_dai = rtd->codec_dai; 184 struct snd_soc_dai *codec_dai = rtd->codec_dai;
216 185
217 pr_debug("Entered %s\n", __func__);
218
219 /* disable the PLL */ 186 /* disable the PLL */
220 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);
221} 188}
@@ -225,335 +192,232 @@ static struct snd_soc_ops neo1973_voice_ops = {
225 .hw_free = neo1973_voice_hw_free, 192 .hw_free = neo1973_voice_hw_free,
226}; 193};
227 194
228static int neo1973_scenario; 195/* Shared routes and controls */
229
230static int neo1973_get_scenario(struct snd_kcontrol *kcontrol,
231 struct snd_ctl_elem_value *ucontrol)
232{
233 ucontrol->value.integer.value[0] = neo1973_scenario;
234 return 0;
235}
236
237static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario)
238{
239 struct snd_soc_dapm_context *dapm = &codec->dapm;
240
241 pr_debug("Entered %s\n", __func__);
242
243 switch (neo1973_scenario) {
244 case NEO_AUDIO_OFF:
245 snd_soc_dapm_disable_pin(dapm, "Audio Out");
246 snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
247 snd_soc_dapm_disable_pin(dapm, "GSM Line In");
248 snd_soc_dapm_disable_pin(dapm, "Headset Mic");
249 snd_soc_dapm_disable_pin(dapm, "Call Mic");
250 break;
251 case NEO_GSM_CALL_AUDIO_HANDSET:
252 snd_soc_dapm_enable_pin(dapm, "Audio Out");
253 snd_soc_dapm_enable_pin(dapm, "GSM Line Out");
254 snd_soc_dapm_enable_pin(dapm, "GSM Line In");
255 snd_soc_dapm_disable_pin(dapm, "Headset Mic");
256 snd_soc_dapm_enable_pin(dapm, "Call Mic");
257 break;
258 case NEO_GSM_CALL_AUDIO_HEADSET:
259 snd_soc_dapm_enable_pin(dapm, "Audio Out");
260 snd_soc_dapm_enable_pin(dapm, "GSM Line Out");
261 snd_soc_dapm_enable_pin(dapm, "GSM Line In");
262 snd_soc_dapm_enable_pin(dapm, "Headset Mic");
263 snd_soc_dapm_disable_pin(dapm, "Call Mic");
264 break;
265 case NEO_GSM_CALL_AUDIO_BLUETOOTH:
266 snd_soc_dapm_disable_pin(dapm, "Audio Out");
267 snd_soc_dapm_enable_pin(dapm, "GSM Line Out");
268 snd_soc_dapm_enable_pin(dapm, "GSM Line In");
269 snd_soc_dapm_disable_pin(dapm, "Headset Mic");
270 snd_soc_dapm_disable_pin(dapm, "Call Mic");
271 break;
272 case NEO_STEREO_TO_SPEAKERS:
273 snd_soc_dapm_enable_pin(dapm, "Audio Out");
274 snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
275 snd_soc_dapm_disable_pin(dapm, "GSM Line In");
276 snd_soc_dapm_disable_pin(dapm, "Headset Mic");
277 snd_soc_dapm_disable_pin(dapm, "Call Mic");
278 break;
279 case NEO_STEREO_TO_HEADPHONES:
280 snd_soc_dapm_enable_pin(dapm, "Audio Out");
281 snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
282 snd_soc_dapm_disable_pin(dapm, "GSM Line In");
283 snd_soc_dapm_disable_pin(dapm, "Headset Mic");
284 snd_soc_dapm_disable_pin(dapm, "Call Mic");
285 break;
286 case NEO_CAPTURE_HANDSET:
287 snd_soc_dapm_disable_pin(dapm, "Audio Out");
288 snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
289 snd_soc_dapm_disable_pin(dapm, "GSM Line In");
290 snd_soc_dapm_disable_pin(dapm, "Headset Mic");
291 snd_soc_dapm_enable_pin(dapm, "Call Mic");
292 break;
293 case NEO_CAPTURE_HEADSET:
294 snd_soc_dapm_disable_pin(dapm, "Audio Out");
295 snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
296 snd_soc_dapm_disable_pin(dapm, "GSM Line In");
297 snd_soc_dapm_enable_pin(dapm, "Headset Mic");
298 snd_soc_dapm_disable_pin(dapm, "Call Mic");
299 break;
300 case NEO_CAPTURE_BLUETOOTH:
301 snd_soc_dapm_disable_pin(dapm, "Audio Out");
302 snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
303 snd_soc_dapm_disable_pin(dapm, "GSM Line In");
304 snd_soc_dapm_disable_pin(dapm, "Headset Mic");
305 snd_soc_dapm_disable_pin(dapm, "Call Mic");
306 break;
307 default:
308 snd_soc_dapm_disable_pin(dapm, "Audio Out");
309 snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
310 snd_soc_dapm_disable_pin(dapm, "GSM Line In");
311 snd_soc_dapm_disable_pin(dapm, "Headset Mic");
312 snd_soc_dapm_disable_pin(dapm, "Call Mic");
313 }
314 196
315 snd_soc_dapm_sync(dapm); 197static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = {
198 SND_SOC_DAPM_LINE("GSM Line Out", NULL),
199 SND_SOC_DAPM_LINE("GSM Line In", NULL),
200 SND_SOC_DAPM_MIC("Headset Mic", NULL),
201 SND_SOC_DAPM_MIC("Handset Mic", NULL),
202};
316 203
317 return 0; 204static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = {
318} 205 /* Connections to the GSM Module */
206 {"GSM Line Out", NULL, "MONO1"},
207 {"GSM Line Out", NULL, "MONO2"},
208 {"RXP", NULL, "GSM Line In"},
209 {"RXN", NULL, "GSM Line In"},
319 210
320static int neo1973_set_scenario(struct snd_kcontrol *kcontrol, 211 /* Connections to Headset */
321 struct snd_ctl_elem_value *ucontrol) 212 {"MIC1", NULL, "Mic Bias"},
322{ 213 {"Mic Bias", NULL, "Headset Mic"},
323 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
324 214
325 pr_debug("Entered %s\n", __func__); 215 /* Call Mic */
216 {"MIC2", NULL, "Mic Bias"},
217 {"MIC2N", NULL, "Mic Bias"},
218 {"Mic Bias", NULL, "Handset Mic"},
326 219
327 if (neo1973_scenario == ucontrol->value.integer.value[0]) 220 /* Connect the ALC pins */
328 return 0; 221 {"ACIN", NULL, "ACOP"},
222};
329 223
330 neo1973_scenario = ucontrol->value.integer.value[0]; 224static const struct snd_kcontrol_new neo1973_wm8753_controls[] = {
331 set_scenario_endpoints(codec, neo1973_scenario); 225 SOC_DAPM_PIN_SWITCH("GSM Line Out"),
332 return 1; 226 SOC_DAPM_PIN_SWITCH("GSM Line In"),
333} 227 SOC_DAPM_PIN_SWITCH("Headset Mic"),
228 SOC_DAPM_PIN_SWITCH("Handset Mic"),
229};
334 230
335static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0}; 231/* GTA02 specific routes and controlls */
336 232
337static void lm4857_write_regs(void) 233#ifdef CONFIG_MACH_NEO1973_GTA02
338{
339 pr_debug("Entered %s\n", __func__);
340 234
341 if (i2c_master_send(i2c, lm4857_regs, 4) != 4) 235static int gta02_speaker_enabled;
342 printk(KERN_ERR "lm4857: i2c write failed\n");
343}
344 236
345static int lm4857_get_reg(struct snd_kcontrol *kcontrol, 237static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
346 struct snd_ctl_elem_value *ucontrol) 238 struct snd_ctl_elem_value *ucontrol)
347{ 239{
348 struct soc_mixer_control *mc = 240 gta02_speaker_enabled = ucontrol->value.integer.value[0];
349 (struct soc_mixer_control *)kcontrol->private_value;
350 int reg = mc->reg;
351 int shift = mc->shift;
352 int mask = mc->max;
353 241
354 pr_debug("Entered %s\n", __func__); 242 gpio_set_value(GTA02_GPIO_HP_IN, !gta02_speaker_enabled);
355 243
356 ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask;
357 return 0; 244 return 0;
358} 245}
359 246
360static int lm4857_set_reg(struct snd_kcontrol *kcontrol, 247static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
361 struct snd_ctl_elem_value *ucontrol) 248 struct snd_ctl_elem_value *ucontrol)
362{ 249{
363 struct soc_mixer_control *mc = 250 ucontrol->value.integer.value[0] = gta02_speaker_enabled;
364 (struct soc_mixer_control *)kcontrol->private_value; 251 return 0;
365 int reg = mc->reg;
366 int shift = mc->shift;
367 int mask = mc->max;
368
369 if (((lm4857_regs[reg] >> shift) & mask) ==
370 ucontrol->value.integer.value[0])
371 return 0;
372
373 lm4857_regs[reg] &= ~(mask << shift);
374 lm4857_regs[reg] |= ucontrol->value.integer.value[0] << shift;
375 lm4857_write_regs();
376 return 1;
377} 252}
378 253
379static int lm4857_get_mode(struct snd_kcontrol *kcontrol, 254static int lm4853_event(struct snd_soc_dapm_widget *w,
380 struct snd_ctl_elem_value *ucontrol) 255 struct snd_kcontrol *k, int event)
381{ 256{
382 u8 value = lm4857_regs[LM4857_CTRL] & 0x0F; 257 gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event));
383
384 pr_debug("Entered %s\n", __func__);
385
386 if (value)
387 value -= 5;
388 258
389 ucontrol->value.integer.value[0] = value;
390 return 0; 259 return 0;
391} 260}
392 261
393static int lm4857_set_mode(struct snd_kcontrol *kcontrol, 262static const struct snd_soc_dapm_route neo1973_gta02_routes[] = {
394 struct snd_ctl_elem_value *ucontrol) 263 /* Connections to the amp */
395{ 264 {"Stereo Out", NULL, "LOUT1"},
396 u8 value = ucontrol->value.integer.value[0]; 265 {"Stereo Out", NULL, "ROUT1"},
397
398 pr_debug("Entered %s\n", __func__);
399
400 if (value)
401 value += 5;
402
403 if ((lm4857_regs[LM4857_CTRL] & 0x0F) == value)
404 return 0;
405
406 lm4857_regs[LM4857_CTRL] &= 0xF0;
407 lm4857_regs[LM4857_CTRL] |= value;
408 lm4857_write_regs();
409 return 1;
410}
411 266
412static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = { 267 /* Call Speaker */
413 SND_SOC_DAPM_LINE("Audio Out", NULL), 268 {"Handset Spk", NULL, "LOUT2"},
414 SND_SOC_DAPM_LINE("GSM Line Out", NULL), 269 {"Handset Spk", NULL, "ROUT2"},
415 SND_SOC_DAPM_LINE("GSM Line In", NULL),
416 SND_SOC_DAPM_MIC("Headset Mic", NULL),
417 SND_SOC_DAPM_MIC("Call Mic", NULL),
418}; 270};
419 271
272static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = {
273 SOC_DAPM_PIN_SWITCH("Handset Spk"),
274 SOC_DAPM_PIN_SWITCH("Stereo Out"),
420 275
421static const struct snd_soc_dapm_route dapm_routes[] = { 276 SOC_SINGLE_BOOL_EXT("Amp Spk Switch", 0,
422 277 lm4853_get_spk,
423 /* Connections to the lm4857 amp */ 278 lm4853_set_spk),
424 {"Audio Out", NULL, "LOUT1"}, 279};
425 {"Audio Out", NULL, "ROUT1"},
426
427 /* Connections to the GSM Module */
428 {"GSM Line Out", NULL, "MONO1"},
429 {"GSM Line Out", NULL, "MONO2"},
430 {"RXP", NULL, "GSM Line In"},
431 {"RXN", NULL, "GSM Line In"},
432 280
433 /* Connections to Headset */ 281static const struct snd_soc_dapm_widget neo1973_gta02_wm8753_dapm_widgets[] = {
434 {"MIC1", NULL, "Mic Bias"}, 282 SND_SOC_DAPM_SPK("Handset Spk", NULL),
435 {"Mic Bias", NULL, "Headset Mic"}, 283 SND_SOC_DAPM_SPK("Stereo Out", lm4853_event),
284};
436 285
437 /* Call Mic */ 286static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
438 {"MIC2", NULL, "Mic Bias"}, 287{
439 {"MIC2N", NULL, "Mic Bias"}, 288 struct snd_soc_dapm_context *dapm = &codec->dapm;
440 {"Mic Bias", NULL, "Call Mic"}, 289 int ret;
441 290
442 /* Connect the ALC pins */ 291 ret = snd_soc_dapm_new_controls(dapm, neo1973_gta02_wm8753_dapm_widgets,
443 {"ACIN", NULL, "ACOP"}, 292 ARRAY_SIZE(neo1973_gta02_wm8753_dapm_widgets));
444}; 293 if (ret)
294 return ret;
445 295
446static const char *lm4857_mode[] = { 296 ret = snd_soc_dapm_add_routes(dapm, neo1973_gta02_routes,
447 "Off", 297 ARRAY_SIZE(neo1973_gta02_routes));
448 "Call Speaker", 298 if (ret)
449 "Stereo Speakers", 299 return ret;
450 "Stereo Speakers + Headphones",
451 "Headphones"
452};
453 300
454static const struct soc_enum lm4857_mode_enum[] = { 301 ret = snd_soc_add_controls(codec, neo1973_gta02_wm8753_controls,
455 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode), 302 ARRAY_SIZE(neo1973_gta02_wm8753_controls));
456}; 303 if (ret)
304 return ret;
457 305
458static const char *neo_scenarios[] = { 306 snd_soc_dapm_disable_pin(dapm, "Stereo Out");
459 "Off", 307 snd_soc_dapm_disable_pin(dapm, "Handset Spk");
460 "GSM Handset", 308 snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
461 "GSM Headset", 309 snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
462 "GSM Bluetooth",
463 "Speakers",
464 "Headphones",
465 "Capture Handset",
466 "Capture Headset",
467 "Capture Bluetooth"
468};
469 310
470static const struct soc_enum neo_scenario_enum[] = { 311 return 0;
471 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(neo_scenarios), neo_scenarios), 312}
472};
473 313
474static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0); 314#else
475static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0); 315static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; }
476 316#endif
477static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {
478 SOC_SINGLE_EXT_TLV("Amp Left Playback Volume", LM4857_LVOL, 0, 31, 0,
479 lm4857_get_reg, lm4857_set_reg, stereo_tlv),
480 SOC_SINGLE_EXT_TLV("Amp Right Playback Volume", LM4857_RVOL, 0, 31, 0,
481 lm4857_get_reg, lm4857_set_reg, stereo_tlv),
482 SOC_SINGLE_EXT_TLV("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0,
483 lm4857_get_reg, lm4857_set_reg, mono_tlv),
484 SOC_ENUM_EXT("Amp Mode", lm4857_mode_enum[0],
485 lm4857_get_mode, lm4857_set_mode),
486 SOC_ENUM_EXT("Neo Mode", neo_scenario_enum[0],
487 neo1973_get_scenario, neo1973_set_scenario),
488 SOC_SINGLE_EXT("Amp Spk 3D Playback Switch", LM4857_LVOL, 5, 1, 0,
489 lm4857_get_reg, lm4857_set_reg),
490 SOC_SINGLE_EXT("Amp HP 3d Playback Switch", LM4857_RVOL, 5, 1, 0,
491 lm4857_get_reg, lm4857_set_reg),
492 SOC_SINGLE_EXT("Amp Fast Wakeup Playback Switch", LM4857_CTRL, 5, 1, 0,
493 lm4857_get_reg, lm4857_set_reg),
494 SOC_SINGLE_EXT("Amp Earpiece 6dB Playback Switch", LM4857_CTRL, 4, 1, 0,
495 lm4857_get_reg, lm4857_set_reg),
496};
497 317
498/*
499 * This is an example machine initialisation for a wm8753 connected to a
500 * neo1973 II. It is missing logic to detect hp/mic insertions and logic
501 * to re-route the audio in such an event.
502 */
503static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) 318static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
504{ 319{
505 struct snd_soc_codec *codec = rtd->codec; 320 struct snd_soc_codec *codec = rtd->codec;
506 struct snd_soc_dapm_context *dapm = &codec->dapm; 321 struct snd_soc_dapm_context *dapm = &codec->dapm;
507 int err; 322 int ret;
508
509 pr_debug("Entered %s\n", __func__);
510 323
511 /* set up NC codec pins */ 324 /* set up NC codec pins */
512 snd_soc_dapm_nc_pin(dapm, "LOUT2"); 325 if (machine_is_neo1973_gta01()) {
513 snd_soc_dapm_nc_pin(dapm, "ROUT2"); 326 snd_soc_dapm_nc_pin(dapm, "LOUT2");
327 snd_soc_dapm_nc_pin(dapm, "ROUT2");
328 }
514 snd_soc_dapm_nc_pin(dapm, "OUT3"); 329 snd_soc_dapm_nc_pin(dapm, "OUT3");
515 snd_soc_dapm_nc_pin(dapm, "OUT4"); 330 snd_soc_dapm_nc_pin(dapm, "OUT4");
516 snd_soc_dapm_nc_pin(dapm, "LINE1"); 331 snd_soc_dapm_nc_pin(dapm, "LINE1");
517 snd_soc_dapm_nc_pin(dapm, "LINE2"); 332 snd_soc_dapm_nc_pin(dapm, "LINE2");
518 333
519 /* Add neo1973 specific widgets */ 334 /* Add neo1973 specific widgets */
520 snd_soc_dapm_new_controls(dapm, wm8753_dapm_widgets, 335 ret = snd_soc_dapm_new_controls(dapm, neo1973_wm8753_dapm_widgets,
521 ARRAY_SIZE(wm8753_dapm_widgets)); 336 ARRAY_SIZE(neo1973_wm8753_dapm_widgets));
522 337 if (ret)
523 /* set endpoints to default mode */ 338 return ret;
524 set_scenario_endpoints(codec, NEO_AUDIO_OFF);
525 339
526 /* add neo1973 specific controls */ 340 /* add neo1973 specific controls */
527 err = snd_soc_add_controls(codec, wm8753_neo1973_controls, 341 ret = snd_soc_add_controls(codec, neo1973_wm8753_controls,
528 ARRAY_SIZE(8753_neo1973_controls)); 342 ARRAY_SIZE(neo1973_wm8753_controls));
529 if (err < 0) 343 if (ret)
530 return err; 344 return ret;
531 345
532 /* set up neo1973 specific audio routes */ 346 /* set up neo1973 specific audio routes */
533 err = snd_soc_dapm_add_routes(dapm, dapm_routes, 347 ret = snd_soc_dapm_add_routes(dapm, neo1973_wm8753_routes,
534 ARRAY_SIZE(dapm_routes)); 348 ARRAY_SIZE(neo1973_wm8753_routes));
349 if (ret)
350 return ret;
351
352 /* set endpoints to default off mode */
353 snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
354 snd_soc_dapm_disable_pin(dapm, "GSM Line In");
355 snd_soc_dapm_disable_pin(dapm, "Headset Mic");
356 snd_soc_dapm_disable_pin(dapm, "Handset Mic");
357
358 /* allow audio paths from the GSM modem to run during suspend */
359 snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out");
360 snd_soc_dapm_ignore_suspend(dapm, "GSM Line In");
361 snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
362 snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
363
364 if (machine_is_neo1973_gta02()) {
365 ret = neo1973_gta02_wm8753_init(codec);
366 if (ret)
367 return ret;
368 }
535 369
536 snd_soc_dapm_sync(dapm); 370 snd_soc_dapm_sync(dapm);
371
537 return 0; 372 return 0;
538} 373}
539 374
540/* 375/* GTA01 specific controlls */
541 * BT Codec DAI 376
542 */ 377#ifdef CONFIG_MACH_NEO1973_GTA01
543static struct snd_soc_dai bt_dai = { 378
544 .name = "bluetooth-dai", 379static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = {
545 .playback = { 380 {"Amp IN", NULL, "ROUT1"},
546 .channels_min = 1, 381 {"Amp IN", NULL, "LOUT1"},
547 .channels_max = 1, 382
548 .rates = SNDRV_PCM_RATE_8000, 383 {"Handset Spk", NULL, "Amp EP"},
549 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 384 {"Stereo Out", NULL, "Amp LS"},
550 .capture = { 385 {"Headphone", NULL, "Amp HP"},
551 .channels_min = 1, 386};
552 .channels_max = 1, 387
553 .rates = SNDRV_PCM_RATE_8000, 388static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = {
554 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 389 SND_SOC_DAPM_SPK("Handset Spk", NULL),
390 SND_SOC_DAPM_SPK("Stereo Out", NULL),
391 SND_SOC_DAPM_HP("Headphone", NULL),
555}; 392};
556 393
394static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm)
395{
396 int ret;
397
398 ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets,
399 ARRAY_SIZE(neo1973_lm4857_dapm_widgets));
400 if (ret)
401 return ret;
402
403 ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes,
404 ARRAY_SIZE(neo1973_lm4857_routes));
405 if (ret)
406 return ret;
407
408 snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
409 snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
410 snd_soc_dapm_ignore_suspend(dapm, "Headphone");
411
412 snd_soc_dapm_sync(dapm);
413
414 return 0;
415}
416
417#else
418static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; };
419#endif
420
557static struct snd_soc_dai_link neo1973_dai[] = { 421static struct snd_soc_dai_link neo1973_dai[] = {
558{ /* Hifi Playback - for similatious use with voice below */ 422{ /* Hifi Playback - for similatious use with voice below */
559 .name = "WM8753", 423 .name = "WM8753",
@@ -569,90 +433,49 @@ static struct snd_soc_dai_link neo1973_dai[] = {
569 .name = "Bluetooth", 433 .name = "Bluetooth",
570 .stream_name = "Voice", 434 .stream_name = "Voice",
571 .platform_name = "samsung-audio", 435 .platform_name = "samsung-audio",
572 .cpu_dai_name = "bluetooth-dai", 436 .cpu_dai_name = "dfbmcs320-pcm",
573 .codec_dai_name = "wm8753-voice", 437 .codec_dai_name = "wm8753-voice",
574 .codec_name = "wm8753-codec.0-001a", 438 .codec_name = "wm8753-codec.0-001a",
575 .ops = &neo1973_voice_ops, 439 .ops = &neo1973_voice_ops,
576}, 440},
577}; 441};
578 442
579static struct snd_soc_card neo1973 = { 443static struct snd_soc_aux_dev neo1973_aux_devs[] = {
580 .name = "neo1973", 444 {
581 .dai_link = neo1973_dai, 445 .name = "dfbmcs320",
582 .num_links = ARRAY_SIZE(neo1973_dai), 446 .codec_name = "dfbmcs320.0",
447 },
448 {
449 .name = "lm4857",
450 .codec_name = "lm4857.0-007c",
451 .init = neo1973_lm4857_init,
452 },
583}; 453};
584 454
585static int lm4857_i2c_probe(struct i2c_client *client, 455static struct snd_soc_codec_conf neo1973_codec_conf[] = {
586 const struct i2c_device_id *id) 456 {
587{ 457 .dev_name = "lm4857.0-007c",
588 pr_debug("Entered %s\n", __func__); 458 .name_prefix = "Amp",
589 459 },
590 i2c = client; 460};
591
592 lm4857_write_regs();
593 return 0;
594}
595
596static int lm4857_i2c_remove(struct i2c_client *client)
597{
598 pr_debug("Entered %s\n", __func__);
599
600 i2c = NULL;
601
602 return 0;
603}
604
605static u8 lm4857_state;
606
607static int lm4857_suspend(struct i2c_client *dev, pm_message_t state)
608{
609 pr_debug("Entered %s\n", __func__);
610
611 dev_dbg(&dev->dev, "lm4857_suspend\n");
612 lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf;
613 if (lm4857_state) {
614 lm4857_regs[LM4857_CTRL] &= 0xf0;
615 lm4857_write_regs();
616 }
617 return 0;
618}
619
620static int lm4857_resume(struct i2c_client *dev)
621{
622 pr_debug("Entered %s\n", __func__);
623
624 if (lm4857_state) {
625 lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f);
626 lm4857_write_regs();
627 }
628 return 0;
629}
630
631static void lm4857_shutdown(struct i2c_client *dev)
632{
633 pr_debug("Entered %s\n", __func__);
634
635 dev_dbg(&dev->dev, "lm4857_shutdown\n");
636 lm4857_regs[LM4857_CTRL] &= 0xf0;
637 lm4857_write_regs();
638}
639 461
640static const struct i2c_device_id lm4857_i2c_id[] = { 462#ifdef CONFIG_MACH_NEO1973_GTA02
641 { "neo1973_lm4857", 0 }, 463static const struct gpio neo1973_gta02_gpios[] = {
642 { } 464 { GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" },
465 { GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" },
643}; 466};
467#else
468static const struct gpio neo1973_gta02_gpios[] = {};
469#endif
644 470
645static struct i2c_driver lm4857_i2c_driver = { 471static struct snd_soc_card neo1973 = {
646 .driver = { 472 .name = "neo1973",
647 .name = "LM4857 I2C Amp", 473 .dai_link = neo1973_dai,
648 .owner = THIS_MODULE, 474 .num_links = ARRAY_SIZE(neo1973_dai),
649 }, 475 .aux_dev = neo1973_aux_devs,
650 .suspend = lm4857_suspend, 476 .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs),
651 .resume = lm4857_resume, 477 .codec_conf = neo1973_codec_conf,
652 .shutdown = lm4857_shutdown, 478 .num_configs = ARRAY_SIZE(neo1973_codec_conf),
653 .probe = lm4857_i2c_probe,
654 .remove = lm4857_i2c_remove,
655 .id_table = lm4857_i2c_id,
656}; 479};
657 480
658static struct platform_device *neo1973_snd_device; 481static struct platform_device *neo1973_snd_device;
@@ -661,46 +484,56 @@ static int __init neo1973_init(void)
661{ 484{
662 int ret; 485 int ret;
663 486
664 pr_debug("Entered %s\n", __func__); 487 if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02())
665
666 if (!machine_is_neo1973_gta01()) {
667 printk(KERN_INFO
668 "Only GTA01 hardware supported by ASoC driver\n");
669 return -ENODEV; 488 return -ENODEV;
489
490 if (machine_is_neo1973_gta02()) {
491 neo1973.name = "neo1973gta02";
492 neo1973.num_aux_devs = 1;
493
494 ret = gpio_request_array(neo1973_gta02_gpios,
495 ARRAY_SIZE(neo1973_gta02_gpios));
496 if (ret)
497 return ret;
670 } 498 }
671 499
672 neo1973_snd_device = platform_device_alloc("soc-audio", -1); 500 neo1973_snd_device = platform_device_alloc("soc-audio", -1);
673 if (!neo1973_snd_device) 501 if (!neo1973_snd_device) {
674 return -ENOMEM; 502 ret = -ENOMEM;
503 goto err_gpio_free;
504 }
675 505
676 platform_set_drvdata(neo1973_snd_device, &neo1973); 506 platform_set_drvdata(neo1973_snd_device, &neo1973);
677 ret = platform_device_add(neo1973_snd_device); 507 ret = platform_device_add(neo1973_snd_device);
678 508
679 if (ret) { 509 if (ret)
680 platform_device_put(neo1973_snd_device); 510 goto err_put_device;
681 return ret;
682 }
683
684 ret = i2c_add_driver(&lm4857_i2c_driver);
685 511
686 if (ret != 0) 512 return 0;
687 platform_device_unregister(neo1973_snd_device);
688 513
514err_put_device:
515 platform_device_put(neo1973_snd_device);
516err_gpio_free:
517 if (machine_is_neo1973_gta02()) {
518 gpio_free_array(neo1973_gta02_gpios,
519 ARRAY_SIZE(neo1973_gta02_gpios));
520 }
689 return ret; 521 return ret;
690} 522}
523module_init(neo1973_init);
691 524
692static void __exit neo1973_exit(void) 525static void __exit neo1973_exit(void)
693{ 526{
694 pr_debug("Entered %s\n", __func__);
695
696 i2c_del_driver(&lm4857_i2c_driver);
697 platform_device_unregister(neo1973_snd_device); 527 platform_device_unregister(neo1973_snd_device);
698}
699 528
700module_init(neo1973_init); 529 if (machine_is_neo1973_gta02()) {
530 gpio_free_array(neo1973_gta02_gpios,
531 ARRAY_SIZE(neo1973_gta02_gpios));
532 }
533}
701module_exit(neo1973_exit); 534module_exit(neo1973_exit);
702 535
703/* Module information */ 536/* Module information */
704MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org"); 537MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org");
705MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973"); 538MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 and Frerunner");
706MODULE_LICENSE("GPL"); 539MODULE_LICENSE("GPL");