diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-08-12 09:40:28 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-08-12 09:40:28 -0400 |
commit | cf7af01aa77ec1b17687f5328ce0a598709efd59 (patch) | |
tree | 4cc46339721366c7498dacf5ebac01906be273e7 /sound/soc/codecs/wm8580.c | |
parent | 6f341d14811550d863ba804ce6ec7757a7145081 (diff) | |
parent | 5dcba5d6741d4533e0ef696507f93f2a4c738efb (diff) |
Merge branch 'topic/multi-component' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/asoc-2.6 into for-2.6.37
Diffstat (limited to 'sound/soc/codecs/wm8580.c')
-rw-r--r-- | sound/soc/codecs/wm8580.c | 183 |
1 files changed, 51 insertions, 132 deletions
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 1881b16bc248..b1a80e5ff8b5 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -199,7 +199,7 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { | |||
199 | 199 | ||
200 | /* codec private data */ | 200 | /* codec private data */ |
201 | struct wm8580_priv { | 201 | struct wm8580_priv { |
202 | struct snd_soc_codec codec; | 202 | enum snd_soc_control_type control_type; |
203 | struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; | 203 | struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; |
204 | u16 reg_cache[WM8580_MAX_REGISTER + 1]; | 204 | u16 reg_cache[WM8580_MAX_REGISTER + 1]; |
205 | struct pll_state a; | 205 | struct pll_state a; |
@@ -484,9 +484,8 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, | |||
484 | struct snd_soc_dai *dai) | 484 | struct snd_soc_dai *dai) |
485 | { | 485 | { |
486 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 486 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
487 | struct snd_soc_device *socdev = rtd->socdev; | 487 | struct snd_soc_codec *codec = rtd->codec; |
488 | struct snd_soc_codec *codec = socdev->card->codec; | 488 | u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->driver->id); |
489 | u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id); | ||
490 | 489 | ||
491 | paifb &= ~WM8580_AIF_LENGTH_MASK; | 490 | paifb &= ~WM8580_AIF_LENGTH_MASK; |
492 | /* bit size */ | 491 | /* bit size */ |
@@ -506,7 +505,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, | |||
506 | return -EINVAL; | 505 | return -EINVAL; |
507 | } | 506 | } |
508 | 507 | ||
509 | snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb); | 508 | snd_soc_write(codec, WM8580_PAIF3 + dai->driver->id, paifb); |
510 | return 0; | 509 | return 0; |
511 | } | 510 | } |
512 | 511 | ||
@@ -518,8 +517,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, | |||
518 | unsigned int aifb; | 517 | unsigned int aifb; |
519 | int can_invert_lrclk; | 518 | int can_invert_lrclk; |
520 | 519 | ||
521 | aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id); | 520 | aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->driver->id); |
522 | aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id); | 521 | aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->driver->id); |
523 | 522 | ||
524 | aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); | 523 | aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); |
525 | 524 | ||
@@ -585,8 +584,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, | |||
585 | return -EINVAL; | 584 | return -EINVAL; |
586 | } | 585 | } |
587 | 586 | ||
588 | snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); | 587 | snd_soc_write(codec, WM8580_PAIF1 + codec_dai->driver->id, aifa); |
589 | snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); | 588 | snd_soc_write(codec, WM8580_PAIF3 + codec_dai->driver->id, aifb); |
590 | 589 | ||
591 | return 0; | 590 | return 0; |
592 | } | 591 | } |
@@ -746,10 +745,10 @@ static struct snd_soc_dai_ops wm8580_dai_ops_capture = { | |||
746 | .set_pll = wm8580_set_dai_pll, | 745 | .set_pll = wm8580_set_dai_pll, |
747 | }; | 746 | }; |
748 | 747 | ||
749 | struct snd_soc_dai wm8580_dai[] = { | 748 | static struct snd_soc_dai_driver wm8580_dai[] = { |
750 | { | 749 | { |
751 | .name = "WM8580 PAIFRX", | 750 | .name = "wm8580-hifi-playback", |
752 | .id = 0, | 751 | .id = WM8580_DAI_PAIFRX, |
753 | .playback = { | 752 | .playback = { |
754 | .stream_name = "Playback", | 753 | .stream_name = "Playback", |
755 | .channels_min = 1, | 754 | .channels_min = 1, |
@@ -760,8 +759,8 @@ struct snd_soc_dai wm8580_dai[] = { | |||
760 | .ops = &wm8580_dai_ops_playback, | 759 | .ops = &wm8580_dai_ops_playback, |
761 | }, | 760 | }, |
762 | { | 761 | { |
763 | .name = "WM8580 PAIFTX", | 762 | .name = "wm8580-hifi-capture", |
764 | .id = 1, | 763 | .id = WM8580_DAI_PAIFTX, |
765 | .capture = { | 764 | .capture = { |
766 | .stream_name = "Capture", | 765 | .stream_name = "Capture", |
767 | .channels_min = 2, | 766 | .channels_min = 2, |
@@ -772,90 +771,16 @@ struct snd_soc_dai wm8580_dai[] = { | |||
772 | .ops = &wm8580_dai_ops_capture, | 771 | .ops = &wm8580_dai_ops_capture, |
773 | }, | 772 | }, |
774 | }; | 773 | }; |
775 | EXPORT_SYMBOL_GPL(wm8580_dai); | ||
776 | 774 | ||
777 | static struct snd_soc_codec *wm8580_codec; | 775 | static int wm8580_probe(struct snd_soc_codec *codec) |
778 | |||
779 | static int wm8580_probe(struct platform_device *pdev) | ||
780 | { | 776 | { |
781 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 777 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
782 | struct snd_soc_codec *codec; | 778 | int ret = 0,i; |
783 | int ret = 0; | ||
784 | |||
785 | if (wm8580_codec == NULL) { | ||
786 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
787 | return -ENODEV; | ||
788 | } | ||
789 | |||
790 | socdev->card->codec = wm8580_codec; | ||
791 | codec = wm8580_codec; | ||
792 | |||
793 | /* register pcms */ | ||
794 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
795 | if (ret < 0) { | ||
796 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
797 | goto pcm_err; | ||
798 | } | ||
799 | |||
800 | snd_soc_add_controls(codec, wm8580_snd_controls, | ||
801 | ARRAY_SIZE(wm8580_snd_controls)); | ||
802 | wm8580_add_widgets(codec); | ||
803 | |||
804 | return ret; | ||
805 | |||
806 | pcm_err: | ||
807 | return ret; | ||
808 | } | ||
809 | |||
810 | /* power down chip */ | ||
811 | static int wm8580_remove(struct platform_device *pdev) | ||
812 | { | ||
813 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
814 | |||
815 | snd_soc_free_pcms(socdev); | ||
816 | snd_soc_dapm_free(socdev); | ||
817 | |||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | struct snd_soc_codec_device soc_codec_dev_wm8580 = { | ||
822 | .probe = wm8580_probe, | ||
823 | .remove = wm8580_remove, | ||
824 | }; | ||
825 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); | ||
826 | |||
827 | static int wm8580_register(struct wm8580_priv *wm8580, | ||
828 | enum snd_soc_control_type control) | ||
829 | { | ||
830 | int ret, i; | ||
831 | struct snd_soc_codec *codec = &wm8580->codec; | ||
832 | |||
833 | if (wm8580_codec) { | ||
834 | dev_err(codec->dev, "Another WM8580 is registered\n"); | ||
835 | ret = -EINVAL; | ||
836 | goto err; | ||
837 | } | ||
838 | |||
839 | mutex_init(&codec->mutex); | ||
840 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
841 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
842 | |||
843 | snd_soc_codec_set_drvdata(codec, wm8580); | ||
844 | codec->name = "WM8580"; | ||
845 | codec->owner = THIS_MODULE; | ||
846 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
847 | codec->set_bias_level = wm8580_set_bias_level; | ||
848 | codec->dai = wm8580_dai; | ||
849 | codec->num_dai = ARRAY_SIZE(wm8580_dai); | ||
850 | codec->reg_cache_size = ARRAY_SIZE(wm8580->reg_cache); | ||
851 | codec->reg_cache = &wm8580->reg_cache; | ||
852 | |||
853 | memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); | ||
854 | 779 | ||
855 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 780 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type); |
856 | if (ret < 0) { | 781 | if (ret < 0) { |
857 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 782 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
858 | goto err; | 783 | return ret; |
859 | } | 784 | } |
860 | 785 | ||
861 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) | 786 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) |
@@ -865,7 +790,7 @@ static int wm8580_register(struct wm8580_priv *wm8580, | |||
865 | wm8580->supplies); | 790 | wm8580->supplies); |
866 | if (ret != 0) { | 791 | if (ret != 0) { |
867 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 792 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); |
868 | goto err; | 793 | return ret; |
869 | } | 794 | } |
870 | 795 | ||
871 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), | 796 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), |
@@ -882,74 +807,68 @@ static int wm8580_register(struct wm8580_priv *wm8580, | |||
882 | goto err_regulator_enable; | 807 | goto err_regulator_enable; |
883 | } | 808 | } |
884 | 809 | ||
885 | for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) | ||
886 | wm8580_dai[i].dev = codec->dev; | ||
887 | |||
888 | wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 810 | wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
889 | 811 | ||
890 | wm8580_codec = codec; | 812 | snd_soc_add_controls(codec, wm8580_snd_controls, |
891 | 813 | ARRAY_SIZE(wm8580_snd_controls)); | |
892 | ret = snd_soc_register_codec(codec); | 814 | wm8580_add_widgets(codec); |
893 | if (ret != 0) { | ||
894 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
895 | goto err_regulator_enable; | ||
896 | } | ||
897 | |||
898 | ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | ||
899 | if (ret != 0) { | ||
900 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
901 | goto err_codec; | ||
902 | } | ||
903 | 815 | ||
904 | return 0; | 816 | return 0; |
905 | 817 | ||
906 | err_codec: | ||
907 | snd_soc_unregister_codec(codec); | ||
908 | err_regulator_enable: | 818 | err_regulator_enable: |
909 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 819 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
910 | err_regulator_get: | 820 | err_regulator_get: |
911 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 821 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
912 | err: | ||
913 | kfree(wm8580); | ||
914 | return ret; | 822 | return ret; |
915 | } | 823 | } |
916 | 824 | ||
917 | static void wm8580_unregister(struct wm8580_priv *wm8580) | 825 | /* power down chip */ |
826 | static int wm8580_remove(struct snd_soc_codec *codec) | ||
918 | { | 827 | { |
919 | wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); | 828 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
920 | snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | 829 | |
921 | snd_soc_unregister_codec(&wm8580->codec); | 830 | wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); |
831 | |||
922 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 832 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
923 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 833 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
924 | kfree(wm8580); | 834 | |
925 | wm8580_codec = NULL; | 835 | return 0; |
926 | } | 836 | } |
927 | 837 | ||
838 | static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { | ||
839 | .probe = wm8580_probe, | ||
840 | .remove = wm8580_remove, | ||
841 | .set_bias_level = wm8580_set_bias_level, | ||
842 | .reg_cache_size = sizeof(wm8580_reg), | ||
843 | .reg_word_size = sizeof(u16), | ||
844 | .reg_cache_default = &wm8580_reg, | ||
845 | }; | ||
846 | |||
928 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 847 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
929 | static int wm8580_i2c_probe(struct i2c_client *i2c, | 848 | static int wm8580_i2c_probe(struct i2c_client *i2c, |
930 | const struct i2c_device_id *id) | 849 | const struct i2c_device_id *id) |
931 | { | 850 | { |
932 | struct wm8580_priv *wm8580; | 851 | struct wm8580_priv *wm8580; |
933 | struct snd_soc_codec *codec; | 852 | int ret; |
934 | 853 | ||
935 | wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); | 854 | wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); |
936 | if (wm8580 == NULL) | 855 | if (wm8580 == NULL) |
937 | return -ENOMEM; | 856 | return -ENOMEM; |
938 | 857 | ||
939 | codec = &wm8580->codec; | ||
940 | |||
941 | i2c_set_clientdata(i2c, wm8580); | 858 | i2c_set_clientdata(i2c, wm8580); |
942 | codec->control_data = i2c; | 859 | wm8580->control_type = SND_SOC_I2C; |
943 | |||
944 | codec->dev = &i2c->dev; | ||
945 | 860 | ||
946 | return wm8580_register(wm8580, SND_SOC_I2C); | 861 | ret = snd_soc_register_codec(&i2c->dev, |
862 | &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); | ||
863 | if (ret < 0) | ||
864 | kfree(wm8580); | ||
865 | return ret; | ||
947 | } | 866 | } |
948 | 867 | ||
949 | static int wm8580_i2c_remove(struct i2c_client *client) | 868 | static int wm8580_i2c_remove(struct i2c_client *client) |
950 | { | 869 | { |
951 | struct wm8580_priv *wm8580 = i2c_get_clientdata(client); | 870 | snd_soc_unregister_codec(&client->dev); |
952 | wm8580_unregister(wm8580); | 871 | kfree(i2c_get_clientdata(client)); |
953 | return 0; | 872 | return 0; |
954 | } | 873 | } |
955 | 874 | ||
@@ -961,7 +880,7 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); | |||
961 | 880 | ||
962 | static struct i2c_driver wm8580_i2c_driver = { | 881 | static struct i2c_driver wm8580_i2c_driver = { |
963 | .driver = { | 882 | .driver = { |
964 | .name = "wm8580", | 883 | .name = "wm8580-codec", |
965 | .owner = THIS_MODULE, | 884 | .owner = THIS_MODULE, |
966 | }, | 885 | }, |
967 | .probe = wm8580_i2c_probe, | 886 | .probe = wm8580_i2c_probe, |
@@ -972,7 +891,7 @@ static struct i2c_driver wm8580_i2c_driver = { | |||
972 | 891 | ||
973 | static int __init wm8580_modinit(void) | 892 | static int __init wm8580_modinit(void) |
974 | { | 893 | { |
975 | int ret; | 894 | int ret = 0; |
976 | 895 | ||
977 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 896 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
978 | ret = i2c_add_driver(&wm8580_i2c_driver); | 897 | ret = i2c_add_driver(&wm8580_i2c_driver); |
@@ -981,7 +900,7 @@ static int __init wm8580_modinit(void) | |||
981 | } | 900 | } |
982 | #endif | 901 | #endif |
983 | 902 | ||
984 | return 0; | 903 | return ret; |
985 | } | 904 | } |
986 | module_init(wm8580_modinit); | 905 | module_init(wm8580_modinit); |
987 | 906 | ||