aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2014-02-19 19:04:06 -0500
committerMark Brown <broonie@linaro.org>2014-02-22 21:53:17 -0500
commit0cd257bf9b9b0cbb4fa1a5c988a232506997867c (patch)
treed562e422de552d4717163d6fe8b5251116fb37f4
parente84f2463765ff34a322511be815ad235dcc1f218 (diff)
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>
-rw-r--r--sound/soc/codecs/alc5623.c87
1 files changed, 49 insertions, 38 deletions
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index ba61c07ebbb2..ed506253a914 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -21,6 +21,7 @@
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/pm.h> 22#include <linux/pm.h>
23#include <linux/i2c.h> 23#include <linux/i2c.h>
24#include <linux/regmap.h>
24#include <linux/slab.h> 25#include <linux/slab.h>
25#include <sound/core.h> 26#include <sound/core.h>
26#include <sound/pcm.h> 27#include <sound/pcm.h>
@@ -38,26 +39,13 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)");
38 39
39/* codec private data */ 40/* codec private data */
40struct alc5623_priv { 41struct alc5623_priv {
41 enum snd_soc_control_type control_type; 42 struct regmap *regmap;
42 u8 id; 43 u8 id;
43 unsigned int sysclk; 44 unsigned int sysclk;
44 u16 reg_cache[ALC5623_VENDOR_ID2+2];
45 unsigned int add_ctrl; 45 unsigned int add_ctrl;
46 unsigned int jack_det_ctrl; 46 unsigned int jack_det_ctrl;
47}; 47};
48 48
49static 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
61static inline int alc5623_reset(struct snd_soc_codec *codec) 49static inline int alc5623_reset(struct snd_soc_codec *codec)
62{ 50{
63 return snd_soc_write(codec, ALC5623_RESET, 0); 51 return snd_soc_write(codec, ALC5623_RESET, 0);
@@ -875,18 +863,28 @@ static struct snd_soc_dai_driver alc5623_dai = {
875 863
876static int alc5623_suspend(struct snd_soc_codec *codec) 864static int alc5623_suspend(struct snd_soc_codec *codec)
877{ 865{
866 struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
867
878 alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); 868 alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF);
869 regcache_cache_only(alc5623->regmap, true);
870
879 return 0; 871 return 0;
880} 872}
881 873
882static int alc5623_resume(struct snd_soc_codec *codec) 874static int alc5623_resume(struct snd_soc_codec *codec)
883{ 875{
884 int i, step = codec->driver->reg_cache_step; 876 struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
885 u16 *cache = codec->reg_cache; 877 int ret;
886 878
887 /* Sync reg_cache with the hardware */ 879 /* Sync reg_cache with the hardware */
888 for (i = 2 ; i < codec->driver->reg_cache_size ; i += step) 880 regcache_cache_only(alc5623->regmap, false);
889 snd_soc_write(codec, i, cache[i]); 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 alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 889 alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
892 890
@@ -906,14 +904,14 @@ static int alc5623_probe(struct snd_soc_codec *codec)
906 struct snd_soc_dapm_context *dapm = &codec->dapm; 904 struct snd_soc_dapm_context *dapm = &codec->dapm;
907 int ret; 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 if (ret < 0) { 909 if (ret < 0) {
911 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 910 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
912 return ret; 911 return ret;
913 } 912 }
914 913
915 alc5623_reset(codec); 914 alc5623_reset(codec);
916 alc5623_fill_cache(codec);
917 915
918 /* power on device */ 916 /* power on device */
919 alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 917 alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -986,9 +984,15 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
986 .suspend = alc5623_suspend, 984 .suspend = alc5623_suspend,
987 .resume = alc5623_resume, 985 .resume = alc5623_resume,
988 .set_bias_level = alc5623_set_bias_level, 986 .set_bias_level = alc5623_set_bias_level,
989 .reg_cache_size = ALC5623_VENDOR_ID2+2, 987};
990 .reg_word_size = sizeof(u16), 988
991 .reg_cache_step = 2, 989static 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,
992}; 996};
993 997
994/* 998/*
@@ -1002,19 +1006,32 @@ static int alc5623_i2c_probe(struct i2c_client *client,
1002{ 1006{
1003 struct alc5623_platform_data *pdata; 1007 struct alc5623_platform_data *pdata;
1004 struct alc5623_priv *alc5623; 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); 1012 alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
1008 if (vid1 < 0) { 1013 GFP_KERNEL);
1009 dev_err(&client->dev, "failed to read I2C\n"); 1014 if (alc5623 == NULL)
1010 return -EIO; 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;
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;
1011 } 1028 }
1012 vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8); 1029 vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8);
1013 1030
1014 vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2); 1031 ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2);
1015 if (vid2 < 0) { 1032 if (ret < 0) {
1016 dev_err(&client->dev, "failed to read I2C\n"); 1033 dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret);
1017 return -EIO; 1034 return ret;
1018 } 1035 }
1019 1036
1020 if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) { 1037 if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) {
@@ -1027,11 +1044,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
1027 1044
1028 dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2); 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 pdata = client->dev.platform_data; 1047 pdata = client->dev.platform_data;
1036 if (pdata) { 1048 if (pdata) {
1037 alc5623->add_ctrl = pdata->add_ctrl; 1049 alc5623->add_ctrl = pdata->add_ctrl;
@@ -1054,7 +1066,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
1054 } 1066 }
1055 1067
1056 i2c_set_clientdata(client, alc5623); 1068 i2c_set_clientdata(client, alc5623);
1057 alc5623->control_type = SND_SOC_I2C;
1058 1069
1059 ret = snd_soc_register_codec(&client->dev, 1070 ret = snd_soc_register_codec(&client->dev,
1060 &soc_codec_device_alc5623, &alc5623_dai, 1); 1071 &soc_codec_device_alc5623, &alc5623_dai, 1);