aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm9712.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /sound/soc/codecs/wm9712.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'sound/soc/codecs/wm9712.c')
-rw-r--r--sound/soc/codecs/wm9712.c144
1 files changed, 58 insertions, 86 deletions
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 28790a2ffe8d..90117f8156e8 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -20,7 +20,6 @@
20#include <sound/ac97_codec.h> 20#include <sound/ac97_codec.h>
21#include <sound/initval.h> 21#include <sound/initval.h>
22#include <sound/soc.h> 22#include <sound/soc.h>
23#include <sound/soc-dapm.h>
24#include "wm9712.h" 23#include "wm9712.h"
25 24
26#define WM9712_VERSION "0.4" 25#define WM9712_VERSION "0.4"
@@ -333,7 +332,7 @@ SND_SOC_DAPM_INPUT("MIC1"),
333SND_SOC_DAPM_INPUT("MIC2"), 332SND_SOC_DAPM_INPUT("MIC2"),
334}; 333};
335 334
336static const struct snd_soc_dapm_route audio_map[] = { 335static const struct snd_soc_dapm_route wm9712_audio_map[] = {
337 /* virtual mixer - mixes left & right channels for spk and mono */ 336 /* virtual mixer - mixes left & right channels for spk and mono */
338 {"AC97 Mixer", NULL, "Left DAC"}, 337 {"AC97 Mixer", NULL, "Left DAC"},
339 {"AC97 Mixer", NULL, "Right DAC"}, 338 {"AC97 Mixer", NULL, "Right DAC"},
@@ -430,16 +429,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
430 {"ROUT2", NULL, "Speaker PGA"}, 429 {"ROUT2", NULL, "Speaker PGA"},
431}; 430};
432 431
433static int wm9712_add_widgets(struct snd_soc_codec *codec)
434{
435 snd_soc_dapm_new_controls(codec, wm9712_dapm_widgets,
436 ARRAY_SIZE(wm9712_dapm_widgets));
437
438 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
439
440 return 0;
441}
442
443static unsigned int ac97_read(struct snd_soc_codec *codec, 432static unsigned int ac97_read(struct snd_soc_codec *codec,
444 unsigned int reg) 433 unsigned int reg)
445{ 434{
@@ -478,8 +467,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
478{ 467{
479 struct snd_pcm_runtime *runtime = substream->runtime; 468 struct snd_pcm_runtime *runtime = substream->runtime;
480 struct snd_soc_pcm_runtime *rtd = substream->private_data; 469 struct snd_soc_pcm_runtime *rtd = substream->private_data;
481 struct snd_soc_device *socdev = rtd->socdev; 470 struct snd_soc_codec *codec =rtd->codec;
482 struct snd_soc_codec *codec = socdev->card->codec;
483 int reg; 471 int reg;
484 u16 vra; 472 u16 vra;
485 473
@@ -499,8 +487,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream,
499{ 487{
500 struct snd_pcm_runtime *runtime = substream->runtime; 488 struct snd_pcm_runtime *runtime = substream->runtime;
501 struct snd_soc_pcm_runtime *rtd = substream->private_data; 489 struct snd_soc_pcm_runtime *rtd = substream->private_data;
502 struct snd_soc_device *socdev = rtd->socdev; 490 struct snd_soc_codec *codec = rtd->codec;
503 struct snd_soc_codec *codec = socdev->card->codec;
504 u16 vra, xsle; 491 u16 vra, xsle;
505 492
506 vra = ac97_read(codec, AC97_EXTENDED_STATUS); 493 vra = ac97_read(codec, AC97_EXTENDED_STATUS);
@@ -526,9 +513,9 @@ static struct snd_soc_dai_ops wm9712_dai_ops_aux = {
526 .prepare = ac97_aux_prepare, 513 .prepare = ac97_aux_prepare,
527}; 514};
528 515
529struct snd_soc_dai wm9712_dai[] = { 516static struct snd_soc_dai_driver wm9712_dai[] = {
530{ 517{
531 .name = "AC97 HiFi", 518 .name = "wm9712-hifi",
532 .ac97_control = 1, 519 .ac97_control = 1,
533 .playback = { 520 .playback = {
534 .stream_name = "HiFi Playback", 521 .stream_name = "HiFi Playback",
@@ -545,7 +532,7 @@ struct snd_soc_dai wm9712_dai[] = {
545 .ops = &wm9712_dai_ops_hifi, 532 .ops = &wm9712_dai_ops_hifi,
546}, 533},
547{ 534{
548 .name = "AC97 Aux", 535 .name = "wm9712-aux",
549 .playback = { 536 .playback = {
550 .stream_name = "Aux Playback", 537 .stream_name = "Aux Playback",
551 .channels_min = 1, 538 .channels_min = 1,
@@ -555,7 +542,6 @@ struct snd_soc_dai wm9712_dai[] = {
555 .ops = &wm9712_dai_ops_aux, 542 .ops = &wm9712_dai_ops_aux,
556} 543}
557}; 544};
558EXPORT_SYMBOL_GPL(wm9712_dai);
559 545
560static int wm9712_set_bias_level(struct snd_soc_codec *codec, 546static int wm9712_set_bias_level(struct snd_soc_codec *codec,
561 enum snd_soc_bias_level level) 547 enum snd_soc_bias_level level)
@@ -573,7 +559,7 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec,
573 ac97_write(codec, AC97_POWERDOWN, 0xffff); 559 ac97_write(codec, AC97_POWERDOWN, 0xffff);
574 break; 560 break;
575 } 561 }
576 codec->bias_level = level; 562 codec->dapm.bias_level = level;
577 return 0; 563 return 0;
578} 564}
579 565
@@ -597,20 +583,15 @@ err:
597 return -EIO; 583 return -EIO;
598} 584}
599 585
600static int wm9712_soc_suspend(struct platform_device *pdev, 586static int wm9712_soc_suspend(struct snd_soc_codec *codec,
601 pm_message_t state) 587 pm_message_t state)
602{ 588{
603 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
604 struct snd_soc_codec *codec = socdev->card->codec;
605
606 wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF); 589 wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF);
607 return 0; 590 return 0;
608} 591}
609 592
610static int wm9712_soc_resume(struct platform_device *pdev) 593static int wm9712_soc_resume(struct snd_soc_codec *codec)
611{ 594{
612 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
613 struct snd_soc_codec *codec = socdev->card->codec;
614 int i, ret; 595 int i, ret;
615 u16 *cache = codec->reg_cache; 596 u16 *cache = codec->reg_cache;
616 597
@@ -635,51 +616,18 @@ static int wm9712_soc_resume(struct platform_device *pdev)
635 return ret; 616 return ret;
636} 617}
637 618
638static int wm9712_soc_probe(struct platform_device *pdev) 619static int wm9712_soc_probe(struct snd_soc_codec *codec)
639{ 620{
640 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
641 struct snd_soc_codec *codec;
642 int ret = 0; 621 int ret = 0;
643 622
644 printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION); 623 printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
645 624
646 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec),
647 GFP_KERNEL);
648 if (socdev->card->codec == NULL)
649 return -ENOMEM;
650 codec = socdev->card->codec;
651 mutex_init(&codec->mutex);
652
653 codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL);
654
655 if (codec->reg_cache == NULL) {
656 ret = -ENOMEM;
657 goto cache_err;
658 }
659 codec->reg_cache_size = sizeof(wm9712_reg);
660 codec->reg_cache_step = 2;
661
662 codec->name = "WM9712";
663 codec->owner = THIS_MODULE;
664 codec->dai = wm9712_dai;
665 codec->num_dai = ARRAY_SIZE(wm9712_dai);
666 codec->write = ac97_write;
667 codec->read = ac97_read;
668 codec->set_bias_level = wm9712_set_bias_level;
669 INIT_LIST_HEAD(&codec->dapm_widgets);
670 INIT_LIST_HEAD(&codec->dapm_paths);
671
672 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); 625 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
673 if (ret < 0) { 626 if (ret < 0) {
674 printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); 627 printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
675 goto codec_err; 628 return ret;
676 } 629 }
677 630
678 /* register pcms */
679 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
680 if (ret < 0)
681 goto pcm_err;
682
683 ret = wm9712_reset(codec, 0); 631 ret = wm9712_reset(codec, 0);
684 if (ret < 0) { 632 if (ret < 0) {
685 printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n"); 633 printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n");
@@ -692,47 +640,71 @@ static int wm9712_soc_probe(struct platform_device *pdev)
692 wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 640 wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
693 snd_soc_add_controls(codec, wm9712_snd_ac97_controls, 641 snd_soc_add_controls(codec, wm9712_snd_ac97_controls,
694 ARRAY_SIZE(wm9712_snd_ac97_controls)); 642 ARRAY_SIZE(wm9712_snd_ac97_controls));
695 wm9712_add_widgets(codec);
696 643
697 return 0; 644 return 0;
698 645
699reset_err: 646reset_err:
700 snd_soc_free_pcms(socdev);
701pcm_err:
702 snd_soc_free_ac97_codec(codec); 647 snd_soc_free_ac97_codec(codec);
703
704codec_err:
705 kfree(codec->reg_cache);
706
707cache_err:
708 kfree(socdev->card->codec);
709 socdev->card->codec = NULL;
710 return ret; 648 return ret;
711} 649}
712 650
713static int wm9712_soc_remove(struct platform_device *pdev) 651static int wm9712_soc_remove(struct snd_soc_codec *codec)
714{ 652{
715 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
716 struct snd_soc_codec *codec = socdev->card->codec;
717
718 if (codec == NULL)
719 return 0;
720
721 snd_soc_dapm_free(socdev);
722 snd_soc_free_pcms(socdev);
723 snd_soc_free_ac97_codec(codec); 653 snd_soc_free_ac97_codec(codec);
724 kfree(codec->reg_cache);
725 kfree(codec);
726 return 0; 654 return 0;
727} 655}
728 656
729struct snd_soc_codec_device soc_codec_dev_wm9712 = { 657static struct snd_soc_codec_driver soc_codec_dev_wm9712 = {
730 .probe = wm9712_soc_probe, 658 .probe = wm9712_soc_probe,
731 .remove = wm9712_soc_remove, 659 .remove = wm9712_soc_remove,
732 .suspend = wm9712_soc_suspend, 660 .suspend = wm9712_soc_suspend,
733 .resume = wm9712_soc_resume, 661 .resume = wm9712_soc_resume,
662 .read = ac97_read,
663 .write = ac97_write,
664 .set_bias_level = wm9712_set_bias_level,
665 .reg_cache_size = ARRAY_SIZE(wm9712_reg),
666 .reg_word_size = sizeof(u16),
667 .reg_cache_step = 2,
668 .reg_cache_default = wm9712_reg,
669 .dapm_widgets = wm9712_dapm_widgets,
670 .num_dapm_widgets = ARRAY_SIZE(wm9712_dapm_widgets),
671 .dapm_routes = wm9712_audio_map,
672 .num_dapm_routes = ARRAY_SIZE(wm9712_audio_map),
734}; 673};
735EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712); 674
675static __devinit int wm9712_probe(struct platform_device *pdev)
676{
677 return snd_soc_register_codec(&pdev->dev,
678 &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai));
679}
680
681static int __devexit wm9712_remove(struct platform_device *pdev)
682{
683 snd_soc_unregister_codec(&pdev->dev);
684 return 0;
685}
686
687static struct platform_driver wm9712_codec_driver = {
688 .driver = {
689 .name = "wm9712-codec",
690 .owner = THIS_MODULE,
691 },
692
693 .probe = wm9712_probe,
694 .remove = __devexit_p(wm9712_remove),
695};
696
697static int __init wm9712_init(void)
698{
699 return platform_driver_register(&wm9712_codec_driver);
700}
701module_init(wm9712_init);
702
703static void __exit wm9712_exit(void)
704{
705 platform_driver_unregister(&wm9712_codec_driver);
706}
707module_exit(wm9712_exit);
736 708
737MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver"); 709MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
738MODULE_AUTHOR("Liam Girdwood"); 710MODULE_AUTHOR("Liam Girdwood");