aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8523.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8523.c')
-rw-r--r--sound/soc/codecs/wm8523.c177
1 files changed, 44 insertions, 133 deletions
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 0ad039b4adf5..712ef7c76f90 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -30,9 +30,6 @@
30 30
31#include "wm8523.h" 31#include "wm8523.h"
32 32
33static struct snd_soc_codec *wm8523_codec;
34struct snd_soc_codec_device soc_codec_dev_wm8523;
35
36#define WM8523_NUM_SUPPLIES 2 33#define WM8523_NUM_SUPPLIES 2
37static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { 34static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
38 "AVDD", 35 "AVDD",
@@ -43,7 +40,7 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
43 40
44/* codec private data */ 41/* codec private data */
45struct wm8523_priv { 42struct wm8523_priv {
46 struct snd_soc_codec codec; 43 enum snd_soc_control_type control_type;
47 u16 reg_cache[WM8523_REGISTER_COUNT]; 44 u16 reg_cache[WM8523_REGISTER_COUNT];
48 struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; 45 struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];
49 unsigned int sysclk; 46 unsigned int sysclk;
@@ -162,8 +159,7 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream,
162 struct snd_soc_dai *dai) 159 struct snd_soc_dai *dai)
163{ 160{
164 struct snd_soc_pcm_runtime *rtd = substream->private_data; 161 struct snd_soc_pcm_runtime *rtd = substream->private_data;
165 struct snd_soc_device *socdev = rtd->socdev; 162 struct snd_soc_codec *codec = rtd->codec;
166 struct snd_soc_codec *codec = socdev->card->codec;
167 struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); 163 struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
168 int i; 164 int i;
169 u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1); 165 u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
@@ -387,8 +383,8 @@ static struct snd_soc_dai_ops wm8523_dai_ops = {
387 .set_fmt = wm8523_set_dai_fmt, 383 .set_fmt = wm8523_set_dai_fmt,
388}; 384};
389 385
390struct snd_soc_dai wm8523_dai = { 386static struct snd_soc_dai_driver wm8523_dai = {
391 .name = "WM8523", 387 .name = "wm8523-hifi",
392 .playback = { 388 .playback = {
393 .stream_name = "Playback", 389 .stream_name = "Playback",
394 .channels_min = 2, /* Mono modes not yet supported */ 390 .channels_min = 2, /* Mono modes not yet supported */
@@ -398,25 +394,17 @@ struct snd_soc_dai wm8523_dai = {
398 }, 394 },
399 .ops = &wm8523_dai_ops, 395 .ops = &wm8523_dai_ops,
400}; 396};
401EXPORT_SYMBOL_GPL(wm8523_dai);
402 397
403#ifdef CONFIG_PM 398#ifdef CONFIG_PM
404static int wm8523_suspend(struct platform_device *pdev, pm_message_t state) 399static int wm8523_suspend(struct snd_soc_codec *codec, pm_message_t state)
405{ 400{
406 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
407 struct snd_soc_codec *codec = socdev->card->codec;
408
409 wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); 401 wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);
410 return 0; 402 return 0;
411} 403}
412 404
413static int wm8523_resume(struct platform_device *pdev) 405static int wm8523_resume(struct snd_soc_codec *codec)
414{ 406{
415 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
416 struct snd_soc_codec *codec = socdev->card->codec;
417
418 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 407 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
419
420 return 0; 408 return 0;
421} 409}
422#else 410#else
@@ -424,93 +412,20 @@ static int wm8523_resume(struct platform_device *pdev)
424#define wm8523_resume NULL 412#define wm8523_resume NULL
425#endif 413#endif
426 414
427static int wm8523_probe(struct platform_device *pdev) 415static int wm8523_probe(struct snd_soc_codec *codec)
428{
429 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
430 struct snd_soc_codec *codec;
431 int ret = 0;
432
433 if (wm8523_codec == NULL) {
434 dev_err(&pdev->dev, "Codec device not registered\n");
435 return -ENODEV;
436 }
437
438 socdev->card->codec = wm8523_codec;
439 codec = wm8523_codec;
440
441 /* register pcms */
442 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
443 if (ret < 0) {
444 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
445 goto pcm_err;
446 }
447
448 snd_soc_add_controls(codec, wm8523_snd_controls,
449 ARRAY_SIZE(wm8523_snd_controls));
450 wm8523_add_widgets(codec);
451
452 return ret;
453
454pcm_err:
455 return ret;
456}
457
458static int wm8523_remove(struct platform_device *pdev)
459{
460 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
461
462 snd_soc_free_pcms(socdev);
463 snd_soc_dapm_free(socdev);
464
465 return 0;
466}
467
468struct snd_soc_codec_device soc_codec_dev_wm8523 = {
469 .probe = wm8523_probe,
470 .remove = wm8523_remove,
471 .suspend = wm8523_suspend,
472 .resume = wm8523_resume,
473};
474EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523);
475
476static int wm8523_register(struct wm8523_priv *wm8523,
477 enum snd_soc_control_type control)
478{ 416{
479 int ret; 417 struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
480 struct snd_soc_codec *codec = &wm8523->codec; 418 int ret, i;
481 int i;
482
483 if (wm8523_codec) {
484 dev_err(codec->dev, "Another WM8523 is registered\n");
485 ret = -EINVAL;
486 goto err;
487 }
488
489 mutex_init(&codec->mutex);
490 INIT_LIST_HEAD(&codec->dapm_widgets);
491 INIT_LIST_HEAD(&codec->dapm_paths);
492
493 snd_soc_codec_set_drvdata(codec, wm8523);
494 codec->name = "WM8523";
495 codec->owner = THIS_MODULE;
496 codec->bias_level = SND_SOC_BIAS_OFF;
497 codec->set_bias_level = wm8523_set_bias_level;
498 codec->dai = &wm8523_dai;
499 codec->num_dai = 1;
500 codec->reg_cache_size = WM8523_REGISTER_COUNT;
501 codec->reg_cache = &wm8523->reg_cache;
502 codec->volatile_register = wm8523_volatile_register;
503 419
420 codec->hw_write = (hw_write_t)i2c_master_send;
504 wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; 421 wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
505 wm8523->rate_constraint.count = 422 wm8523->rate_constraint.count =
506 ARRAY_SIZE(wm8523->rate_constraint_list); 423 ARRAY_SIZE(wm8523->rate_constraint_list);
507 424
508 memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg)); 425 ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type);
509
510 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
511 if (ret != 0) { 426 if (ret != 0) {
512 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 427 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
513 goto err; 428 return ret;
514 } 429 }
515 430
516 for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) 431 for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++)
@@ -520,7 +435,7 @@ static int wm8523_register(struct wm8523_priv *wm8523,
520 wm8523->supplies); 435 wm8523->supplies);
521 if (ret != 0) { 436 if (ret != 0) {
522 dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 437 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
523 goto err; 438 return ret;
524 } 439 }
525 440
526 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), 441 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
@@ -555,8 +470,6 @@ static int wm8523_register(struct wm8523_priv *wm8523,
555 goto err_enable; 470 goto err_enable;
556 } 471 }
557 472
558 wm8523_dai.dev = codec->dev;
559
560 /* Change some default settings - latch VU and enable ZC */ 473 /* Change some default settings - latch VU and enable ZC */
561 wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; 474 wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
562 wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; 475 wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
@@ -566,69 +479,67 @@ static int wm8523_register(struct wm8523_priv *wm8523,
566 /* Bias level configuration will have done an extra enable */ 479 /* Bias level configuration will have done an extra enable */
567 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); 480 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
568 481
569 wm8523_codec = codec; 482 snd_soc_add_controls(codec, wm8523_snd_controls,
570 483 ARRAY_SIZE(wm8523_snd_controls));
571 ret = snd_soc_register_codec(codec); 484 wm8523_add_widgets(codec);
572 if (ret != 0) {
573 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
574 goto err_enable;
575 }
576
577 ret = snd_soc_register_dai(&wm8523_dai);
578 if (ret != 0) {
579 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
580 goto err_codec;
581 }
582 485
583 return 0; 486 return 0;
584 487
585err_codec:
586 snd_soc_unregister_codec(codec);
587err_enable: 488err_enable:
588 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); 489 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
589err_get: 490err_get:
590 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); 491 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
591err: 492
592 kfree(wm8523);
593 return ret; 493 return ret;
594} 494}
595 495
596static void wm8523_unregister(struct wm8523_priv *wm8523) 496static int wm8523_remove(struct snd_soc_codec *codec)
597{ 497{
598 wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF); 498 struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
499
500 wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);
599 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); 501 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
600 snd_soc_unregister_dai(&wm8523_dai); 502 return 0;
601 snd_soc_unregister_codec(&wm8523->codec);
602 kfree(wm8523);
603 wm8523_codec = NULL;
604} 503}
605 504
505static struct snd_soc_codec_driver soc_codec_dev_wm8523 = {
506 .probe = wm8523_probe,
507 .remove = wm8523_remove,
508 .suspend = wm8523_suspend,
509 .resume = wm8523_resume,
510 .set_bias_level = wm8523_set_bias_level,
511 .reg_cache_size = WM8523_REGISTER_COUNT,
512 .reg_word_size = sizeof(u16),
513 .reg_cache_default = wm8523_reg,
514 .volatile_register = wm8523_volatile_register,
515};
516
606#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 517#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
607static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, 518static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
608 const struct i2c_device_id *id) 519 const struct i2c_device_id *id)
609{ 520{
610 struct wm8523_priv *wm8523; 521 struct wm8523_priv *wm8523;
611 struct snd_soc_codec *codec; 522 int ret;
612 523
613 wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); 524 wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL);
614 if (wm8523 == NULL) 525 if (wm8523 == NULL)
615 return -ENOMEM; 526 return -ENOMEM;
616 527
617 codec = &wm8523->codec;
618 codec->hw_write = (hw_write_t)i2c_master_send;
619
620 i2c_set_clientdata(i2c, wm8523); 528 i2c_set_clientdata(i2c, wm8523);
621 codec->control_data = i2c; 529 wm8523->control_type = SND_SOC_I2C;
622 530
623 codec->dev = &i2c->dev; 531 ret = snd_soc_register_codec(&i2c->dev,
532 &soc_codec_dev_wm8523, &wm8523_dai, 1);
533 if (ret < 0)
534 kfree(wm8523);
535 return ret;
624 536
625 return wm8523_register(wm8523, SND_SOC_I2C);
626} 537}
627 538
628static __devexit int wm8523_i2c_remove(struct i2c_client *client) 539static __devexit int wm8523_i2c_remove(struct i2c_client *client)
629{ 540{
630 struct wm8523_priv *wm8523 = i2c_get_clientdata(client); 541 snd_soc_unregister_codec(&client->dev);
631 wm8523_unregister(wm8523); 542 kfree(i2c_get_clientdata(client));
632 return 0; 543 return 0;
633} 544}
634 545
@@ -640,7 +551,7 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
640 551
641static struct i2c_driver wm8523_i2c_driver = { 552static struct i2c_driver wm8523_i2c_driver = {
642 .driver = { 553 .driver = {
643 .name = "WM8523", 554 .name = "wm8523-codec",
644 .owner = THIS_MODULE, 555 .owner = THIS_MODULE,
645 }, 556 },
646 .probe = wm8523_i2c_probe, 557 .probe = wm8523_i2c_probe,