aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/alc5623.c
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2014-03-23 10:00:41 -0400
committerMark Brown <broonie@linaro.org>2014-03-23 10:00:41 -0400
commitd66fa86956149a211db3d7ae9e9f2536b65ccde4 (patch)
tree013c71ec06c6d9710a183854ce1a0fe33530a0db /sound/soc/codecs/alc5623.c
parentebec909345bbb1e2d06cd0d94f65664edcc0f208 (diff)
parentdeeed33850c8a376addabbf971df433b2a1ba74c (diff)
Merge tag 'asoc-v3.15' into asoc-next
ASoC: Updates for v3.15 Quite a busy release for ASoC this time, more on janitorial work than exciting new features but welcome nontheless: - Lots of cleanups from Takashi for enumerations; the original API for these was error prone so he's refactored lots of code to use more modern APIs which avoid issues. - Elimination of the ASoC level wrappers for I2C and SPI moving us closer to converting to regmap completely and avoiding some randconfig hassle. - Provide both manually and transparently locked DAPM APIs rather than a mix of the two fixing some concurrency issues. - Start converting CODEC drivers to use separate bus interface drivers rather than having them all in one file helping avoid dependency issues. - DPCM support for Intel Haswell and Bay Trail platforms. - Lots of work on improvements for simple-card, DaVinci and the Renesas rcar drivers. - New drivers for Analog Devices ADAU1977, TI PCM512x and parts of the CSR SiRF SoC. # gpg: Signature made Wed 12 Mar 2014 23:05:45 GMT using RSA key ID 7EA229BD # gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>" # gpg: aka "Mark Brown <broonie@debian.org>" # gpg: aka "Mark Brown <broonie@kernel.org>" # gpg: aka "Mark Brown <broonie@tardis.ed.ac.uk>" # gpg: aka "Mark Brown <broonie@linaro.org>" # gpg: aka "Mark Brown <Mark.Brown@linaro.org>"
Diffstat (limited to 'sound/soc/codecs/alc5623.c')
-rw-r--r--sound/soc/codecs/alc5623.c117
1 files changed, 67 insertions, 50 deletions
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index d3036283482a..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);
@@ -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,14 @@ 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); 907 codec->control_data = alc5623->regmap;
908 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
904 if (ret < 0) { 909 if (ret < 0) {
905 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);
906 return ret; 911 return ret;
907 } 912 }
908 913
909 alc5623_reset(codec); 914 alc5623_reset(codec);
910 alc5623_fill_cache(codec);
911 915
912 /* power on device */ 916 /* power on device */
913 alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 917 alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -980,9 +984,15 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
980 .suspend = alc5623_suspend, 984 .suspend = alc5623_suspend,
981 .resume = alc5623_resume, 985 .resume = alc5623_resume,
982 .set_bias_level = alc5623_set_bias_level, 986 .set_bias_level = alc5623_set_bias_level,
983 .reg_cache_size = ALC5623_VENDOR_ID2+2, 987};
984 .reg_word_size = sizeof(u16), 988
985 .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,
986}; 996};
987 997
988/* 998/*
@@ -996,19 +1006,32 @@ static int alc5623_i2c_probe(struct i2c_client *client,
996{ 1006{
997 struct alc5623_platform_data *pdata; 1007 struct alc5623_platform_data *pdata;
998 struct alc5623_priv *alc5623; 1008 struct alc5623_priv *alc5623;
999 int ret, vid1, vid2; 1009 unsigned int vid1, vid2;
1010 int ret;
1000 1011
1001 vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1); 1012 alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
1002 if (vid1 < 0) { 1013 GFP_KERNEL);
1003 dev_err(&client->dev, "failed to read I2C\n"); 1014 if (alc5623 == NULL)
1004 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;
1005 } 1028 }
1006 vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8); 1029 vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8);
1007 1030
1008 vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2); 1031 ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2);
1009 if (vid2 < 0) { 1032 if (ret < 0) {
1010 dev_err(&client->dev, "failed to read I2C\n"); 1033 dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret);
1011 return -EIO; 1034 return ret;
1012 } 1035 }
1013 1036
1014 if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) { 1037 if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) {
@@ -1021,11 +1044,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
1021 1044
1022 dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2); 1045 dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2);
1023 1046
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; 1047 pdata = client->dev.platform_data;
1030 if (pdata) { 1048 if (pdata) {
1031 alc5623->add_ctrl = pdata->add_ctrl; 1049 alc5623->add_ctrl = pdata->add_ctrl;
@@ -1048,7 +1066,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
1048 } 1066 }
1049 1067
1050 i2c_set_clientdata(client, alc5623); 1068 i2c_set_clientdata(client, alc5623);
1051 alc5623->control_type = SND_SOC_I2C;
1052 1069
1053 ret = snd_soc_register_codec(&client->dev, 1070 ret = snd_soc_register_codec(&client->dev,
1054 &soc_codec_device_alc5623, &alc5623_dai, 1); 1071 &soc_codec_device_alc5623, &alc5623_dai, 1);