aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/samsung
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2011-03-07 02:04:55 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-03-07 07:19:22 -0500
commit9b0a25f0386f9775b69c46ced9b5632b649f00ba (patch)
tree82aa924b21417d281c4eeb19f5b4b7fbbefc3d9e /sound/soc/samsung
parent004c52e009e3c585eb0692740b714867fd2b3555 (diff)
ASoC: neo1973_wm8753: Move lm4857 specefic code to its own module
This patch moves the code for the lm4857 AMP from the neo1973_wm8753 sound board driver to its own module. The lm4857 is a generic AMP IC and not specific to the neo1973. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Acked-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/samsung')
-rw-r--r--sound/soc/samsung/Kconfig1
-rw-r--r--sound/soc/samsung/lm4857.h32
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c269
3 files changed, 66 insertions, 236 deletions
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index a6a6b5fa2f2f..ba78e26e20f2 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -39,6 +39,7 @@ config SND_SOC_SAMSUNG_NEO1973_WM8753
39 depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA01 39 depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA01
40 select SND_S3C24XX_I2S 40 select SND_S3C24XX_I2S
41 select SND_SOC_WM8753 41 select SND_SOC_WM8753
42 select SND_SOC_LM4857
42 help 43 help
43 Say Y if you want to add support for SoC audio on smdk2440 44 Say Y if you want to add support for SoC audio on smdk2440
44 with the WM8753. 45 with the WM8753.
diff --git a/sound/soc/samsung/lm4857.h b/sound/soc/samsung/lm4857.h
deleted file mode 100644
index 0cf5b7011d6f..000000000000
--- a/sound/soc/samsung/lm4857.h
+++ /dev/null
@@ -1,32 +0,0 @@
1/*
2 * lm4857.h -- ALSA Soc Audio Layer
3 *
4 * Copyright 2007 Wolfson Microelectronics PLC.
5 * Author: Graeme Gregory
6 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * Revision history
14 * 18th Jun 2007 Initial version.
15 */
16
17#ifndef LM4857_H_
18#define LM4857_H_
19
20/* The register offsets in the cache array */
21#define LM4857_MVOL 0
22#define LM4857_LVOL 1
23#define LM4857_RVOL 2
24#define LM4857_CTRL 3
25
26/* the shifts required to set these bits */
27#define LM4857_3D 5
28#define LM4857_WAKEUP 5
29#define LM4857_EPGAIN 4
30
31#endif /*LM4857_H_*/
32
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index fe929467f93c..7761827314b2 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -17,11 +17,9 @@
17#include <linux/timer.h> 17#include <linux/timer.h>
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/i2c.h>
21#include <sound/core.h> 20#include <sound/core.h>
22#include <sound/pcm.h> 21#include <sound/pcm.h>
23#include <sound/soc.h> 22#include <sound/soc.h>
24#include <sound/tlv.h>
25 23
26#include <asm/mach-types.h> 24#include <asm/mach-types.h>
27#include <mach/regs-clock.h> 25#include <mach/regs-clock.h>
@@ -33,12 +31,10 @@
33#include <plat/regs-iis.h> 31#include <plat/regs-iis.h>
34 32
35#include "../codecs/wm8753.h" 33#include "../codecs/wm8753.h"
36#include "lm4857.h"
37#include "dma.h" 34#include "dma.h"
38#include "s3c24xx-i2s.h" 35#include "s3c24xx-i2s.h"
39 36
40static struct snd_soc_card neo1973; 37static struct snd_soc_card neo1973;
41static struct i2c_client *i2c;
42 38
43static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, 39static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
44 struct snd_pcm_hw_params *params) 40 struct snd_pcm_hw_params *params)
@@ -213,85 +209,7 @@ static struct snd_soc_ops neo1973_voice_ops = {
213 .hw_free = neo1973_voice_hw_free, 209 .hw_free = neo1973_voice_hw_free,
214}; 210};
215 211
216static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0};
217
218static void lm4857_write_regs(void)
219{
220 pr_debug("Entered %s\n", __func__);
221
222 if (i2c_master_send(i2c, lm4857_regs, 4) != 4)
223 printk(KERN_ERR "lm4857: i2c write failed\n");
224}
225
226static int lm4857_get_reg(struct snd_kcontrol *kcontrol,
227 struct snd_ctl_elem_value *ucontrol)
228{
229 struct soc_mixer_control *mc =
230 (struct soc_mixer_control *)kcontrol->private_value;
231 int reg = mc->reg;
232 int shift = mc->shift;
233 int mask = mc->max;
234
235 pr_debug("Entered %s\n", __func__);
236
237 ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask;
238 return 0;
239}
240
241static int lm4857_set_reg(struct snd_kcontrol *kcontrol,
242 struct snd_ctl_elem_value *ucontrol)
243{
244 struct soc_mixer_control *mc =
245 (struct soc_mixer_control *)kcontrol->private_value;
246 int reg = mc->reg;
247 int shift = mc->shift;
248 int mask = mc->max;
249
250 if (((lm4857_regs[reg] >> shift) & mask) ==
251 ucontrol->value.integer.value[0])
252 return 0;
253
254 lm4857_regs[reg] &= ~(mask << shift);
255 lm4857_regs[reg] |= ucontrol->value.integer.value[0] << shift;
256 lm4857_write_regs();
257 return 1;
258}
259
260static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
261 struct snd_ctl_elem_value *ucontrol)
262{
263 u8 value = lm4857_regs[LM4857_CTRL] & 0x0F;
264
265 pr_debug("Entered %s\n", __func__);
266
267 if (value)
268 value -= 5;
269
270 ucontrol->value.integer.value[0] = value;
271 return 0;
272}
273
274static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
275 struct snd_ctl_elem_value *ucontrol)
276{
277 u8 value = ucontrol->value.integer.value[0];
278
279 pr_debug("Entered %s\n", __func__);
280
281 if (value)
282 value += 5;
283
284 if ((lm4857_regs[LM4857_CTRL] & 0x0F) == value)
285 return 0;
286
287 lm4857_regs[LM4857_CTRL] &= 0xF0;
288 lm4857_regs[LM4857_CTRL] |= value;
289 lm4857_write_regs();
290 return 1;
291}
292
293static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = { 212static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
294 SND_SOC_DAPM_LINE("Audio Out", NULL),
295 SND_SOC_DAPM_LINE("GSM Line Out", NULL), 213 SND_SOC_DAPM_LINE("GSM Line Out", NULL),
296 SND_SOC_DAPM_LINE("GSM Line In", NULL), 214 SND_SOC_DAPM_LINE("GSM Line In", NULL),
297 SND_SOC_DAPM_MIC("Headset Mic", NULL), 215 SND_SOC_DAPM_MIC("Headset Mic", NULL),
@@ -299,12 +217,7 @@ static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
299}; 217};
300 218
301 219
302static const struct snd_soc_dapm_route dapm_routes[] = { 220static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = {
303
304 /* Connections to the lm4857 amp */
305 {"Audio Out", NULL, "LOUT1"},
306 {"Audio Out", NULL, "ROUT1"},
307
308 /* Connections to the GSM Module */ 221 /* Connections to the GSM Module */
309 {"GSM Line Out", NULL, "MONO1"}, 222 {"GSM Line Out", NULL, "MONO1"},
310 {"GSM Line Out", NULL, "MONO2"}, 223 {"GSM Line Out", NULL, "MONO2"},
@@ -324,46 +237,14 @@ static const struct snd_soc_dapm_route dapm_routes[] = {
324 {"ACIN", NULL, "ACOP"}, 237 {"ACIN", NULL, "ACOP"},
325}; 238};
326 239
327static const char *lm4857_mode[] = { 240static const struct snd_kcontrol_new neo1973_wm8753_controls[] = {
328 "Off",
329 "Call Speaker",
330 "Stereo Speakers",
331 "Stereo Speakers + Headphones",
332 "Headphones"
333};
334
335static const struct soc_enum lm4857_mode_enum[] = {
336 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode),
337};
338
339static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0);
340static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0);
341
342static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {
343 SOC_DAPM_PIN_SWITCH("Audio Out"),
344 SOC_DAPM_PIN_SWITCH("GSM Line Out"), 241 SOC_DAPM_PIN_SWITCH("GSM Line Out"),
345 SOC_DAPM_PIN_SWITCH("GSM Line In"), 242 SOC_DAPM_PIN_SWITCH("GSM Line In"),
346 SOC_DAPM_PIN_SWITCH("Headset Mic"), 243 SOC_DAPM_PIN_SWITCH("Headset Mic"),
347 SOC_DAPM_PIN_SWITCH("Call Mic"), 244 SOC_DAPM_PIN_SWITCH("Call Mic"),
348
349 SOC_SINGLE_EXT_TLV("Amp Left Playback Volume", LM4857_LVOL, 0, 31, 0,
350 lm4857_get_reg, lm4857_set_reg, stereo_tlv),
351 SOC_SINGLE_EXT_TLV("Amp Right Playback Volume", LM4857_RVOL, 0, 31, 0,
352 lm4857_get_reg, lm4857_set_reg, stereo_tlv),
353 SOC_SINGLE_EXT_TLV("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0,
354 lm4857_get_reg, lm4857_set_reg, mono_tlv),
355 SOC_ENUM_EXT("Amp Mode", lm4857_mode_enum[0],
356 lm4857_get_mode, lm4857_set_mode),
357 SOC_SINGLE_EXT("Amp Spk 3D Playback Switch", LM4857_LVOL, 5, 1, 0,
358 lm4857_get_reg, lm4857_set_reg),
359 SOC_SINGLE_EXT("Amp HP 3d Playback Switch", LM4857_RVOL, 5, 1, 0,
360 lm4857_get_reg, lm4857_set_reg),
361 SOC_SINGLE_EXT("Amp Fast Wakeup Playback Switch", LM4857_CTRL, 5, 1, 0,
362 lm4857_get_reg, lm4857_set_reg),
363 SOC_SINGLE_EXT("Amp Earpiece 6dB Playback Switch", LM4857_CTRL, 4, 1, 0,
364 lm4857_get_reg, lm4857_set_reg),
365}; 245};
366 246
247
367/* 248/*
368 * This is an example machine initialisation for a wm8753 connected to a 249 * This is an example machine initialisation for a wm8753 connected to a
369 * neo1973 II. It is missing logic to detect hp/mic insertions and logic 250 * neo1973 II. It is missing logic to detect hp/mic insertions and logic
@@ -387,29 +268,66 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
387 268
388 /* Add neo1973 specific widgets */ 269 /* Add neo1973 specific widgets */
389 snd_soc_dapm_new_controls(dapm, wm8753_dapm_widgets, 270 snd_soc_dapm_new_controls(dapm, wm8753_dapm_widgets,
390 ARRAY_SIZE(wm8753_dapm_widgets)); 271 ARRAY_SIZE(wm8753_dapm_widgets));
391 272
392 /* set endpoints to default mode */ 273 /* set endpoints to default mode */
393 snd_soc_dapm_disable_pin(dapm, "Audio Out");
394 snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); 274 snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
395 snd_soc_dapm_disable_pin(dapm, "GSM Line In"); 275 snd_soc_dapm_disable_pin(dapm, "GSM Line In");
396 snd_soc_dapm_disable_pin(dapm, "Headset Mic"); 276 snd_soc_dapm_disable_pin(dapm, "Headset Mic");
397 snd_soc_dapm_disable_pin(dapm, "Call Mic"); 277 snd_soc_dapm_disable_pin(dapm, "Call Mic");
398 278
399 /* add neo1973 specific controls */ 279 /* add neo1973 specific controls */
400 err = snd_soc_add_controls(codec, wm8753_neo1973_controls, 280 err = snd_soc_add_controls(codec, neo1973_wm8753_controls,
401 ARRAY_SIZE(8753_neo1973_controls)); 281 ARRAY_SIZE(neo1973_wm8753_controls));
402 if (err < 0) 282 if (err < 0)
403 return err; 283 return err;
404 284
405 /* set up neo1973 specific audio routes */ 285 /* set up neo1973 specific audio routes */
406 err = snd_soc_dapm_add_routes(dapm, dapm_routes, 286 err = snd_soc_dapm_add_routes(dapm, neo1973_wm8753_routes,
407 ARRAY_SIZE(dapm_routes)); 287 ARRAY_SIZE(neo1973_wm8753_routes));
408 288
409 snd_soc_dapm_sync(dapm); 289 snd_soc_dapm_sync(dapm);
410 return 0; 290 return 0;
411} 291}
412 292
293static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = {
294 {"Amp IN", NULL, "ROUT1"},
295 {"Amp IN", NULL, "LOUT1"},
296
297 {"Handset Spk", NULL, "Amp EP"},
298 {"Stereo Out", NULL, "Amp LS"},
299 {"Headphone", NULL, "Amp HP"},
300};
301
302static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = {
303 SND_SOC_DAPM_SPK("Handset Spk", NULL),
304 SND_SOC_DAPM_SPK("Stereo Out", NULL),
305 SND_SOC_DAPM_HP("Headphone", NULL),
306};
307
308static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm)
309{
310 int ret;
311
312 ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets,
313 ARRAY_SIZE(neo1973_lm4857_dapm_widgets));
314 if (ret)
315 return ret;
316
317 ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes,
318 ARRAY_SIZE(neo1973_lm4857_routes));
319 if (ret)
320 return ret;
321
322 snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
323 snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
324 snd_soc_dapm_ignore_suspend(dapm, "Headphone");
325
326 snd_soc_dapm_sync(dapm);
327
328 return 0;
329}
330
413/* 331/*
414 * BT Codec DAI 332 * BT Codec DAI
415 */ 333 */
@@ -449,83 +367,29 @@ static struct snd_soc_dai_link neo1973_dai[] = {
449}, 367},
450}; 368};
451 369
452static struct snd_soc_card neo1973 = { 370static struct snd_soc_aux_dev neo1973_aux_devs[] = {
453 .name = "neo1973", 371 {
454 .dai_link = neo1973_dai, 372 .name = "lm4857",
455 .num_links = ARRAY_SIZE(neo1973_dai), 373 .codec_name = "lm4857.0-007c",
374 .init = neo1973_lm4857_init,
375 },
456}; 376};
457 377
458static int lm4857_i2c_probe(struct i2c_client *client, 378static struct snd_soc_codec_conf neo1973_codec_conf[] = {
459 const struct i2c_device_id *id) 379 {
460{ 380 .dev_name = "lm4857.0-007c",
461 pr_debug("Entered %s\n", __func__); 381 .name_prefix = "Amp",
462 382 },
463 i2c = client;
464
465 lm4857_write_regs();
466 return 0;
467}
468
469static int lm4857_i2c_remove(struct i2c_client *client)
470{
471 pr_debug("Entered %s\n", __func__);
472
473 i2c = NULL;
474
475 return 0;
476}
477
478static u8 lm4857_state;
479
480static int lm4857_suspend(struct i2c_client *dev, pm_message_t state)
481{
482 pr_debug("Entered %s\n", __func__);
483
484 dev_dbg(&dev->dev, "lm4857_suspend\n");
485 lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf;
486 if (lm4857_state) {
487 lm4857_regs[LM4857_CTRL] &= 0xf0;
488 lm4857_write_regs();
489 }
490 return 0;
491}
492
493static int lm4857_resume(struct i2c_client *dev)
494{
495 pr_debug("Entered %s\n", __func__);
496
497 if (lm4857_state) {
498 lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f);
499 lm4857_write_regs();
500 }
501 return 0;
502}
503
504static void lm4857_shutdown(struct i2c_client *dev)
505{
506 pr_debug("Entered %s\n", __func__);
507
508 dev_dbg(&dev->dev, "lm4857_shutdown\n");
509 lm4857_regs[LM4857_CTRL] &= 0xf0;
510 lm4857_write_regs();
511}
512
513static const struct i2c_device_id lm4857_i2c_id[] = {
514 { "neo1973_lm4857", 0 },
515 { }
516}; 383};
517 384
518static struct i2c_driver lm4857_i2c_driver = { 385static struct snd_soc_card neo1973 = {
519 .driver = { 386 .name = "neo1973",
520 .name = "LM4857 I2C Amp", 387 .dai_link = neo1973_dai,
521 .owner = THIS_MODULE, 388 .num_links = ARRAY_SIZE(neo1973_dai),
522 }, 389 .aux_dev = neo1973_aux_devs,
523 .suspend = lm4857_suspend, 390 .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs),
524 .resume = lm4857_resume, 391 .codec_conf = neo1973_codec_conf,
525 .shutdown = lm4857_shutdown, 392 .num_configs = ARRAY_SIZE(neo1973_codec_conf),
526 .probe = lm4857_i2c_probe,
527 .remove = lm4857_i2c_remove,
528 .id_table = lm4857_i2c_id,
529}; 393};
530 394
531static struct platform_device *neo1973_snd_device; 395static struct platform_device *neo1973_snd_device;
@@ -554,8 +418,6 @@ static int __init neo1973_init(void)
554 return ret; 418 return ret;
555 } 419 }
556 420
557 ret = i2c_add_driver(&lm4857_i2c_driver);
558
559 if (ret != 0) 421 if (ret != 0)
560 platform_device_unregister(neo1973_snd_device); 422 platform_device_unregister(neo1973_snd_device);
561 423
@@ -566,7 +428,6 @@ static void __exit neo1973_exit(void)
566{ 428{
567 pr_debug("Entered %s\n", __func__); 429 pr_debug("Entered %s\n", __func__);
568 430
569 i2c_del_driver(&lm4857_i2c_driver);
570 platform_device_unregister(neo1973_snd_device); 431 platform_device_unregister(neo1973_snd_device);
571} 432}
572 433