diff options
Diffstat (limited to 'sound/soc/codecs/uda1380.c')
-rw-r--r-- | sound/soc/codecs/uda1380.c | 211 |
1 files changed, 57 insertions, 154 deletions
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 2f925a27dcde..1a51c816e542 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c | |||
@@ -33,11 +33,9 @@ | |||
33 | 33 | ||
34 | #include "uda1380.h" | 34 | #include "uda1380.h" |
35 | 35 | ||
36 | static struct snd_soc_codec *uda1380_codec; | ||
37 | |||
38 | /* codec private data */ | 36 | /* codec private data */ |
39 | struct uda1380_priv { | 37 | struct uda1380_priv { |
40 | struct snd_soc_codec codec; | 38 | struct snd_soc_codec *codec; |
41 | u16 reg_cache[UDA1380_CACHEREGNUM]; | 39 | u16 reg_cache[UDA1380_CACHEREGNUM]; |
42 | unsigned int dac_clk; | 40 | unsigned int dac_clk; |
43 | struct work_struct work; | 41 | struct work_struct work; |
@@ -135,6 +133,8 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, | |||
135 | 133 | ||
136 | static void uda1380_flush_work(struct work_struct *work) | 134 | static void uda1380_flush_work(struct work_struct *work) |
137 | { | 135 | { |
136 | struct uda1380_priv *uda1380 = container_of(work, struct uda1380_priv, work); | ||
137 | struct snd_soc_codec *uda1380_codec = uda1380->codec; | ||
138 | int bit, reg; | 138 | int bit, reg; |
139 | 139 | ||
140 | for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { | 140 | for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { |
@@ -145,6 +145,7 @@ static void uda1380_flush_work(struct work_struct *work) | |||
145 | uda1380_read_reg_cache(uda1380_codec, reg)); | 145 | uda1380_read_reg_cache(uda1380_codec, reg)); |
146 | clear_bit(bit, &uda1380_cache_dirty); | 146 | clear_bit(bit, &uda1380_cache_dirty); |
147 | } | 147 | } |
148 | |||
148 | } | 149 | } |
149 | 150 | ||
150 | /* declarations of ALSA reg_elem_REAL controls */ | 151 | /* declarations of ALSA reg_elem_REAL controls */ |
@@ -474,8 +475,7 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, | |||
474 | struct snd_soc_dai *dai) | 475 | struct snd_soc_dai *dai) |
475 | { | 476 | { |
476 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 477 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
477 | struct snd_soc_device *socdev = rtd->socdev; | 478 | struct snd_soc_codec *codec = rtd->codec; |
478 | struct snd_soc_codec *codec = socdev->card->codec; | ||
479 | struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); | 479 | struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); |
480 | int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); | 480 | int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); |
481 | 481 | ||
@@ -501,8 +501,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, | |||
501 | struct snd_soc_dai *dai) | 501 | struct snd_soc_dai *dai) |
502 | { | 502 | { |
503 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 503 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
504 | struct snd_soc_device *socdev = rtd->socdev; | 504 | struct snd_soc_codec *codec = rtd->codec; |
505 | struct snd_soc_codec *codec = socdev->card->codec; | ||
506 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); | 505 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); |
507 | 506 | ||
508 | /* set WSPLL power and divider if running from this clock */ | 507 | /* set WSPLL power and divider if running from this clock */ |
@@ -540,8 +539,7 @@ static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, | |||
540 | struct snd_soc_dai *dai) | 539 | struct snd_soc_dai *dai) |
541 | { | 540 | { |
542 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 541 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
543 | struct snd_soc_device *socdev = rtd->socdev; | 542 | struct snd_soc_codec *codec = rtd->codec; |
544 | struct snd_soc_codec *codec = socdev->card->codec; | ||
545 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); | 543 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); |
546 | 544 | ||
547 | /* shut down WSPLL power if running from this clock */ | 545 | /* shut down WSPLL power if running from this clock */ |
@@ -604,9 +602,9 @@ static struct snd_soc_dai_ops uda1380_dai_ops_capture = { | |||
604 | .set_fmt = uda1380_set_dai_fmt_capture, | 602 | .set_fmt = uda1380_set_dai_fmt_capture, |
605 | }; | 603 | }; |
606 | 604 | ||
607 | struct snd_soc_dai uda1380_dai[] = { | 605 | static struct snd_soc_dai_driver uda1380_dai[] = { |
608 | { | 606 | { |
609 | .name = "UDA1380", | 607 | .name = "uda1380-hifi", |
610 | .playback = { | 608 | .playback = { |
611 | .stream_name = "Playback", | 609 | .stream_name = "Playback", |
612 | .channels_min = 1, | 610 | .channels_min = 1, |
@@ -622,7 +620,7 @@ struct snd_soc_dai uda1380_dai[] = { | |||
622 | .ops = &uda1380_dai_ops, | 620 | .ops = &uda1380_dai_ops, |
623 | }, | 621 | }, |
624 | { /* playback only - dual interface */ | 622 | { /* playback only - dual interface */ |
625 | .name = "UDA1380", | 623 | .name = "uda1380-hifi-playback", |
626 | .playback = { | 624 | .playback = { |
627 | .stream_name = "Playback", | 625 | .stream_name = "Playback", |
628 | .channels_min = 1, | 626 | .channels_min = 1, |
@@ -633,7 +631,7 @@ struct snd_soc_dai uda1380_dai[] = { | |||
633 | .ops = &uda1380_dai_ops_playback, | 631 | .ops = &uda1380_dai_ops_playback, |
634 | }, | 632 | }, |
635 | { /* capture only - dual interface*/ | 633 | { /* capture only - dual interface*/ |
636 | .name = "UDA1380", | 634 | .name = "uda1380-hifi-capture", |
637 | .capture = { | 635 | .capture = { |
638 | .stream_name = "Capture", | 636 | .stream_name = "Capture", |
639 | .channels_min = 1, | 637 | .channels_min = 1, |
@@ -644,21 +642,15 @@ struct snd_soc_dai uda1380_dai[] = { | |||
644 | .ops = &uda1380_dai_ops_capture, | 642 | .ops = &uda1380_dai_ops_capture, |
645 | }, | 643 | }, |
646 | }; | 644 | }; |
647 | EXPORT_SYMBOL_GPL(uda1380_dai); | ||
648 | 645 | ||
649 | static int uda1380_suspend(struct platform_device *pdev, pm_message_t state) | 646 | static int uda1380_suspend(struct snd_soc_codec *codec, pm_message_t state) |
650 | { | 647 | { |
651 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
652 | struct snd_soc_codec *codec = socdev->card->codec; | ||
653 | |||
654 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); | 648 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); |
655 | return 0; | 649 | return 0; |
656 | } | 650 | } |
657 | 651 | ||
658 | static int uda1380_resume(struct platform_device *pdev) | 652 | static int uda1380_resume(struct snd_soc_codec *codec) |
659 | { | 653 | { |
660 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
661 | struct snd_soc_codec *codec = socdev->card->codec; | ||
662 | int i; | 654 | int i; |
663 | u8 data[2]; | 655 | u8 data[2]; |
664 | u16 *cache = codec->reg_cache; | 656 | u16 *cache = codec->reg_cache; |
@@ -673,91 +665,20 @@ static int uda1380_resume(struct platform_device *pdev) | |||
673 | return 0; | 665 | return 0; |
674 | } | 666 | } |
675 | 667 | ||
676 | static int uda1380_probe(struct platform_device *pdev) | 668 | static int uda1380_probe(struct snd_soc_codec *codec) |
677 | { | ||
678 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
679 | struct snd_soc_codec *codec; | ||
680 | struct uda1380_platform_data *pdata; | ||
681 | int ret = 0; | ||
682 | |||
683 | if (uda1380_codec == NULL) { | ||
684 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
685 | return -ENODEV; | ||
686 | } | ||
687 | |||
688 | socdev->card->codec = uda1380_codec; | ||
689 | codec = uda1380_codec; | ||
690 | pdata = codec->dev->platform_data; | ||
691 | |||
692 | /* register pcms */ | ||
693 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
694 | if (ret < 0) { | ||
695 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
696 | goto pcm_err; | ||
697 | } | ||
698 | |||
699 | /* power on device */ | ||
700 | uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
701 | /* set clock input */ | ||
702 | switch (pdata->dac_clk) { | ||
703 | case UDA1380_DAC_CLK_SYSCLK: | ||
704 | uda1380_write(codec, UDA1380_CLK, 0); | ||
705 | break; | ||
706 | case UDA1380_DAC_CLK_WSPLL: | ||
707 | uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK); | ||
708 | break; | ||
709 | } | ||
710 | |||
711 | snd_soc_add_controls(codec, uda1380_snd_controls, | ||
712 | ARRAY_SIZE(uda1380_snd_controls)); | ||
713 | uda1380_add_widgets(codec); | ||
714 | |||
715 | return ret; | ||
716 | |||
717 | pcm_err: | ||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | /* power down chip */ | ||
722 | static int uda1380_remove(struct platform_device *pdev) | ||
723 | { | ||
724 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
725 | struct snd_soc_codec *codec = socdev->card->codec; | ||
726 | |||
727 | if (codec->control_data) | ||
728 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
729 | |||
730 | snd_soc_free_pcms(socdev); | ||
731 | snd_soc_dapm_free(socdev); | ||
732 | |||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | struct snd_soc_codec_device soc_codec_dev_uda1380 = { | ||
737 | .probe = uda1380_probe, | ||
738 | .remove = uda1380_remove, | ||
739 | .suspend = uda1380_suspend, | ||
740 | .resume = uda1380_resume, | ||
741 | }; | ||
742 | EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); | ||
743 | |||
744 | static int uda1380_register(struct uda1380_priv *uda1380) | ||
745 | { | 669 | { |
746 | int ret, i; | 670 | struct uda1380_platform_data *pdata =codec->dev->platform_data; |
747 | struct snd_soc_codec *codec = &uda1380->codec; | 671 | struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); |
748 | struct uda1380_platform_data *pdata = codec->dev->platform_data; | 672 | int ret; |
749 | 673 | ||
750 | if (uda1380_codec) { | 674 | codec->hw_write = (hw_write_t)i2c_master_send; |
751 | dev_err(codec->dev, "Another UDA1380 is registered\n"); | ||
752 | return -EINVAL; | ||
753 | } | ||
754 | 675 | ||
755 | if (!pdata || !pdata->gpio_power || !pdata->gpio_reset) | 676 | if (!pdata || !pdata->gpio_power || !pdata->gpio_reset) |
756 | return -EINVAL; | 677 | return -EINVAL; |
757 | 678 | ||
758 | ret = gpio_request(pdata->gpio_power, "uda1380 power"); | 679 | ret = gpio_request(pdata->gpio_power, "uda1380 power"); |
759 | if (ret) | 680 | if (ret) |
760 | goto err_out; | 681 | return ret; |
761 | ret = gpio_request(pdata->gpio_reset, "uda1380 reset"); | 682 | ret = gpio_request(pdata->gpio_reset, "uda1380 reset"); |
762 | if (ret) | 683 | if (ret) |
763 | goto err_gpio; | 684 | goto err_gpio; |
@@ -769,25 +690,6 @@ static int uda1380_register(struct uda1380_priv *uda1380) | |||
769 | udelay(5); | 690 | udelay(5); |
770 | gpio_set_value(pdata->gpio_reset, 0); | 691 | gpio_set_value(pdata->gpio_reset, 0); |
771 | 692 | ||
772 | mutex_init(&codec->mutex); | ||
773 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
774 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
775 | |||
776 | snd_soc_codec_set_drvdata(codec, uda1380); | ||
777 | codec->name = "UDA1380"; | ||
778 | codec->owner = THIS_MODULE; | ||
779 | codec->read = uda1380_read_reg_cache; | ||
780 | codec->write = uda1380_write; | ||
781 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
782 | codec->set_bias_level = uda1380_set_bias_level; | ||
783 | codec->dai = uda1380_dai; | ||
784 | codec->num_dai = ARRAY_SIZE(uda1380_dai); | ||
785 | codec->reg_cache_size = ARRAY_SIZE(uda1380_reg); | ||
786 | codec->reg_cache = &uda1380->reg_cache; | ||
787 | codec->reg_cache_step = 1; | ||
788 | |||
789 | memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg)); | ||
790 | |||
791 | ret = uda1380_reset(codec); | 693 | ret = uda1380_reset(codec); |
792 | if (ret < 0) { | 694 | if (ret < 0) { |
793 | dev_err(codec->dev, "Failed to issue reset\n"); | 695 | dev_err(codec->dev, "Failed to issue reset\n"); |
@@ -796,83 +698,84 @@ static int uda1380_register(struct uda1380_priv *uda1380) | |||
796 | 698 | ||
797 | INIT_WORK(&uda1380->work, uda1380_flush_work); | 699 | INIT_WORK(&uda1380->work, uda1380_flush_work); |
798 | 700 | ||
799 | for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++) | 701 | /* power on device */ |
800 | uda1380_dai[i].dev = codec->dev; | 702 | uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
801 | 703 | /* set clock input */ | |
802 | uda1380_codec = codec; | 704 | switch (pdata->dac_clk) { |
803 | 705 | case UDA1380_DAC_CLK_SYSCLK: | |
804 | ret = snd_soc_register_codec(codec); | 706 | uda1380_write(codec, UDA1380_CLK, 0); |
805 | if (ret != 0) { | 707 | break; |
806 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | 708 | case UDA1380_DAC_CLK_WSPLL: |
807 | goto err_reset; | 709 | uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK); |
710 | break; | ||
808 | } | 711 | } |
809 | 712 | ||
810 | ret = snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); | 713 | snd_soc_add_controls(codec, uda1380_snd_controls, |
811 | if (ret != 0) { | 714 | ARRAY_SIZE(uda1380_snd_controls)); |
812 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | 715 | uda1380_add_widgets(codec); |
813 | goto err_dai; | ||
814 | } | ||
815 | 716 | ||
816 | return 0; | 717 | return 0; |
817 | 718 | ||
818 | err_dai: | ||
819 | snd_soc_unregister_codec(codec); | ||
820 | err_reset: | 719 | err_reset: |
821 | gpio_set_value(pdata->gpio_power, 0); | 720 | gpio_set_value(pdata->gpio_power, 0); |
822 | gpio_free(pdata->gpio_reset); | 721 | gpio_free(pdata->gpio_reset); |
823 | err_gpio: | 722 | err_gpio: |
824 | gpio_free(pdata->gpio_power); | 723 | gpio_free(pdata->gpio_power); |
825 | err_out: | ||
826 | return ret; | 724 | return ret; |
827 | } | 725 | } |
828 | 726 | ||
829 | static void uda1380_unregister(struct uda1380_priv *uda1380) | 727 | /* power down chip */ |
728 | static int uda1380_remove(struct snd_soc_codec *codec) | ||
830 | { | 729 | { |
831 | struct snd_soc_codec *codec = &uda1380->codec; | 730 | struct uda1380_platform_data *pdata =codec->dev->platform_data; |
832 | struct uda1380_platform_data *pdata = codec->dev->platform_data; | ||
833 | 731 | ||
834 | snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); | 732 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); |
835 | snd_soc_unregister_codec(&uda1380->codec); | ||
836 | 733 | ||
837 | gpio_set_value(pdata->gpio_power, 0); | 734 | gpio_set_value(pdata->gpio_power, 0); |
838 | gpio_free(pdata->gpio_reset); | 735 | gpio_free(pdata->gpio_reset); |
839 | gpio_free(pdata->gpio_power); | 736 | gpio_free(pdata->gpio_power); |
840 | 737 | ||
841 | kfree(uda1380); | 738 | return 0; |
842 | uda1380_codec = NULL; | ||
843 | } | 739 | } |
844 | 740 | ||
741 | static struct snd_soc_codec_driver soc_codec_dev_uda1380 = { | ||
742 | .probe = uda1380_probe, | ||
743 | .remove = uda1380_remove, | ||
744 | .suspend = uda1380_suspend, | ||
745 | .resume = uda1380_resume, | ||
746 | .read = uda1380_read_reg_cache, | ||
747 | .write = uda1380_write, | ||
748 | .set_bias_level = uda1380_set_bias_level, | ||
749 | .reg_cache_size = ARRAY_SIZE(uda1380_reg), | ||
750 | .reg_word_size = sizeof(u16), | ||
751 | .reg_cache_default = uda1380_reg, | ||
752 | .reg_cache_step = 1, | ||
753 | }; | ||
754 | |||
845 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 755 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
846 | static __devinit int uda1380_i2c_probe(struct i2c_client *i2c, | 756 | static __devinit int uda1380_i2c_probe(struct i2c_client *i2c, |
847 | const struct i2c_device_id *id) | 757 | const struct i2c_device_id *id) |
848 | { | 758 | { |
849 | struct uda1380_priv *uda1380; | 759 | struct uda1380_priv *uda1380; |
850 | struct snd_soc_codec *codec; | ||
851 | int ret; | 760 | int ret; |
852 | 761 | ||
853 | uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL); | 762 | uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL); |
854 | if (uda1380 == NULL) | 763 | if (uda1380 == NULL) |
855 | return -ENOMEM; | 764 | return -ENOMEM; |
856 | 765 | ||
857 | codec = &uda1380->codec; | ||
858 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
859 | |||
860 | i2c_set_clientdata(i2c, uda1380); | 766 | i2c_set_clientdata(i2c, uda1380); |
861 | codec->control_data = i2c; | ||
862 | |||
863 | codec->dev = &i2c->dev; | ||
864 | 767 | ||
865 | ret = uda1380_register(uda1380); | 768 | ret = snd_soc_register_codec(&i2c->dev, |
866 | if (ret != 0) | 769 | &soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai)); |
770 | if (ret < 0) | ||
867 | kfree(uda1380); | 771 | kfree(uda1380); |
868 | |||
869 | return ret; | 772 | return ret; |
870 | } | 773 | } |
871 | 774 | ||
872 | static int __devexit uda1380_i2c_remove(struct i2c_client *i2c) | 775 | static int __devexit uda1380_i2c_remove(struct i2c_client *i2c) |
873 | { | 776 | { |
874 | struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c); | 777 | snd_soc_unregister_codec(&i2c->dev); |
875 | uda1380_unregister(uda1380); | 778 | kfree(i2c_get_clientdata(i2c)); |
876 | return 0; | 779 | return 0; |
877 | } | 780 | } |
878 | 781 | ||
@@ -884,7 +787,7 @@ MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); | |||
884 | 787 | ||
885 | static struct i2c_driver uda1380_i2c_driver = { | 788 | static struct i2c_driver uda1380_i2c_driver = { |
886 | .driver = { | 789 | .driver = { |
887 | .name = "UDA1380 I2C Codec", | 790 | .name = "uda1380-codec", |
888 | .owner = THIS_MODULE, | 791 | .owner = THIS_MODULE, |
889 | }, | 792 | }, |
890 | .probe = uda1380_i2c_probe, | 793 | .probe = uda1380_i2c_probe, |