diff options
Diffstat (limited to 'sound/soc/codecs/adav80x.c')
-rw-r--r-- | sound/soc/codecs/adav80x.c | 152 |
1 files changed, 22 insertions, 130 deletions
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index f78b27a7c461..7470831ba756 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c | |||
@@ -8,17 +8,15 @@ | |||
8 | * Licensed under the GPL-2 or later. | 8 | * Licensed under the GPL-2 or later. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | 11 | #include <linux/module.h> |
13 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
14 | #include <linux/i2c.h> | 13 | #include <linux/regmap.h> |
15 | #include <linux/spi/spi.h> | ||
16 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
17 | #include <sound/core.h> | 15 | |
18 | #include <sound/pcm.h> | 16 | #include <sound/pcm.h> |
19 | #include <sound/pcm_params.h> | 17 | #include <sound/pcm_params.h> |
20 | #include <sound/tlv.h> | ||
21 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
19 | #include <sound/tlv.h> | ||
22 | 20 | ||
23 | #include "adav80x.h" | 21 | #include "adav80x.h" |
24 | 22 | ||
@@ -541,6 +539,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, | |||
541 | unsigned int freq, int dir) | 539 | unsigned int freq, int dir) |
542 | { | 540 | { |
543 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 541 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
542 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
544 | 543 | ||
545 | if (dir == SND_SOC_CLOCK_IN) { | 544 | if (dir == SND_SOC_CLOCK_IN) { |
546 | switch (clk_id) { | 545 | switch (clk_id) { |
@@ -573,7 +572,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, | |||
573 | regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2, | 572 | regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2, |
574 | iclk_ctrl2); | 573 | iclk_ctrl2); |
575 | 574 | ||
576 | snd_soc_dapm_sync(&codec->dapm); | 575 | snd_soc_dapm_sync(dapm); |
577 | } | 576 | } |
578 | } else { | 577 | } else { |
579 | unsigned int mask; | 578 | unsigned int mask; |
@@ -600,17 +599,21 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, | |||
600 | adav80x->sysclk_pd[clk_id] = false; | 599 | adav80x->sysclk_pd[clk_id] = false; |
601 | } | 600 | } |
602 | 601 | ||
602 | snd_soc_dapm_mutex_lock(dapm); | ||
603 | |||
603 | if (adav80x->sysclk_pd[0]) | 604 | if (adav80x->sysclk_pd[0]) |
604 | snd_soc_dapm_disable_pin(&codec->dapm, "PLL1"); | 605 | snd_soc_dapm_disable_pin_unlocked(dapm, "PLL1"); |
605 | else | 606 | else |
606 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); | 607 | snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL1"); |
607 | 608 | ||
608 | if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) | 609 | if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) |
609 | snd_soc_dapm_disable_pin(&codec->dapm, "PLL2"); | 610 | snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2"); |
610 | else | 611 | else |
611 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); | 612 | snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2"); |
612 | 613 | ||
613 | snd_soc_dapm_sync(&codec->dapm); | 614 | snd_soc_dapm_sync_unlocked(dapm); |
615 | |||
616 | snd_soc_dapm_mutex_unlock(dapm); | ||
614 | } | 617 | } |
615 | 618 | ||
616 | return 0; | 619 | return 0; |
@@ -722,7 +725,7 @@ static int adav80x_dai_startup(struct snd_pcm_substream *substream, | |||
722 | struct snd_soc_codec *codec = dai->codec; | 725 | struct snd_soc_codec *codec = dai->codec; |
723 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 726 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
724 | 727 | ||
725 | if (!codec->active || !adav80x->rate) | 728 | if (!snd_soc_codec_is_active(codec) || !adav80x->rate) |
726 | return 0; | 729 | return 0; |
727 | 730 | ||
728 | return snd_pcm_hw_constraint_minmax(substream->runtime, | 731 | return snd_pcm_hw_constraint_minmax(substream->runtime, |
@@ -735,7 +738,7 @@ static void adav80x_dai_shutdown(struct snd_pcm_substream *substream, | |||
735 | struct snd_soc_codec *codec = dai->codec; | 738 | struct snd_soc_codec *codec = dai->codec; |
736 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 739 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
737 | 740 | ||
738 | if (!codec->active) | 741 | if (!snd_soc_codec_is_active(codec)) |
739 | adav80x->rate = 0; | 742 | adav80x->rate = 0; |
740 | } | 743 | } |
741 | 744 | ||
@@ -864,39 +867,26 @@ static struct snd_soc_codec_driver adav80x_codec_driver = { | |||
864 | .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), | 867 | .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), |
865 | }; | 868 | }; |
866 | 869 | ||
867 | static int adav80x_bus_probe(struct device *dev, struct regmap *regmap) | 870 | int adav80x_bus_probe(struct device *dev, struct regmap *regmap) |
868 | { | 871 | { |
869 | struct adav80x *adav80x; | 872 | struct adav80x *adav80x; |
870 | int ret; | ||
871 | 873 | ||
872 | if (IS_ERR(regmap)) | 874 | if (IS_ERR(regmap)) |
873 | return PTR_ERR(regmap); | 875 | return PTR_ERR(regmap); |
874 | 876 | ||
875 | adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL); | 877 | adav80x = devm_kzalloc(dev, sizeof(*adav80x), GFP_KERNEL); |
876 | if (!adav80x) | 878 | if (!adav80x) |
877 | return -ENOMEM; | 879 | return -ENOMEM; |
878 | 880 | ||
879 | |||
880 | dev_set_drvdata(dev, adav80x); | 881 | dev_set_drvdata(dev, adav80x); |
881 | adav80x->regmap = regmap; | 882 | adav80x->regmap = regmap; |
882 | 883 | ||
883 | ret = snd_soc_register_codec(dev, &adav80x_codec_driver, | 884 | return snd_soc_register_codec(dev, &adav80x_codec_driver, |
884 | adav80x_dais, ARRAY_SIZE(adav80x_dais)); | 885 | adav80x_dais, ARRAY_SIZE(adav80x_dais)); |
885 | if (ret) | ||
886 | kfree(adav80x); | ||
887 | |||
888 | return ret; | ||
889 | } | 886 | } |
887 | EXPORT_SYMBOL_GPL(adav80x_bus_probe); | ||
890 | 888 | ||
891 | static int adav80x_bus_remove(struct device *dev) | 889 | const struct regmap_config adav80x_regmap_config = { |
892 | { | ||
893 | snd_soc_unregister_codec(dev); | ||
894 | kfree(dev_get_drvdata(dev)); | ||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | #if defined(CONFIG_SPI_MASTER) | ||
899 | static const struct regmap_config adav80x_spi_regmap_config = { | ||
900 | .val_bits = 8, | 890 | .val_bits = 8, |
901 | .pad_bits = 1, | 891 | .pad_bits = 1, |
902 | .reg_bits = 7, | 892 | .reg_bits = 7, |
@@ -908,105 +898,7 @@ static const struct regmap_config adav80x_spi_regmap_config = { | |||
908 | .reg_defaults = adav80x_reg_defaults, | 898 | .reg_defaults = adav80x_reg_defaults, |
909 | .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), | 899 | .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), |
910 | }; | 900 | }; |
911 | 901 | EXPORT_SYMBOL_GPL(adav80x_regmap_config); | |
912 | static const struct spi_device_id adav80x_spi_id[] = { | ||
913 | { "adav801", 0 }, | ||
914 | { } | ||
915 | }; | ||
916 | MODULE_DEVICE_TABLE(spi, adav80x_spi_id); | ||
917 | |||
918 | static int adav80x_spi_probe(struct spi_device *spi) | ||
919 | { | ||
920 | return adav80x_bus_probe(&spi->dev, | ||
921 | devm_regmap_init_spi(spi, &adav80x_spi_regmap_config)); | ||
922 | } | ||
923 | |||
924 | static int adav80x_spi_remove(struct spi_device *spi) | ||
925 | { | ||
926 | return adav80x_bus_remove(&spi->dev); | ||
927 | } | ||
928 | |||
929 | static struct spi_driver adav80x_spi_driver = { | ||
930 | .driver = { | ||
931 | .name = "adav801", | ||
932 | .owner = THIS_MODULE, | ||
933 | }, | ||
934 | .probe = adav80x_spi_probe, | ||
935 | .remove = adav80x_spi_remove, | ||
936 | .id_table = adav80x_spi_id, | ||
937 | }; | ||
938 | #endif | ||
939 | |||
940 | #if IS_ENABLED(CONFIG_I2C) | ||
941 | static const struct regmap_config adav80x_i2c_regmap_config = { | ||
942 | .val_bits = 8, | ||
943 | .pad_bits = 1, | ||
944 | .reg_bits = 7, | ||
945 | |||
946 | .max_register = ADAV80X_PLL_OUTE, | ||
947 | |||
948 | .cache_type = REGCACHE_RBTREE, | ||
949 | .reg_defaults = adav80x_reg_defaults, | ||
950 | .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), | ||
951 | }; | ||
952 | |||
953 | static const struct i2c_device_id adav80x_i2c_id[] = { | ||
954 | { "adav803", 0 }, | ||
955 | { } | ||
956 | }; | ||
957 | MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id); | ||
958 | |||
959 | static int adav80x_i2c_probe(struct i2c_client *client, | ||
960 | const struct i2c_device_id *id) | ||
961 | { | ||
962 | return adav80x_bus_probe(&client->dev, | ||
963 | devm_regmap_init_i2c(client, &adav80x_i2c_regmap_config)); | ||
964 | } | ||
965 | |||
966 | static int adav80x_i2c_remove(struct i2c_client *client) | ||
967 | { | ||
968 | return adav80x_bus_remove(&client->dev); | ||
969 | } | ||
970 | |||
971 | static struct i2c_driver adav80x_i2c_driver = { | ||
972 | .driver = { | ||
973 | .name = "adav803", | ||
974 | .owner = THIS_MODULE, | ||
975 | }, | ||
976 | .probe = adav80x_i2c_probe, | ||
977 | .remove = adav80x_i2c_remove, | ||
978 | .id_table = adav80x_i2c_id, | ||
979 | }; | ||
980 | #endif | ||
981 | |||
982 | static int __init adav80x_init(void) | ||
983 | { | ||
984 | int ret = 0; | ||
985 | |||
986 | #if IS_ENABLED(CONFIG_I2C) | ||
987 | ret = i2c_add_driver(&adav80x_i2c_driver); | ||
988 | if (ret) | ||
989 | return ret; | ||
990 | #endif | ||
991 | |||
992 | #if defined(CONFIG_SPI_MASTER) | ||
993 | ret = spi_register_driver(&adav80x_spi_driver); | ||
994 | #endif | ||
995 | |||
996 | return ret; | ||
997 | } | ||
998 | module_init(adav80x_init); | ||
999 | |||
1000 | static void __exit adav80x_exit(void) | ||
1001 | { | ||
1002 | #if IS_ENABLED(CONFIG_I2C) | ||
1003 | i2c_del_driver(&adav80x_i2c_driver); | ||
1004 | #endif | ||
1005 | #if defined(CONFIG_SPI_MASTER) | ||
1006 | spi_unregister_driver(&adav80x_spi_driver); | ||
1007 | #endif | ||
1008 | } | ||
1009 | module_exit(adav80x_exit); | ||
1010 | 902 | ||
1011 | MODULE_DESCRIPTION("ASoC ADAV80x driver"); | 903 | MODULE_DESCRIPTION("ASoC ADAV80x driver"); |
1012 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 904 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |