diff options
Diffstat (limited to 'sound/soc/codecs')
28 files changed, 1729 insertions, 328 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 45b72561c615..2f45f00e31b0 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -26,6 +26,7 @@ config SND_SOC_ALL_CODECS | |||
26 | select SND_SOC_AK4641 if I2C | 26 | select SND_SOC_AK4641 if I2C |
27 | select SND_SOC_AK4642 if I2C | 27 | select SND_SOC_AK4642 if I2C |
28 | select SND_SOC_AK4671 if I2C | 28 | select SND_SOC_AK4671 if I2C |
29 | select SND_SOC_AK5386 | ||
29 | select SND_SOC_ALC5623 if I2C | 30 | select SND_SOC_ALC5623 if I2C |
30 | select SND_SOC_ALC5632 if I2C | 31 | select SND_SOC_ALC5632 if I2C |
31 | select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC | 32 | select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC |
@@ -63,6 +64,7 @@ config SND_SOC_ALL_CODECS | |||
63 | select SND_SOC_STA32X if I2C | 64 | select SND_SOC_STA32X if I2C |
64 | select SND_SOC_STA529 if I2C | 65 | select SND_SOC_STA529 if I2C |
65 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS | 66 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS |
67 | select SND_SOC_TAS5086 if I2C | ||
66 | select SND_SOC_TLV320AIC23 if I2C | 68 | select SND_SOC_TLV320AIC23 if I2C |
67 | select SND_SOC_TLV320AIC26 if SPI_MASTER | 69 | select SND_SOC_TLV320AIC26 if SPI_MASTER |
68 | select SND_SOC_TLV320AIC32X4 if I2C | 70 | select SND_SOC_TLV320AIC32X4 if I2C |
@@ -203,6 +205,9 @@ config SND_SOC_AK4642 | |||
203 | config SND_SOC_AK4671 | 205 | config SND_SOC_AK4671 |
204 | tristate | 206 | tristate |
205 | 207 | ||
208 | config SND_SOC_AK5386 | ||
209 | tristate | ||
210 | |||
206 | config SND_SOC_ALC5623 | 211 | config SND_SOC_ALC5623 |
207 | tristate | 212 | tristate |
208 | config SND_SOC_ALC5632 | 213 | config SND_SOC_ALC5632 |
@@ -320,11 +325,14 @@ config SND_SOC_STA529 | |||
320 | config SND_SOC_STAC9766 | 325 | config SND_SOC_STAC9766 |
321 | tristate | 326 | tristate |
322 | 327 | ||
328 | config SND_SOC_TAS5086 | ||
329 | tristate | ||
330 | |||
323 | config SND_SOC_TLV320AIC23 | 331 | config SND_SOC_TLV320AIC23 |
324 | tristate | 332 | tristate |
325 | 333 | ||
326 | config SND_SOC_TLV320AIC26 | 334 | config SND_SOC_TLV320AIC26 |
327 | tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE | 335 | tristate |
328 | depends on SPI | 336 | depends on SPI |
329 | 337 | ||
330 | config SND_SOC_TLV320AIC32X4 | 338 | config SND_SOC_TLV320AIC32X4 |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 6a3b3c3b8b41..b9e41c9a1f4c 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -14,6 +14,7 @@ snd-soc-ak4535-objs := ak4535.o | |||
14 | snd-soc-ak4641-objs := ak4641.o | 14 | snd-soc-ak4641-objs := ak4641.o |
15 | snd-soc-ak4642-objs := ak4642.o | 15 | snd-soc-ak4642-objs := ak4642.o |
16 | snd-soc-ak4671-objs := ak4671.o | 16 | snd-soc-ak4671-objs := ak4671.o |
17 | snd-soc-ak5386-objs := ak5386.o | ||
17 | snd-soc-arizona-objs := arizona.o | 18 | snd-soc-arizona-objs := arizona.o |
18 | snd-soc-cq93vc-objs := cq93vc.o | 19 | snd-soc-cq93vc-objs := cq93vc.o |
19 | snd-soc-cs42l51-objs := cs42l51.o | 20 | snd-soc-cs42l51-objs := cs42l51.o |
@@ -55,6 +56,7 @@ snd-soc-ssm2602-objs := ssm2602.o | |||
55 | snd-soc-sta32x-objs := sta32x.o | 56 | snd-soc-sta32x-objs := sta32x.o |
56 | snd-soc-sta529-objs := sta529.o | 57 | snd-soc-sta529-objs := sta529.o |
57 | snd-soc-stac9766-objs := stac9766.o | 58 | snd-soc-stac9766-objs := stac9766.o |
59 | snd-soc-tas5086-objs := tas5086.o | ||
58 | snd-soc-tlv320aic23-objs := tlv320aic23.o | 60 | snd-soc-tlv320aic23-objs := tlv320aic23.o |
59 | snd-soc-tlv320aic26-objs := tlv320aic26.o | 61 | snd-soc-tlv320aic26-objs := tlv320aic26.o |
60 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o | 62 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o |
@@ -137,6 +139,7 @@ obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o | |||
137 | obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o | 139 | obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o |
138 | obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o | 140 | obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o |
139 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o | 141 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o |
142 | obj-$(CONFIG_SND_SOC_AK5386) += snd-soc-ak5386.o | ||
140 | obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o | 143 | obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o |
141 | obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o | 144 | obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o |
142 | obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o | 145 | obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o |
@@ -177,6 +180,7 @@ obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o | |||
177 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o | 180 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o |
178 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o | 181 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o |
179 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o | 182 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o |
183 | obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o | ||
180 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o | 184 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o |
181 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o | 185 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o |
182 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o | 186 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o |
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 068b3ae56a17..1aa10ddf3a61 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c | |||
@@ -133,6 +133,8 @@ struct adau1373 { | |||
133 | #define ADAU1373_DAI_FORMAT_DSP 0x3 | 133 | #define ADAU1373_DAI_FORMAT_DSP 0x3 |
134 | 134 | ||
135 | #define ADAU1373_BCLKDIV_SOURCE BIT(5) | 135 | #define ADAU1373_BCLKDIV_SOURCE BIT(5) |
136 | #define ADAU1373_BCLKDIV_SR_MASK (0x07 << 2) | ||
137 | #define ADAU1373_BCLKDIV_BCLK_MASK 0x03 | ||
136 | #define ADAU1373_BCLKDIV_32 0x03 | 138 | #define ADAU1373_BCLKDIV_32 0x03 |
137 | #define ADAU1373_BCLKDIV_64 0x02 | 139 | #define ADAU1373_BCLKDIV_64 0x02 |
138 | #define ADAU1373_BCLKDIV_128 0x01 | 140 | #define ADAU1373_BCLKDIV_128 0x01 |
@@ -937,7 +939,8 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream, | |||
937 | adau1373_dai->enable_src = (div != 0); | 939 | adau1373_dai->enable_src = (div != 0); |
938 | 940 | ||
939 | snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id), | 941 | snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id), |
940 | ~ADAU1373_BCLKDIV_SOURCE, (div << 2) | ADAU1373_BCLKDIV_64); | 942 | ADAU1373_BCLKDIV_SR_MASK | ADAU1373_BCLKDIV_BCLK_MASK, |
943 | (div << 2) | ADAU1373_BCLKDIV_64); | ||
941 | 944 | ||
942 | switch (params_format(params)) { | 945 | switch (params_format(params)) { |
943 | case SNDRV_PCM_FORMAT_S16_LE: | 946 | case SNDRV_PCM_FORMAT_S16_LE: |
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index 6f6c335a5baa..c7cfdf957e4d 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c | |||
@@ -55,6 +55,7 @@ static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
55 | unsigned int format) | 55 | unsigned int format) |
56 | { | 56 | { |
57 | struct snd_soc_codec *codec = codec_dai->codec; | 57 | struct snd_soc_codec *codec = codec_dai->codec; |
58 | struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); | ||
58 | int val = 0; | 59 | int val = 0; |
59 | int ret; | 60 | int ret; |
60 | 61 | ||
@@ -77,9 +78,9 @@ static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
77 | if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) | 78 | if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) |
78 | return -EINVAL; | 79 | return -EINVAL; |
79 | 80 | ||
80 | ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1, | 81 | ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1, |
81 | AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1, | 82 | AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1, |
82 | val); | 83 | val); |
83 | if (ret < 0) | 84 | if (ret < 0) |
84 | return ret; | 85 | return ret; |
85 | 86 | ||
@@ -91,11 +92,12 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream, | |||
91 | struct snd_soc_dai *dai) | 92 | struct snd_soc_dai *dai) |
92 | { | 93 | { |
93 | struct snd_soc_codec *codec = dai->codec; | 94 | struct snd_soc_codec *codec = dai->codec; |
94 | int val = 0; | 95 | struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); |
96 | int ret, val = 0; | ||
95 | 97 | ||
96 | /* set the IEC958 bits: consumer mode, no copyright bit */ | 98 | /* set the IEC958 bits: consumer mode, no copyright bit */ |
97 | val |= IEC958_AES0_CON_NOT_COPYRIGHT; | 99 | val |= IEC958_AES0_CON_NOT_COPYRIGHT; |
98 | snd_soc_write(codec, AK4104_REG_CHN_STATUS(0), val); | 100 | regmap_write(ak4104->regmap, AK4104_REG_CHN_STATUS(0), val); |
99 | 101 | ||
100 | val = 0; | 102 | val = 0; |
101 | 103 | ||
@@ -132,11 +134,33 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream, | |||
132 | return -EINVAL; | 134 | return -EINVAL; |
133 | } | 135 | } |
134 | 136 | ||
135 | return snd_soc_write(codec, AK4104_REG_CHN_STATUS(3), val); | 137 | ret = regmap_write(ak4104->regmap, AK4104_REG_CHN_STATUS(3), val); |
138 | if (ret < 0) | ||
139 | return ret; | ||
140 | |||
141 | /* enable transmitter */ | ||
142 | ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX, | ||
143 | AK4104_TX_TXE, AK4104_TX_TXE); | ||
144 | if (ret < 0) | ||
145 | return ret; | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static int ak4104_hw_free(struct snd_pcm_substream *substream, | ||
151 | struct snd_soc_dai *dai) | ||
152 | { | ||
153 | struct snd_soc_codec *codec = dai->codec; | ||
154 | struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); | ||
155 | |||
156 | /* disable transmitter */ | ||
157 | return regmap_update_bits(ak4104->regmap, AK4104_REG_TX, | ||
158 | AK4104_TX_TXE, 0); | ||
136 | } | 159 | } |
137 | 160 | ||
138 | static const struct snd_soc_dai_ops ak4101_dai_ops = { | 161 | static const struct snd_soc_dai_ops ak4101_dai_ops = { |
139 | .hw_params = ak4104_hw_params, | 162 | .hw_params = ak4104_hw_params, |
163 | .hw_free = ak4104_hw_free, | ||
140 | .set_fmt = ak4104_set_dai_fmt, | 164 | .set_fmt = ak4104_set_dai_fmt, |
141 | }; | 165 | }; |
142 | 166 | ||
@@ -160,20 +184,17 @@ static int ak4104_probe(struct snd_soc_codec *codec) | |||
160 | int ret; | 184 | int ret; |
161 | 185 | ||
162 | codec->control_data = ak4104->regmap; | 186 | codec->control_data = ak4104->regmap; |
163 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
164 | if (ret != 0) | ||
165 | return ret; | ||
166 | 187 | ||
167 | /* set power-up and non-reset bits */ | 188 | /* set power-up and non-reset bits */ |
168 | ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1, | 189 | ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1, |
169 | AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, | 190 | AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, |
170 | AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN); | 191 | AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN); |
171 | if (ret < 0) | 192 | if (ret < 0) |
172 | return ret; | 193 | return ret; |
173 | 194 | ||
174 | /* enable transmitter */ | 195 | /* enable transmitter */ |
175 | ret = snd_soc_update_bits(codec, AK4104_REG_TX, | 196 | ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX, |
176 | AK4104_TX_TXE, AK4104_TX_TXE); | 197 | AK4104_TX_TXE, AK4104_TX_TXE); |
177 | if (ret < 0) | 198 | if (ret < 0) |
178 | return ret; | 199 | return ret; |
179 | 200 | ||
@@ -182,8 +203,10 @@ static int ak4104_probe(struct snd_soc_codec *codec) | |||
182 | 203 | ||
183 | static int ak4104_remove(struct snd_soc_codec *codec) | 204 | static int ak4104_remove(struct snd_soc_codec *codec) |
184 | { | 205 | { |
185 | snd_soc_update_bits(codec, AK4104_REG_CONTROL1, | 206 | struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); |
186 | AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0); | 207 | |
208 | regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1, | ||
209 | AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0); | ||
187 | 210 | ||
188 | return 0; | 211 | return 0; |
189 | } | 212 | } |
diff --git a/sound/soc/codecs/ak5386.c b/sound/soc/codecs/ak5386.c new file mode 100644 index 000000000000..1f303983ae02 --- /dev/null +++ b/sound/soc/codecs/ak5386.c | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | * ALSA SoC driver for | ||
3 | * Asahi Kasei AK5386 Single-ended 24-Bit 192kHz delta-sigma ADC | ||
4 | * | ||
5 | * (c) 2013 Daniel Mack <zonque@gmail.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/of_gpio.h> | ||
16 | #include <linux/of_device.h> | ||
17 | #include <sound/soc.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/initval.h> | ||
20 | |||
21 | struct ak5386_priv { | ||
22 | int reset_gpio; | ||
23 | }; | ||
24 | |||
25 | static struct snd_soc_codec_driver soc_codec_ak5386; | ||
26 | |||
27 | static int ak5386_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
28 | unsigned int format) | ||
29 | { | ||
30 | struct snd_soc_codec *codec = codec_dai->codec; | ||
31 | |||
32 | format &= SND_SOC_DAIFMT_FORMAT_MASK; | ||
33 | if (format != SND_SOC_DAIFMT_LEFT_J && | ||
34 | format != SND_SOC_DAIFMT_I2S) { | ||
35 | dev_err(codec->dev, "Invalid DAI format\n"); | ||
36 | return -EINVAL; | ||
37 | } | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static int ak5386_hw_params(struct snd_pcm_substream *substream, | ||
43 | struct snd_pcm_hw_params *params, | ||
44 | struct snd_soc_dai *dai) | ||
45 | { | ||
46 | struct snd_soc_codec *codec = dai->codec; | ||
47 | struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
48 | |||
49 | /* | ||
50 | * From the datasheet: | ||
51 | * | ||
52 | * All external clocks (MCLK, SCLK and LRCK) must be present unless | ||
53 | * PDN pin = “L”. If these clocks are not provided, the AK5386 may | ||
54 | * draw excess current due to its use of internal dynamically | ||
55 | * refreshed logic. If the external clocks are not present, place | ||
56 | * the AK5386 in power-down mode (PDN pin = “L”). | ||
57 | */ | ||
58 | |||
59 | if (gpio_is_valid(priv->reset_gpio)) | ||
60 | gpio_set_value(priv->reset_gpio, 1); | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int ak5386_hw_free(struct snd_pcm_substream *substream, | ||
66 | struct snd_soc_dai *dai) | ||
67 | { | ||
68 | struct snd_soc_codec *codec = dai->codec; | ||
69 | struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
70 | |||
71 | if (gpio_is_valid(priv->reset_gpio)) | ||
72 | gpio_set_value(priv->reset_gpio, 0); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static const struct snd_soc_dai_ops ak5386_dai_ops = { | ||
78 | .set_fmt = ak5386_set_dai_fmt, | ||
79 | .hw_params = ak5386_hw_params, | ||
80 | .hw_free = ak5386_hw_free, | ||
81 | }; | ||
82 | |||
83 | static struct snd_soc_dai_driver ak5386_dai = { | ||
84 | .name = "ak5386-hifi", | ||
85 | .capture = { | ||
86 | .stream_name = "Capture", | ||
87 | .channels_min = 1, | ||
88 | .channels_max = 2, | ||
89 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
90 | .formats = SNDRV_PCM_FMTBIT_S8 | | ||
91 | SNDRV_PCM_FMTBIT_S16_LE | | ||
92 | SNDRV_PCM_FMTBIT_S24_LE | | ||
93 | SNDRV_PCM_FMTBIT_S24_3LE, | ||
94 | }, | ||
95 | .ops = &ak5386_dai_ops, | ||
96 | }; | ||
97 | |||
98 | #ifdef CONFIG_OF | ||
99 | static const struct of_device_id ak5386_dt_ids[] = { | ||
100 | { .compatible = "asahi-kasei,ak5386", }, | ||
101 | { } | ||
102 | }; | ||
103 | MODULE_DEVICE_TABLE(of, ak5386_dt_ids); | ||
104 | #endif | ||
105 | |||
106 | static int ak5386_probe(struct platform_device *pdev) | ||
107 | { | ||
108 | struct device *dev = &pdev->dev; | ||
109 | struct ak5386_priv *priv; | ||
110 | |||
111 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
112 | if (!priv) | ||
113 | return -ENOMEM; | ||
114 | |||
115 | priv->reset_gpio = -EINVAL; | ||
116 | dev_set_drvdata(dev, priv); | ||
117 | |||
118 | if (of_match_device(of_match_ptr(ak5386_dt_ids), dev)) | ||
119 | priv->reset_gpio = of_get_named_gpio(dev->of_node, | ||
120 | "reset-gpio", 0); | ||
121 | |||
122 | if (gpio_is_valid(priv->reset_gpio)) | ||
123 | if (devm_gpio_request_one(dev, priv->reset_gpio, | ||
124 | GPIOF_OUT_INIT_LOW, | ||
125 | "AK5386 Reset")) | ||
126 | priv->reset_gpio = -EINVAL; | ||
127 | |||
128 | return snd_soc_register_codec(dev, &soc_codec_ak5386, | ||
129 | &ak5386_dai, 1); | ||
130 | } | ||
131 | |||
132 | static int ak5386_remove(struct platform_device *pdev) | ||
133 | { | ||
134 | snd_soc_unregister_codec(&pdev->dev); | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static struct platform_driver ak5386_driver = { | ||
139 | .probe = ak5386_probe, | ||
140 | .remove = ak5386_remove, | ||
141 | .driver = { | ||
142 | .name = "ak5386", | ||
143 | .owner = THIS_MODULE, | ||
144 | .of_match_table = of_match_ptr(ak5386_dt_ids), | ||
145 | }, | ||
146 | }; | ||
147 | |||
148 | module_platform_driver(ak5386_driver); | ||
149 | |||
150 | MODULE_DESCRIPTION("ASoC driver for AK5386 ADC"); | ||
151 | MODULE_AUTHOR("Daniel Mack <zonque@gmail.com>"); | ||
152 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index e7d34711412c..389f23253831 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/delay.h> | ||
13 | #include <linux/gcd.h> | 14 | #include <linux/gcd.h> |
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
15 | #include <linux/pm_runtime.h> | 16 | #include <linux/pm_runtime.h> |
@@ -65,6 +66,163 @@ | |||
65 | #define arizona_aif_dbg(_dai, fmt, ...) \ | 66 | #define arizona_aif_dbg(_dai, fmt, ...) \ |
66 | dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) | 67 | dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) |
67 | 68 | ||
69 | static int arizona_spk_ev(struct snd_soc_dapm_widget *w, | ||
70 | struct snd_kcontrol *kcontrol, | ||
71 | int event) | ||
72 | { | ||
73 | struct snd_soc_codec *codec = w->codec; | ||
74 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
75 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
76 | bool manual_ena = false; | ||
77 | int val; | ||
78 | |||
79 | switch (arizona->type) { | ||
80 | case WM5102: | ||
81 | switch (arizona->rev) { | ||
82 | case 0: | ||
83 | break; | ||
84 | default: | ||
85 | manual_ena = true; | ||
86 | break; | ||
87 | } | ||
88 | default: | ||
89 | break; | ||
90 | } | ||
91 | |||
92 | switch (event) { | ||
93 | case SND_SOC_DAPM_PRE_PMU: | ||
94 | if (!priv->spk_ena && manual_ena) { | ||
95 | snd_soc_write(codec, 0x4f5, 0x25a); | ||
96 | priv->spk_ena_pending = true; | ||
97 | } | ||
98 | break; | ||
99 | case SND_SOC_DAPM_POST_PMU: | ||
100 | val = snd_soc_read(codec, ARIZONA_INTERRUPT_RAW_STATUS_3); | ||
101 | if (val & ARIZONA_SPK_SHUTDOWN_STS) { | ||
102 | dev_crit(arizona->dev, | ||
103 | "Speaker not enabled due to temperature\n"); | ||
104 | return -EBUSY; | ||
105 | } | ||
106 | |||
107 | snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1, | ||
108 | 1 << w->shift, 1 << w->shift); | ||
109 | |||
110 | if (priv->spk_ena_pending) { | ||
111 | msleep(75); | ||
112 | snd_soc_write(codec, 0x4f5, 0xda); | ||
113 | priv->spk_ena_pending = false; | ||
114 | priv->spk_ena++; | ||
115 | } | ||
116 | break; | ||
117 | case SND_SOC_DAPM_PRE_PMD: | ||
118 | if (manual_ena) { | ||
119 | priv->spk_ena--; | ||
120 | if (!priv->spk_ena) | ||
121 | snd_soc_write(codec, 0x4f5, 0x25a); | ||
122 | } | ||
123 | |||
124 | snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1, | ||
125 | 1 << w->shift, 0); | ||
126 | break; | ||
127 | case SND_SOC_DAPM_POST_PMD: | ||
128 | if (manual_ena) { | ||
129 | if (!priv->spk_ena) | ||
130 | snd_soc_write(codec, 0x4f5, 0x0da); | ||
131 | } | ||
132 | break; | ||
133 | } | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static irqreturn_t arizona_thermal_warn(int irq, void *data) | ||
139 | { | ||
140 | struct arizona *arizona = data; | ||
141 | unsigned int val; | ||
142 | int ret; | ||
143 | |||
144 | ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3, | ||
145 | &val); | ||
146 | if (ret != 0) { | ||
147 | dev_err(arizona->dev, "Failed to read thermal status: %d\n", | ||
148 | ret); | ||
149 | } else if (val & ARIZONA_SPK_SHUTDOWN_WARN_STS) { | ||
150 | dev_crit(arizona->dev, "Thermal warning\n"); | ||
151 | } | ||
152 | |||
153 | return IRQ_HANDLED; | ||
154 | } | ||
155 | |||
156 | static irqreturn_t arizona_thermal_shutdown(int irq, void *data) | ||
157 | { | ||
158 | struct arizona *arizona = data; | ||
159 | unsigned int val; | ||
160 | int ret; | ||
161 | |||
162 | ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3, | ||
163 | &val); | ||
164 | if (ret != 0) { | ||
165 | dev_err(arizona->dev, "Failed to read thermal status: %d\n", | ||
166 | ret); | ||
167 | } else if (val & ARIZONA_SPK_SHUTDOWN_STS) { | ||
168 | dev_crit(arizona->dev, "Thermal shutdown\n"); | ||
169 | ret = regmap_update_bits(arizona->regmap, | ||
170 | ARIZONA_OUTPUT_ENABLES_1, | ||
171 | ARIZONA_OUT4L_ENA | | ||
172 | ARIZONA_OUT4R_ENA, 0); | ||
173 | if (ret != 0) | ||
174 | dev_crit(arizona->dev, | ||
175 | "Failed to disable speaker outputs: %d\n", | ||
176 | ret); | ||
177 | } | ||
178 | |||
179 | return IRQ_HANDLED; | ||
180 | } | ||
181 | |||
182 | static const struct snd_soc_dapm_widget arizona_spkl = | ||
183 | SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM, | ||
184 | ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev, | ||
185 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU); | ||
186 | |||
187 | static const struct snd_soc_dapm_widget arizona_spkr = | ||
188 | SND_SOC_DAPM_PGA_E("OUT4R", SND_SOC_NOPM, | ||
189 | ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev, | ||
190 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU); | ||
191 | |||
192 | int arizona_init_spk(struct snd_soc_codec *codec) | ||
193 | { | ||
194 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
195 | struct arizona *arizona = priv->arizona; | ||
196 | int ret; | ||
197 | |||
198 | ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkl, 1); | ||
199 | if (ret != 0) | ||
200 | return ret; | ||
201 | |||
202 | ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkr, 1); | ||
203 | if (ret != 0) | ||
204 | return ret; | ||
205 | |||
206 | ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN_WARN, | ||
207 | "Thermal warning", arizona_thermal_warn, | ||
208 | arizona); | ||
209 | if (ret != 0) | ||
210 | dev_err(arizona->dev, | ||
211 | "Failed to get thermal warning IRQ: %d\n", | ||
212 | ret); | ||
213 | |||
214 | ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN, | ||
215 | "Thermal shutdown", arizona_thermal_shutdown, | ||
216 | arizona); | ||
217 | if (ret != 0) | ||
218 | dev_err(arizona->dev, | ||
219 | "Failed to get thermal shutdown IRQ: %d\n", | ||
220 | ret); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | EXPORT_SYMBOL_GPL(arizona_init_spk); | ||
225 | |||
68 | const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { | 226 | const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { |
69 | "None", | 227 | "None", |
70 | "Tone Generator 1", | 228 | "Tone Generator 1", |
@@ -274,6 +432,33 @@ EXPORT_SYMBOL_GPL(arizona_mixer_values); | |||
274 | const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0); | 432 | const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0); |
275 | EXPORT_SYMBOL_GPL(arizona_mixer_tlv); | 433 | EXPORT_SYMBOL_GPL(arizona_mixer_tlv); |
276 | 434 | ||
435 | const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = { | ||
436 | "SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate", | ||
437 | }; | ||
438 | EXPORT_SYMBOL_GPL(arizona_rate_text); | ||
439 | |||
440 | const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = { | ||
441 | 0, 1, 2, 8, | ||
442 | }; | ||
443 | EXPORT_SYMBOL_GPL(arizona_rate_val); | ||
444 | |||
445 | |||
446 | const struct soc_enum arizona_isrc_fsl[] = { | ||
447 | SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_2, | ||
448 | ARIZONA_ISRC1_FSL_SHIFT, 0xf, | ||
449 | ARIZONA_RATE_ENUM_SIZE, | ||
450 | arizona_rate_text, arizona_rate_val), | ||
451 | SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_2, | ||
452 | ARIZONA_ISRC2_FSL_SHIFT, 0xf, | ||
453 | ARIZONA_RATE_ENUM_SIZE, | ||
454 | arizona_rate_text, arizona_rate_val), | ||
455 | SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_2, | ||
456 | ARIZONA_ISRC3_FSL_SHIFT, 0xf, | ||
457 | ARIZONA_RATE_ENUM_SIZE, | ||
458 | arizona_rate_text, arizona_rate_val), | ||
459 | }; | ||
460 | EXPORT_SYMBOL_GPL(arizona_isrc_fsl); | ||
461 | |||
277 | static const char *arizona_vol_ramp_text[] = { | 462 | static const char *arizona_vol_ramp_text[] = { |
278 | "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", | 463 | "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", |
279 | "15ms/6dB", "30ms/6dB", | 464 | "15ms/6dB", "30ms/6dB", |
@@ -332,9 +517,27 @@ const struct soc_enum arizona_ng_hold = | |||
332 | 4, arizona_ng_hold_text); | 517 | 4, arizona_ng_hold_text); |
333 | EXPORT_SYMBOL_GPL(arizona_ng_hold); | 518 | EXPORT_SYMBOL_GPL(arizona_ng_hold); |
334 | 519 | ||
520 | static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena) | ||
521 | { | ||
522 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
523 | unsigned int val; | ||
524 | int i; | ||
525 | |||
526 | if (ena) | ||
527 | val = ARIZONA_IN_VU; | ||
528 | else | ||
529 | val = 0; | ||
530 | |||
531 | for (i = 0; i < priv->num_inputs; i++) | ||
532 | snd_soc_update_bits(codec, | ||
533 | ARIZONA_ADC_DIGITAL_VOLUME_1L + (i * 4), | ||
534 | ARIZONA_IN_VU, val); | ||
535 | } | ||
536 | |||
335 | int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, | 537 | int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, |
336 | int event) | 538 | int event) |
337 | { | 539 | { |
540 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec); | ||
338 | unsigned int reg; | 541 | unsigned int reg; |
339 | 542 | ||
340 | if (w->shift % 2) | 543 | if (w->shift % 2) |
@@ -343,13 +546,29 @@ int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, | |||
343 | reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8); | 546 | reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8); |
344 | 547 | ||
345 | switch (event) { | 548 | switch (event) { |
549 | case SND_SOC_DAPM_PRE_PMU: | ||
550 | priv->in_pending++; | ||
551 | break; | ||
346 | case SND_SOC_DAPM_POST_PMU: | 552 | case SND_SOC_DAPM_POST_PMU: |
347 | snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0); | 553 | snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0); |
554 | |||
555 | /* If this is the last input pending then allow VU */ | ||
556 | priv->in_pending--; | ||
557 | if (priv->in_pending == 0) { | ||
558 | msleep(1); | ||
559 | arizona_in_set_vu(w->codec, 1); | ||
560 | } | ||
348 | break; | 561 | break; |
349 | case SND_SOC_DAPM_PRE_PMD: | 562 | case SND_SOC_DAPM_PRE_PMD: |
350 | snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, | 563 | snd_soc_update_bits(w->codec, reg, |
351 | ARIZONA_IN1L_MUTE); | 564 | ARIZONA_IN1L_MUTE | ARIZONA_IN_VU, |
565 | ARIZONA_IN1L_MUTE | ARIZONA_IN_VU); | ||
352 | break; | 566 | break; |
567 | case SND_SOC_DAPM_POST_PMD: | ||
568 | /* Disable volume updates if no inputs are enabled */ | ||
569 | reg = snd_soc_read(w->codec, ARIZONA_INPUT_ENABLES); | ||
570 | if (reg == 0) | ||
571 | arizona_in_set_vu(w->codec, 0); | ||
353 | } | 572 | } |
354 | 573 | ||
355 | return 0; | 574 | return 0; |
@@ -360,6 +579,24 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, | |||
360 | struct snd_kcontrol *kcontrol, | 579 | struct snd_kcontrol *kcontrol, |
361 | int event) | 580 | int event) |
362 | { | 581 | { |
582 | switch (event) { | ||
583 | case SND_SOC_DAPM_POST_PMU: | ||
584 | switch (w->shift) { | ||
585 | case ARIZONA_OUT1L_ENA_SHIFT: | ||
586 | case ARIZONA_OUT1R_ENA_SHIFT: | ||
587 | case ARIZONA_OUT2L_ENA_SHIFT: | ||
588 | case ARIZONA_OUT2R_ENA_SHIFT: | ||
589 | case ARIZONA_OUT3L_ENA_SHIFT: | ||
590 | case ARIZONA_OUT3R_ENA_SHIFT: | ||
591 | msleep(17); | ||
592 | break; | ||
593 | |||
594 | default: | ||
595 | break; | ||
596 | } | ||
597 | break; | ||
598 | } | ||
599 | |||
363 | return 0; | 600 | return 0; |
364 | } | 601 | } |
365 | EXPORT_SYMBOL_GPL(arizona_out_ev); | 602 | EXPORT_SYMBOL_GPL(arizona_out_ev); |
@@ -502,27 +739,27 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
502 | break; | 739 | break; |
503 | case 11289600: | 740 | case 11289600: |
504 | case 12288000: | 741 | case 12288000: |
505 | val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT; | 742 | val |= ARIZONA_CLK_12MHZ << ARIZONA_SYSCLK_FREQ_SHIFT; |
506 | break; | 743 | break; |
507 | case 22579200: | 744 | case 22579200: |
508 | case 24576000: | 745 | case 24576000: |
509 | val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT; | 746 | val |= ARIZONA_CLK_24MHZ << ARIZONA_SYSCLK_FREQ_SHIFT; |
510 | break; | 747 | break; |
511 | case 45158400: | 748 | case 45158400: |
512 | case 49152000: | 749 | case 49152000: |
513 | val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT; | 750 | val |= ARIZONA_CLK_49MHZ << ARIZONA_SYSCLK_FREQ_SHIFT; |
514 | break; | 751 | break; |
515 | case 67737600: | 752 | case 67737600: |
516 | case 73728000: | 753 | case 73728000: |
517 | val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT; | 754 | val |= ARIZONA_CLK_73MHZ << ARIZONA_SYSCLK_FREQ_SHIFT; |
518 | break; | 755 | break; |
519 | case 90316800: | 756 | case 90316800: |
520 | case 98304000: | 757 | case 98304000: |
521 | val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT; | 758 | val |= ARIZONA_CLK_98MHZ << ARIZONA_SYSCLK_FREQ_SHIFT; |
522 | break; | 759 | break; |
523 | case 135475200: | 760 | case 135475200: |
524 | case 147456000: | 761 | case 147456000: |
525 | val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT; | 762 | val |= ARIZONA_CLK_147MHZ << ARIZONA_SYSCLK_FREQ_SHIFT; |
526 | break; | 763 | break; |
527 | case 0: | 764 | case 0: |
528 | dev_dbg(arizona->dev, "%s cleared\n", name); | 765 | dev_dbg(arizona->dev, "%s cleared\n", name); |
@@ -816,7 +1053,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
816 | struct arizona *arizona = priv->arizona; | 1053 | struct arizona *arizona = priv->arizona; |
817 | int base = dai->driver->base; | 1054 | int base = dai->driver->base; |
818 | const int *rates; | 1055 | const int *rates; |
819 | int i, ret; | 1056 | int i, ret, val; |
820 | int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1]; | 1057 | int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1]; |
821 | int bclk, lrclk, wl, frame, bclk_target; | 1058 | int bclk, lrclk, wl, frame, bclk_target; |
822 | 1059 | ||
@@ -832,6 +1069,13 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
832 | bclk_target *= chan_limit; | 1069 | bclk_target *= chan_limit; |
833 | } | 1070 | } |
834 | 1071 | ||
1072 | /* Force stereo for I2S mode */ | ||
1073 | val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT); | ||
1074 | if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) { | ||
1075 | arizona_aif_dbg(dai, "Forcing stereo mode\n"); | ||
1076 | bclk_target *= 2; | ||
1077 | } | ||
1078 | |||
835 | for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { | 1079 | for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { |
836 | if (rates[i] >= bclk_target && | 1080 | if (rates[i] >= bclk_target && |
837 | rates[i] % params_rate(params) == 0) { | 1081 | rates[i] % params_rate(params) == 0) { |
@@ -988,6 +1232,16 @@ static struct { | |||
988 | { 1000000, 13500000, 0, 1 }, | 1232 | { 1000000, 13500000, 0, 1 }, |
989 | }; | 1233 | }; |
990 | 1234 | ||
1235 | static struct { | ||
1236 | unsigned int min; | ||
1237 | unsigned int max; | ||
1238 | u16 gain; | ||
1239 | } fll_gains[] = { | ||
1240 | { 0, 256000, 0 }, | ||
1241 | { 256000, 1000000, 2 }, | ||
1242 | { 1000000, 13500000, 4 }, | ||
1243 | }; | ||
1244 | |||
991 | struct arizona_fll_cfg { | 1245 | struct arizona_fll_cfg { |
992 | int n; | 1246 | int n; |
993 | int theta; | 1247 | int theta; |
@@ -995,6 +1249,7 @@ struct arizona_fll_cfg { | |||
995 | int refdiv; | 1249 | int refdiv; |
996 | int outdiv; | 1250 | int outdiv; |
997 | int fratio; | 1251 | int fratio; |
1252 | int gain; | ||
998 | }; | 1253 | }; |
999 | 1254 | ||
1000 | static int arizona_calc_fll(struct arizona_fll *fll, | 1255 | static int arizona_calc_fll(struct arizona_fll *fll, |
@@ -1054,6 +1309,18 @@ static int arizona_calc_fll(struct arizona_fll *fll, | |||
1054 | return -EINVAL; | 1309 | return -EINVAL; |
1055 | } | 1310 | } |
1056 | 1311 | ||
1312 | for (i = 0; i < ARRAY_SIZE(fll_gains); i++) { | ||
1313 | if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) { | ||
1314 | cfg->gain = fll_gains[i].gain; | ||
1315 | break; | ||
1316 | } | ||
1317 | } | ||
1318 | if (i == ARRAY_SIZE(fll_gains)) { | ||
1319 | arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n", | ||
1320 | Fref); | ||
1321 | return -EINVAL; | ||
1322 | } | ||
1323 | |||
1057 | cfg->n = target / (ratio * Fref); | 1324 | cfg->n = target / (ratio * Fref); |
1058 | 1325 | ||
1059 | if (target % (ratio * Fref)) { | 1326 | if (target % (ratio * Fref)) { |
@@ -1081,13 +1348,15 @@ static int arizona_calc_fll(struct arizona_fll *fll, | |||
1081 | cfg->n, cfg->theta, cfg->lambda); | 1348 | cfg->n, cfg->theta, cfg->lambda); |
1082 | arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", | 1349 | arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", |
1083 | cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv); | 1350 | cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv); |
1351 | arizona_fll_dbg(fll, "GAIN=%d\n", cfg->gain); | ||
1084 | 1352 | ||
1085 | return 0; | 1353 | return 0; |
1086 | 1354 | ||
1087 | } | 1355 | } |
1088 | 1356 | ||
1089 | static void arizona_apply_fll(struct arizona *arizona, unsigned int base, | 1357 | static void arizona_apply_fll(struct arizona *arizona, unsigned int base, |
1090 | struct arizona_fll_cfg *cfg, int source) | 1358 | struct arizona_fll_cfg *cfg, int source, |
1359 | bool sync) | ||
1091 | { | 1360 | { |
1092 | regmap_update_bits(arizona->regmap, base + 3, | 1361 | regmap_update_bits(arizona->regmap, base + 3, |
1093 | ARIZONA_FLL1_THETA_MASK, cfg->theta); | 1362 | ARIZONA_FLL1_THETA_MASK, cfg->theta); |
@@ -1102,87 +1371,84 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base, | |||
1102 | cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | | 1371 | cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | |
1103 | source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); | 1372 | source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); |
1104 | 1373 | ||
1374 | if (sync) | ||
1375 | regmap_update_bits(arizona->regmap, base + 0x7, | ||
1376 | ARIZONA_FLL1_GAIN_MASK, | ||
1377 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); | ||
1378 | else | ||
1379 | regmap_update_bits(arizona->regmap, base + 0x9, | ||
1380 | ARIZONA_FLL1_GAIN_MASK, | ||
1381 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); | ||
1382 | |||
1105 | regmap_update_bits(arizona->regmap, base + 2, | 1383 | regmap_update_bits(arizona->regmap, base + 2, |
1106 | ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, | 1384 | ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, |
1107 | ARIZONA_FLL1_CTRL_UPD | cfg->n); | 1385 | ARIZONA_FLL1_CTRL_UPD | cfg->n); |
1108 | } | 1386 | } |
1109 | 1387 | ||
1110 | int arizona_set_fll(struct arizona_fll *fll, int source, | 1388 | static bool arizona_is_enabled_fll(struct arizona_fll *fll) |
1111 | unsigned int Fref, unsigned int Fout) | ||
1112 | { | 1389 | { |
1113 | struct arizona *arizona = fll->arizona; | 1390 | struct arizona *arizona = fll->arizona; |
1114 | struct arizona_fll_cfg cfg, sync; | 1391 | unsigned int reg; |
1115 | unsigned int reg, val; | ||
1116 | int syncsrc; | ||
1117 | bool ena; | ||
1118 | int ret; | 1392 | int ret; |
1119 | 1393 | ||
1120 | if (fll->fref == Fref && fll->fout == Fout) | ||
1121 | return 0; | ||
1122 | |||
1123 | ret = regmap_read(arizona->regmap, fll->base + 1, ®); | 1394 | ret = regmap_read(arizona->regmap, fll->base + 1, ®); |
1124 | if (ret != 0) { | 1395 | if (ret != 0) { |
1125 | arizona_fll_err(fll, "Failed to read current state: %d\n", | 1396 | arizona_fll_err(fll, "Failed to read current state: %d\n", |
1126 | ret); | 1397 | ret); |
1127 | return ret; | 1398 | return ret; |
1128 | } | 1399 | } |
1129 | ena = reg & ARIZONA_FLL1_ENA; | ||
1130 | 1400 | ||
1131 | if (Fout) { | 1401 | return reg & ARIZONA_FLL1_ENA; |
1132 | /* Do we have a 32kHz reference? */ | 1402 | } |
1133 | regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val); | ||
1134 | switch (val & ARIZONA_CLK_32K_SRC_MASK) { | ||
1135 | case ARIZONA_CLK_SRC_MCLK1: | ||
1136 | case ARIZONA_CLK_SRC_MCLK2: | ||
1137 | syncsrc = val & ARIZONA_CLK_32K_SRC_MASK; | ||
1138 | break; | ||
1139 | default: | ||
1140 | syncsrc = -1; | ||
1141 | } | ||
1142 | 1403 | ||
1143 | if (source == syncsrc) | 1404 | static void arizona_enable_fll(struct arizona_fll *fll, |
1144 | syncsrc = -1; | 1405 | struct arizona_fll_cfg *ref, |
1406 | struct arizona_fll_cfg *sync) | ||
1407 | { | ||
1408 | struct arizona *arizona = fll->arizona; | ||
1409 | int ret; | ||
1145 | 1410 | ||
1146 | if (syncsrc >= 0) { | 1411 | /* |
1147 | ret = arizona_calc_fll(fll, &sync, Fref, Fout); | 1412 | * If we have both REFCLK and SYNCCLK then enable both, |
1148 | if (ret != 0) | 1413 | * otherwise apply the SYNCCLK settings to REFCLK. |
1149 | return ret; | 1414 | */ |
1415 | if (fll->ref_src >= 0 && fll->ref_src != fll->sync_src) { | ||
1416 | regmap_update_bits(arizona->regmap, fll->base + 5, | ||
1417 | ARIZONA_FLL1_OUTDIV_MASK, | ||
1418 | ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); | ||
1419 | |||
1420 | arizona_apply_fll(arizona, fll->base, ref, fll->ref_src, | ||
1421 | false); | ||
1422 | if (fll->sync_src >= 0) | ||
1423 | arizona_apply_fll(arizona, fll->base + 0x10, sync, | ||
1424 | fll->sync_src, true); | ||
1425 | } else if (fll->sync_src >= 0) { | ||
1426 | regmap_update_bits(arizona->regmap, fll->base + 5, | ||
1427 | ARIZONA_FLL1_OUTDIV_MASK, | ||
1428 | sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); | ||
1429 | |||
1430 | arizona_apply_fll(arizona, fll->base, sync, | ||
1431 | fll->sync_src, false); | ||
1150 | 1432 | ||
1151 | ret = arizona_calc_fll(fll, &cfg, 32768, Fout); | ||
1152 | if (ret != 0) | ||
1153 | return ret; | ||
1154 | } else { | ||
1155 | ret = arizona_calc_fll(fll, &cfg, Fref, Fout); | ||
1156 | if (ret != 0) | ||
1157 | return ret; | ||
1158 | } | ||
1159 | } else { | ||
1160 | regmap_update_bits(arizona->regmap, fll->base + 1, | ||
1161 | ARIZONA_FLL1_ENA, 0); | ||
1162 | regmap_update_bits(arizona->regmap, fll->base + 0x11, | 1433 | regmap_update_bits(arizona->regmap, fll->base + 0x11, |
1163 | ARIZONA_FLL1_SYNC_ENA, 0); | 1434 | ARIZONA_FLL1_SYNC_ENA, 0); |
1164 | |||
1165 | if (ena) | ||
1166 | pm_runtime_put_autosuspend(arizona->dev); | ||
1167 | |||
1168 | fll->fref = Fref; | ||
1169 | fll->fout = Fout; | ||
1170 | |||
1171 | return 0; | ||
1172 | } | ||
1173 | |||
1174 | regmap_update_bits(arizona->regmap, fll->base + 5, | ||
1175 | ARIZONA_FLL1_OUTDIV_MASK, | ||
1176 | cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); | ||
1177 | |||
1178 | if (syncsrc >= 0) { | ||
1179 | arizona_apply_fll(arizona, fll->base, &cfg, syncsrc); | ||
1180 | arizona_apply_fll(arizona, fll->base + 0x10, &sync, source); | ||
1181 | } else { | 1435 | } else { |
1182 | arizona_apply_fll(arizona, fll->base, &cfg, source); | 1436 | arizona_fll_err(fll, "No clocks provided\n"); |
1437 | return; | ||
1183 | } | 1438 | } |
1184 | 1439 | ||
1185 | if (!ena) | 1440 | /* |
1441 | * Increase the bandwidth if we're not using a low frequency | ||
1442 | * sync source. | ||
1443 | */ | ||
1444 | if (fll->sync_src >= 0 && fll->sync_freq > 100000) | ||
1445 | regmap_update_bits(arizona->regmap, fll->base + 0x17, | ||
1446 | ARIZONA_FLL1_SYNC_BW, 0); | ||
1447 | else | ||
1448 | regmap_update_bits(arizona->regmap, fll->base + 0x17, | ||
1449 | ARIZONA_FLL1_SYNC_BW, ARIZONA_FLL1_SYNC_BW); | ||
1450 | |||
1451 | if (!arizona_is_enabled_fll(fll)) | ||
1186 | pm_runtime_get(arizona->dev); | 1452 | pm_runtime_get(arizona->dev); |
1187 | 1453 | ||
1188 | /* Clear any pending completions */ | 1454 | /* Clear any pending completions */ |
@@ -1190,7 +1456,8 @@ int arizona_set_fll(struct arizona_fll *fll, int source, | |||
1190 | 1456 | ||
1191 | regmap_update_bits(arizona->regmap, fll->base + 1, | 1457 | regmap_update_bits(arizona->regmap, fll->base + 1, |
1192 | ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); | 1458 | ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); |
1193 | if (syncsrc >= 0) | 1459 | if (fll->ref_src >= 0 && fll->sync_src >= 0 && |
1460 | fll->ref_src != fll->sync_src) | ||
1194 | regmap_update_bits(arizona->regmap, fll->base + 0x11, | 1461 | regmap_update_bits(arizona->regmap, fll->base + 0x11, |
1195 | ARIZONA_FLL1_SYNC_ENA, | 1462 | ARIZONA_FLL1_SYNC_ENA, |
1196 | ARIZONA_FLL1_SYNC_ENA); | 1463 | ARIZONA_FLL1_SYNC_ENA); |
@@ -1199,10 +1466,88 @@ int arizona_set_fll(struct arizona_fll *fll, int source, | |||
1199 | msecs_to_jiffies(250)); | 1466 | msecs_to_jiffies(250)); |
1200 | if (ret == 0) | 1467 | if (ret == 0) |
1201 | arizona_fll_warn(fll, "Timed out waiting for lock\n"); | 1468 | arizona_fll_warn(fll, "Timed out waiting for lock\n"); |
1469 | } | ||
1470 | |||
1471 | static void arizona_disable_fll(struct arizona_fll *fll) | ||
1472 | { | ||
1473 | struct arizona *arizona = fll->arizona; | ||
1474 | bool change; | ||
1475 | |||
1476 | regmap_update_bits_check(arizona->regmap, fll->base + 1, | ||
1477 | ARIZONA_FLL1_ENA, 0, &change); | ||
1478 | regmap_update_bits(arizona->regmap, fll->base + 0x11, | ||
1479 | ARIZONA_FLL1_SYNC_ENA, 0); | ||
1480 | |||
1481 | if (change) | ||
1482 | pm_runtime_put_autosuspend(arizona->dev); | ||
1483 | } | ||
1484 | |||
1485 | int arizona_set_fll_refclk(struct arizona_fll *fll, int source, | ||
1486 | unsigned int Fref, unsigned int Fout) | ||
1487 | { | ||
1488 | struct arizona_fll_cfg ref, sync; | ||
1489 | int ret; | ||
1202 | 1490 | ||
1203 | fll->fref = Fref; | 1491 | if (fll->ref_src == source && fll->ref_freq == Fref) |
1492 | return 0; | ||
1493 | |||
1494 | if (fll->fout && Fref > 0) { | ||
1495 | ret = arizona_calc_fll(fll, &ref, Fref, fll->fout); | ||
1496 | if (ret != 0) | ||
1497 | return ret; | ||
1498 | |||
1499 | if (fll->sync_src >= 0) { | ||
1500 | ret = arizona_calc_fll(fll, &sync, fll->sync_freq, | ||
1501 | fll->fout); | ||
1502 | if (ret != 0) | ||
1503 | return ret; | ||
1504 | } | ||
1505 | } | ||
1506 | |||
1507 | fll->ref_src = source; | ||
1508 | fll->ref_freq = Fref; | ||
1509 | |||
1510 | if (fll->fout && Fref > 0) { | ||
1511 | arizona_enable_fll(fll, &ref, &sync); | ||
1512 | } | ||
1513 | |||
1514 | return 0; | ||
1515 | } | ||
1516 | EXPORT_SYMBOL_GPL(arizona_set_fll_refclk); | ||
1517 | |||
1518 | int arizona_set_fll(struct arizona_fll *fll, int source, | ||
1519 | unsigned int Fref, unsigned int Fout) | ||
1520 | { | ||
1521 | struct arizona_fll_cfg ref, sync; | ||
1522 | int ret; | ||
1523 | |||
1524 | if (fll->sync_src == source && | ||
1525 | fll->sync_freq == Fref && fll->fout == Fout) | ||
1526 | return 0; | ||
1527 | |||
1528 | if (Fout) { | ||
1529 | if (fll->ref_src >= 0) { | ||
1530 | ret = arizona_calc_fll(fll, &ref, fll->ref_freq, | ||
1531 | Fout); | ||
1532 | if (ret != 0) | ||
1533 | return ret; | ||
1534 | } | ||
1535 | |||
1536 | ret = arizona_calc_fll(fll, &sync, Fref, Fout); | ||
1537 | if (ret != 0) | ||
1538 | return ret; | ||
1539 | } | ||
1540 | |||
1541 | fll->sync_src = source; | ||
1542 | fll->sync_freq = Fref; | ||
1204 | fll->fout = Fout; | 1543 | fll->fout = Fout; |
1205 | 1544 | ||
1545 | if (Fout) { | ||
1546 | arizona_enable_fll(fll, &ref, &sync); | ||
1547 | } else { | ||
1548 | arizona_disable_fll(fll); | ||
1549 | } | ||
1550 | |||
1206 | return 0; | 1551 | return 0; |
1207 | } | 1552 | } |
1208 | EXPORT_SYMBOL_GPL(arizona_set_fll); | 1553 | EXPORT_SYMBOL_GPL(arizona_set_fll); |
@@ -1211,12 +1556,26 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq, | |||
1211 | int ok_irq, struct arizona_fll *fll) | 1556 | int ok_irq, struct arizona_fll *fll) |
1212 | { | 1557 | { |
1213 | int ret; | 1558 | int ret; |
1559 | unsigned int val; | ||
1214 | 1560 | ||
1215 | init_completion(&fll->ok); | 1561 | init_completion(&fll->ok); |
1216 | 1562 | ||
1217 | fll->id = id; | 1563 | fll->id = id; |
1218 | fll->base = base; | 1564 | fll->base = base; |
1219 | fll->arizona = arizona; | 1565 | fll->arizona = arizona; |
1566 | fll->sync_src = ARIZONA_FLL_SRC_NONE; | ||
1567 | |||
1568 | /* Configure default refclk to 32kHz if we have one */ | ||
1569 | regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val); | ||
1570 | switch (val & ARIZONA_CLK_32K_SRC_MASK) { | ||
1571 | case ARIZONA_CLK_SRC_MCLK1: | ||
1572 | case ARIZONA_CLK_SRC_MCLK2: | ||
1573 | fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK; | ||
1574 | break; | ||
1575 | default: | ||
1576 | fll->ref_src = ARIZONA_FLL_SRC_NONE; | ||
1577 | } | ||
1578 | fll->ref_freq = 32768; | ||
1220 | 1579 | ||
1221 | snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id); | 1580 | snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id); |
1222 | snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name), | 1581 | snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name), |
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 13dd2916b721..af39f1006427 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #define ARIZONA_CLK_SRC_AIF2BCLK 0x9 | 32 | #define ARIZONA_CLK_SRC_AIF2BCLK 0x9 |
33 | #define ARIZONA_CLK_SRC_AIF3BCLK 0xa | 33 | #define ARIZONA_CLK_SRC_AIF3BCLK 0xa |
34 | 34 | ||
35 | #define ARIZONA_FLL_SRC_NONE -1 | ||
35 | #define ARIZONA_FLL_SRC_MCLK1 0 | 36 | #define ARIZONA_FLL_SRC_MCLK1 0 |
36 | #define ARIZONA_FLL_SRC_MCLK2 1 | 37 | #define ARIZONA_FLL_SRC_MCLK2 1 |
37 | #define ARIZONA_FLL_SRC_SLIMCLK 3 | 38 | #define ARIZONA_FLL_SRC_SLIMCLK 3 |
@@ -48,6 +49,14 @@ | |||
48 | #define ARIZONA_MIXER_VOL_SHIFT 1 | 49 | #define ARIZONA_MIXER_VOL_SHIFT 1 |
49 | #define ARIZONA_MIXER_VOL_WIDTH 7 | 50 | #define ARIZONA_MIXER_VOL_WIDTH 7 |
50 | 51 | ||
52 | #define ARIZONA_CLK_6MHZ 0 | ||
53 | #define ARIZONA_CLK_12MHZ 1 | ||
54 | #define ARIZONA_CLK_24MHZ 2 | ||
55 | #define ARIZONA_CLK_49MHZ 3 | ||
56 | #define ARIZONA_CLK_73MHZ 4 | ||
57 | #define ARIZONA_CLK_98MHZ 5 | ||
58 | #define ARIZONA_CLK_147MHZ 6 | ||
59 | |||
51 | #define ARIZONA_MAX_DAI 4 | 60 | #define ARIZONA_MAX_DAI 4 |
52 | #define ARIZONA_MAX_ADSP 4 | 61 | #define ARIZONA_MAX_ADSP 4 |
53 | 62 | ||
@@ -64,6 +73,12 @@ struct arizona_priv { | |||
64 | int sysclk; | 73 | int sysclk; |
65 | int asyncclk; | 74 | int asyncclk; |
66 | struct arizona_dai_priv dai[ARIZONA_MAX_DAI]; | 75 | struct arizona_dai_priv dai[ARIZONA_MAX_DAI]; |
76 | |||
77 | int num_inputs; | ||
78 | unsigned int in_pending; | ||
79 | |||
80 | unsigned int spk_ena:2; | ||
81 | unsigned int spk_ena_pending:1; | ||
67 | }; | 82 | }; |
68 | 83 | ||
69 | #define ARIZONA_NUM_MIXER_INPUTS 99 | 84 | #define ARIZONA_NUM_MIXER_INPUTS 99 |
@@ -165,6 +180,12 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; | |||
165 | ARIZONA_MIXER_ROUTES(name, name "L"), \ | 180 | ARIZONA_MIXER_ROUTES(name, name "L"), \ |
166 | ARIZONA_MIXER_ROUTES(name, name "R") | 181 | ARIZONA_MIXER_ROUTES(name, name "R") |
167 | 182 | ||
183 | #define ARIZONA_RATE_ENUM_SIZE 4 | ||
184 | extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE]; | ||
185 | extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE]; | ||
186 | |||
187 | extern const struct soc_enum arizona_isrc_fsl[]; | ||
188 | |||
168 | extern const struct soc_enum arizona_in_vi_ramp; | 189 | extern const struct soc_enum arizona_in_vi_ramp; |
169 | extern const struct soc_enum arizona_in_vd_ramp; | 190 | extern const struct soc_enum arizona_in_vd_ramp; |
170 | 191 | ||
@@ -201,8 +222,12 @@ struct arizona_fll { | |||
201 | unsigned int base; | 222 | unsigned int base; |
202 | unsigned int vco_mult; | 223 | unsigned int vco_mult; |
203 | struct completion ok; | 224 | struct completion ok; |
204 | unsigned int fref; | 225 | |
205 | unsigned int fout; | 226 | unsigned int fout; |
227 | int sync_src; | ||
228 | unsigned int sync_freq; | ||
229 | int ref_src; | ||
230 | unsigned int ref_freq; | ||
206 | 231 | ||
207 | char lock_name[ARIZONA_FLL_NAME_LEN]; | 232 | char lock_name[ARIZONA_FLL_NAME_LEN]; |
208 | char clock_ok_name[ARIZONA_FLL_NAME_LEN]; | 233 | char clock_ok_name[ARIZONA_FLL_NAME_LEN]; |
@@ -210,9 +235,13 @@ struct arizona_fll { | |||
210 | 235 | ||
211 | extern int arizona_init_fll(struct arizona *arizona, int id, int base, | 236 | extern int arizona_init_fll(struct arizona *arizona, int id, int base, |
212 | int lock_irq, int ok_irq, struct arizona_fll *fll); | 237 | int lock_irq, int ok_irq, struct arizona_fll *fll); |
238 | extern int arizona_set_fll_refclk(struct arizona_fll *fll, int source, | ||
239 | unsigned int Fref, unsigned int Fout); | ||
213 | extern int arizona_set_fll(struct arizona_fll *fll, int source, | 240 | extern int arizona_set_fll(struct arizona_fll *fll, int source, |
214 | unsigned int Fref, unsigned int Fout); | 241 | unsigned int Fref, unsigned int Fout); |
215 | 242 | ||
243 | extern int arizona_init_spk(struct snd_soc_codec *codec); | ||
244 | |||
216 | extern int arizona_init_dai(struct arizona_priv *priv, int dai); | 245 | extern int arizona_init_dai(struct arizona_priv *priv, int dai); |
217 | 246 | ||
218 | int arizona_set_output_mode(struct snd_soc_codec *codec, int output, | 247 | int arizona_set_output_mode(struct snd_soc_codec *codec, int output, |
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 2415a4118dbd..03036b326732 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c | |||
@@ -39,17 +39,15 @@ | |||
39 | 39 | ||
40 | /* | 40 | /* |
41 | * CS4271 registers | 41 | * CS4271 registers |
42 | * High byte represents SPI chip address (0x10) + write command (0) | ||
43 | * Low byte - codec register address | ||
44 | */ | 42 | */ |
45 | #define CS4271_MODE1 0x2001 /* Mode Control 1 */ | 43 | #define CS4271_MODE1 0x01 /* Mode Control 1 */ |
46 | #define CS4271_DACCTL 0x2002 /* DAC Control */ | 44 | #define CS4271_DACCTL 0x02 /* DAC Control */ |
47 | #define CS4271_DACVOL 0x2003 /* DAC Volume & Mixing Control */ | 45 | #define CS4271_DACVOL 0x03 /* DAC Volume & Mixing Control */ |
48 | #define CS4271_VOLA 0x2004 /* DAC Channel A Volume Control */ | 46 | #define CS4271_VOLA 0x04 /* DAC Channel A Volume Control */ |
49 | #define CS4271_VOLB 0x2005 /* DAC Channel B Volume Control */ | 47 | #define CS4271_VOLB 0x05 /* DAC Channel B Volume Control */ |
50 | #define CS4271_ADCCTL 0x2006 /* ADC Control */ | 48 | #define CS4271_ADCCTL 0x06 /* ADC Control */ |
51 | #define CS4271_MODE2 0x2007 /* Mode Control 2 */ | 49 | #define CS4271_MODE2 0x07 /* Mode Control 2 */ |
52 | #define CS4271_CHIPID 0x2008 /* Chip ID */ | 50 | #define CS4271_CHIPID 0x08 /* Chip ID */ |
53 | 51 | ||
54 | #define CS4271_FIRSTREG CS4271_MODE1 | 52 | #define CS4271_FIRSTREG CS4271_MODE1 |
55 | #define CS4271_LASTREG CS4271_MODE2 | 53 | #define CS4271_LASTREG CS4271_MODE2 |
@@ -144,23 +142,27 @@ | |||
144 | * Array do not include Chip ID, as codec driver does not use | 142 | * Array do not include Chip ID, as codec driver does not use |
145 | * registers read operations at all | 143 | * registers read operations at all |
146 | */ | 144 | */ |
147 | static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = { | 145 | static const struct reg_default cs4271_reg_defaults[] = { |
148 | 0, | 146 | { CS4271_MODE1, 0, }, |
149 | 0, | 147 | { CS4271_DACCTL, CS4271_DACCTL_AMUTE, }, |
150 | CS4271_DACCTL_AMUTE, | 148 | { CS4271_DACVOL, CS4271_DACVOL_SOFT | CS4271_DACVOL_ATAPI_AL_BR, }, |
151 | CS4271_DACVOL_SOFT | CS4271_DACVOL_ATAPI_AL_BR, | 149 | { CS4271_VOLA, 0, }, |
152 | 0, | 150 | { CS4271_VOLB, 0, }, |
153 | 0, | 151 | { CS4271_ADCCTL, 0, }, |
154 | 0, | 152 | { CS4271_MODE2, 0, }, |
155 | 0, | ||
156 | }; | 153 | }; |
157 | 154 | ||
155 | static bool cs4271_volatile_reg(struct device *dev, unsigned int reg) | ||
156 | { | ||
157 | return reg == CS4271_CHIPID; | ||
158 | } | ||
159 | |||
158 | struct cs4271_private { | 160 | struct cs4271_private { |
159 | /* SND_SOC_I2C or SND_SOC_SPI */ | 161 | /* SND_SOC_I2C or SND_SOC_SPI */ |
160 | enum snd_soc_control_type bus_type; | ||
161 | unsigned int mclk; | 162 | unsigned int mclk; |
162 | bool master; | 163 | bool master; |
163 | bool deemph; | 164 | bool deemph; |
165 | struct regmap *regmap; | ||
164 | /* Current sample rate for de-emphasis control */ | 166 | /* Current sample rate for de-emphasis control */ |
165 | int rate; | 167 | int rate; |
166 | /* GPIO driving Reset pin, if any */ | 168 | /* GPIO driving Reset pin, if any */ |
@@ -210,14 +212,14 @@ static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
210 | switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { | 212 | switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { |
211 | case SND_SOC_DAIFMT_LEFT_J: | 213 | case SND_SOC_DAIFMT_LEFT_J: |
212 | val |= CS4271_MODE1_DAC_DIF_LJ; | 214 | val |= CS4271_MODE1_DAC_DIF_LJ; |
213 | ret = snd_soc_update_bits(codec, CS4271_ADCCTL, | 215 | ret = regmap_update_bits(cs4271->regmap, CS4271_ADCCTL, |
214 | CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_LJ); | 216 | CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_LJ); |
215 | if (ret < 0) | 217 | if (ret < 0) |
216 | return ret; | 218 | return ret; |
217 | break; | 219 | break; |
218 | case SND_SOC_DAIFMT_I2S: | 220 | case SND_SOC_DAIFMT_I2S: |
219 | val |= CS4271_MODE1_DAC_DIF_I2S; | 221 | val |= CS4271_MODE1_DAC_DIF_I2S; |
220 | ret = snd_soc_update_bits(codec, CS4271_ADCCTL, | 222 | ret = regmap_update_bits(cs4271->regmap, CS4271_ADCCTL, |
221 | CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_I2S); | 223 | CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_I2S); |
222 | if (ret < 0) | 224 | if (ret < 0) |
223 | return ret; | 225 | return ret; |
@@ -227,7 +229,7 @@ static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
227 | return -EINVAL; | 229 | return -EINVAL; |
228 | } | 230 | } |
229 | 231 | ||
230 | ret = snd_soc_update_bits(codec, CS4271_MODE1, | 232 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE1, |
231 | CS4271_MODE1_DAC_DIF_MASK | CS4271_MODE1_MASTER, val); | 233 | CS4271_MODE1_DAC_DIF_MASK | CS4271_MODE1_MASTER, val); |
232 | if (ret < 0) | 234 | if (ret < 0) |
233 | return ret; | 235 | return ret; |
@@ -252,7 +254,7 @@ static int cs4271_set_deemph(struct snd_soc_codec *codec) | |||
252 | val <<= 4; | 254 | val <<= 4; |
253 | } | 255 | } |
254 | 256 | ||
255 | ret = snd_soc_update_bits(codec, CS4271_DACCTL, | 257 | ret = regmap_update_bits(cs4271->regmap, CS4271_DACCTL, |
256 | CS4271_DACCTL_DEM_MASK, val); | 258 | CS4271_DACCTL_DEM_MASK, val); |
257 | if (ret < 0) | 259 | if (ret < 0) |
258 | return ret; | 260 | return ret; |
@@ -341,14 +343,14 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream, | |||
341 | !dai->capture_active) || | 343 | !dai->capture_active) || |
342 | (substream->stream == SNDRV_PCM_STREAM_CAPTURE && | 344 | (substream->stream == SNDRV_PCM_STREAM_CAPTURE && |
343 | !dai->playback_active)) { | 345 | !dai->playback_active)) { |
344 | ret = snd_soc_update_bits(codec, CS4271_MODE2, | 346 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
345 | CS4271_MODE2_PDN, | 347 | CS4271_MODE2_PDN, |
346 | CS4271_MODE2_PDN); | 348 | CS4271_MODE2_PDN); |
347 | if (ret < 0) | 349 | if (ret < 0) |
348 | return ret; | 350 | return ret; |
349 | 351 | ||
350 | ret = snd_soc_update_bits(codec, CS4271_MODE2, | 352 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
351 | CS4271_MODE2_PDN, 0); | 353 | CS4271_MODE2_PDN, 0); |
352 | if (ret < 0) | 354 | if (ret < 0) |
353 | return ret; | 355 | return ret; |
354 | } | 356 | } |
@@ -378,7 +380,7 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream, | |||
378 | 380 | ||
379 | val |= cs4271_clk_tab[i].ratio_mask; | 381 | val |= cs4271_clk_tab[i].ratio_mask; |
380 | 382 | ||
381 | ret = snd_soc_update_bits(codec, CS4271_MODE1, | 383 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE1, |
382 | CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val); | 384 | CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val); |
383 | if (ret < 0) | 385 | if (ret < 0) |
384 | return ret; | 386 | return ret; |
@@ -386,22 +388,29 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream, | |||
386 | return cs4271_set_deemph(codec); | 388 | return cs4271_set_deemph(codec); |
387 | } | 389 | } |
388 | 390 | ||
389 | static int cs4271_digital_mute(struct snd_soc_dai *dai, int mute) | 391 | static int cs4271_mute_stream(struct snd_soc_dai *dai, int mute, int stream) |
390 | { | 392 | { |
391 | struct snd_soc_codec *codec = dai->codec; | 393 | struct snd_soc_codec *codec = dai->codec; |
394 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
392 | int ret; | 395 | int ret; |
393 | int val_a = 0; | 396 | int val_a = 0; |
394 | int val_b = 0; | 397 | int val_b = 0; |
395 | 398 | ||
399 | if (stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
400 | return 0; | ||
401 | |||
396 | if (mute) { | 402 | if (mute) { |
397 | val_a = CS4271_VOLA_MUTE; | 403 | val_a = CS4271_VOLA_MUTE; |
398 | val_b = CS4271_VOLB_MUTE; | 404 | val_b = CS4271_VOLB_MUTE; |
399 | } | 405 | } |
400 | 406 | ||
401 | ret = snd_soc_update_bits(codec, CS4271_VOLA, CS4271_VOLA_MUTE, val_a); | 407 | ret = regmap_update_bits(cs4271->regmap, CS4271_VOLA, |
408 | CS4271_VOLA_MUTE, val_a); | ||
402 | if (ret < 0) | 409 | if (ret < 0) |
403 | return ret; | 410 | return ret; |
404 | ret = snd_soc_update_bits(codec, CS4271_VOLB, CS4271_VOLB_MUTE, val_b); | 411 | |
412 | ret = regmap_update_bits(cs4271->regmap, CS4271_VOLB, | ||
413 | CS4271_VOLB_MUTE, val_b); | ||
405 | if (ret < 0) | 414 | if (ret < 0) |
406 | return ret; | 415 | return ret; |
407 | 416 | ||
@@ -436,7 +445,7 @@ static const struct snd_soc_dai_ops cs4271_dai_ops = { | |||
436 | .hw_params = cs4271_hw_params, | 445 | .hw_params = cs4271_hw_params, |
437 | .set_sysclk = cs4271_set_dai_sysclk, | 446 | .set_sysclk = cs4271_set_dai_sysclk, |
438 | .set_fmt = cs4271_set_dai_fmt, | 447 | .set_fmt = cs4271_set_dai_fmt, |
439 | .digital_mute = cs4271_digital_mute, | 448 | .mute_stream = cs4271_mute_stream, |
440 | }; | 449 | }; |
441 | 450 | ||
442 | static struct snd_soc_dai_driver cs4271_dai = { | 451 | static struct snd_soc_dai_driver cs4271_dai = { |
@@ -463,25 +472,33 @@ static struct snd_soc_dai_driver cs4271_dai = { | |||
463 | static int cs4271_soc_suspend(struct snd_soc_codec *codec) | 472 | static int cs4271_soc_suspend(struct snd_soc_codec *codec) |
464 | { | 473 | { |
465 | int ret; | 474 | int ret; |
475 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
476 | |||
466 | /* Set power-down bit */ | 477 | /* Set power-down bit */ |
467 | ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, | 478 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
468 | CS4271_MODE2_PDN); | 479 | CS4271_MODE2_PDN, CS4271_MODE2_PDN); |
469 | if (ret < 0) | 480 | if (ret < 0) |
470 | return ret; | 481 | return ret; |
482 | |||
471 | return 0; | 483 | return 0; |
472 | } | 484 | } |
473 | 485 | ||
474 | static int cs4271_soc_resume(struct snd_soc_codec *codec) | 486 | static int cs4271_soc_resume(struct snd_soc_codec *codec) |
475 | { | 487 | { |
476 | int ret; | 488 | int ret; |
489 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
490 | |||
477 | /* Restore codec state */ | 491 | /* Restore codec state */ |
478 | ret = snd_soc_cache_sync(codec); | 492 | ret = regcache_sync(cs4271->regmap); |
479 | if (ret < 0) | 493 | if (ret < 0) |
480 | return ret; | 494 | return ret; |
495 | |||
481 | /* then disable the power-down bit */ | 496 | /* then disable the power-down bit */ |
482 | ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0); | 497 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
498 | CS4271_MODE2_PDN, 0); | ||
483 | if (ret < 0) | 499 | if (ret < 0) |
484 | return ret; | 500 | return ret; |
501 | |||
485 | return 0; | 502 | return 0; |
486 | } | 503 | } |
487 | #else | 504 | #else |
@@ -542,40 +559,22 @@ static int cs4271_probe(struct snd_soc_codec *codec) | |||
542 | 559 | ||
543 | cs4271->gpio_nreset = gpio_nreset; | 560 | cs4271->gpio_nreset = gpio_nreset; |
544 | 561 | ||
545 | /* | 562 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
546 | * In case of I2C, chip address specified in board data. | 563 | CS4271_MODE2_PDN | CS4271_MODE2_CPEN, |
547 | * So cache IO operations use 8 bit codec register address. | 564 | CS4271_MODE2_PDN | CS4271_MODE2_CPEN); |
548 | * In case of SPI, chip address and register address | ||
549 | * passed together as 16 bit value. | ||
550 | * Anyway, register address is masked with 0xFF inside | ||
551 | * soc-cache code. | ||
552 | */ | ||
553 | if (cs4271->bus_type == SND_SOC_SPI) | ||
554 | ret = snd_soc_codec_set_cache_io(codec, 16, 8, | ||
555 | cs4271->bus_type); | ||
556 | else | ||
557 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, | ||
558 | cs4271->bus_type); | ||
559 | if (ret) { | ||
560 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
561 | return ret; | ||
562 | } | ||
563 | |||
564 | ret = snd_soc_update_bits(codec, CS4271_MODE2, | ||
565 | CS4271_MODE2_PDN | CS4271_MODE2_CPEN, | ||
566 | CS4271_MODE2_PDN | CS4271_MODE2_CPEN); | ||
567 | if (ret < 0) | 565 | if (ret < 0) |
568 | return ret; | 566 | return ret; |
569 | ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0); | 567 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
568 | CS4271_MODE2_PDN, 0); | ||
570 | if (ret < 0) | 569 | if (ret < 0) |
571 | return ret; | 570 | return ret; |
572 | /* Power-up sequence requires 85 uS */ | 571 | /* Power-up sequence requires 85 uS */ |
573 | udelay(85); | 572 | udelay(85); |
574 | 573 | ||
575 | if (amutec_eq_bmutec) | 574 | if (amutec_eq_bmutec) |
576 | snd_soc_update_bits(codec, CS4271_MODE2, | 575 | regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
577 | CS4271_MODE2_MUTECAEQUB, | 576 | CS4271_MODE2_MUTECAEQUB, |
578 | CS4271_MODE2_MUTECAEQUB); | 577 | CS4271_MODE2_MUTECAEQUB); |
579 | 578 | ||
580 | return snd_soc_add_codec_controls(codec, cs4271_snd_controls, | 579 | return snd_soc_add_codec_controls(codec, cs4271_snd_controls, |
581 | ARRAY_SIZE(cs4271_snd_controls)); | 580 | ARRAY_SIZE(cs4271_snd_controls)); |
@@ -597,13 +596,24 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { | |||
597 | .remove = cs4271_remove, | 596 | .remove = cs4271_remove, |
598 | .suspend = cs4271_soc_suspend, | 597 | .suspend = cs4271_soc_suspend, |
599 | .resume = cs4271_soc_resume, | 598 | .resume = cs4271_soc_resume, |
600 | .reg_cache_default = cs4271_dflt_reg, | ||
601 | .reg_cache_size = ARRAY_SIZE(cs4271_dflt_reg), | ||
602 | .reg_word_size = sizeof(cs4271_dflt_reg[0]), | ||
603 | .compress_type = SND_SOC_FLAT_COMPRESSION, | ||
604 | }; | 599 | }; |
605 | 600 | ||
606 | #if defined(CONFIG_SPI_MASTER) | 601 | #if defined(CONFIG_SPI_MASTER) |
602 | |||
603 | static const struct regmap_config cs4271_spi_regmap = { | ||
604 | .reg_bits = 16, | ||
605 | .val_bits = 8, | ||
606 | .max_register = CS4271_LASTREG, | ||
607 | .read_flag_mask = 0x21, | ||
608 | .write_flag_mask = 0x20, | ||
609 | |||
610 | .reg_defaults = cs4271_reg_defaults, | ||
611 | .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), | ||
612 | .cache_type = REGCACHE_RBTREE, | ||
613 | |||
614 | .volatile_reg = cs4271_volatile_reg, | ||
615 | }; | ||
616 | |||
607 | static int cs4271_spi_probe(struct spi_device *spi) | 617 | static int cs4271_spi_probe(struct spi_device *spi) |
608 | { | 618 | { |
609 | struct cs4271_private *cs4271; | 619 | struct cs4271_private *cs4271; |
@@ -613,7 +623,9 @@ static int cs4271_spi_probe(struct spi_device *spi) | |||
613 | return -ENOMEM; | 623 | return -ENOMEM; |
614 | 624 | ||
615 | spi_set_drvdata(spi, cs4271); | 625 | spi_set_drvdata(spi, cs4271); |
616 | cs4271->bus_type = SND_SOC_SPI; | 626 | cs4271->regmap = devm_regmap_init_spi(spi, &cs4271_spi_regmap); |
627 | if (IS_ERR(cs4271->regmap)) | ||
628 | return PTR_ERR(cs4271->regmap); | ||
617 | 629 | ||
618 | return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271, | 630 | return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271, |
619 | &cs4271_dai, 1); | 631 | &cs4271_dai, 1); |
@@ -643,6 +655,18 @@ static const struct i2c_device_id cs4271_i2c_id[] = { | |||
643 | }; | 655 | }; |
644 | MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); | 656 | MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); |
645 | 657 | ||
658 | static const struct regmap_config cs4271_i2c_regmap = { | ||
659 | .reg_bits = 8, | ||
660 | .val_bits = 8, | ||
661 | .max_register = CS4271_LASTREG, | ||
662 | |||
663 | .reg_defaults = cs4271_reg_defaults, | ||
664 | .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), | ||
665 | .cache_type = REGCACHE_RBTREE, | ||
666 | |||
667 | .volatile_reg = cs4271_volatile_reg, | ||
668 | }; | ||
669 | |||
646 | static int cs4271_i2c_probe(struct i2c_client *client, | 670 | static int cs4271_i2c_probe(struct i2c_client *client, |
647 | const struct i2c_device_id *id) | 671 | const struct i2c_device_id *id) |
648 | { | 672 | { |
@@ -653,7 +677,9 @@ static int cs4271_i2c_probe(struct i2c_client *client, | |||
653 | return -ENOMEM; | 677 | return -ENOMEM; |
654 | 678 | ||
655 | i2c_set_clientdata(client, cs4271); | 679 | i2c_set_clientdata(client, cs4271); |
656 | cs4271->bus_type = SND_SOC_I2C; | 680 | cs4271->regmap = devm_regmap_init_i2c(client, &cs4271_i2c_regmap); |
681 | if (IS_ERR(cs4271->regmap)) | ||
682 | return PTR_ERR(cs4271->regmap); | ||
657 | 683 | ||
658 | return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271, | 684 | return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271, |
659 | &cs4271_dai, 1); | 685 | &cs4271_dai, 1); |
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 6361dab48bd1..3b20c86cdb01 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c | |||
@@ -1180,7 +1180,11 @@ static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream, | |||
1180 | priv->config[id].mmcc &= 0xC0; | 1180 | priv->config[id].mmcc &= 0xC0; |
1181 | priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc; | 1181 | priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc; |
1182 | priv->config[id].spc &= 0xFC; | 1182 | priv->config[id].spc &= 0xFC; |
1183 | priv->config[id].spc |= MCK_SCLK_MCLK; | 1183 | /* Use SCLK=64*Fs if internal MCLK >= 6.4MHz */ |
1184 | if (priv->mclk >= 6400000) | ||
1185 | priv->config[id].spc |= MCK_SCLK_64FS; | ||
1186 | else | ||
1187 | priv->config[id].spc |= MCK_SCLK_MCLK; | ||
1184 | } else { | 1188 | } else { |
1185 | /* CS42L73 Slave */ | 1189 | /* CS42L73 Slave */ |
1186 | priv->config[id].spc &= 0xFC; | 1190 | priv->config[id].spc &= 0xFC; |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index a4c16fd70f77..3eeada57e87d 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -739,14 +739,32 @@ static const unsigned int max98088_micboost_tlv[] = { | |||
739 | 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), | 739 | 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), |
740 | }; | 740 | }; |
741 | 741 | ||
742 | static const unsigned int max98088_hp_tlv[] = { | ||
743 | TLV_DB_RANGE_HEAD(5), | ||
744 | 0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0), | ||
745 | 7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0), | ||
746 | 15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0), | ||
747 | 22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0), | ||
748 | 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0), | ||
749 | }; | ||
750 | |||
751 | static const unsigned int max98088_spk_tlv[] = { | ||
752 | TLV_DB_RANGE_HEAD(5), | ||
753 | 0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0), | ||
754 | 7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0), | ||
755 | 15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0), | ||
756 | 22, 27, TLV_DB_SCALE_ITEM(100, 100, 0), | ||
757 | 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0), | ||
758 | }; | ||
759 | |||
742 | static const struct snd_kcontrol_new max98088_snd_controls[] = { | 760 | static const struct snd_kcontrol_new max98088_snd_controls[] = { |
743 | 761 | ||
744 | SOC_DOUBLE_R("Headphone Volume", M98088_REG_39_LVL_HP_L, | 762 | SOC_DOUBLE_R_TLV("Headphone Volume", M98088_REG_39_LVL_HP_L, |
745 | M98088_REG_3A_LVL_HP_R, 0, 31, 0), | 763 | M98088_REG_3A_LVL_HP_R, 0, 31, 0, max98088_hp_tlv), |
746 | SOC_DOUBLE_R("Speaker Volume", M98088_REG_3D_LVL_SPK_L, | 764 | SOC_DOUBLE_R_TLV("Speaker Volume", M98088_REG_3D_LVL_SPK_L, |
747 | M98088_REG_3E_LVL_SPK_R, 0, 31, 0), | 765 | M98088_REG_3E_LVL_SPK_R, 0, 31, 0, max98088_spk_tlv), |
748 | SOC_DOUBLE_R("Receiver Volume", M98088_REG_3B_LVL_REC_L, | 766 | SOC_DOUBLE_R_TLV("Receiver Volume", M98088_REG_3B_LVL_REC_L, |
749 | M98088_REG_3C_LVL_REC_R, 0, 31, 0), | 767 | M98088_REG_3C_LVL_REC_R, 0, 31, 0, max98088_spk_tlv), |
750 | 768 | ||
751 | SOC_DOUBLE_R("Headphone Switch", M98088_REG_39_LVL_HP_L, | 769 | SOC_DOUBLE_R("Headphone Switch", M98088_REG_39_LVL_HP_L, |
752 | M98088_REG_3A_LVL_HP_R, 7, 1, 1), | 770 | M98088_REG_3A_LVL_HP_R, 7, 1, 1), |
@@ -2006,7 +2024,7 @@ static int max98088_probe(struct snd_soc_codec *codec) | |||
2006 | ret); | 2024 | ret); |
2007 | goto err_access; | 2025 | goto err_access; |
2008 | } | 2026 | } |
2009 | dev_info(codec->dev, "revision %c\n", ret + 'A'); | 2027 | dev_info(codec->dev, "revision %c\n", ret - 0x40 + 'A'); |
2010 | 2028 | ||
2011 | snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV); | 2029 | snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV); |
2012 | 2030 | ||
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index fc176044994d..ce0d36412c97 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c | |||
@@ -23,8 +23,6 @@ | |||
23 | #include <sound/max98090.h> | 23 | #include <sound/max98090.h> |
24 | #include "max98090.h" | 24 | #include "max98090.h" |
25 | 25 | ||
26 | #include <linux/version.h> | ||
27 | |||
28 | #define DEBUG | 26 | #define DEBUG |
29 | #define EXTMIC_METHOD | 27 | #define EXTMIC_METHOD |
30 | #define EXTMIC_METHOD_TEST | 28 | #define EXTMIC_METHOD_TEST |
@@ -509,16 +507,16 @@ static int max98090_put_enab_tlv(struct snd_kcontrol *kcontrol, | |||
509 | return 0; | 507 | return 0; |
510 | } | 508 | } |
511 | 509 | ||
512 | static const char * max98090_perf_pwr_text[] = | 510 | static const char *max98090_perf_pwr_text[] = |
513 | { "High Performance", "Low Power" }; | 511 | { "High Performance", "Low Power" }; |
514 | static const char * max98090_pwr_perf_text[] = | 512 | static const char *max98090_pwr_perf_text[] = |
515 | { "Low Power", "High Performance" }; | 513 | { "Low Power", "High Performance" }; |
516 | 514 | ||
517 | static const struct soc_enum max98090_vcmbandgap_enum = | 515 | static const struct soc_enum max98090_vcmbandgap_enum = |
518 | SOC_ENUM_SINGLE(M98090_REG_BIAS_CONTROL, M98090_VCM_MODE_SHIFT, | 516 | SOC_ENUM_SINGLE(M98090_REG_BIAS_CONTROL, M98090_VCM_MODE_SHIFT, |
519 | ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); | 517 | ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); |
520 | 518 | ||
521 | static const char * max98090_osr128_text[] = { "64*fs", "128*fs" }; | 519 | static const char *max98090_osr128_text[] = { "64*fs", "128*fs" }; |
522 | 520 | ||
523 | static const struct soc_enum max98090_osr128_enum = | 521 | static const struct soc_enum max98090_osr128_enum = |
524 | SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_OSR128_SHIFT, | 522 | SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_OSR128_SHIFT, |
@@ -535,28 +533,28 @@ static const struct soc_enum max98090_filter_dmic34mode_enum = | |||
535 | M98090_FLT_DMIC34MODE_SHIFT, | 533 | M98090_FLT_DMIC34MODE_SHIFT, |
536 | ARRAY_SIZE(max98090_mode_text), max98090_mode_text); | 534 | ARRAY_SIZE(max98090_mode_text), max98090_mode_text); |
537 | 535 | ||
538 | static const char * max98090_drcatk_text[] = | 536 | static const char *max98090_drcatk_text[] = |
539 | { "0.5ms", "1ms", "5ms", "10ms", "25ms", "50ms", "100ms", "200ms" }; | 537 | { "0.5ms", "1ms", "5ms", "10ms", "25ms", "50ms", "100ms", "200ms" }; |
540 | 538 | ||
541 | static const struct soc_enum max98090_drcatk_enum = | 539 | static const struct soc_enum max98090_drcatk_enum = |
542 | SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCATK_SHIFT, | 540 | SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCATK_SHIFT, |
543 | ARRAY_SIZE(max98090_drcatk_text), max98090_drcatk_text); | 541 | ARRAY_SIZE(max98090_drcatk_text), max98090_drcatk_text); |
544 | 542 | ||
545 | static const char * max98090_drcrls_text[] = | 543 | static const char *max98090_drcrls_text[] = |
546 | { "8s", "4s", "2s", "1s", "0.5s", "0.25s", "0.125s", "0.0625s" }; | 544 | { "8s", "4s", "2s", "1s", "0.5s", "0.25s", "0.125s", "0.0625s" }; |
547 | 545 | ||
548 | static const struct soc_enum max98090_drcrls_enum = | 546 | static const struct soc_enum max98090_drcrls_enum = |
549 | SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCRLS_SHIFT, | 547 | SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCRLS_SHIFT, |
550 | ARRAY_SIZE(max98090_drcrls_text), max98090_drcrls_text); | 548 | ARRAY_SIZE(max98090_drcrls_text), max98090_drcrls_text); |
551 | 549 | ||
552 | static const char * max98090_alccmp_text[] = | 550 | static const char *max98090_alccmp_text[] = |
553 | { "1:1", "1:1.5", "1:2", "1:4", "1:INF" }; | 551 | { "1:1", "1:1.5", "1:2", "1:4", "1:INF" }; |
554 | 552 | ||
555 | static const struct soc_enum max98090_alccmp_enum = | 553 | static const struct soc_enum max98090_alccmp_enum = |
556 | SOC_ENUM_SINGLE(M98090_REG_DRC_COMPRESSOR, M98090_DRCCMP_SHIFT, | 554 | SOC_ENUM_SINGLE(M98090_REG_DRC_COMPRESSOR, M98090_DRCCMP_SHIFT, |
557 | ARRAY_SIZE(max98090_alccmp_text), max98090_alccmp_text); | 555 | ARRAY_SIZE(max98090_alccmp_text), max98090_alccmp_text); |
558 | 556 | ||
559 | static const char * max98090_drcexp_text[] = { "1:1", "2:1", "3:1" }; | 557 | static const char *max98090_drcexp_text[] = { "1:1", "2:1", "3:1" }; |
560 | 558 | ||
561 | static const struct soc_enum max98090_drcexp_enum = | 559 | static const struct soc_enum max98090_drcexp_enum = |
562 | SOC_ENUM_SINGLE(M98090_REG_DRC_EXPANDER, M98090_DRCEXP_SHIFT, | 560 | SOC_ENUM_SINGLE(M98090_REG_DRC_EXPANDER, M98090_DRCEXP_SHIFT, |
@@ -859,7 +857,7 @@ static const struct soc_enum mic2_mux_enum = | |||
859 | static const struct snd_kcontrol_new max98090_mic2_mux = | 857 | static const struct snd_kcontrol_new max98090_mic2_mux = |
860 | SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum); | 858 | SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum); |
861 | 859 | ||
862 | static const char * max98090_micpre_text[] = { "Off", "On" }; | 860 | static const char *max98090_micpre_text[] = { "Off", "On" }; |
863 | 861 | ||
864 | static const struct soc_enum max98090_pa1en_enum = | 862 | static const struct soc_enum max98090_pa1en_enum = |
865 | SOC_ENUM_SINGLE(M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT, | 863 | SOC_ENUM_SINGLE(M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT, |
@@ -1703,9 +1701,8 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai, | |||
1703 | * seen for the case of TDM mode. The remaining cases have | 1701 | * seen for the case of TDM mode. The remaining cases have |
1704 | * normal logic. | 1702 | * normal logic. |
1705 | */ | 1703 | */ |
1706 | if (max98090->tdm_slots > 1) { | 1704 | if (max98090->tdm_slots > 1) |
1707 | regval ^= M98090_BCI_MASK; | 1705 | regval ^= M98090_BCI_MASK; |
1708 | } | ||
1709 | 1706 | ||
1710 | snd_soc_write(codec, | 1707 | snd_soc_write(codec, |
1711 | M98090_REG_INTERFACE_FORMAT, regval); | 1708 | M98090_REG_INTERFACE_FORMAT, regval); |
@@ -2059,17 +2056,14 @@ static irqreturn_t max98090_interrupt(int irq, void *data) | |||
2059 | if (!active) | 2056 | if (!active) |
2060 | return IRQ_NONE; | 2057 | return IRQ_NONE; |
2061 | 2058 | ||
2062 | if (active & M98090_CLD_MASK) { | 2059 | if (active & M98090_CLD_MASK) |
2063 | dev_err(codec->dev, "M98090_CLD_MASK\n"); | 2060 | dev_err(codec->dev, "M98090_CLD_MASK\n"); |
2064 | } | ||
2065 | 2061 | ||
2066 | if (active & M98090_SLD_MASK) { | 2062 | if (active & M98090_SLD_MASK) |
2067 | dev_dbg(codec->dev, "M98090_SLD_MASK\n"); | 2063 | dev_dbg(codec->dev, "M98090_SLD_MASK\n"); |
2068 | } | ||
2069 | 2064 | ||
2070 | if (active & M98090_ULK_MASK) { | 2065 | if (active & M98090_ULK_MASK) |
2071 | dev_err(codec->dev, "M98090_ULK_MASK\n"); | 2066 | dev_err(codec->dev, "M98090_ULK_MASK\n"); |
2072 | } | ||
2073 | 2067 | ||
2074 | if (active & M98090_JDET_MASK) { | 2068 | if (active & M98090_JDET_MASK) { |
2075 | dev_dbg(codec->dev, "M98090_JDET_MASK\n"); | 2069 | dev_dbg(codec->dev, "M98090_JDET_MASK\n"); |
@@ -2080,13 +2074,11 @@ static irqreturn_t max98090_interrupt(int irq, void *data) | |||
2080 | msecs_to_jiffies(100)); | 2074 | msecs_to_jiffies(100)); |
2081 | } | 2075 | } |
2082 | 2076 | ||
2083 | if (active & M98090_DRCACT_MASK) { | 2077 | if (active & M98090_DRCACT_MASK) |
2084 | dev_dbg(codec->dev, "M98090_DRCACT_MASK\n"); | 2078 | dev_dbg(codec->dev, "M98090_DRCACT_MASK\n"); |
2085 | } | ||
2086 | 2079 | ||
2087 | if (active & M98090_DRCCLP_MASK) { | 2080 | if (active & M98090_DRCCLP_MASK) |
2088 | dev_err(codec->dev, "M98090_DRCCLP_MASK\n"); | 2081 | dev_err(codec->dev, "M98090_DRCCLP_MASK\n"); |
2089 | } | ||
2090 | 2082 | ||
2091 | return IRQ_HANDLED; | 2083 | return IRQ_HANDLED; |
2092 | } | 2084 | } |
@@ -2324,7 +2316,7 @@ static int max98090_i2c_probe(struct i2c_client *i2c, | |||
2324 | max98090->pdata = i2c->dev.platform_data; | 2316 | max98090->pdata = i2c->dev.platform_data; |
2325 | max98090->irq = i2c->irq; | 2317 | max98090->irq = i2c->irq; |
2326 | 2318 | ||
2327 | max98090->regmap = regmap_init_i2c(i2c, &max98090_regmap); | 2319 | max98090->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap); |
2328 | if (IS_ERR(max98090->regmap)) { | 2320 | if (IS_ERR(max98090->regmap)) { |
2329 | ret = PTR_ERR(max98090->regmap); | 2321 | ret = PTR_ERR(max98090->regmap); |
2330 | dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); | 2322 | dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); |
@@ -2334,18 +2326,13 @@ static int max98090_i2c_probe(struct i2c_client *i2c, | |||
2334 | ret = snd_soc_register_codec(&i2c->dev, | 2326 | ret = snd_soc_register_codec(&i2c->dev, |
2335 | &soc_codec_dev_max98090, max98090_dai, | 2327 | &soc_codec_dev_max98090, max98090_dai, |
2336 | ARRAY_SIZE(max98090_dai)); | 2328 | ARRAY_SIZE(max98090_dai)); |
2337 | if (ret < 0) | ||
2338 | regmap_exit(max98090->regmap); | ||
2339 | |||
2340 | err_enable: | 2329 | err_enable: |
2341 | return ret; | 2330 | return ret; |
2342 | } | 2331 | } |
2343 | 2332 | ||
2344 | static int max98090_i2c_remove(struct i2c_client *client) | 2333 | static int max98090_i2c_remove(struct i2c_client *client) |
2345 | { | 2334 | { |
2346 | struct max98090_priv *max98090 = dev_get_drvdata(&client->dev); | ||
2347 | snd_soc_unregister_codec(&client->dev); | 2335 | snd_soc_unregister_codec(&client->dev); |
2348 | regmap_exit(max98090->regmap); | ||
2349 | return 0; | 2336 | return 0; |
2350 | } | 2337 | } |
2351 | 2338 | ||
@@ -2369,7 +2356,7 @@ static int max98090_runtime_suspend(struct device *dev) | |||
2369 | return 0; | 2356 | return 0; |
2370 | } | 2357 | } |
2371 | 2358 | ||
2372 | static struct dev_pm_ops max98090_pm = { | 2359 | static const struct dev_pm_ops max98090_pm = { |
2373 | SET_RUNTIME_PM_OPS(max98090_runtime_suspend, | 2360 | SET_RUNTIME_PM_OPS(max98090_runtime_suspend, |
2374 | max98090_runtime_resume, NULL) | 2361 | max98090_runtime_resume, NULL) |
2375 | }; | 2362 | }; |
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index 566ea3256e2d..721587c9cd84 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c | |||
@@ -1,3 +1,22 @@ | |||
1 | /* | ||
2 | * sound/soc/codecs/si476x.c -- Codec driver for SI476X chips | ||
3 | * | ||
4 | * Copyright (C) 2012 Innovative Converged Devices(ICD) | ||
5 | * Copyright (C) 2013 Andrey Smirnov | ||
6 | * | ||
7 | * Author: Andrey Smirnov <andrew.smirnov@gmail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | |||
1 | #include <linux/module.h> | 20 | #include <linux/module.h> |
2 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
3 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
@@ -45,13 +64,23 @@ static unsigned int si476x_codec_read(struct snd_soc_codec *codec, | |||
45 | unsigned int reg) | 64 | unsigned int reg) |
46 | { | 65 | { |
47 | int err; | 66 | int err; |
67 | unsigned int val; | ||
48 | struct si476x_core *core = codec->control_data; | 68 | struct si476x_core *core = codec->control_data; |
49 | 69 | ||
50 | si476x_core_lock(core); | 70 | si476x_core_lock(core); |
51 | err = si476x_core_cmd_get_property(core, reg); | 71 | if (!si476x_core_is_powered_up(core)) |
72 | regcache_cache_only(core->regmap, true); | ||
73 | |||
74 | err = regmap_read(core->regmap, reg, &val); | ||
75 | |||
76 | if (!si476x_core_is_powered_up(core)) | ||
77 | regcache_cache_only(core->regmap, false); | ||
52 | si476x_core_unlock(core); | 78 | si476x_core_unlock(core); |
53 | 79 | ||
54 | return err; | 80 | if (err < 0) |
81 | return err; | ||
82 | |||
83 | return val; | ||
55 | } | 84 | } |
56 | 85 | ||
57 | static int si476x_codec_write(struct snd_soc_codec *codec, | 86 | static int si476x_codec_write(struct snd_soc_codec *codec, |
@@ -61,7 +90,13 @@ static int si476x_codec_write(struct snd_soc_codec *codec, | |||
61 | struct si476x_core *core = codec->control_data; | 90 | struct si476x_core *core = codec->control_data; |
62 | 91 | ||
63 | si476x_core_lock(core); | 92 | si476x_core_lock(core); |
64 | err = si476x_core_cmd_set_property(core, reg, val); | 93 | if (!si476x_core_is_powered_up(core)) |
94 | regcache_cache_only(core->regmap, true); | ||
95 | |||
96 | err = regmap_write(core->regmap, reg, val); | ||
97 | |||
98 | if (!si476x_core_is_powered_up(core)) | ||
99 | regcache_cache_only(core->regmap, false); | ||
65 | si476x_core_unlock(core); | 100 | si476x_core_unlock(core); |
66 | 101 | ||
67 | return err; | 102 | return err; |
@@ -140,7 +175,7 @@ static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
140 | dev_err(codec_dai->codec->dev, "Failed to set output format\n"); | 175 | dev_err(codec_dai->codec->dev, "Failed to set output format\n"); |
141 | return err; | 176 | return err; |
142 | } | 177 | } |
143 | 178 | ||
144 | return 0; | 179 | return 0; |
145 | } | 180 | } |
146 | 181 | ||
@@ -182,7 +217,7 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream, | |||
182 | 217 | ||
183 | err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT, | 218 | err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT, |
184 | SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK, | 219 | SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK, |
185 | (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | | 220 | (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | |
186 | (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT)); | 221 | (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT)); |
187 | if (err < 0) { | 222 | if (err < 0) { |
188 | dev_err(dai->codec->dev, "Failed to set output width\n"); | 223 | dev_err(dai->codec->dev, "Failed to set output width\n"); |
@@ -251,6 +286,6 @@ static struct platform_driver si476x_platform_driver = { | |||
251 | }; | 286 | }; |
252 | module_platform_driver(si476x_platform_driver); | 287 | module_platform_driver(si476x_platform_driver); |
253 | 288 | ||
254 | MODULE_AUTHOR("Andrey Smirnov <andrey.smirnov@convergeddevices.net>"); | 289 | MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>"); |
255 | MODULE_DESCRIPTION("ASoC Si4761/64 codec driver"); | 290 | MODULE_DESCRIPTION("ASoC Si4761/64 codec driver"); |
256 | MODULE_LICENSE("GPL"); | 291 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c new file mode 100644 index 000000000000..d447c4aa1d5e --- /dev/null +++ b/sound/soc/codecs/tas5086.c | |||
@@ -0,0 +1,591 @@ | |||
1 | /* | ||
2 | * TAS5086 ASoC codec driver | ||
3 | * | ||
4 | * Copyright (c) 2013 Daniel Mack <zonque@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * TODO: | ||
17 | * - implement DAPM and input muxing | ||
18 | * - implement modulation limit | ||
19 | * - implement non-default PWM start | ||
20 | * | ||
21 | * Note that this chip has a very unusual register layout, specifically | ||
22 | * because the registers are of unequal size, and multi-byte registers | ||
23 | * require bulk writes to take effect. Regmap does not support that kind | ||
24 | * of devices. | ||
25 | * | ||
26 | * Currently, the driver does not touch any of the registers >= 0x20, so | ||
27 | * it doesn't matter because the entire map can be accessed as 8-bit | ||
28 | * array. In case more features will be added in the future | ||
29 | * that require access to higher registers, the entire regmap H/W I/O | ||
30 | * routines have to be open-coded. | ||
31 | */ | ||
32 | |||
33 | #include <linux/module.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <linux/gpio.h> | ||
37 | #include <linux/i2c.h> | ||
38 | #include <linux/regmap.h> | ||
39 | #include <linux/spi/spi.h> | ||
40 | #include <linux/of_device.h> | ||
41 | #include <linux/of_gpio.h> | ||
42 | #include <sound/pcm.h> | ||
43 | #include <sound/pcm_params.h> | ||
44 | #include <sound/soc.h> | ||
45 | #include <sound/tlv.h> | ||
46 | #include <sound/tas5086.h> | ||
47 | |||
48 | #define TAS5086_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
49 | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
50 | SNDRV_PCM_FMTBIT_S24_3LE) | ||
51 | |||
52 | #define TAS5086_PCM_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
53 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \ | ||
54 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | \ | ||
55 | SNDRV_PCM_RATE_192000) | ||
56 | |||
57 | /* | ||
58 | * TAS5086 registers | ||
59 | */ | ||
60 | #define TAS5086_CLOCK_CONTROL 0x00 /* Clock control register */ | ||
61 | #define TAS5086_CLOCK_RATE(val) (val << 5) | ||
62 | #define TAS5086_CLOCK_RATE_MASK (0x7 << 5) | ||
63 | #define TAS5086_CLOCK_RATIO(val) (val << 2) | ||
64 | #define TAS5086_CLOCK_RATIO_MASK (0x7 << 2) | ||
65 | #define TAS5086_CLOCK_SCLK_RATIO_48 (1 << 1) | ||
66 | #define TAS5086_CLOCK_VALID (1 << 0) | ||
67 | |||
68 | #define TAS5086_DEEMPH_MASK 0x03 | ||
69 | #define TAS5086_SOFT_MUTE_ALL 0x3f | ||
70 | |||
71 | #define TAS5086_DEV_ID 0x01 /* Device ID register */ | ||
72 | #define TAS5086_ERROR_STATUS 0x02 /* Error status register */ | ||
73 | #define TAS5086_SYS_CONTROL_1 0x03 /* System control register 1 */ | ||
74 | #define TAS5086_SERIAL_DATA_IF 0x04 /* Serial data interface register */ | ||
75 | #define TAS5086_SYS_CONTROL_2 0x05 /* System control register 2 */ | ||
76 | #define TAS5086_SOFT_MUTE 0x06 /* Soft mute register */ | ||
77 | #define TAS5086_MASTER_VOL 0x07 /* Master volume */ | ||
78 | #define TAS5086_CHANNEL_VOL(X) (0x08 + (X)) /* Channel 1-6 volume */ | ||
79 | #define TAS5086_VOLUME_CONTROL 0x09 /* Volume control register */ | ||
80 | #define TAS5086_MOD_LIMIT 0x10 /* Modulation limit register */ | ||
81 | #define TAS5086_PWM_START 0x18 /* PWM start register */ | ||
82 | #define TAS5086_SURROUND 0x19 /* Surround register */ | ||
83 | #define TAS5086_SPLIT_CAP_CHARGE 0x1a /* Split cap charge period register */ | ||
84 | #define TAS5086_OSC_TRIM 0x1b /* Oscillator trim register */ | ||
85 | #define TAS5086_BKNDERR 0x1c | ||
86 | |||
87 | /* | ||
88 | * Default TAS5086 power-up configuration | ||
89 | */ | ||
90 | static const struct reg_default tas5086_reg_defaults[] = { | ||
91 | { 0x00, 0x6c }, | ||
92 | { 0x01, 0x03 }, | ||
93 | { 0x02, 0x00 }, | ||
94 | { 0x03, 0xa0 }, | ||
95 | { 0x04, 0x05 }, | ||
96 | { 0x05, 0x60 }, | ||
97 | { 0x06, 0x00 }, | ||
98 | { 0x07, 0xff }, | ||
99 | { 0x08, 0x30 }, | ||
100 | { 0x09, 0x30 }, | ||
101 | { 0x0a, 0x30 }, | ||
102 | { 0x0b, 0x30 }, | ||
103 | { 0x0c, 0x30 }, | ||
104 | { 0x0d, 0x30 }, | ||
105 | { 0x0e, 0xb1 }, | ||
106 | { 0x0f, 0x00 }, | ||
107 | { 0x10, 0x02 }, | ||
108 | { 0x11, 0x00 }, | ||
109 | { 0x12, 0x00 }, | ||
110 | { 0x13, 0x00 }, | ||
111 | { 0x14, 0x00 }, | ||
112 | { 0x15, 0x00 }, | ||
113 | { 0x16, 0x00 }, | ||
114 | { 0x17, 0x00 }, | ||
115 | { 0x18, 0x3f }, | ||
116 | { 0x19, 0x00 }, | ||
117 | { 0x1a, 0x18 }, | ||
118 | { 0x1b, 0x82 }, | ||
119 | { 0x1c, 0x05 }, | ||
120 | }; | ||
121 | |||
122 | static bool tas5086_accessible_reg(struct device *dev, unsigned int reg) | ||
123 | { | ||
124 | return !((reg == 0x0f) || (reg >= 0x11 && reg <= 0x17)); | ||
125 | } | ||
126 | |||
127 | static bool tas5086_volatile_reg(struct device *dev, unsigned int reg) | ||
128 | { | ||
129 | switch (reg) { | ||
130 | case TAS5086_DEV_ID: | ||
131 | case TAS5086_ERROR_STATUS: | ||
132 | return true; | ||
133 | } | ||
134 | |||
135 | return false; | ||
136 | } | ||
137 | |||
138 | static bool tas5086_writeable_reg(struct device *dev, unsigned int reg) | ||
139 | { | ||
140 | return tas5086_accessible_reg(dev, reg) && (reg != TAS5086_DEV_ID); | ||
141 | } | ||
142 | |||
143 | struct tas5086_private { | ||
144 | struct regmap *regmap; | ||
145 | unsigned int mclk, sclk; | ||
146 | unsigned int format; | ||
147 | bool deemph; | ||
148 | /* Current sample rate for de-emphasis control */ | ||
149 | int rate; | ||
150 | /* GPIO driving Reset pin, if any */ | ||
151 | int gpio_nreset; | ||
152 | }; | ||
153 | |||
154 | static int tas5086_deemph[] = { 0, 32000, 44100, 48000 }; | ||
155 | |||
156 | static int tas5086_set_deemph(struct snd_soc_codec *codec) | ||
157 | { | ||
158 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | ||
159 | int i, val = 0; | ||
160 | |||
161 | if (priv->deemph) | ||
162 | for (i = 0; i < ARRAY_SIZE(tas5086_deemph); i++) | ||
163 | if (tas5086_deemph[i] == priv->rate) | ||
164 | val = i; | ||
165 | |||
166 | return regmap_update_bits(priv->regmap, TAS5086_SYS_CONTROL_1, | ||
167 | TAS5086_DEEMPH_MASK, val); | ||
168 | } | ||
169 | |||
170 | static int tas5086_get_deemph(struct snd_kcontrol *kcontrol, | ||
171 | struct snd_ctl_elem_value *ucontrol) | ||
172 | { | ||
173 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
174 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | ||
175 | |||
176 | ucontrol->value.enumerated.item[0] = priv->deemph; | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static int tas5086_put_deemph(struct snd_kcontrol *kcontrol, | ||
182 | struct snd_ctl_elem_value *ucontrol) | ||
183 | { | ||
184 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
185 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | ||
186 | |||
187 | priv->deemph = ucontrol->value.enumerated.item[0]; | ||
188 | |||
189 | return tas5086_set_deemph(codec); | ||
190 | } | ||
191 | |||
192 | |||
193 | static int tas5086_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
194 | int clk_id, unsigned int freq, int dir) | ||
195 | { | ||
196 | struct snd_soc_codec *codec = codec_dai->codec; | ||
197 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | ||
198 | |||
199 | switch (clk_id) { | ||
200 | case TAS5086_CLK_IDX_MCLK: | ||
201 | priv->mclk = freq; | ||
202 | break; | ||
203 | case TAS5086_CLK_IDX_SCLK: | ||
204 | priv->sclk = freq; | ||
205 | break; | ||
206 | } | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static int tas5086_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
212 | unsigned int format) | ||
213 | { | ||
214 | struct snd_soc_codec *codec = codec_dai->codec; | ||
215 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | ||
216 | |||
217 | /* The TAS5086 can only be slave to all clocks */ | ||
218 | if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { | ||
219 | dev_err(codec->dev, "Invalid clocking mode\n"); | ||
220 | return -EINVAL; | ||
221 | } | ||
222 | |||
223 | /* we need to refer to the data format from hw_params() */ | ||
224 | priv->format = format; | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static const int tas5086_sample_rates[] = { | ||
230 | 32000, 38000, 44100, 48000, 88200, 96000, 176400, 192000 | ||
231 | }; | ||
232 | |||
233 | static const int tas5086_ratios[] = { | ||
234 | 64, 128, 192, 256, 384, 512 | ||
235 | }; | ||
236 | |||
237 | static int index_in_array(const int *array, int len, int needle) | ||
238 | { | ||
239 | int i; | ||
240 | |||
241 | for (i = 0; i < len; i++) | ||
242 | if (array[i] == needle) | ||
243 | return i; | ||
244 | |||
245 | return -ENOENT; | ||
246 | } | ||
247 | |||
248 | static int tas5086_hw_params(struct snd_pcm_substream *substream, | ||
249 | struct snd_pcm_hw_params *params, | ||
250 | struct snd_soc_dai *dai) | ||
251 | { | ||
252 | struct snd_soc_codec *codec = dai->codec; | ||
253 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | ||
254 | int val; | ||
255 | int ret; | ||
256 | |||
257 | priv->rate = params_rate(params); | ||
258 | |||
259 | /* Look up the sample rate and refer to the offset in the list */ | ||
260 | val = index_in_array(tas5086_sample_rates, | ||
261 | ARRAY_SIZE(tas5086_sample_rates), priv->rate); | ||
262 | |||
263 | if (val < 0) { | ||
264 | dev_err(codec->dev, "Invalid sample rate\n"); | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | |||
268 | ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL, | ||
269 | TAS5086_CLOCK_RATE_MASK, | ||
270 | TAS5086_CLOCK_RATE(val)); | ||
271 | if (ret < 0) | ||
272 | return ret; | ||
273 | |||
274 | /* MCLK / Fs ratio */ | ||
275 | val = index_in_array(tas5086_ratios, ARRAY_SIZE(tas5086_ratios), | ||
276 | priv->mclk / priv->rate); | ||
277 | if (val < 0) { | ||
278 | dev_err(codec->dev, "Inavlid MCLK / Fs ratio\n"); | ||
279 | return -EINVAL; | ||
280 | } | ||
281 | |||
282 | ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL, | ||
283 | TAS5086_CLOCK_RATIO_MASK, | ||
284 | TAS5086_CLOCK_RATIO(val)); | ||
285 | if (ret < 0) | ||
286 | return ret; | ||
287 | |||
288 | |||
289 | ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL, | ||
290 | TAS5086_CLOCK_SCLK_RATIO_48, | ||
291 | (priv->sclk == 48 * priv->rate) ? | ||
292 | TAS5086_CLOCK_SCLK_RATIO_48 : 0); | ||
293 | if (ret < 0) | ||
294 | return ret; | ||
295 | |||
296 | /* | ||
297 | * The chip has a very unituitive register mapping and muxes information | ||
298 | * about data format and sample depth into the same register, but not on | ||
299 | * a logical bit-boundary. Hence, we have to refer to the format passed | ||
300 | * in the set_dai_fmt() callback and set up everything from here. | ||
301 | * | ||
302 | * First, determine the 'base' value, using the format ... | ||
303 | */ | ||
304 | switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
305 | case SND_SOC_DAIFMT_RIGHT_J: | ||
306 | val = 0x00; | ||
307 | break; | ||
308 | case SND_SOC_DAIFMT_I2S: | ||
309 | val = 0x03; | ||
310 | break; | ||
311 | case SND_SOC_DAIFMT_LEFT_J: | ||
312 | val = 0x06; | ||
313 | break; | ||
314 | default: | ||
315 | dev_err(codec->dev, "Invalid DAI format\n"); | ||
316 | return -EINVAL; | ||
317 | } | ||
318 | |||
319 | /* ... then add the offset for the sample bit depth. */ | ||
320 | switch (params_format(params)) { | ||
321 | case SNDRV_PCM_FORMAT_S16_LE: | ||
322 | val += 0; | ||
323 | break; | ||
324 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
325 | val += 1; | ||
326 | break; | ||
327 | case SNDRV_PCM_FORMAT_S24_3LE: | ||
328 | val += 2; | ||
329 | break; | ||
330 | default: | ||
331 | dev_err(codec->dev, "Invalid bit width\n"); | ||
332 | return -EINVAL; | ||
333 | }; | ||
334 | |||
335 | ret = regmap_write(priv->regmap, TAS5086_SERIAL_DATA_IF, val); | ||
336 | if (ret < 0) | ||
337 | return ret; | ||
338 | |||
339 | /* clock is considered valid now */ | ||
340 | ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL, | ||
341 | TAS5086_CLOCK_VALID, TAS5086_CLOCK_VALID); | ||
342 | if (ret < 0) | ||
343 | return ret; | ||
344 | |||
345 | return tas5086_set_deemph(codec); | ||
346 | } | ||
347 | |||
348 | static int tas5086_mute_stream(struct snd_soc_dai *dai, int mute, int stream) | ||
349 | { | ||
350 | struct snd_soc_codec *codec = dai->codec; | ||
351 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | ||
352 | unsigned int val = 0; | ||
353 | |||
354 | if (mute) | ||
355 | val = TAS5086_SOFT_MUTE_ALL; | ||
356 | |||
357 | return regmap_write(priv->regmap, TAS5086_SOFT_MUTE, val); | ||
358 | } | ||
359 | |||
360 | /* TAS5086 controls */ | ||
361 | static const DECLARE_TLV_DB_SCALE(tas5086_dac_tlv, -10350, 50, 1); | ||
362 | |||
363 | static const struct snd_kcontrol_new tas5086_controls[] = { | ||
364 | SOC_SINGLE_TLV("Master Playback Volume", TAS5086_MASTER_VOL, | ||
365 | 0, 0xff, 1, tas5086_dac_tlv), | ||
366 | SOC_DOUBLE_R_TLV("Channel 1/2 Playback Volume", | ||
367 | TAS5086_CHANNEL_VOL(0), TAS5086_CHANNEL_VOL(1), | ||
368 | 0, 0xff, 1, tas5086_dac_tlv), | ||
369 | SOC_DOUBLE_R_TLV("Channel 3/4 Playback Volume", | ||
370 | TAS5086_CHANNEL_VOL(2), TAS5086_CHANNEL_VOL(3), | ||
371 | 0, 0xff, 1, tas5086_dac_tlv), | ||
372 | SOC_DOUBLE_R_TLV("Channel 5/6 Playback Volume", | ||
373 | TAS5086_CHANNEL_VOL(4), TAS5086_CHANNEL_VOL(5), | ||
374 | 0, 0xff, 1, tas5086_dac_tlv), | ||
375 | SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0, | ||
376 | tas5086_get_deemph, tas5086_put_deemph), | ||
377 | }; | ||
378 | |||
379 | static const struct snd_soc_dai_ops tas5086_dai_ops = { | ||
380 | .hw_params = tas5086_hw_params, | ||
381 | .set_sysclk = tas5086_set_dai_sysclk, | ||
382 | .set_fmt = tas5086_set_dai_fmt, | ||
383 | .mute_stream = tas5086_mute_stream, | ||
384 | }; | ||
385 | |||
386 | static struct snd_soc_dai_driver tas5086_dai = { | ||
387 | .name = "tas5086-hifi", | ||
388 | .playback = { | ||
389 | .stream_name = "Playback", | ||
390 | .channels_min = 2, | ||
391 | .channels_max = 6, | ||
392 | .rates = TAS5086_PCM_RATES, | ||
393 | .formats = TAS5086_PCM_FORMATS, | ||
394 | }, | ||
395 | .ops = &tas5086_dai_ops, | ||
396 | }; | ||
397 | |||
398 | #ifdef CONFIG_PM | ||
399 | static int tas5086_soc_resume(struct snd_soc_codec *codec) | ||
400 | { | ||
401 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | ||
402 | |||
403 | /* Restore codec state */ | ||
404 | return regcache_sync(priv->regmap); | ||
405 | } | ||
406 | #else | ||
407 | #define tas5086_soc_resume NULL | ||
408 | #endif /* CONFIG_PM */ | ||
409 | |||
410 | #ifdef CONFIG_OF | ||
411 | static const struct of_device_id tas5086_dt_ids[] = { | ||
412 | { .compatible = "ti,tas5086", }, | ||
413 | { } | ||
414 | }; | ||
415 | MODULE_DEVICE_TABLE(of, tas5086_dt_ids); | ||
416 | #endif | ||
417 | |||
418 | /* charge period values in microseconds */ | ||
419 | static const int tas5086_charge_period[] = { | ||
420 | 13000, 16900, 23400, 31200, 41600, 54600, 72800, 96200, | ||
421 | 130000, 156000, 234000, 312000, 416000, 546000, 728000, 962000, | ||
422 | 1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000, | ||
423 | }; | ||
424 | |||
425 | static int tas5086_probe(struct snd_soc_codec *codec) | ||
426 | { | ||
427 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | ||
428 | int charge_period = 1300000; /* hardware default is 1300 ms */ | ||
429 | int i, ret; | ||
430 | |||
431 | if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) { | ||
432 | struct device_node *of_node = codec->dev->of_node; | ||
433 | of_property_read_u32(of_node, "ti,charge-period", &charge_period); | ||
434 | } | ||
435 | |||
436 | /* lookup and set split-capacitor charge period */ | ||
437 | if (charge_period == 0) { | ||
438 | regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0); | ||
439 | } else { | ||
440 | i = index_in_array(tas5086_charge_period, | ||
441 | ARRAY_SIZE(tas5086_charge_period), | ||
442 | charge_period); | ||
443 | if (i >= 0) | ||
444 | regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, | ||
445 | i + 0x08); | ||
446 | else | ||
447 | dev_warn(codec->dev, | ||
448 | "Invalid split-cap charge period of %d ns.\n", | ||
449 | charge_period); | ||
450 | } | ||
451 | |||
452 | /* enable factory trim */ | ||
453 | ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00); | ||
454 | if (ret < 0) | ||
455 | return ret; | ||
456 | |||
457 | /* start all channels */ | ||
458 | ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20); | ||
459 | if (ret < 0) | ||
460 | return ret; | ||
461 | |||
462 | /* set master volume to 0 dB */ | ||
463 | ret = regmap_write(priv->regmap, TAS5086_MASTER_VOL, 0x30); | ||
464 | if (ret < 0) | ||
465 | return ret; | ||
466 | |||
467 | /* mute all channels for now */ | ||
468 | ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE, | ||
469 | TAS5086_SOFT_MUTE_ALL); | ||
470 | if (ret < 0) | ||
471 | return ret; | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | static int tas5086_remove(struct snd_soc_codec *codec) | ||
477 | { | ||
478 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | ||
479 | |||
480 | if (gpio_is_valid(priv->gpio_nreset)) | ||
481 | /* Set codec to the reset state */ | ||
482 | gpio_set_value(priv->gpio_nreset, 0); | ||
483 | |||
484 | return 0; | ||
485 | }; | ||
486 | |||
487 | static struct snd_soc_codec_driver soc_codec_dev_tas5086 = { | ||
488 | .probe = tas5086_probe, | ||
489 | .remove = tas5086_remove, | ||
490 | .resume = tas5086_soc_resume, | ||
491 | .controls = tas5086_controls, | ||
492 | .num_controls = ARRAY_SIZE(tas5086_controls), | ||
493 | }; | ||
494 | |||
495 | static const struct i2c_device_id tas5086_i2c_id[] = { | ||
496 | { "tas5086", 0 }, | ||
497 | { } | ||
498 | }; | ||
499 | MODULE_DEVICE_TABLE(i2c, tas5086_i2c_id); | ||
500 | |||
501 | static const struct regmap_config tas5086_regmap = { | ||
502 | .reg_bits = 8, | ||
503 | .val_bits = 8, | ||
504 | .max_register = ARRAY_SIZE(tas5086_reg_defaults), | ||
505 | .reg_defaults = tas5086_reg_defaults, | ||
506 | .num_reg_defaults = ARRAY_SIZE(tas5086_reg_defaults), | ||
507 | .cache_type = REGCACHE_RBTREE, | ||
508 | .volatile_reg = tas5086_volatile_reg, | ||
509 | .writeable_reg = tas5086_writeable_reg, | ||
510 | .readable_reg = tas5086_accessible_reg, | ||
511 | }; | ||
512 | |||
513 | static int tas5086_i2c_probe(struct i2c_client *i2c, | ||
514 | const struct i2c_device_id *id) | ||
515 | { | ||
516 | struct tas5086_private *priv; | ||
517 | struct device *dev = &i2c->dev; | ||
518 | int gpio_nreset = -EINVAL; | ||
519 | int i, ret; | ||
520 | |||
521 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
522 | if (!priv) | ||
523 | return -ENOMEM; | ||
524 | |||
525 | priv->regmap = devm_regmap_init_i2c(i2c, &tas5086_regmap); | ||
526 | if (IS_ERR(priv->regmap)) { | ||
527 | ret = PTR_ERR(priv->regmap); | ||
528 | dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); | ||
529 | return ret; | ||
530 | } | ||
531 | |||
532 | i2c_set_clientdata(i2c, priv); | ||
533 | |||
534 | if (of_match_device(of_match_ptr(tas5086_dt_ids), dev)) { | ||
535 | struct device_node *of_node = dev->of_node; | ||
536 | gpio_nreset = of_get_named_gpio(of_node, "reset-gpio", 0); | ||
537 | } | ||
538 | |||
539 | if (gpio_is_valid(gpio_nreset)) | ||
540 | if (devm_gpio_request(dev, gpio_nreset, "TAS5086 Reset")) | ||
541 | gpio_nreset = -EINVAL; | ||
542 | |||
543 | if (gpio_is_valid(gpio_nreset)) { | ||
544 | /* Reset codec - minimum assertion time is 400ns */ | ||
545 | gpio_direction_output(gpio_nreset, 0); | ||
546 | udelay(1); | ||
547 | gpio_set_value(gpio_nreset, 1); | ||
548 | |||
549 | /* Codec needs ~15ms to wake up */ | ||
550 | msleep(15); | ||
551 | } | ||
552 | |||
553 | priv->gpio_nreset = gpio_nreset; | ||
554 | |||
555 | /* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */ | ||
556 | ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i); | ||
557 | if (ret < 0) | ||
558 | return ret; | ||
559 | |||
560 | if (i != 0x3) { | ||
561 | dev_err(dev, | ||
562 | "Failed to identify TAS5086 codec (got %02x)\n", i); | ||
563 | return -ENODEV; | ||
564 | } | ||
565 | |||
566 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086, | ||
567 | &tas5086_dai, 1); | ||
568 | } | ||
569 | |||
570 | static int tas5086_i2c_remove(struct i2c_client *i2c) | ||
571 | { | ||
572 | snd_soc_unregister_codec(&i2c->dev); | ||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | static struct i2c_driver tas5086_i2c_driver = { | ||
577 | .driver = { | ||
578 | .name = "tas5086", | ||
579 | .owner = THIS_MODULE, | ||
580 | .of_match_table = of_match_ptr(tas5086_dt_ids), | ||
581 | }, | ||
582 | .id_table = tas5086_i2c_id, | ||
583 | .probe = tas5086_i2c_probe, | ||
584 | .remove = tas5086_i2c_remove, | ||
585 | }; | ||
586 | |||
587 | module_i2c_driver(tas5086_i2c_driver); | ||
588 | |||
589 | MODULE_AUTHOR("Daniel Mack <zonque@gmail.com>"); | ||
590 | MODULE_DESCRIPTION("Texas Instruments TAS5086 ALSA SoC Codec Driver"); | ||
591 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index ad2fee4bb4cd..8df2b6e1a1a6 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c | |||
@@ -342,7 +342,7 @@ static void byte_swap_64(u64 *data_in, u64 *data_out, u32 len) | |||
342 | data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i])); | 342 | data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i])); |
343 | } | 343 | } |
344 | 344 | ||
345 | static int wm0010_firmware_load(char *name, struct snd_soc_codec *codec) | 345 | static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec) |
346 | { | 346 | { |
347 | struct spi_device *spi = to_spi_device(codec->dev); | 347 | struct spi_device *spi = to_spi_device(codec->dev); |
348 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | 348 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); |
@@ -361,8 +361,8 @@ static int wm0010_firmware_load(char *name, struct snd_soc_codec *codec) | |||
361 | 361 | ||
362 | ret = request_firmware(&fw, name, codec->dev); | 362 | ret = request_firmware(&fw, name, codec->dev); |
363 | if (ret != 0) { | 363 | if (ret != 0) { |
364 | dev_err(codec->dev, "Failed to request application: %d\n", | 364 | dev_err(codec->dev, "Failed to request application(%s): %d\n", |
365 | ret); | 365 | name, ret); |
366 | return ret; | 366 | return ret; |
367 | } | 367 | } |
368 | 368 | ||
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index f2ac38b61a1b..7fefd766b582 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -761,6 +761,8 @@ static bool wm2000_readable_reg(struct device *dev, unsigned int reg) | |||
761 | case WM2000_REG_SYS_CTL2: | 761 | case WM2000_REG_SYS_CTL2: |
762 | case WM2000_REG_ANC_STAT: | 762 | case WM2000_REG_ANC_STAT: |
763 | case WM2000_REG_IF_CTL: | 763 | case WM2000_REG_IF_CTL: |
764 | case WM2000_REG_ANA_MIC_CTL: | ||
765 | case WM2000_REG_SPK_CTL: | ||
764 | return true; | 766 | return true; |
765 | default: | 767 | default: |
766 | return false; | 768 | return false; |
@@ -771,7 +773,7 @@ static const struct regmap_config wm2000_regmap = { | |||
771 | .reg_bits = 16, | 773 | .reg_bits = 16, |
772 | .val_bits = 8, | 774 | .val_bits = 8, |
773 | 775 | ||
774 | .max_register = WM2000_REG_IF_CTL, | 776 | .max_register = WM2000_REG_SPK_CTL, |
775 | .readable_reg = wm2000_readable_reg, | 777 | .readable_reg = wm2000_readable_reg, |
776 | }; | 778 | }; |
777 | 779 | ||
diff --git a/sound/soc/codecs/wm2000.h b/sound/soc/codecs/wm2000.h index fb812cd9e77d..3870c0e1d246 100644 --- a/sound/soc/codecs/wm2000.h +++ b/sound/soc/codecs/wm2000.h | |||
@@ -30,6 +30,8 @@ | |||
30 | #define WM2000_REG_SYS_CTL2 0xf004 | 30 | #define WM2000_REG_SYS_CTL2 0xf004 |
31 | #define WM2000_REG_ANC_STAT 0xf005 | 31 | #define WM2000_REG_ANC_STAT 0xf005 |
32 | #define WM2000_REG_IF_CTL 0xf006 | 32 | #define WM2000_REG_IF_CTL 0xf006 |
33 | #define WM2000_REG_ANA_MIC_CTL 0xf028 | ||
34 | #define WM2000_REG_SPK_CTL 0xf034 | ||
33 | 35 | ||
34 | /* SPEECH_CLARITY */ | 36 | /* SPEECH_CLARITY */ |
35 | #define WM2000_SPEECH_CLARITY 0x01 | 37 | #define WM2000_SPEECH_CLARITY 0x01 |
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index ddc98f02ecbd..57ba315d0c84 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c | |||
@@ -1565,7 +1565,7 @@ static int wm2200_probe(struct snd_soc_codec *codec) | |||
1565 | return ret; | 1565 | return ret; |
1566 | } | 1566 | } |
1567 | 1567 | ||
1568 | ret = snd_soc_add_codec_controls(codec, wm_adsp_fw_controls, 2); | 1568 | ret = snd_soc_add_codec_controls(codec, wm_adsp1_fw_controls, 2); |
1569 | if (ret != 0) | 1569 | if (ret != 0) |
1570 | return ret; | 1570 | return ret; |
1571 | 1571 | ||
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 15bc31f1abb1..e895d3939eef 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -36,9 +36,6 @@ | |||
36 | struct wm5102_priv { | 36 | struct wm5102_priv { |
37 | struct arizona_priv core; | 37 | struct arizona_priv core; |
38 | struct arizona_fll fll[2]; | 38 | struct arizona_fll fll[2]; |
39 | |||
40 | unsigned int spk_ena:2; | ||
41 | unsigned int spk_ena_pending:1; | ||
42 | }; | 39 | }; |
43 | 40 | ||
44 | static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); | 41 | static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); |
@@ -615,6 +612,26 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
615 | return 0; | 612 | return 0; |
616 | } | 613 | } |
617 | 614 | ||
615 | static const char *wm5102_osr_text[] = { | ||
616 | "Low power", "Normal", "High performance", | ||
617 | }; | ||
618 | |||
619 | static const unsigned int wm5102_osr_val[] = { | ||
620 | 0x0, 0x3, 0x5, | ||
621 | }; | ||
622 | |||
623 | static const struct soc_enum wm5102_hpout_osr[] = { | ||
624 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L, | ||
625 | ARIZONA_OUT1_OSR_SHIFT, 0x7, 3, | ||
626 | wm5102_osr_text, wm5102_osr_val), | ||
627 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L, | ||
628 | ARIZONA_OUT2_OSR_SHIFT, 0x7, 3, | ||
629 | wm5102_osr_text, wm5102_osr_val), | ||
630 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L, | ||
631 | ARIZONA_OUT3_OSR_SHIFT, 0x7, 3, | ||
632 | wm5102_osr_text, wm5102_osr_val), | ||
633 | }; | ||
634 | |||
618 | #define WM5102_NG_SRC(name, base) \ | 635 | #define WM5102_NG_SRC(name, base) \ |
619 | SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ | 636 | SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ |
620 | SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ | 637 | SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ |
@@ -745,6 +762,9 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), | |||
745 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), | 762 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), |
746 | SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), | 763 | SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), |
747 | 764 | ||
765 | SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]), | ||
766 | SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]), | ||
767 | |||
748 | ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), | 768 | ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), |
749 | ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), | 769 | ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), |
750 | 770 | ||
@@ -761,6 +781,8 @@ ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE), | |||
761 | ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), | 781 | ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), |
762 | ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), | 782 | ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), |
763 | 783 | ||
784 | SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L, | ||
785 | ARIZONA_OUT4_OSR_SHIFT, 1, 0), | ||
764 | SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L, | 786 | SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L, |
765 | ARIZONA_OUT5_OSR_SHIFT, 1, 0), | 787 | ARIZONA_OUT5_OSR_SHIFT, 1, 0), |
766 | 788 | ||
@@ -790,6 +812,10 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L, | |||
790 | ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT, | 812 | ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT, |
791 | 0xbf, 0, digital_tlv), | 813 | 0xbf, 0, digital_tlv), |
792 | 814 | ||
815 | SOC_VALUE_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]), | ||
816 | SOC_VALUE_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]), | ||
817 | SOC_VALUE_ENUM("HPOUT3 OSR", wm5102_hpout_osr[2]), | ||
818 | |||
793 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), | 819 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), |
794 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), | 820 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), |
795 | 821 | ||
@@ -828,47 +854,6 @@ ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), | |||
828 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), | 854 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), |
829 | }; | 855 | }; |
830 | 856 | ||
831 | static int wm5102_spk_ev(struct snd_soc_dapm_widget *w, | ||
832 | struct snd_kcontrol *kcontrol, | ||
833 | int event) | ||
834 | { | ||
835 | struct snd_soc_codec *codec = w->codec; | ||
836 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
837 | struct wm5102_priv *wm5102 = snd_soc_codec_get_drvdata(codec); | ||
838 | |||
839 | if (arizona->rev < 1) | ||
840 | return 0; | ||
841 | |||
842 | switch (event) { | ||
843 | case SND_SOC_DAPM_PRE_PMU: | ||
844 | if (!wm5102->spk_ena) { | ||
845 | snd_soc_write(codec, 0x4f5, 0x25a); | ||
846 | wm5102->spk_ena_pending = true; | ||
847 | } | ||
848 | break; | ||
849 | case SND_SOC_DAPM_POST_PMU: | ||
850 | if (wm5102->spk_ena_pending) { | ||
851 | msleep(75); | ||
852 | snd_soc_write(codec, 0x4f5, 0xda); | ||
853 | wm5102->spk_ena_pending = false; | ||
854 | wm5102->spk_ena++; | ||
855 | } | ||
856 | break; | ||
857 | case SND_SOC_DAPM_PRE_PMD: | ||
858 | wm5102->spk_ena--; | ||
859 | if (!wm5102->spk_ena) | ||
860 | snd_soc_write(codec, 0x4f5, 0x25a); | ||
861 | break; | ||
862 | case SND_SOC_DAPM_POST_PMD: | ||
863 | if (!wm5102->spk_ena) | ||
864 | snd_soc_write(codec, 0x4f5, 0x0da); | ||
865 | break; | ||
866 | } | ||
867 | |||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | |||
872 | ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); | 857 | ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); |
873 | ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE); | 858 | ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE); |
874 | ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE); | 859 | ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE); |
@@ -984,22 +969,28 @@ SND_SOC_DAPM_INPUT("IN3R"), | |||
984 | 969 | ||
985 | SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, | 970 | SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, |
986 | 0, NULL, 0, arizona_in_ev, | 971 | 0, NULL, 0, arizona_in_ev, |
987 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 972 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
973 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
988 | SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, | 974 | SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, |
989 | 0, NULL, 0, arizona_in_ev, | 975 | 0, NULL, 0, arizona_in_ev, |
990 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 976 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
977 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
991 | SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, | 978 | SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, |
992 | 0, NULL, 0, arizona_in_ev, | 979 | 0, NULL, 0, arizona_in_ev, |
993 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 980 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
981 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
994 | SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, | 982 | SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, |
995 | 0, NULL, 0, arizona_in_ev, | 983 | 0, NULL, 0, arizona_in_ev, |
996 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 984 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
985 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
997 | SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, | 986 | SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, |
998 | 0, NULL, 0, arizona_in_ev, | 987 | 0, NULL, 0, arizona_in_ev, |
999 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 988 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
989 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
1000 | SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, | 990 | SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, |
1001 | 0, NULL, 0, arizona_in_ev, | 991 | 0, NULL, 0, arizona_in_ev, |
1002 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 992 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
993 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
1003 | 994 | ||
1004 | SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, | 995 | SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, |
1005 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | 996 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), |
@@ -1146,12 +1137,6 @@ SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, | |||
1146 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, | 1137 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, |
1147 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 1138 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
1148 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 1139 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
1149 | SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1, | ||
1150 | ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev, | ||
1151 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
1152 | SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1, | ||
1153 | ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev, | ||
1154 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
1155 | SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, | 1140 | SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, |
1156 | ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 1141 | ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
1157 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 1142 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
@@ -1494,6 +1479,12 @@ static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
1494 | return arizona_set_fll(&wm5102->fll[0], source, Fref, Fout); | 1479 | return arizona_set_fll(&wm5102->fll[0], source, Fref, Fout); |
1495 | case WM5102_FLL2: | 1480 | case WM5102_FLL2: |
1496 | return arizona_set_fll(&wm5102->fll[1], source, Fref, Fout); | 1481 | return arizona_set_fll(&wm5102->fll[1], source, Fref, Fout); |
1482 | case WM5102_FLL1_REFCLK: | ||
1483 | return arizona_set_fll_refclk(&wm5102->fll[0], source, Fref, | ||
1484 | Fout); | ||
1485 | case WM5102_FLL2_REFCLK: | ||
1486 | return arizona_set_fll_refclk(&wm5102->fll[1], source, Fref, | ||
1487 | Fout); | ||
1497 | default: | 1488 | default: |
1498 | return -EINVAL; | 1489 | return -EINVAL; |
1499 | } | 1490 | } |
@@ -1581,10 +1572,12 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec) | |||
1581 | if (ret != 0) | 1572 | if (ret != 0) |
1582 | return ret; | 1573 | return ret; |
1583 | 1574 | ||
1584 | ret = snd_soc_add_codec_controls(codec, wm_adsp_fw_controls, 1); | 1575 | ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 2); |
1585 | if (ret != 0) | 1576 | if (ret != 0) |
1586 | return ret; | 1577 | return ret; |
1587 | 1578 | ||
1579 | arizona_init_spk(codec); | ||
1580 | |||
1588 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); | 1581 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); |
1589 | 1582 | ||
1590 | priv->core.arizona->dapm = &codec->dapm; | 1583 | priv->core.arizona->dapm = &codec->dapm; |
@@ -1604,13 +1597,6 @@ static int wm5102_codec_remove(struct snd_soc_codec *codec) | |||
1604 | #define WM5102_DIG_VU 0x0200 | 1597 | #define WM5102_DIG_VU 0x0200 |
1605 | 1598 | ||
1606 | static unsigned int wm5102_digital_vu[] = { | 1599 | static unsigned int wm5102_digital_vu[] = { |
1607 | ARIZONA_ADC_DIGITAL_VOLUME_1L, | ||
1608 | ARIZONA_ADC_DIGITAL_VOLUME_1R, | ||
1609 | ARIZONA_ADC_DIGITAL_VOLUME_2L, | ||
1610 | ARIZONA_ADC_DIGITAL_VOLUME_2R, | ||
1611 | ARIZONA_ADC_DIGITAL_VOLUME_3L, | ||
1612 | ARIZONA_ADC_DIGITAL_VOLUME_3R, | ||
1613 | |||
1614 | ARIZONA_DAC_DIGITAL_VOLUME_1L, | 1600 | ARIZONA_DAC_DIGITAL_VOLUME_1L, |
1615 | ARIZONA_DAC_DIGITAL_VOLUME_1R, | 1601 | ARIZONA_DAC_DIGITAL_VOLUME_1R, |
1616 | ARIZONA_DAC_DIGITAL_VOLUME_2L, | 1602 | ARIZONA_DAC_DIGITAL_VOLUME_2L, |
@@ -1653,6 +1639,7 @@ static int wm5102_probe(struct platform_device *pdev) | |||
1653 | platform_set_drvdata(pdev, wm5102); | 1639 | platform_set_drvdata(pdev, wm5102); |
1654 | 1640 | ||
1655 | wm5102->core.arizona = arizona; | 1641 | wm5102->core.arizona = arizona; |
1642 | wm5102->core.num_inputs = 6; | ||
1656 | 1643 | ||
1657 | wm5102->core.adsp[0].part = "wm5102"; | 1644 | wm5102->core.adsp[0].part = "wm5102"; |
1658 | wm5102->core.adsp[0].num = 1; | 1645 | wm5102->core.adsp[0].num = 1; |
@@ -1677,6 +1664,12 @@ static int wm5102_probe(struct platform_device *pdev) | |||
1677 | ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, | 1664 | ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, |
1678 | &wm5102->fll[1]); | 1665 | &wm5102->fll[1]); |
1679 | 1666 | ||
1667 | /* SR2 fixed at 8kHz, SR3 fixed at 16kHz */ | ||
1668 | regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_2, | ||
1669 | ARIZONA_SAMPLE_RATE_2_MASK, 0x11); | ||
1670 | regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_3, | ||
1671 | ARIZONA_SAMPLE_RATE_3_MASK, 0x12); | ||
1672 | |||
1680 | for (i = 0; i < ARRAY_SIZE(wm5102_dai); i++) | 1673 | for (i = 0; i < ARRAY_SIZE(wm5102_dai); i++) |
1681 | arizona_init_dai(&wm5102->core, i); | 1674 | arizona_init_dai(&wm5102->core, i); |
1682 | 1675 | ||
diff --git a/sound/soc/codecs/wm5102.h b/sound/soc/codecs/wm5102.h index d30477f3070c..adb38040f661 100644 --- a/sound/soc/codecs/wm5102.h +++ b/sound/soc/codecs/wm5102.h | |||
@@ -15,7 +15,9 @@ | |||
15 | 15 | ||
16 | #include "arizona.h" | 16 | #include "arizona.h" |
17 | 17 | ||
18 | #define WM5102_FLL1 1 | 18 | #define WM5102_FLL1 1 |
19 | #define WM5102_FLL2 2 | 19 | #define WM5102_FLL2 2 |
20 | #define WM5102_FLL1_REFCLK 3 | ||
21 | #define WM5102_FLL2_REFCLK 4 | ||
20 | 22 | ||
21 | #endif | 23 | #endif |
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 7841b42a819c..731884e04776 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -416,28 +416,36 @@ SND_SOC_DAPM_INPUT("IN4R"), | |||
416 | 416 | ||
417 | SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, | 417 | SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, |
418 | 0, NULL, 0, arizona_in_ev, | 418 | 0, NULL, 0, arizona_in_ev, |
419 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 419 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
420 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
420 | SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, | 421 | SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, |
421 | 0, NULL, 0, arizona_in_ev, | 422 | 0, NULL, 0, arizona_in_ev, |
422 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 423 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
424 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
423 | SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, | 425 | SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, |
424 | 0, NULL, 0, arizona_in_ev, | 426 | 0, NULL, 0, arizona_in_ev, |
425 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 427 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
428 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
426 | SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, | 429 | SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, |
427 | 0, NULL, 0, arizona_in_ev, | 430 | 0, NULL, 0, arizona_in_ev, |
428 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 431 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
432 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
429 | SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, | 433 | SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, |
430 | 0, NULL, 0, arizona_in_ev, | 434 | 0, NULL, 0, arizona_in_ev, |
431 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 435 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
436 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
432 | SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, | 437 | SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, |
433 | 0, NULL, 0, arizona_in_ev, | 438 | 0, NULL, 0, arizona_in_ev, |
434 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 439 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
440 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
435 | SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT, | 441 | SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT, |
436 | 0, NULL, 0, arizona_in_ev, | 442 | 0, NULL, 0, arizona_in_ev, |
437 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 443 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
444 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
438 | SND_SOC_DAPM_PGA_E("IN4R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4R_ENA_SHIFT, | 445 | SND_SOC_DAPM_PGA_E("IN4R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4R_ENA_SHIFT, |
439 | 0, NULL, 0, arizona_in_ev, | 446 | 0, NULL, 0, arizona_in_ev, |
440 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 447 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
448 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
441 | 449 | ||
442 | SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, | 450 | SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, |
443 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | 451 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), |
@@ -569,12 +577,6 @@ SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, | |||
569 | SND_SOC_DAPM_PGA_E("OUT3R", ARIZONA_OUTPUT_ENABLES_1, | 577 | SND_SOC_DAPM_PGA_E("OUT3R", ARIZONA_OUTPUT_ENABLES_1, |
570 | ARIZONA_OUT3R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 578 | ARIZONA_OUT3R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
571 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 579 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
572 | SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1, | ||
573 | ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
574 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
575 | SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1, | ||
576 | ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
577 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
578 | SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, | 580 | SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, |
579 | ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 581 | ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
580 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 582 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
@@ -880,6 +882,12 @@ static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
880 | return arizona_set_fll(&wm5110->fll[0], source, Fref, Fout); | 882 | return arizona_set_fll(&wm5110->fll[0], source, Fref, Fout); |
881 | case WM5110_FLL2: | 883 | case WM5110_FLL2: |
882 | return arizona_set_fll(&wm5110->fll[1], source, Fref, Fout); | 884 | return arizona_set_fll(&wm5110->fll[1], source, Fref, Fout); |
885 | case WM5110_FLL1_REFCLK: | ||
886 | return arizona_set_fll_refclk(&wm5110->fll[0], source, Fref, | ||
887 | Fout); | ||
888 | case WM5110_FLL2_REFCLK: | ||
889 | return arizona_set_fll_refclk(&wm5110->fll[1], source, Fref, | ||
890 | Fout); | ||
883 | default: | 891 | default: |
884 | return -EINVAL; | 892 | return -EINVAL; |
885 | } | 893 | } |
@@ -987,15 +995,6 @@ static int wm5110_codec_remove(struct snd_soc_codec *codec) | |||
987 | #define WM5110_DIG_VU 0x0200 | 995 | #define WM5110_DIG_VU 0x0200 |
988 | 996 | ||
989 | static unsigned int wm5110_digital_vu[] = { | 997 | static unsigned int wm5110_digital_vu[] = { |
990 | ARIZONA_ADC_DIGITAL_VOLUME_1L, | ||
991 | ARIZONA_ADC_DIGITAL_VOLUME_1R, | ||
992 | ARIZONA_ADC_DIGITAL_VOLUME_2L, | ||
993 | ARIZONA_ADC_DIGITAL_VOLUME_2R, | ||
994 | ARIZONA_ADC_DIGITAL_VOLUME_3L, | ||
995 | ARIZONA_ADC_DIGITAL_VOLUME_3R, | ||
996 | ARIZONA_ADC_DIGITAL_VOLUME_4L, | ||
997 | ARIZONA_ADC_DIGITAL_VOLUME_4R, | ||
998 | |||
999 | ARIZONA_DAC_DIGITAL_VOLUME_1L, | 998 | ARIZONA_DAC_DIGITAL_VOLUME_1L, |
1000 | ARIZONA_DAC_DIGITAL_VOLUME_1R, | 999 | ARIZONA_DAC_DIGITAL_VOLUME_1R, |
1001 | ARIZONA_DAC_DIGITAL_VOLUME_2L, | 1000 | ARIZONA_DAC_DIGITAL_VOLUME_2L, |
@@ -1040,6 +1039,7 @@ static int wm5110_probe(struct platform_device *pdev) | |||
1040 | platform_set_drvdata(pdev, wm5110); | 1039 | platform_set_drvdata(pdev, wm5110); |
1041 | 1040 | ||
1042 | wm5110->core.arizona = arizona; | 1041 | wm5110->core.arizona = arizona; |
1042 | wm5110->core.num_inputs = 8; | ||
1043 | 1043 | ||
1044 | for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++) | 1044 | for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++) |
1045 | wm5110->fll[i].vco_mult = 3; | 1045 | wm5110->fll[i].vco_mult = 3; |
diff --git a/sound/soc/codecs/wm5110.h b/sound/soc/codecs/wm5110.h index 75e9351ccab0..e6c0cd4235c5 100644 --- a/sound/soc/codecs/wm5110.h +++ b/sound/soc/codecs/wm5110.h | |||
@@ -15,7 +15,9 @@ | |||
15 | 15 | ||
16 | #include "arizona.h" | 16 | #include "arizona.h" |
17 | 17 | ||
18 | #define WM5110_FLL1 1 | 18 | #define WM5110_FLL1 1 |
19 | #define WM5110_FLL2 2 | 19 | #define WM5110_FLL2 2 |
20 | #define WM5110_FLL1_REFCLK 3 | ||
21 | #define WM5110_FLL2_REFCLK 4 | ||
20 | 22 | ||
21 | #endif | 23 | #endif |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index f8a31ad0b203..9d88437cdcd1 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -478,6 +478,8 @@ static int wm8903_put_deemph(struct snd_kcontrol *kcontrol, | |||
478 | /* ALSA can only do steps of .01dB */ | 478 | /* ALSA can only do steps of .01dB */ |
479 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); | 479 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); |
480 | 480 | ||
481 | static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0); | ||
482 | |||
481 | static const DECLARE_TLV_DB_SCALE(digital_sidetone_tlv, -3600, 300, 0); | 483 | static const DECLARE_TLV_DB_SCALE(digital_sidetone_tlv, -3600, 300, 0); |
482 | static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); | 484 | static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); |
483 | 485 | ||
@@ -698,6 +700,8 @@ SOC_ENUM("DAC Mute Mode", mute_mode), | |||
698 | SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0), | 700 | SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0), |
699 | SOC_ENUM("DAC Companding Mode", dac_companding), | 701 | SOC_ENUM("DAC Companding Mode", dac_companding), |
700 | SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0), | 702 | SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0), |
703 | SOC_SINGLE_TLV("DAC Boost Volume", WM8903_AUDIO_INTERFACE_0, 9, 3, 0, | ||
704 | dac_boost_tlv), | ||
701 | SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0, | 705 | SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0, |
702 | wm8903_get_deemph, wm8903_put_deemph), | 706 | wm8903_get_deemph, wm8903_put_deemph), |
703 | 707 | ||
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index a64b93425ae3..0a4ffdd1d2a7 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -204,6 +204,7 @@ static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0); | |||
204 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1); | 204 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1); |
205 | static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0); | 205 | static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0); |
206 | static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); | 206 | static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); |
207 | static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1); | ||
207 | 208 | ||
208 | static const struct snd_kcontrol_new wm8960_snd_controls[] = { | 209 | static const struct snd_kcontrol_new wm8960_snd_controls[] = { |
209 | SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL, | 210 | SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL, |
@@ -213,6 +214,15 @@ SOC_DOUBLE_R("Capture Volume ZC Switch", WM8960_LINVOL, WM8960_RINVOL, | |||
213 | SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL, | 214 | SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL, |
214 | 7, 1, 0), | 215 | 7, 1, 0), |
215 | 216 | ||
217 | SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT3 Volume", | ||
218 | WM8960_INBMIX1, 4, 7, 0, boost_tlv), | ||
219 | SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT2 Volume", | ||
220 | WM8960_INBMIX1, 1, 7, 0, boost_tlv), | ||
221 | SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT3 Volume", | ||
222 | WM8960_INBMIX2, 4, 7, 0, boost_tlv), | ||
223 | SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT2 Volume", | ||
224 | WM8960_INBMIX2, 1, 7, 0, boost_tlv), | ||
225 | |||
216 | SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC, | 226 | SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC, |
217 | 0, 255, 0, dac_tlv), | 227 | 0, 255, 0, dac_tlv), |
218 | 228 | ||
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index c9bd445c4976..14094f558e03 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -2209,7 +2209,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
2209 | vmid_reference(codec); | 2209 | vmid_reference(codec); |
2210 | break; | 2210 | break; |
2211 | case WM8958: | 2211 | case WM8958: |
2212 | if (wm8994->revision < 1) | 2212 | if (control->revision < 1) |
2213 | vmid_reference(codec); | 2213 | vmid_reference(codec); |
2214 | break; | 2214 | break; |
2215 | default: | 2215 | default: |
@@ -2244,7 +2244,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
2244 | vmid_dereference(codec); | 2244 | vmid_dereference(codec); |
2245 | break; | 2245 | break; |
2246 | case WM8958: | 2246 | case WM8958: |
2247 | if (wm8994->revision < 1) | 2247 | if (control->revision < 1) |
2248 | vmid_dereference(codec); | 2248 | vmid_dereference(codec); |
2249 | break; | 2249 | break; |
2250 | default: | 2250 | default: |
@@ -2268,10 +2268,26 @@ out: | |||
2268 | */ | 2268 | */ |
2269 | if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { | 2269 | if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { |
2270 | dev_dbg(codec->dev, "Configuring AIFs for 128fs\n"); | 2270 | dev_dbg(codec->dev, "Configuring AIFs for 128fs\n"); |
2271 | |||
2272 | wm8994->aifdiv[0] = snd_soc_read(codec, WM8994_AIF1_RATE) | ||
2273 | & WM8994_AIF1CLK_RATE_MASK; | ||
2274 | wm8994->aifdiv[1] = snd_soc_read(codec, WM8994_AIF2_RATE) | ||
2275 | & WM8994_AIF1CLK_RATE_MASK; | ||
2276 | |||
2271 | snd_soc_update_bits(codec, WM8994_AIF1_RATE, | 2277 | snd_soc_update_bits(codec, WM8994_AIF1_RATE, |
2272 | WM8994_AIF1CLK_RATE_MASK, 0x1); | 2278 | WM8994_AIF1CLK_RATE_MASK, 0x1); |
2273 | snd_soc_update_bits(codec, WM8994_AIF2_RATE, | 2279 | snd_soc_update_bits(codec, WM8994_AIF2_RATE, |
2274 | WM8994_AIF2CLK_RATE_MASK, 0x1); | 2280 | WM8994_AIF2CLK_RATE_MASK, 0x1); |
2281 | } else if (wm8994->aifdiv[0]) { | ||
2282 | snd_soc_update_bits(codec, WM8994_AIF1_RATE, | ||
2283 | WM8994_AIF1CLK_RATE_MASK, | ||
2284 | wm8994->aifdiv[0]); | ||
2285 | snd_soc_update_bits(codec, WM8994_AIF2_RATE, | ||
2286 | WM8994_AIF2CLK_RATE_MASK, | ||
2287 | wm8994->aifdiv[1]); | ||
2288 | |||
2289 | wm8994->aifdiv[0] = 0; | ||
2290 | wm8994->aifdiv[1] = 0; | ||
2275 | } | 2291 | } |
2276 | 2292 | ||
2277 | return 0; | 2293 | return 0; |
@@ -2368,10 +2384,26 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, | |||
2368 | */ | 2384 | */ |
2369 | if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { | 2385 | if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { |
2370 | dev_dbg(codec->dev, "Configuring AIFs for 128fs\n"); | 2386 | dev_dbg(codec->dev, "Configuring AIFs for 128fs\n"); |
2387 | |||
2388 | wm8994->aifdiv[0] = snd_soc_read(codec, WM8994_AIF1_RATE) | ||
2389 | & WM8994_AIF1CLK_RATE_MASK; | ||
2390 | wm8994->aifdiv[1] = snd_soc_read(codec, WM8994_AIF2_RATE) | ||
2391 | & WM8994_AIF1CLK_RATE_MASK; | ||
2392 | |||
2371 | snd_soc_update_bits(codec, WM8994_AIF1_RATE, | 2393 | snd_soc_update_bits(codec, WM8994_AIF1_RATE, |
2372 | WM8994_AIF1CLK_RATE_MASK, 0x1); | 2394 | WM8994_AIF1CLK_RATE_MASK, 0x1); |
2373 | snd_soc_update_bits(codec, WM8994_AIF2_RATE, | 2395 | snd_soc_update_bits(codec, WM8994_AIF2_RATE, |
2374 | WM8994_AIF2CLK_RATE_MASK, 0x1); | 2396 | WM8994_AIF2CLK_RATE_MASK, 0x1); |
2397 | } else if (wm8994->aifdiv[0]) { | ||
2398 | snd_soc_update_bits(codec, WM8994_AIF1_RATE, | ||
2399 | WM8994_AIF1CLK_RATE_MASK, | ||
2400 | wm8994->aifdiv[0]); | ||
2401 | snd_soc_update_bits(codec, WM8994_AIF2_RATE, | ||
2402 | WM8994_AIF2CLK_RATE_MASK, | ||
2403 | wm8994->aifdiv[1]); | ||
2404 | |||
2405 | wm8994->aifdiv[0] = 0; | ||
2406 | wm8994->aifdiv[1] = 0; | ||
2375 | } | 2407 | } |
2376 | 2408 | ||
2377 | return 0; | 2409 | return 0; |
@@ -2411,7 +2443,7 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
2411 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 2443 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
2412 | switch (control->type) { | 2444 | switch (control->type) { |
2413 | case WM8958: | 2445 | case WM8958: |
2414 | if (wm8994->revision == 0) { | 2446 | if (control->revision == 0) { |
2415 | /* Optimise performance for rev A */ | 2447 | /* Optimise performance for rev A */ |
2416 | snd_soc_update_bits(codec, | 2448 | snd_soc_update_bits(codec, |
2417 | WM8958_CHARGE_PUMP_2, | 2449 | WM8958_CHARGE_PUMP_2, |
@@ -2656,6 +2688,8 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, | |||
2656 | { | 2688 | { |
2657 | struct snd_soc_codec *codec = dai->codec; | 2689 | struct snd_soc_codec *codec = dai->codec; |
2658 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2690 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2691 | struct wm8994 *control = wm8994->wm8994; | ||
2692 | struct wm8994_pdata *pdata = &control->pdata; | ||
2659 | int aif1_reg; | 2693 | int aif1_reg; |
2660 | int aif2_reg; | 2694 | int aif2_reg; |
2661 | int bclk_reg; | 2695 | int bclk_reg; |
@@ -2723,7 +2757,14 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, | |||
2723 | } | 2757 | } |
2724 | 2758 | ||
2725 | wm8994->channels[id] = params_channels(params); | 2759 | wm8994->channels[id] = params_channels(params); |
2726 | switch (params_channels(params)) { | 2760 | if (pdata->max_channels_clocked[id] && |
2761 | wm8994->channels[id] > pdata->max_channels_clocked[id]) { | ||
2762 | dev_dbg(dai->dev, "Constraining channels to %d from %d\n", | ||
2763 | pdata->max_channels_clocked[id], wm8994->channels[id]); | ||
2764 | wm8994->channels[id] = pdata->max_channels_clocked[id]; | ||
2765 | } | ||
2766 | |||
2767 | switch (wm8994->channels[id]) { | ||
2727 | case 1: | 2768 | case 1: |
2728 | case 2: | 2769 | case 2: |
2729 | bclk_rate *= 2; | 2770 | bclk_rate *= 2; |
@@ -2745,7 +2786,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, | |||
2745 | dev_dbg(dai->dev, "AIF%dCLK is %dHz, target BCLK %dHz\n", | 2786 | dev_dbg(dai->dev, "AIF%dCLK is %dHz, target BCLK %dHz\n", |
2746 | dai->id, wm8994->aifclk[id], bclk_rate); | 2787 | dai->id, wm8994->aifclk[id], bclk_rate); |
2747 | 2788 | ||
2748 | if (params_channels(params) == 1 && | 2789 | if (wm8994->channels[id] == 1 && |
2749 | (snd_soc_read(codec, aif1_reg) & 0x18) == 0x18) | 2790 | (snd_soc_read(codec, aif1_reg) & 0x18) == 0x18) |
2750 | aif2 |= WM8994_AIF1_MONO; | 2791 | aif2 |= WM8994_AIF1_MONO; |
2751 | 2792 | ||
@@ -3053,7 +3094,7 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec) | |||
3053 | int i, ret; | 3094 | int i, ret; |
3054 | unsigned int val, mask; | 3095 | unsigned int val, mask; |
3055 | 3096 | ||
3056 | if (wm8994->revision < 4) { | 3097 | if (control->revision < 4) { |
3057 | /* force a HW read */ | 3098 | /* force a HW read */ |
3058 | ret = regmap_read(control->regmap, | 3099 | ret = regmap_read(control->regmap, |
3059 | WM8994_POWER_MANAGEMENT_5, &val); | 3100 | WM8994_POWER_MANAGEMENT_5, &val); |
@@ -3870,7 +3911,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3870 | codec->dapm.idle_bias_off = 1; | 3911 | codec->dapm.idle_bias_off = 1; |
3871 | 3912 | ||
3872 | /* Set revision-specific configuration */ | 3913 | /* Set revision-specific configuration */ |
3873 | wm8994->revision = snd_soc_read(codec, WM8994_CHIP_REVISION); | ||
3874 | switch (control->type) { | 3914 | switch (control->type) { |
3875 | case WM8994: | 3915 | case WM8994: |
3876 | /* Single ended line outputs should have VMID on. */ | 3916 | /* Single ended line outputs should have VMID on. */ |
@@ -3878,7 +3918,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3878 | !control->pdata.lineout2_diff) | 3918 | !control->pdata.lineout2_diff) |
3879 | codec->dapm.idle_bias_off = 0; | 3919 | codec->dapm.idle_bias_off = 0; |
3880 | 3920 | ||
3881 | switch (wm8994->revision) { | 3921 | switch (control->revision) { |
3882 | case 2: | 3922 | case 2: |
3883 | case 3: | 3923 | case 3: |
3884 | wm8994->hubs.dcs_codes_l = -5; | 3924 | wm8994->hubs.dcs_codes_l = -5; |
@@ -3897,7 +3937,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3897 | wm8994->hubs.dcs_readback_mode = 1; | 3937 | wm8994->hubs.dcs_readback_mode = 1; |
3898 | wm8994->hubs.hp_startup_mode = 1; | 3938 | wm8994->hubs.hp_startup_mode = 1; |
3899 | 3939 | ||
3900 | switch (wm8994->revision) { | 3940 | switch (control->revision) { |
3901 | case 0: | 3941 | case 0: |
3902 | break; | 3942 | break; |
3903 | default: | 3943 | default: |
@@ -4000,7 +4040,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
4000 | 4040 | ||
4001 | switch (control->type) { | 4041 | switch (control->type) { |
4002 | case WM1811: | 4042 | case WM1811: |
4003 | if (control->cust_id > 1 || wm8994->revision > 1) { | 4043 | if (control->cust_id > 1 || control->revision > 1) { |
4004 | ret = wm8994_request_irq(wm8994->wm8994, | 4044 | ret = wm8994_request_irq(wm8994->wm8994, |
4005 | WM8994_IRQ_GPIO(6), | 4045 | WM8994_IRQ_GPIO(6), |
4006 | wm1811_jackdet_irq, "JACKDET", | 4046 | wm1811_jackdet_irq, "JACKDET", |
@@ -4114,7 +4154,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
4114 | case WM8994: | 4154 | case WM8994: |
4115 | snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets, | 4155 | snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets, |
4116 | ARRAY_SIZE(wm8994_specific_dapm_widgets)); | 4156 | ARRAY_SIZE(wm8994_specific_dapm_widgets)); |
4117 | if (wm8994->revision < 4) { | 4157 | if (control->revision < 4) { |
4118 | snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, | 4158 | snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, |
4119 | ARRAY_SIZE(wm8994_lateclk_revd_widgets)); | 4159 | ARRAY_SIZE(wm8994_lateclk_revd_widgets)); |
4120 | snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets, | 4160 | snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets, |
@@ -4135,7 +4175,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
4135 | ARRAY_SIZE(wm8958_snd_controls)); | 4175 | ARRAY_SIZE(wm8958_snd_controls)); |
4136 | snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, | 4176 | snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, |
4137 | ARRAY_SIZE(wm8958_dapm_widgets)); | 4177 | ARRAY_SIZE(wm8958_dapm_widgets)); |
4138 | if (wm8994->revision < 1) { | 4178 | if (control->revision < 1) { |
4139 | snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, | 4179 | snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, |
4140 | ARRAY_SIZE(wm8994_lateclk_revd_widgets)); | 4180 | ARRAY_SIZE(wm8994_lateclk_revd_widgets)); |
4141 | snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets, | 4181 | snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets, |
@@ -4174,7 +4214,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
4174 | snd_soc_dapm_add_routes(dapm, wm8994_intercon, | 4214 | snd_soc_dapm_add_routes(dapm, wm8994_intercon, |
4175 | ARRAY_SIZE(wm8994_intercon)); | 4215 | ARRAY_SIZE(wm8994_intercon)); |
4176 | 4216 | ||
4177 | if (wm8994->revision < 4) { | 4217 | if (control->revision < 4) { |
4178 | snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon, | 4218 | snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon, |
4179 | ARRAY_SIZE(wm8994_revd_intercon)); | 4219 | ARRAY_SIZE(wm8994_revd_intercon)); |
4180 | snd_soc_dapm_add_routes(dapm, wm8994_lateclk_revd_intercon, | 4220 | snd_soc_dapm_add_routes(dapm, wm8994_lateclk_revd_intercon, |
@@ -4185,7 +4225,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
4185 | } | 4225 | } |
4186 | break; | 4226 | break; |
4187 | case WM8958: | 4227 | case WM8958: |
4188 | if (wm8994->revision < 1) { | 4228 | if (control->revision < 1) { |
4189 | snd_soc_dapm_add_routes(dapm, wm8994_intercon, | 4229 | snd_soc_dapm_add_routes(dapm, wm8994_intercon, |
4190 | ARRAY_SIZE(wm8994_intercon)); | 4230 | ARRAY_SIZE(wm8994_intercon)); |
4191 | snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon, | 4231 | snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon, |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 45f192702024..55ddf4d57d9b 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -79,6 +79,7 @@ struct wm8994_priv { | |||
79 | int sysclk_rate[2]; | 79 | int sysclk_rate[2]; |
80 | int mclk[2]; | 80 | int mclk[2]; |
81 | int aifclk[2]; | 81 | int aifclk[2]; |
82 | int aifdiv[2]; | ||
82 | int channels[2]; | 83 | int channels[2]; |
83 | struct wm8994_fll_config fll[2], fll_suspend[2]; | 84 | struct wm8994_fll_config fll[2], fll_suspend[2]; |
84 | struct completion fll_locked[2]; | 85 | struct completion fll_locked[2]; |
@@ -146,8 +147,6 @@ struct wm8994_priv { | |||
146 | wm1811_mic_id_cb mic_id_cb; | 147 | wm1811_mic_id_cb mic_id_cb; |
147 | void *mic_id_cb_data; | 148 | void *mic_id_cb_data; |
148 | 149 | ||
149 | int revision; | ||
150 | |||
151 | unsigned int aif1clk_enable:1; | 150 | unsigned int aif1clk_enable:1; |
152 | unsigned int aif2clk_enable:1; | 151 | unsigned int aif2clk_enable:1; |
153 | 152 | ||
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 9af1bddc4c62..3470b649c0b2 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -31,6 +31,7 @@ | |||
31 | 31 | ||
32 | #include <linux/mfd/arizona/registers.h> | 32 | #include <linux/mfd/arizona/registers.h> |
33 | 33 | ||
34 | #include "arizona.h" | ||
34 | #include "wm_adsp.h" | 35 | #include "wm_adsp.h" |
35 | 36 | ||
36 | #define adsp_crit(_dsp, fmt, ...) \ | 37 | #define adsp_crit(_dsp, fmt, ...) \ |
@@ -193,17 +194,25 @@ static void wm_adsp_buf_free(struct list_head *list) | |||
193 | 194 | ||
194 | #define WM_ADSP_NUM_FW 4 | 195 | #define WM_ADSP_NUM_FW 4 |
195 | 196 | ||
197 | #define WM_ADSP_FW_MBC_VSS 0 | ||
198 | #define WM_ADSP_FW_TX 1 | ||
199 | #define WM_ADSP_FW_TX_SPK 2 | ||
200 | #define WM_ADSP_FW_RX_ANC 3 | ||
201 | |||
196 | static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { | 202 | static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { |
197 | "MBC/VSS", "Tx", "Tx Speaker", "Rx ANC" | 203 | [WM_ADSP_FW_MBC_VSS] = "MBC/VSS", |
204 | [WM_ADSP_FW_TX] = "Tx", | ||
205 | [WM_ADSP_FW_TX_SPK] = "Tx Speaker", | ||
206 | [WM_ADSP_FW_RX_ANC] = "Rx ANC", | ||
198 | }; | 207 | }; |
199 | 208 | ||
200 | static struct { | 209 | static struct { |
201 | const char *file; | 210 | const char *file; |
202 | } wm_adsp_fw[WM_ADSP_NUM_FW] = { | 211 | } wm_adsp_fw[WM_ADSP_NUM_FW] = { |
203 | { .file = "mbc-vss" }, | 212 | [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" }, |
204 | { .file = "tx" }, | 213 | [WM_ADSP_FW_TX] = { .file = "tx" }, |
205 | { .file = "tx-spk" }, | 214 | [WM_ADSP_FW_TX_SPK] = { .file = "tx-spk" }, |
206 | { .file = "rx-anc" }, | 215 | [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" }, |
207 | }; | 216 | }; |
208 | 217 | ||
209 | static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, | 218 | static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, |
@@ -246,17 +255,52 @@ static const struct soc_enum wm_adsp_fw_enum[] = { | |||
246 | SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), | 255 | SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), |
247 | }; | 256 | }; |
248 | 257 | ||
249 | const struct snd_kcontrol_new wm_adsp_fw_controls[] = { | 258 | const struct snd_kcontrol_new wm_adsp1_fw_controls[] = { |
259 | SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], | ||
260 | wm_adsp_fw_get, wm_adsp_fw_put), | ||
261 | SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], | ||
262 | wm_adsp_fw_get, wm_adsp_fw_put), | ||
263 | SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], | ||
264 | wm_adsp_fw_get, wm_adsp_fw_put), | ||
265 | }; | ||
266 | EXPORT_SYMBOL_GPL(wm_adsp1_fw_controls); | ||
267 | |||
268 | #if IS_ENABLED(CONFIG_SND_SOC_ARIZONA) | ||
269 | static const struct soc_enum wm_adsp2_rate_enum[] = { | ||
270 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1, | ||
271 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | ||
272 | ARIZONA_RATE_ENUM_SIZE, | ||
273 | arizona_rate_text, arizona_rate_val), | ||
274 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1, | ||
275 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | ||
276 | ARIZONA_RATE_ENUM_SIZE, | ||
277 | arizona_rate_text, arizona_rate_val), | ||
278 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1, | ||
279 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | ||
280 | ARIZONA_RATE_ENUM_SIZE, | ||
281 | arizona_rate_text, arizona_rate_val), | ||
282 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1, | ||
283 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | ||
284 | ARIZONA_RATE_ENUM_SIZE, | ||
285 | arizona_rate_text, arizona_rate_val), | ||
286 | }; | ||
287 | |||
288 | const struct snd_kcontrol_new wm_adsp2_fw_controls[] = { | ||
250 | SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], | 289 | SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], |
251 | wm_adsp_fw_get, wm_adsp_fw_put), | 290 | wm_adsp_fw_get, wm_adsp_fw_put), |
291 | SOC_ENUM("DSP1 Rate", wm_adsp2_rate_enum[0]), | ||
252 | SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], | 292 | SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], |
253 | wm_adsp_fw_get, wm_adsp_fw_put), | 293 | wm_adsp_fw_get, wm_adsp_fw_put), |
294 | SOC_ENUM("DSP2 Rate", wm_adsp2_rate_enum[1]), | ||
254 | SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], | 295 | SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], |
255 | wm_adsp_fw_get, wm_adsp_fw_put), | 296 | wm_adsp_fw_get, wm_adsp_fw_put), |
297 | SOC_ENUM("DSP3 Rate", wm_adsp2_rate_enum[2]), | ||
256 | SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3], | 298 | SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3], |
257 | wm_adsp_fw_get, wm_adsp_fw_put), | 299 | wm_adsp_fw_get, wm_adsp_fw_put), |
300 | SOC_ENUM("DSP4 Rate", wm_adsp2_rate_enum[3]), | ||
258 | }; | 301 | }; |
259 | EXPORT_SYMBOL_GPL(wm_adsp_fw_controls); | 302 | EXPORT_SYMBOL_GPL(wm_adsp2_fw_controls); |
303 | #endif | ||
260 | 304 | ||
261 | static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, | 305 | static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, |
262 | int type) | 306 | int type) |
@@ -549,13 +593,30 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
549 | buf_size = sizeof(adsp1_id); | 593 | buf_size = sizeof(adsp1_id); |
550 | 594 | ||
551 | algs = be32_to_cpu(adsp1_id.algs); | 595 | algs = be32_to_cpu(adsp1_id.algs); |
596 | dsp->fw_id = be32_to_cpu(adsp1_id.fw.id); | ||
552 | adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", | 597 | adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", |
553 | be32_to_cpu(adsp1_id.fw.id), | 598 | dsp->fw_id, |
554 | (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16, | 599 | (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16, |
555 | (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8, | 600 | (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8, |
556 | be32_to_cpu(adsp1_id.fw.ver) & 0xff, | 601 | be32_to_cpu(adsp1_id.fw.ver) & 0xff, |
557 | algs); | 602 | algs); |
558 | 603 | ||
604 | region = kzalloc(sizeof(*region), GFP_KERNEL); | ||
605 | if (!region) | ||
606 | return -ENOMEM; | ||
607 | region->type = WMFW_ADSP1_ZM; | ||
608 | region->alg = be32_to_cpu(adsp1_id.fw.id); | ||
609 | region->base = be32_to_cpu(adsp1_id.zm); | ||
610 | list_add_tail(®ion->list, &dsp->alg_regions); | ||
611 | |||
612 | region = kzalloc(sizeof(*region), GFP_KERNEL); | ||
613 | if (!region) | ||
614 | return -ENOMEM; | ||
615 | region->type = WMFW_ADSP1_DM; | ||
616 | region->alg = be32_to_cpu(adsp1_id.fw.id); | ||
617 | region->base = be32_to_cpu(adsp1_id.dm); | ||
618 | list_add_tail(®ion->list, &dsp->alg_regions); | ||
619 | |||
559 | pos = sizeof(adsp1_id) / 2; | 620 | pos = sizeof(adsp1_id) / 2; |
560 | term = pos + ((sizeof(*adsp1_alg) * algs) / 2); | 621 | term = pos + ((sizeof(*adsp1_alg) * algs) / 2); |
561 | break; | 622 | break; |
@@ -573,13 +634,38 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
573 | buf_size = sizeof(adsp2_id); | 634 | buf_size = sizeof(adsp2_id); |
574 | 635 | ||
575 | algs = be32_to_cpu(adsp2_id.algs); | 636 | algs = be32_to_cpu(adsp2_id.algs); |
637 | dsp->fw_id = be32_to_cpu(adsp2_id.fw.id); | ||
576 | adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", | 638 | adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", |
577 | be32_to_cpu(adsp2_id.fw.id), | 639 | dsp->fw_id, |
578 | (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16, | 640 | (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16, |
579 | (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8, | 641 | (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8, |
580 | be32_to_cpu(adsp2_id.fw.ver) & 0xff, | 642 | be32_to_cpu(adsp2_id.fw.ver) & 0xff, |
581 | algs); | 643 | algs); |
582 | 644 | ||
645 | region = kzalloc(sizeof(*region), GFP_KERNEL); | ||
646 | if (!region) | ||
647 | return -ENOMEM; | ||
648 | region->type = WMFW_ADSP2_XM; | ||
649 | region->alg = be32_to_cpu(adsp2_id.fw.id); | ||
650 | region->base = be32_to_cpu(adsp2_id.xm); | ||
651 | list_add_tail(®ion->list, &dsp->alg_regions); | ||
652 | |||
653 | region = kzalloc(sizeof(*region), GFP_KERNEL); | ||
654 | if (!region) | ||
655 | return -ENOMEM; | ||
656 | region->type = WMFW_ADSP2_YM; | ||
657 | region->alg = be32_to_cpu(adsp2_id.fw.id); | ||
658 | region->base = be32_to_cpu(adsp2_id.ym); | ||
659 | list_add_tail(®ion->list, &dsp->alg_regions); | ||
660 | |||
661 | region = kzalloc(sizeof(*region), GFP_KERNEL); | ||
662 | if (!region) | ||
663 | return -ENOMEM; | ||
664 | region->type = WMFW_ADSP2_ZM; | ||
665 | region->alg = be32_to_cpu(adsp2_id.fw.id); | ||
666 | region->base = be32_to_cpu(adsp2_id.zm); | ||
667 | list_add_tail(®ion->list, &dsp->alg_regions); | ||
668 | |||
583 | pos = sizeof(adsp2_id) / 2; | 669 | pos = sizeof(adsp2_id) / 2; |
584 | term = pos + ((sizeof(*adsp2_alg) * algs) / 2); | 670 | term = pos + ((sizeof(*adsp2_alg) * algs) / 2); |
585 | break; | 671 | break; |
@@ -781,8 +867,24 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) | |||
781 | case (WMFW_INFO_TEXT << 8): | 867 | case (WMFW_INFO_TEXT << 8): |
782 | break; | 868 | break; |
783 | case (WMFW_ABSOLUTE << 8): | 869 | case (WMFW_ABSOLUTE << 8): |
784 | region_name = "register"; | 870 | /* |
785 | reg = offset; | 871 | * Old files may use this for global |
872 | * coefficients. | ||
873 | */ | ||
874 | if (le32_to_cpu(blk->id) == dsp->fw_id && | ||
875 | offset == 0) { | ||
876 | region_name = "global coefficients"; | ||
877 | mem = wm_adsp_find_region(dsp, type); | ||
878 | if (!mem) { | ||
879 | adsp_err(dsp, "No ZM\n"); | ||
880 | break; | ||
881 | } | ||
882 | reg = wm_adsp_region_to_reg(mem, 0); | ||
883 | |||
884 | } else { | ||
885 | region_name = "register"; | ||
886 | reg = offset; | ||
887 | } | ||
786 | break; | 888 | break; |
787 | 889 | ||
788 | case WMFW_ADSP1_DM: | 890 | case WMFW_ADSP1_DM: |
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index cb8871a3ec00..fea514627526 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h | |||
@@ -46,6 +46,8 @@ struct wm_adsp { | |||
46 | 46 | ||
47 | struct list_head alg_regions; | 47 | struct list_head alg_regions; |
48 | 48 | ||
49 | int fw_id; | ||
50 | |||
49 | const struct wm_adsp_region *mem; | 51 | const struct wm_adsp_region *mem; |
50 | int num_mems; | 52 | int num_mems; |
51 | 53 | ||
@@ -65,7 +67,8 @@ struct wm_adsp { | |||
65 | .shift = num, .event = wm_adsp2_event, \ | 67 | .shift = num, .event = wm_adsp2_event, \ |
66 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } | 68 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } |
67 | 69 | ||
68 | extern const struct snd_kcontrol_new wm_adsp_fw_controls[]; | 70 | extern const struct snd_kcontrol_new wm_adsp1_fw_controls[]; |
71 | extern const struct snd_kcontrol_new wm_adsp2_fw_controls[]; | ||
69 | 72 | ||
70 | int wm_adsp1_init(struct wm_adsp *adsp); | 73 | int wm_adsp1_init(struct wm_adsp *adsp); |
71 | int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs); | 74 | int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs); |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 867ae97ddcec..f5d81b948759 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -199,11 +199,12 @@ static void wm_hubs_dcs_cache_set(struct snd_soc_codec *codec, u16 dcs_cfg) | |||
199 | list_add_tail(&cache->list, &hubs->dcs_cache); | 199 | list_add_tail(&cache->list, &hubs->dcs_cache); |
200 | } | 200 | } |
201 | 201 | ||
202 | static void wm_hubs_read_dc_servo(struct snd_soc_codec *codec, | 202 | static int wm_hubs_read_dc_servo(struct snd_soc_codec *codec, |
203 | u16 *reg_l, u16 *reg_r) | 203 | u16 *reg_l, u16 *reg_r) |
204 | { | 204 | { |
205 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 205 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
206 | u16 dcs_reg, reg; | 206 | u16 dcs_reg, reg; |
207 | int ret = 0; | ||
207 | 208 | ||
208 | switch (hubs->dcs_readback_mode) { | 209 | switch (hubs->dcs_readback_mode) { |
209 | case 2: | 210 | case 2: |
@@ -236,8 +237,9 @@ static void wm_hubs_read_dc_servo(struct snd_soc_codec *codec, | |||
236 | break; | 237 | break; |
237 | default: | 238 | default: |
238 | WARN(1, "Unknown DCS readback method\n"); | 239 | WARN(1, "Unknown DCS readback method\n"); |
239 | return; | 240 | ret = -1; |
240 | } | 241 | } |
242 | return ret; | ||
241 | } | 243 | } |
242 | 244 | ||
243 | /* | 245 | /* |
@@ -286,7 +288,8 @@ static void enable_dc_servo(struct snd_soc_codec *codec) | |||
286 | WM8993_DCS_TRIG_STARTUP_1); | 288 | WM8993_DCS_TRIG_STARTUP_1); |
287 | } | 289 | } |
288 | 290 | ||
289 | wm_hubs_read_dc_servo(codec, ®_l, ®_r); | 291 | if (wm_hubs_read_dc_servo(codec, ®_l, ®_r) < 0) |
292 | return; | ||
290 | 293 | ||
291 | dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); | 294 | dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); |
292 | 295 | ||