Commit 0cd257bf9b9b0cbb4fa1a5c988a232506997867c
1 parent
e84f246376
Exists in
master
and in
13 other branches
ASoC: alc5623: Convert to direct regmap API usage
Convert to directly use the regmap API, allowing us to eliminate the last user of the ASoC level I/O implementations (there are still open coded I/O implementations in drivers), avoiding duplicating code in regmap. We no longer cache the entire CODEC register map on probe since the more advanced cache infrastructure in regmap is able to fill the cache on demand. Signed-off-by: Mark Brown <broonie@linaro.org>
Showing 1 changed file with 49 additions and 38 deletions Side-by-side Diff
sound/soc/codecs/alc5623.c
... | ... | @@ -21,6 +21,7 @@ |
21 | 21 | #include <linux/delay.h> |
22 | 22 | #include <linux/pm.h> |
23 | 23 | #include <linux/i2c.h> |
24 | +#include <linux/regmap.h> | |
24 | 25 | #include <linux/slab.h> |
25 | 26 | #include <sound/core.h> |
26 | 27 | #include <sound/pcm.h> |
27 | 28 | |
28 | 29 | |
... | ... | @@ -38,26 +39,13 @@ |
38 | 39 | |
39 | 40 | /* codec private data */ |
40 | 41 | struct alc5623_priv { |
41 | - enum snd_soc_control_type control_type; | |
42 | + struct regmap *regmap; | |
42 | 43 | u8 id; |
43 | 44 | unsigned int sysclk; |
44 | - u16 reg_cache[ALC5623_VENDOR_ID2+2]; | |
45 | 45 | unsigned int add_ctrl; |
46 | 46 | unsigned int jack_det_ctrl; |
47 | 47 | }; |
48 | 48 | |
49 | -static void alc5623_fill_cache(struct snd_soc_codec *codec) | |
50 | -{ | |
51 | - int i, step = codec->driver->reg_cache_step; | |
52 | - u16 *cache = codec->reg_cache; | |
53 | - | |
54 | - /* not really efficient ... */ | |
55 | - codec->cache_bypass = 1; | |
56 | - for (i = 0 ; i < codec->driver->reg_cache_size ; i += step) | |
57 | - cache[i] = snd_soc_read(codec, i); | |
58 | - codec->cache_bypass = 0; | |
59 | -} | |
60 | - | |
61 | 49 | static inline int alc5623_reset(struct snd_soc_codec *codec) |
62 | 50 | { |
63 | 51 | return snd_soc_write(codec, ALC5623_RESET, 0); |
64 | 52 | |
65 | 53 | |
66 | 54 | |
... | ... | @@ -875,18 +863,28 @@ |
875 | 863 | |
876 | 864 | static int alc5623_suspend(struct snd_soc_codec *codec) |
877 | 865 | { |
866 | + struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); | |
867 | + | |
878 | 868 | alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); |
869 | + regcache_cache_only(alc5623->regmap, true); | |
870 | + | |
879 | 871 | return 0; |
880 | 872 | } |
881 | 873 | |
882 | 874 | static int alc5623_resume(struct snd_soc_codec *codec) |
883 | 875 | { |
884 | - int i, step = codec->driver->reg_cache_step; | |
885 | - u16 *cache = codec->reg_cache; | |
876 | + struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); | |
877 | + int ret; | |
886 | 878 | |
887 | 879 | /* Sync reg_cache with the hardware */ |
888 | - for (i = 2 ; i < codec->driver->reg_cache_size ; i += step) | |
889 | - snd_soc_write(codec, i, cache[i]); | |
880 | + regcache_cache_only(alc5623->regmap, false); | |
881 | + ret = regcache_sync(alc5623->regmap); | |
882 | + if (ret != 0) { | |
883 | + dev_err(codec->dev, "Failed to sync register cache: %d\n", | |
884 | + ret); | |
885 | + regcache_cache_only(alc5623->regmap, true); | |
886 | + return ret; | |
887 | + } | |
890 | 888 | |
891 | 889 | alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
892 | 890 | |
893 | 891 | |
... | ... | @@ -906,14 +904,14 @@ |
906 | 904 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
907 | 905 | int ret; |
908 | 906 | |
909 | - ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type); | |
907 | + codec->control_data = alc5623->regmap; | |
908 | + ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | |
910 | 909 | if (ret < 0) { |
911 | 910 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
912 | 911 | return ret; |
913 | 912 | } |
914 | 913 | |
915 | 914 | alc5623_reset(codec); |
916 | - alc5623_fill_cache(codec); | |
917 | 915 | |
918 | 916 | /* power on device */ |
919 | 917 | alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
920 | 918 | |
... | ... | @@ -986,11 +984,17 @@ |
986 | 984 | .suspend = alc5623_suspend, |
987 | 985 | .resume = alc5623_resume, |
988 | 986 | .set_bias_level = alc5623_set_bias_level, |
989 | - .reg_cache_size = ALC5623_VENDOR_ID2+2, | |
990 | - .reg_word_size = sizeof(u16), | |
991 | - .reg_cache_step = 2, | |
992 | 987 | }; |
993 | 988 | |
989 | +static const struct regmap_config alc5623_regmap = { | |
990 | + .reg_bits = 8, | |
991 | + .val_bits = 16, | |
992 | + .reg_stride = 2, | |
993 | + | |
994 | + .max_register = ALC5623_VENDOR_ID2, | |
995 | + .cache_type = REGCACHE_RBTREE, | |
996 | +}; | |
997 | + | |
994 | 998 | /* |
995 | 999 | * ALC5623 2 wire address is determined by A1 pin |
996 | 1000 | * state during powerup. |
997 | 1001 | |
998 | 1002 | |
999 | 1003 | |
... | ... | @@ -1002,19 +1006,32 @@ |
1002 | 1006 | { |
1003 | 1007 | struct alc5623_platform_data *pdata; |
1004 | 1008 | struct alc5623_priv *alc5623; |
1005 | - int ret, vid1, vid2; | |
1009 | + unsigned int vid1, vid2; | |
1010 | + int ret; | |
1006 | 1011 | |
1007 | - vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1); | |
1008 | - if (vid1 < 0) { | |
1009 | - dev_err(&client->dev, "failed to read I2C\n"); | |
1010 | - return -EIO; | |
1012 | + alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv), | |
1013 | + GFP_KERNEL); | |
1014 | + if (alc5623 == NULL) | |
1015 | + return -ENOMEM; | |
1016 | + | |
1017 | + alc5623->regmap = devm_regmap_init_i2c(client, &alc5623_regmap); | |
1018 | + if (IS_ERR(alc5623->regmap)) { | |
1019 | + ret = PTR_ERR(alc5623->regmap); | |
1020 | + dev_err(&client->dev, "Failed to initialise I/O: %d\n", ret); | |
1021 | + return ret; | |
1011 | 1022 | } |
1023 | + | |
1024 | + ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID1, &vid1); | |
1025 | + if (ret < 0) { | |
1026 | + dev_err(&client->dev, "failed to read vendor ID1: %d\n", ret); | |
1027 | + return ret; | |
1028 | + } | |
1012 | 1029 | vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8); |
1013 | 1030 | |
1014 | - vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2); | |
1015 | - if (vid2 < 0) { | |
1016 | - dev_err(&client->dev, "failed to read I2C\n"); | |
1017 | - return -EIO; | |
1031 | + ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2); | |
1032 | + if (ret < 0) { | |
1033 | + dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret); | |
1034 | + return ret; | |
1018 | 1035 | } |
1019 | 1036 | |
1020 | 1037 | if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) { |
... | ... | @@ -1027,11 +1044,6 @@ |
1027 | 1044 | |
1028 | 1045 | dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2); |
1029 | 1046 | |
1030 | - alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv), | |
1031 | - GFP_KERNEL); | |
1032 | - if (alc5623 == NULL) | |
1033 | - return -ENOMEM; | |
1034 | - | |
1035 | 1047 | pdata = client->dev.platform_data; |
1036 | 1048 | if (pdata) { |
1037 | 1049 | alc5623->add_ctrl = pdata->add_ctrl; |
... | ... | @@ -1054,7 +1066,6 @@ |
1054 | 1066 | } |
1055 | 1067 | |
1056 | 1068 | i2c_set_clientdata(client, alc5623); |
1057 | - alc5623->control_type = SND_SOC_I2C; | |
1058 | 1069 | |
1059 | 1070 | ret = snd_soc_register_codec(&client->dev, |
1060 | 1071 | &soc_codec_device_alc5623, &alc5623_dai, 1); |