aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/alc5623.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/alc5623.c')
-rw-r--r--sound/soc/codecs/alc5623.c120
1 files changed, 65 insertions, 55 deletions
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index d3036283482a..09f7e773bafb 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);
@@ -228,32 +216,37 @@ static const char *alc5623_aux_out_input_sel[] = {
228 "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"}; 216 "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
229 217
230/* auxout output mux */ 218/* auxout output mux */
231static const struct soc_enum alc5623_aux_out_input_enum = 219static SOC_ENUM_SINGLE_DECL(alc5623_aux_out_input_enum,
232SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 6, 4, alc5623_aux_out_input_sel); 220 ALC5623_OUTPUT_MIXER_CTRL, 6,
221 alc5623_aux_out_input_sel);
233static const struct snd_kcontrol_new alc5623_auxout_mux_controls = 222static const struct snd_kcontrol_new alc5623_auxout_mux_controls =
234SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum); 223SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum);
235 224
236/* speaker output mux */ 225/* speaker output mux */
237static const struct soc_enum alc5623_spkout_input_enum = 226static SOC_ENUM_SINGLE_DECL(alc5623_spkout_input_enum,
238SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 10, 4, alc5623_spkout_input_sel); 227 ALC5623_OUTPUT_MIXER_CTRL, 10,
228 alc5623_spkout_input_sel);
239static const struct snd_kcontrol_new alc5623_spkout_mux_controls = 229static const struct snd_kcontrol_new alc5623_spkout_mux_controls =
240SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum); 230SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum);
241 231
242/* headphone left output mux */ 232/* headphone left output mux */
243static const struct soc_enum alc5623_hpl_out_input_enum = 233static SOC_ENUM_SINGLE_DECL(alc5623_hpl_out_input_enum,
244SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 9, 2, alc5623_hpl_out_input_sel); 234 ALC5623_OUTPUT_MIXER_CTRL, 9,
235 alc5623_hpl_out_input_sel);
245static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls = 236static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls =
246SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum); 237SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum);
247 238
248/* headphone right output mux */ 239/* headphone right output mux */
249static const struct soc_enum alc5623_hpr_out_input_enum = 240static SOC_ENUM_SINGLE_DECL(alc5623_hpr_out_input_enum,
250SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 8, 2, alc5623_hpr_out_input_sel); 241 ALC5623_OUTPUT_MIXER_CTRL, 8,
242 alc5623_hpr_out_input_sel);
251static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls = 243static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls =
252SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum); 244SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum);
253 245
254/* speaker output N select */ 246/* speaker output N select */
255static const struct soc_enum alc5623_spk_n_sour_enum = 247static SOC_ENUM_SINGLE_DECL(alc5623_spk_n_sour_enum,
256SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 14, 4, alc5623_spk_n_sour_sel); 248 ALC5623_OUTPUT_MIXER_CTRL, 14,
249 alc5623_spk_n_sour_sel);
257static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls = 250static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls =
258SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum); 251SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum);
259 252
@@ -338,8 +331,9 @@ SND_SOC_DAPM_VMID("Vmid"),
338}; 331};
339 332
340static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"}; 333static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"};
341static const struct soc_enum alc5623_amp_enum = 334static SOC_ENUM_SINGLE_DECL(alc5623_amp_enum,
342 SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 13, 2, alc5623_amp_names); 335 ALC5623_OUTPUT_MIXER_CTRL, 13,
336 alc5623_amp_names);
343static const struct snd_kcontrol_new alc5623_amp_mux_controls = 337static const struct snd_kcontrol_new alc5623_amp_mux_controls =
344 SOC_DAPM_ENUM("Route", alc5623_amp_enum); 338 SOC_DAPM_ENUM("Route", alc5623_amp_enum);
345 339
@@ -869,18 +863,28 @@ static struct snd_soc_dai_driver alc5623_dai = {
869 863
870static int alc5623_suspend(struct snd_soc_codec *codec) 864static int alc5623_suspend(struct snd_soc_codec *codec)
871{ 865{
866 struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
867
872 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
873 return 0; 871 return 0;
874} 872}
875 873
876static int alc5623_resume(struct snd_soc_codec *codec) 874static int alc5623_resume(struct snd_soc_codec *codec)
877{ 875{
878 int i, step = codec->driver->reg_cache_step; 876 struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
879 u16 *cache = codec->reg_cache; 877 int ret;
880 878
881 /* Sync reg_cache with the hardware */ 879 /* Sync reg_cache with the hardware */
882 for (i = 2 ; i < codec->driver->reg_cache_size ; i += step) 880 regcache_cache_only(alc5623->regmap, false);
883 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 }
884 888
885 alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 889 alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
886 890
@@ -900,14 +904,7 @@ static int alc5623_probe(struct snd_soc_codec *codec)
900 struct snd_soc_dapm_context *dapm = &codec->dapm; 904 struct snd_soc_dapm_context *dapm = &codec->dapm;
901 int ret; 905 int ret;
902 906
903 ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type);
904 if (ret < 0) {
905 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
906 return ret;
907 }
908
909 alc5623_reset(codec); 907 alc5623_reset(codec);
910 alc5623_fill_cache(codec);
911 908
912 /* power on device */ 909 /* power on device */
913 alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 910 alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -980,9 +977,15 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
980 .suspend = alc5623_suspend, 977 .suspend = alc5623_suspend,
981 .resume = alc5623_resume, 978 .resume = alc5623_resume,
982 .set_bias_level = alc5623_set_bias_level, 979 .set_bias_level = alc5623_set_bias_level,
983 .reg_cache_size = ALC5623_VENDOR_ID2+2, 980};
984 .reg_word_size = sizeof(u16), 981
985 .reg_cache_step = 2, 982static const struct regmap_config alc5623_regmap = {
983 .reg_bits = 8,
984 .val_bits = 16,
985 .reg_stride = 2,
986
987 .max_register = ALC5623_VENDOR_ID2,
988 .cache_type = REGCACHE_RBTREE,
986}; 989};
987 990
988/* 991/*
@@ -996,19 +999,32 @@ static int alc5623_i2c_probe(struct i2c_client *client,
996{ 999{
997 struct alc5623_platform_data *pdata; 1000 struct alc5623_platform_data *pdata;
998 struct alc5623_priv *alc5623; 1001 struct alc5623_priv *alc5623;
999 int ret, vid1, vid2; 1002 unsigned int vid1, vid2;
1003 int ret;
1000 1004
1001 vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1); 1005 alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
1002 if (vid1 < 0) { 1006 GFP_KERNEL);
1003 dev_err(&client->dev, "failed to read I2C\n"); 1007 if (alc5623 == NULL)
1004 return -EIO; 1008 return -ENOMEM;
1009
1010 alc5623->regmap = devm_regmap_init_i2c(client, &alc5623_regmap);
1011 if (IS_ERR(alc5623->regmap)) {
1012 ret = PTR_ERR(alc5623->regmap);
1013 dev_err(&client->dev, "Failed to initialise I/O: %d\n", ret);
1014 return ret;
1015 }
1016
1017 ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID1, &vid1);
1018 if (ret < 0) {
1019 dev_err(&client->dev, "failed to read vendor ID1: %d\n", ret);
1020 return ret;
1005 } 1021 }
1006 vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8); 1022 vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8);
1007 1023
1008 vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2); 1024 ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2);
1009 if (vid2 < 0) { 1025 if (ret < 0) {
1010 dev_err(&client->dev, "failed to read I2C\n"); 1026 dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret);
1011 return -EIO; 1027 return ret;
1012 } 1028 }
1013 1029
1014 if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) { 1030 if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) {
@@ -1021,11 +1037,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
1021 1037
1022 dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2); 1038 dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2);
1023 1039
1024 alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
1025 GFP_KERNEL);
1026 if (alc5623 == NULL)
1027 return -ENOMEM;
1028
1029 pdata = client->dev.platform_data; 1040 pdata = client->dev.platform_data;
1030 if (pdata) { 1041 if (pdata) {
1031 alc5623->add_ctrl = pdata->add_ctrl; 1042 alc5623->add_ctrl = pdata->add_ctrl;
@@ -1048,7 +1059,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
1048 } 1059 }
1049 1060
1050 i2c_set_clientdata(client, alc5623); 1061 i2c_set_clientdata(client, alc5623);
1051 alc5623->control_type = SND_SOC_I2C;
1052 1062
1053 ret = snd_soc_register_codec(&client->dev, 1063 ret = snd_soc_register_codec(&client->dev,
1054 &soc_codec_device_alc5623, &alc5623_dai, 1); 1064 &soc_codec_device_alc5623, &alc5623_dai, 1);