diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /sound/soc/codecs/wm9712.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (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.c | 144 |
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"), | |||
333 | SND_SOC_DAPM_INPUT("MIC2"), | 332 | SND_SOC_DAPM_INPUT("MIC2"), |
334 | }; | 333 | }; |
335 | 334 | ||
336 | static const struct snd_soc_dapm_route audio_map[] = { | 335 | static 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 | ||
433 | static 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 | |||
443 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 432 | static 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 | ||
529 | struct snd_soc_dai wm9712_dai[] = { | 516 | static 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 | }; |
558 | EXPORT_SYMBOL_GPL(wm9712_dai); | ||
559 | 545 | ||
560 | static int wm9712_set_bias_level(struct snd_soc_codec *codec, | 546 | static 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 | ||
600 | static int wm9712_soc_suspend(struct platform_device *pdev, | 586 | static 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 | ||
610 | static int wm9712_soc_resume(struct platform_device *pdev) | 593 | static 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 | ||
638 | static int wm9712_soc_probe(struct platform_device *pdev) | 619 | static 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 | ||
699 | reset_err: | 646 | reset_err: |
700 | snd_soc_free_pcms(socdev); | ||
701 | pcm_err: | ||
702 | snd_soc_free_ac97_codec(codec); | 647 | snd_soc_free_ac97_codec(codec); |
703 | |||
704 | codec_err: | ||
705 | kfree(codec->reg_cache); | ||
706 | |||
707 | cache_err: | ||
708 | kfree(socdev->card->codec); | ||
709 | socdev->card->codec = NULL; | ||
710 | return ret; | 648 | return ret; |
711 | } | 649 | } |
712 | 650 | ||
713 | static int wm9712_soc_remove(struct platform_device *pdev) | 651 | static 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 | ||
729 | struct snd_soc_codec_device soc_codec_dev_wm9712 = { | 657 | static 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 | }; |
735 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712); | 674 | |
675 | static __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 | |||
681 | static int __devexit wm9712_remove(struct platform_device *pdev) | ||
682 | { | ||
683 | snd_soc_unregister_codec(&pdev->dev); | ||
684 | return 0; | ||
685 | } | ||
686 | |||
687 | static 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 | |||
697 | static int __init wm9712_init(void) | ||
698 | { | ||
699 | return platform_driver_register(&wm9712_codec_driver); | ||
700 | } | ||
701 | module_init(wm9712_init); | ||
702 | |||
703 | static void __exit wm9712_exit(void) | ||
704 | { | ||
705 | platform_driver_unregister(&wm9712_codec_driver); | ||
706 | } | ||
707 | module_exit(wm9712_exit); | ||
736 | 708 | ||
737 | MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver"); | 709 | MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver"); |
738 | MODULE_AUTHOR("Liam Girdwood"); | 710 | MODULE_AUTHOR("Liam Girdwood"); |