diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/tlv320aic32x4.txt | 30 | ||||
-rw-r--r-- | include/sound/soc.h | 15 | ||||
-rw-r--r-- | sound/soc/atmel/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/blackfin/Kconfig | 3 | ||||
-rw-r--r-- | sound/soc/cirrus/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/codecs/88pm860x-codec.c | 3 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 22 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 12 | ||||
-rw-r--r-- | sound/soc/codecs/ad193x-i2c.c | 54 | ||||
-rw-r--r-- | sound/soc/codecs/ad193x-spi.c | 48 | ||||
-rw-r--r-- | sound/soc/codecs/ad193x.c | 144 | ||||
-rw-r--r-- | sound/soc/codecs/ad193x.h | 7 | ||||
-rw-r--r-- | sound/soc/codecs/si476x.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic23-i2c.c | 59 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic23-spi.c | 57 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic23.c | 69 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic23.h | 6 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic32x4.c | 232 | ||||
-rw-r--r-- | sound/soc/codecs/wm8991.c | 44 | ||||
-rw-r--r-- | sound/soc/fsl/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/omap/Kconfig | 4 | ||||
-rw-r--r-- | sound/soc/samsung/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 68 | ||||
-rw-r--r-- | sound/soc/tegra/Kconfig | 2 |
24 files changed, 639 insertions, 250 deletions
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt new file mode 100644 index 000000000000..5e2741af27be --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt | |||
@@ -0,0 +1,30 @@ | |||
1 | Texas Instruments - tlv320aic32x4 Codec module | ||
2 | |||
3 | The tlv320aic32x4 serial control bus communicates through I2C protocols | ||
4 | |||
5 | Required properties: | ||
6 | - compatible: Should be "ti,tlv320aic32x4" | ||
7 | - reg: I2C slave address | ||
8 | - supply-*: Required supply regulators are: | ||
9 | "iov" - digital IO power supply | ||
10 | "ldoin" - LDO power supply | ||
11 | "dv" - Digital core power supply | ||
12 | "av" - Analog core power supply | ||
13 | If you supply ldoin, dv and av are optional. Otherwise they are required | ||
14 | See regulator/regulator.txt for more information about the detailed binding | ||
15 | format. | ||
16 | |||
17 | Optional properties: | ||
18 | - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt | ||
19 | - clocks/clock-names: Clock named 'mclk' for the master clock of the codec. | ||
20 | See clock/clock-bindings.txt for information about the detailed format. | ||
21 | |||
22 | |||
23 | Example: | ||
24 | |||
25 | codec: tlv320aic32x4@18 { | ||
26 | compatible = "ti,tlv320aic32x4"; | ||
27 | reg = <0x18>; | ||
28 | clocks = <&clks 201>; | ||
29 | clock-names = "mclk"; | ||
30 | }; | ||
diff --git a/include/sound/soc.h b/include/sound/soc.h index 14fb921c373f..2d8982db0344 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -45,6 +45,11 @@ | |||
45 | ((unsigned long)&(struct soc_mixer_control) \ | 45 | ((unsigned long)&(struct soc_mixer_control) \ |
46 | {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ | 46 | {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ |
47 | .max = xmax, .platform_max = xmax, .invert = xinvert}) | 47 | .max = xmax, .platform_max = xmax, .invert = xinvert}) |
48 | #define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \ | ||
49 | ((unsigned long)&(struct soc_mixer_control) \ | ||
50 | {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ | ||
51 | .max = xmax, .min = xmin, .platform_max = xmax, .sign_bit = xsign_bit, \ | ||
52 | .invert = xinvert}) | ||
48 | #define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ | 53 | #define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ |
49 | ((unsigned long)&(struct soc_mixer_control) \ | 54 | ((unsigned long)&(struct soc_mixer_control) \ |
50 | {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ | 55 | {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ |
@@ -152,6 +157,15 @@ | |||
152 | {.reg = xreg, .rreg = xrreg, \ | 157 | {.reg = xreg, .rreg = xrreg, \ |
153 | .shift = xshift, .rshift = xshift, \ | 158 | .shift = xshift, .rshift = xshift, \ |
154 | .max = xmax, .min = xmin} } | 159 | .max = xmax, .min = xmin} } |
160 | #define SOC_DOUBLE_R_S_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \ | ||
161 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | ||
162 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
163 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
164 | .tlv.p = (tlv_array), \ | ||
165 | .info = snd_soc_info_volsw, \ | ||
166 | .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ | ||
167 | .private_value = SOC_DOUBLE_R_S_VALUE(reg_left, reg_right, xshift, \ | ||
168 | xmin, xmax, xsign_bit, xinvert) } | ||
155 | #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ | 169 | #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ |
156 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | 170 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ |
157 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | 171 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ |
@@ -1064,6 +1078,7 @@ struct soc_mixer_control { | |||
1064 | int min, max, platform_max; | 1078 | int min, max, platform_max; |
1065 | int reg, rreg; | 1079 | int reg, rreg; |
1066 | unsigned int shift, rshift; | 1080 | unsigned int shift, rshift; |
1081 | unsigned int sign_bit; | ||
1067 | unsigned int invert:1; | 1082 | unsigned int invert:1; |
1068 | unsigned int autodisable:1; | 1083 | unsigned int autodisable:1; |
1069 | }; | 1084 | }; |
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index e634eb78ed03..4789619a52d8 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig | |||
@@ -58,6 +58,6 @@ config SND_AT91_SOC_AFEB9260 | |||
58 | depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC | 58 | depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC |
59 | select SND_ATMEL_SOC_PDC | 59 | select SND_ATMEL_SOC_PDC |
60 | select SND_ATMEL_SOC_SSC | 60 | select SND_ATMEL_SOC_SSC |
61 | select SND_SOC_TLV320AIC23 | 61 | select SND_SOC_TLV320AIC23_I2C |
62 | help | 62 | help |
63 | Say Y here to support sound on AFEB9260 board. | 63 | Say Y here to support sound on AFEB9260 board. |
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 54f74f8cbb75..359136777c4d 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig | |||
@@ -68,7 +68,8 @@ config SND_BF5XX_SOC_AD193X | |||
68 | tristate "SoC AD193X Audio support for Blackfin" | 68 | tristate "SoC AD193X Audio support for Blackfin" |
69 | depends on SND_BF5XX_I2S | 69 | depends on SND_BF5XX_I2S |
70 | select SND_BF5XX_SOC_I2S | 70 | select SND_BF5XX_SOC_I2S |
71 | select SND_SOC_AD193X | 71 | select SND_SOC_AD193X_I2C if I2C |
72 | select SND_SOC_AD193X_SPI if SPI_MASTER | ||
72 | help | 73 | help |
73 | Say Y if you want to add support for AD193X codec on Blackfin. | 74 | Say Y if you want to add support for AD193X codec on Blackfin. |
74 | This driver supports AD1936, AD1937, AD1938 and AD1939. | 75 | This driver supports AD1936, AD1937, AD1938 and AD1939. |
diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig index 06f938deda15..a0bf4a610397 100644 --- a/sound/soc/cirrus/Kconfig +++ b/sound/soc/cirrus/Kconfig | |||
@@ -18,7 +18,7 @@ config SND_EP93XX_SOC_SNAPPERCL15 | |||
18 | tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" | 18 | tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" |
19 | depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 | 19 | depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 |
20 | select SND_EP93XX_SOC_I2S | 20 | select SND_EP93XX_SOC_I2S |
21 | select SND_SOC_TLV320AIC23 | 21 | select SND_SOC_TLV320AIC23_I2C |
22 | help | 22 | help |
23 | Say Y or M here if you want to add support for I2S audio on the | 23 | Say Y or M here if you want to add support for I2S audio on the |
24 | Bluewater Systems Snapper CL15 module. | 24 | Bluewater Systems Snapper CL15 module. |
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 75d0ad5d2dcb..647a72cda005 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c | |||
@@ -1328,6 +1328,9 @@ static int pm860x_probe(struct snd_soc_codec *codec) | |||
1328 | pm860x->codec = codec; | 1328 | pm860x->codec = codec; |
1329 | 1329 | ||
1330 | codec->control_data = pm860x->regmap; | 1330 | codec->control_data = pm860x->regmap; |
1331 | ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); | ||
1332 | if (ret) | ||
1333 | return ret; | ||
1331 | 1334 | ||
1332 | for (i = 0; i < 4; i++) { | 1335 | for (i = 0; i < 4; i++) { |
1333 | ret = request_threaded_irq(pm860x->irq[i], NULL, | 1336 | ret = request_threaded_irq(pm860x->irq[i], NULL, |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92a..555f32f39f8a 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -16,7 +16,8 @@ config SND_SOC_ALL_CODECS | |||
16 | select SND_SOC_AB8500_CODEC if ABX500_CORE | 16 | select SND_SOC_AB8500_CODEC if ABX500_CORE |
17 | select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS | 17 | select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS |
18 | select SND_SOC_AD1836 if SPI_MASTER | 18 | select SND_SOC_AD1836 if SPI_MASTER |
19 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI | 19 | select SND_SOC_AD193X_SPI if SPI_MASTER |
20 | select SND_SOC_AD193X_I2C if I2C | ||
20 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS | 21 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS |
21 | select SND_SOC_AD73311 | 22 | select SND_SOC_AD73311 |
22 | select SND_SOC_ADAU1373 if I2C | 23 | select SND_SOC_ADAU1373 if I2C |
@@ -71,7 +72,8 @@ config SND_SOC_ALL_CODECS | |||
71 | select SND_SOC_STA529 if I2C | 72 | select SND_SOC_STA529 if I2C |
72 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS | 73 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS |
73 | select SND_SOC_TAS5086 if I2C | 74 | select SND_SOC_TAS5086 if I2C |
74 | select SND_SOC_TLV320AIC23 if I2C | 75 | select SND_SOC_TLV320AIC23_I2C if I2C |
76 | select SND_SOC_TLV320AIC23_SPI if SPI_MASTER | ||
75 | select SND_SOC_TLV320AIC26 if SPI_MASTER | 77 | select SND_SOC_TLV320AIC26 if SPI_MASTER |
76 | select SND_SOC_TLV320AIC32X4 if I2C | 78 | select SND_SOC_TLV320AIC32X4 if I2C |
77 | select SND_SOC_TLV320AIC3X if I2C | 79 | select SND_SOC_TLV320AIC3X if I2C |
@@ -182,6 +184,14 @@ config SND_SOC_AD1836 | |||
182 | config SND_SOC_AD193X | 184 | config SND_SOC_AD193X |
183 | tristate | 185 | tristate |
184 | 186 | ||
187 | config SND_SOC_AD193X_SPI | ||
188 | tristate | ||
189 | select SND_SOC_AD193X | ||
190 | |||
191 | config SND_SOC_AD193X_I2C | ||
192 | tristate | ||
193 | select SND_SOC_AD193X | ||
194 | |||
185 | config SND_SOC_AD1980 | 195 | config SND_SOC_AD1980 |
186 | tristate | 196 | tristate |
187 | 197 | ||
@@ -357,6 +367,14 @@ config SND_SOC_TAS5086 | |||
357 | config SND_SOC_TLV320AIC23 | 367 | config SND_SOC_TLV320AIC23 |
358 | tristate | 368 | tristate |
359 | 369 | ||
370 | config SND_SOC_TLV320AIC23_I2C | ||
371 | tristate | ||
372 | select SND_SOC_TLV320AIC23 | ||
373 | |||
374 | config SND_SOC_TLV320AIC23_SPI | ||
375 | tristate | ||
376 | select SND_SOC_TLV320AIC23 | ||
377 | |||
360 | config SND_SOC_TLV320AIC26 | 378 | config SND_SOC_TLV320AIC26 |
361 | tristate | 379 | tristate |
362 | depends on SPI | 380 | depends on SPI |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44d..bfda5c60932a 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -3,6 +3,8 @@ snd-soc-ab8500-codec-objs := ab8500-codec.o | |||
3 | snd-soc-ac97-objs := ac97.o | 3 | snd-soc-ac97-objs := ac97.o |
4 | snd-soc-ad1836-objs := ad1836.o | 4 | snd-soc-ad1836-objs := ad1836.o |
5 | snd-soc-ad193x-objs := ad193x.o | 5 | snd-soc-ad193x-objs := ad193x.o |
6 | snd-soc-ad193x-spi-objs := ad193x-spi.o | ||
7 | snd-soc-ad193x-i2c-objs := ad193x-i2c.o | ||
6 | snd-soc-ad1980-objs := ad1980.o | 8 | snd-soc-ad1980-objs := ad1980.o |
7 | snd-soc-ad73311-objs := ad73311.o | 9 | snd-soc-ad73311-objs := ad73311.o |
8 | snd-soc-adau1701-objs := adau1701.o | 10 | snd-soc-adau1701-objs := adau1701.o |
@@ -63,9 +65,11 @@ snd-soc-sta529-objs := sta529.o | |||
63 | snd-soc-stac9766-objs := stac9766.o | 65 | snd-soc-stac9766-objs := stac9766.o |
64 | snd-soc-tas5086-objs := tas5086.o | 66 | snd-soc-tas5086-objs := tas5086.o |
65 | snd-soc-tlv320aic23-objs := tlv320aic23.o | 67 | snd-soc-tlv320aic23-objs := tlv320aic23.o |
68 | snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o | ||
69 | snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o | ||
66 | snd-soc-tlv320aic26-objs := tlv320aic26.o | 70 | snd-soc-tlv320aic26-objs := tlv320aic26.o |
67 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o | ||
68 | snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o | 71 | snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o |
72 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o | ||
69 | snd-soc-tlv320dac33-objs := tlv320dac33.o | 73 | snd-soc-tlv320dac33-objs := tlv320dac33.o |
70 | snd-soc-twl4030-objs := twl4030.o | 74 | snd-soc-twl4030-objs := twl4030.o |
71 | snd-soc-twl6040-objs := twl6040.o | 75 | snd-soc-twl6040-objs := twl6040.o |
@@ -134,6 +138,8 @@ obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o | |||
134 | obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o | 138 | obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o |
135 | obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o | 139 | obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o |
136 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o | 140 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o |
141 | obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o | ||
142 | obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o | ||
137 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o | 143 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o |
138 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o | 144 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o |
139 | obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o | 145 | obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o |
@@ -193,9 +199,11 @@ obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o | |||
193 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o | 199 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o |
194 | obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o | 200 | obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o |
195 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o | 201 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o |
202 | obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o | ||
203 | obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o | ||
196 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o | 204 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o |
197 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o | ||
198 | obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o | 205 | obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o |
206 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o | ||
199 | obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o | 207 | obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o |
200 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o | 208 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o |
201 | obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o | 209 | obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o |
diff --git a/sound/soc/codecs/ad193x-i2c.c b/sound/soc/codecs/ad193x-i2c.c new file mode 100644 index 000000000000..df3a1a415825 --- /dev/null +++ b/sound/soc/codecs/ad193x-i2c.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * AD1936/AD1937 audio driver | ||
3 | * | ||
4 | * Copyright 2014 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/i2c.h> | ||
11 | #include <linux/regmap.h> | ||
12 | |||
13 | #include <sound/soc.h> | ||
14 | |||
15 | #include "ad193x.h" | ||
16 | |||
17 | static const struct i2c_device_id ad193x_id[] = { | ||
18 | { "ad1936", 0 }, | ||
19 | { "ad1937", 0 }, | ||
20 | { } | ||
21 | }; | ||
22 | MODULE_DEVICE_TABLE(i2c, ad193x_id); | ||
23 | |||
24 | static int ad193x_i2c_probe(struct i2c_client *client, | ||
25 | const struct i2c_device_id *id) | ||
26 | { | ||
27 | struct regmap_config config; | ||
28 | |||
29 | config = ad193x_regmap_config; | ||
30 | config.val_bits = 8; | ||
31 | config.reg_bits = 8; | ||
32 | |||
33 | return ad193x_probe(&client->dev, devm_regmap_init_i2c(client, &config)); | ||
34 | } | ||
35 | |||
36 | static int ad193x_i2c_remove(struct i2c_client *client) | ||
37 | { | ||
38 | snd_soc_unregister_codec(&client->dev); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static struct i2c_driver ad193x_i2c_driver = { | ||
43 | .driver = { | ||
44 | .name = "ad193x", | ||
45 | }, | ||
46 | .probe = ad193x_i2c_probe, | ||
47 | .remove = ad193x_i2c_remove, | ||
48 | .id_table = ad193x_id, | ||
49 | }; | ||
50 | module_i2c_driver(ad193x_i2c_driver); | ||
51 | |||
52 | MODULE_DESCRIPTION("ASoC AD1936/AD1937 audio CODEC driver"); | ||
53 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | ||
54 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/ad193x-spi.c b/sound/soc/codecs/ad193x-spi.c new file mode 100644 index 000000000000..390cef9b9dc2 --- /dev/null +++ b/sound/soc/codecs/ad193x-spi.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * AD1938/AD1939 audio driver | ||
3 | * | ||
4 | * Copyright 2014 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/spi/spi.h> | ||
11 | #include <linux/regmap.h> | ||
12 | |||
13 | #include <sound/soc.h> | ||
14 | |||
15 | #include "ad193x.h" | ||
16 | |||
17 | static int ad193x_spi_probe(struct spi_device *spi) | ||
18 | { | ||
19 | struct regmap_config config; | ||
20 | |||
21 | config = ad193x_regmap_config; | ||
22 | config.val_bits = 8; | ||
23 | config.reg_bits = 16; | ||
24 | config.read_flag_mask = 0x09; | ||
25 | config.write_flag_mask = 0x08; | ||
26 | |||
27 | return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); | ||
28 | } | ||
29 | |||
30 | static int ad193x_spi_remove(struct spi_device *spi) | ||
31 | { | ||
32 | snd_soc_unregister_codec(&spi->dev); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static struct spi_driver ad193x_spi_driver = { | ||
37 | .driver = { | ||
38 | .name = "ad193x", | ||
39 | .owner = THIS_MODULE, | ||
40 | }, | ||
41 | .probe = ad193x_spi_probe, | ||
42 | .remove = ad193x_spi_remove, | ||
43 | }; | ||
44 | module_spi_driver(ad193x_spi_driver); | ||
45 | |||
46 | MODULE_DESCRIPTION("ASoC AD1938/AD1939 audio CODEC driver"); | ||
47 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | ||
48 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 5a42dca535b7..9381a767e75f 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -6,12 +6,10 @@ | |||
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/module.h> | 9 | #include <linux/module.h> |
11 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
12 | #include <linux/device.h> | 11 | #include <linux/device.h> |
13 | #include <linux/i2c.h> | 12 | #include <linux/regmap.h> |
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
16 | #include <sound/core.h> | 14 | #include <sound/core.h> |
17 | #include <sound/pcm.h> | 15 | #include <sound/pcm.h> |
@@ -19,6 +17,7 @@ | |||
19 | #include <sound/initval.h> | 17 | #include <sound/initval.h> |
20 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
21 | #include <sound/tlv.h> | 19 | #include <sound/tlv.h> |
20 | |||
22 | #include "ad193x.h" | 21 | #include "ad193x.h" |
23 | 22 | ||
24 | /* codec private data */ | 23 | /* codec private data */ |
@@ -32,8 +31,8 @@ struct ad193x_priv { | |||
32 | */ | 31 | */ |
33 | static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; | 32 | static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; |
34 | 33 | ||
35 | static const struct soc_enum ad193x_deemp_enum = | 34 | static SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1, |
36 | SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp); | 35 | ad193x_deemp); |
37 | 36 | ||
38 | static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0); | 37 | static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0); |
39 | 38 | ||
@@ -320,7 +319,7 @@ static struct snd_soc_dai_driver ad193x_dai = { | |||
320 | .ops = &ad193x_dai_ops, | 319 | .ops = &ad193x_dai_ops, |
321 | }; | 320 | }; |
322 | 321 | ||
323 | static int ad193x_probe(struct snd_soc_codec *codec) | 322 | static int ad193x_codec_probe(struct snd_soc_codec *codec) |
324 | { | 323 | { |
325 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); | 324 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); |
326 | int ret; | 325 | int ret; |
@@ -352,7 +351,7 @@ static int ad193x_probe(struct snd_soc_codec *codec) | |||
352 | } | 351 | } |
353 | 352 | ||
354 | static struct snd_soc_codec_driver soc_codec_dev_ad193x = { | 353 | static struct snd_soc_codec_driver soc_codec_dev_ad193x = { |
355 | .probe = ad193x_probe, | 354 | .probe = ad193x_codec_probe, |
356 | .controls = ad193x_snd_controls, | 355 | .controls = ad193x_snd_controls, |
357 | .num_controls = ARRAY_SIZE(ad193x_snd_controls), | 356 | .num_controls = ARRAY_SIZE(ad193x_snd_controls), |
358 | .dapm_widgets = ad193x_dapm_widgets, | 357 | .dapm_widgets = ad193x_dapm_widgets, |
@@ -366,140 +365,31 @@ static bool adau193x_reg_volatile(struct device *dev, unsigned int reg) | |||
366 | return false; | 365 | return false; |
367 | } | 366 | } |
368 | 367 | ||
369 | #if defined(CONFIG_SPI_MASTER) | 368 | const struct regmap_config ad193x_regmap_config = { |
370 | |||
371 | static const struct regmap_config ad193x_spi_regmap_config = { | ||
372 | .val_bits = 8, | ||
373 | .reg_bits = 16, | ||
374 | .read_flag_mask = 0x09, | ||
375 | .write_flag_mask = 0x08, | ||
376 | |||
377 | .max_register = AD193X_NUM_REGS - 1, | 369 | .max_register = AD193X_NUM_REGS - 1, |
378 | .volatile_reg = adau193x_reg_volatile, | 370 | .volatile_reg = adau193x_reg_volatile, |
379 | }; | 371 | }; |
372 | EXPORT_SYMBOL_GPL(ad193x_regmap_config); | ||
380 | 373 | ||
381 | static int ad193x_spi_probe(struct spi_device *spi) | 374 | int ad193x_probe(struct device *dev, struct regmap *regmap) |
382 | { | 375 | { |
383 | struct ad193x_priv *ad193x; | 376 | struct ad193x_priv *ad193x; |
384 | 377 | ||
385 | ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv), | 378 | if (IS_ERR(regmap)) |
386 | GFP_KERNEL); | 379 | return PTR_ERR(regmap); |
387 | if (ad193x == NULL) | ||
388 | return -ENOMEM; | ||
389 | |||
390 | ad193x->regmap = devm_regmap_init_spi(spi, &ad193x_spi_regmap_config); | ||
391 | if (IS_ERR(ad193x->regmap)) | ||
392 | return PTR_ERR(ad193x->regmap); | ||
393 | |||
394 | spi_set_drvdata(spi, ad193x); | ||
395 | |||
396 | return snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x, | ||
397 | &ad193x_dai, 1); | ||
398 | } | ||
399 | |||
400 | static int ad193x_spi_remove(struct spi_device *spi) | ||
401 | { | ||
402 | snd_soc_unregister_codec(&spi->dev); | ||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static struct spi_driver ad193x_spi_driver = { | ||
407 | .driver = { | ||
408 | .name = "ad193x", | ||
409 | .owner = THIS_MODULE, | ||
410 | }, | ||
411 | .probe = ad193x_spi_probe, | ||
412 | .remove = ad193x_spi_remove, | ||
413 | }; | ||
414 | #endif | ||
415 | |||
416 | #if IS_ENABLED(CONFIG_I2C) | ||
417 | |||
418 | static const struct regmap_config ad193x_i2c_regmap_config = { | ||
419 | .val_bits = 8, | ||
420 | .reg_bits = 8, | ||
421 | |||
422 | .max_register = AD193X_NUM_REGS - 1, | ||
423 | .volatile_reg = adau193x_reg_volatile, | ||
424 | }; | ||
425 | |||
426 | static const struct i2c_device_id ad193x_id[] = { | ||
427 | { "ad1936", 0 }, | ||
428 | { "ad1937", 0 }, | ||
429 | { } | ||
430 | }; | ||
431 | MODULE_DEVICE_TABLE(i2c, ad193x_id); | ||
432 | 380 | ||
433 | static int ad193x_i2c_probe(struct i2c_client *client, | 381 | ad193x = devm_kzalloc(dev, sizeof(*ad193x), GFP_KERNEL); |
434 | const struct i2c_device_id *id) | ||
435 | { | ||
436 | struct ad193x_priv *ad193x; | ||
437 | |||
438 | ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv), | ||
439 | GFP_KERNEL); | ||
440 | if (ad193x == NULL) | 382 | if (ad193x == NULL) |
441 | return -ENOMEM; | 383 | return -ENOMEM; |
442 | 384 | ||
443 | ad193x->regmap = devm_regmap_init_i2c(client, &ad193x_i2c_regmap_config); | 385 | ad193x->regmap = regmap; |
444 | if (IS_ERR(ad193x->regmap)) | ||
445 | return PTR_ERR(ad193x->regmap); | ||
446 | |||
447 | i2c_set_clientdata(client, ad193x); | ||
448 | |||
449 | return snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x, | ||
450 | &ad193x_dai, 1); | ||
451 | } | ||
452 | |||
453 | static int ad193x_i2c_remove(struct i2c_client *client) | ||
454 | { | ||
455 | snd_soc_unregister_codec(&client->dev); | ||
456 | return 0; | ||
457 | } | ||
458 | 386 | ||
459 | static struct i2c_driver ad193x_i2c_driver = { | 387 | dev_set_drvdata(dev, ad193x); |
460 | .driver = { | ||
461 | .name = "ad193x", | ||
462 | }, | ||
463 | .probe = ad193x_i2c_probe, | ||
464 | .remove = ad193x_i2c_remove, | ||
465 | .id_table = ad193x_id, | ||
466 | }; | ||
467 | #endif | ||
468 | |||
469 | static int __init ad193x_modinit(void) | ||
470 | { | ||
471 | int ret; | ||
472 | |||
473 | #if IS_ENABLED(CONFIG_I2C) | ||
474 | ret = i2c_add_driver(&ad193x_i2c_driver); | ||
475 | if (ret != 0) { | ||
476 | printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n", | ||
477 | ret); | ||
478 | } | ||
479 | #endif | ||
480 | |||
481 | #if defined(CONFIG_SPI_MASTER) | ||
482 | ret = spi_register_driver(&ad193x_spi_driver); | ||
483 | if (ret != 0) { | ||
484 | printk(KERN_ERR "Failed to register AD193X SPI driver: %d\n", | ||
485 | ret); | ||
486 | } | ||
487 | #endif | ||
488 | return ret; | ||
489 | } | ||
490 | module_init(ad193x_modinit); | ||
491 | |||
492 | static void __exit ad193x_modexit(void) | ||
493 | { | ||
494 | #if defined(CONFIG_SPI_MASTER) | ||
495 | spi_unregister_driver(&ad193x_spi_driver); | ||
496 | #endif | ||
497 | 388 | ||
498 | #if IS_ENABLED(CONFIG_I2C) | 389 | return snd_soc_register_codec(dev, &soc_codec_dev_ad193x, |
499 | i2c_del_driver(&ad193x_i2c_driver); | 390 | &ad193x_dai, 1); |
500 | #endif | ||
501 | } | 391 | } |
502 | module_exit(ad193x_modexit); | 392 | EXPORT_SYMBOL_GPL(ad193x_probe); |
503 | 393 | ||
504 | MODULE_DESCRIPTION("ASoC ad193x driver"); | 394 | MODULE_DESCRIPTION("ASoC ad193x driver"); |
505 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | 395 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); |
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index 473388049992..ab9a998f15be 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h | |||
@@ -9,6 +9,13 @@ | |||
9 | #ifndef __AD193X_H__ | 9 | #ifndef __AD193X_H__ |
10 | #define __AD193X_H__ | 10 | #define __AD193X_H__ |
11 | 11 | ||
12 | #include <linux/regmap.h> | ||
13 | |||
14 | struct device; | ||
15 | |||
16 | extern const struct regmap_config ad193x_regmap_config; | ||
17 | int ad193x_probe(struct device *dev, struct regmap *regmap); | ||
18 | |||
12 | #define AD193X_PLL_CLK_CTRL0 0x00 | 19 | #define AD193X_PLL_CLK_CTRL0 0x00 |
13 | #define AD193X_PLL_POWERDOWN 0x01 | 20 | #define AD193X_PLL_POWERDOWN 0x01 |
14 | #define AD193X_PLL_INPUT_MASK 0x6 | 21 | #define AD193X_PLL_INPUT_MASK 0x6 |
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index 52e7cb08434b..fa2b8e07f420 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c | |||
@@ -210,7 +210,7 @@ out: | |||
210 | static int si476x_codec_probe(struct snd_soc_codec *codec) | 210 | static int si476x_codec_probe(struct snd_soc_codec *codec) |
211 | { | 211 | { |
212 | codec->control_data = dev_get_regmap(codec->dev->parent, NULL); | 212 | codec->control_data = dev_get_regmap(codec->dev->parent, NULL); |
213 | return 0; | 213 | return snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); |
214 | } | 214 | } |
215 | 215 | ||
216 | static struct snd_soc_dai_ops si476x_dai_ops = { | 216 | static struct snd_soc_dai_ops si476x_dai_ops = { |
diff --git a/sound/soc/codecs/tlv320aic23-i2c.c b/sound/soc/codecs/tlv320aic23-i2c.c new file mode 100644 index 000000000000..20fc46092c2c --- /dev/null +++ b/sound/soc/codecs/tlv320aic23-i2c.c | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * ALSA SoC TLV320AIC23 codec driver I2C interface | ||
3 | * | ||
4 | * Author: Arun KS, <arunks@mistralsolutions.com> | ||
5 | * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., | ||
6 | * | ||
7 | * Based on sound/soc/codecs/wm8731.c by Richard Purdie | ||
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 version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/regmap.h> | ||
17 | #include <sound/soc.h> | ||
18 | |||
19 | #include "tlv320aic23.h" | ||
20 | |||
21 | static int tlv320aic23_i2c_probe(struct i2c_client *i2c, | ||
22 | const struct i2c_device_id *i2c_id) | ||
23 | { | ||
24 | struct regmap *regmap; | ||
25 | |||
26 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
27 | return -EINVAL; | ||
28 | |||
29 | regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); | ||
30 | return tlv320aic23_probe(&i2c->dev, regmap); | ||
31 | } | ||
32 | |||
33 | static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) | ||
34 | { | ||
35 | snd_soc_unregister_codec(&i2c->dev); | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | static const struct i2c_device_id tlv320aic23_id[] = { | ||
40 | {"tlv320aic23", 0}, | ||
41 | {} | ||
42 | }; | ||
43 | |||
44 | MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); | ||
45 | |||
46 | static struct i2c_driver tlv320aic23_i2c_driver = { | ||
47 | .driver = { | ||
48 | .name = "tlv320aic23-codec", | ||
49 | }, | ||
50 | .probe = tlv320aic23_i2c_probe, | ||
51 | .remove = __exit_p(tlv320aic23_i2c_remove), | ||
52 | .id_table = tlv320aic23_id, | ||
53 | }; | ||
54 | |||
55 | module_i2c_driver(tlv320aic23_i2c_driver); | ||
56 | |||
57 | MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver I2C"); | ||
58 | MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); | ||
59 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/tlv320aic23-spi.c b/sound/soc/codecs/tlv320aic23-spi.c new file mode 100644 index 000000000000..585aea436c6a --- /dev/null +++ b/sound/soc/codecs/tlv320aic23-spi.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * ALSA SoC TLV320AIC23 codec driver SPI interface | ||
3 | * | ||
4 | * Author: Arun KS, <arunks@mistralsolutions.com> | ||
5 | * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., | ||
6 | * | ||
7 | * Based on sound/soc/codecs/wm8731.c by Richard Purdie | ||
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 version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/regmap.h> | ||
16 | #include <linux/spi/spi.h> | ||
17 | #include <sound/soc.h> | ||
18 | |||
19 | #include "tlv320aic23.h" | ||
20 | |||
21 | static int aic23_spi_probe(struct spi_device *spi) | ||
22 | { | ||
23 | int ret; | ||
24 | struct regmap *regmap; | ||
25 | |||
26 | dev_dbg(&spi->dev, "probing tlv320aic23 spi device\n"); | ||
27 | |||
28 | spi->bits_per_word = 16; | ||
29 | spi->mode = SPI_MODE_0; | ||
30 | ret = spi_setup(spi); | ||
31 | if (ret < 0) | ||
32 | return ret; | ||
33 | |||
34 | regmap = devm_regmap_init_spi(spi, &tlv320aic23_regmap); | ||
35 | return tlv320aic23_probe(&spi->dev, regmap); | ||
36 | } | ||
37 | |||
38 | static int aic23_spi_remove(struct spi_device *spi) | ||
39 | { | ||
40 | snd_soc_unregister_codec(&spi->dev); | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | static struct spi_driver aic23_spi = { | ||
45 | .driver = { | ||
46 | .name = "tlv320aic23", | ||
47 | .owner = THIS_MODULE, | ||
48 | }, | ||
49 | .probe = aic23_spi_probe, | ||
50 | .remove = aic23_spi_remove, | ||
51 | }; | ||
52 | |||
53 | module_spi_driver(aic23_spi); | ||
54 | |||
55 | MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver SPI"); | ||
56 | MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); | ||
57 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 5d430cc56f51..7b4cfef232ea 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
26 | #include <linux/i2c.h> | ||
27 | #include <linux/regmap.h> | 26 | #include <linux/regmap.h> |
28 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
29 | #include <sound/core.h> | 28 | #include <sound/core.h> |
@@ -51,7 +50,7 @@ static const struct reg_default tlv320aic23_reg[] = { | |||
51 | { 9, 0x0000 }, | 50 | { 9, 0x0000 }, |
52 | }; | 51 | }; |
53 | 52 | ||
54 | static const struct regmap_config tlv320aic23_regmap = { | 53 | const struct regmap_config tlv320aic23_regmap = { |
55 | .reg_bits = 7, | 54 | .reg_bits = 7, |
56 | .val_bits = 9, | 55 | .val_bits = 9, |
57 | 56 | ||
@@ -60,20 +59,21 @@ static const struct regmap_config tlv320aic23_regmap = { | |||
60 | .num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg), | 59 | .num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg), |
61 | .cache_type = REGCACHE_RBTREE, | 60 | .cache_type = REGCACHE_RBTREE, |
62 | }; | 61 | }; |
62 | EXPORT_SYMBOL(tlv320aic23_regmap); | ||
63 | 63 | ||
64 | static const char *rec_src_text[] = { "Line", "Mic" }; | 64 | static const char *rec_src_text[] = { "Line", "Mic" }; |
65 | static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; | 65 | static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; |
66 | 66 | ||
67 | static const struct soc_enum rec_src_enum = | 67 | static SOC_ENUM_SINGLE_DECL(rec_src_enum, |
68 | SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); | 68 | TLV320AIC23_ANLG, 2, rec_src_text); |
69 | 69 | ||
70 | static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls = | 70 | static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls = |
71 | SOC_DAPM_ENUM("Input Select", rec_src_enum); | 71 | SOC_DAPM_ENUM("Input Select", rec_src_enum); |
72 | 72 | ||
73 | static const struct soc_enum tlv320aic23_rec_src = | 73 | static SOC_ENUM_SINGLE_DECL(tlv320aic23_rec_src, |
74 | SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); | 74 | TLV320AIC23_ANLG, 2, rec_src_text); |
75 | static const struct soc_enum tlv320aic23_deemph = | 75 | static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph, |
76 | SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text); | 76 | TLV320AIC23_DIGT, 1, deemph_text); |
77 | 77 | ||
78 | static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0); | 78 | static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0); |
79 | static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0); | 79 | static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0); |
@@ -557,7 +557,7 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec) | |||
557 | return 0; | 557 | return 0; |
558 | } | 558 | } |
559 | 559 | ||
560 | static int tlv320aic23_probe(struct snd_soc_codec *codec) | 560 | static int tlv320aic23_codec_probe(struct snd_soc_codec *codec) |
561 | { | 561 | { |
562 | int ret; | 562 | int ret; |
563 | 563 | ||
@@ -604,7 +604,7 @@ static int tlv320aic23_remove(struct snd_soc_codec *codec) | |||
604 | } | 604 | } |
605 | 605 | ||
606 | static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { | 606 | static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { |
607 | .probe = tlv320aic23_probe, | 607 | .probe = tlv320aic23_codec_probe, |
608 | .remove = tlv320aic23_remove, | 608 | .remove = tlv320aic23_remove, |
609 | .suspend = tlv320aic23_suspend, | 609 | .suspend = tlv320aic23_suspend, |
610 | .resume = tlv320aic23_resume, | 610 | .resume = tlv320aic23_resume, |
@@ -617,56 +617,25 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { | |||
617 | .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), | 617 | .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), |
618 | }; | 618 | }; |
619 | 619 | ||
620 | /* | 620 | int tlv320aic23_probe(struct device *dev, struct regmap *regmap) |
621 | * If the i2c layer weren't so broken, we could pass this kind of data | ||
622 | * around | ||
623 | */ | ||
624 | static int tlv320aic23_codec_probe(struct i2c_client *i2c, | ||
625 | const struct i2c_device_id *i2c_id) | ||
626 | { | 621 | { |
627 | struct aic23 *aic23; | 622 | struct aic23 *aic23; |
628 | int ret; | ||
629 | 623 | ||
630 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 624 | if (IS_ERR(regmap)) |
631 | return -EINVAL; | 625 | return PTR_ERR(regmap); |
632 | 626 | ||
633 | aic23 = devm_kzalloc(&i2c->dev, sizeof(struct aic23), GFP_KERNEL); | 627 | aic23 = devm_kzalloc(dev, sizeof(struct aic23), GFP_KERNEL); |
634 | if (aic23 == NULL) | 628 | if (aic23 == NULL) |
635 | return -ENOMEM; | 629 | return -ENOMEM; |
636 | 630 | ||
637 | aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); | 631 | aic23->regmap = regmap; |
638 | if (IS_ERR(aic23->regmap)) | ||
639 | return PTR_ERR(aic23->regmap); | ||
640 | 632 | ||
641 | i2c_set_clientdata(i2c, aic23); | 633 | dev_set_drvdata(dev, aic23); |
642 | 634 | ||
643 | ret = snd_soc_register_codec(&i2c->dev, | 635 | return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23, |
644 | &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); | 636 | &tlv320aic23_dai, 1); |
645 | return ret; | ||
646 | } | ||
647 | static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) | ||
648 | { | ||
649 | snd_soc_unregister_codec(&i2c->dev); | ||
650 | return 0; | ||
651 | } | 637 | } |
652 | 638 | EXPORT_SYMBOL(tlv320aic23_probe); | |
653 | static const struct i2c_device_id tlv320aic23_id[] = { | ||
654 | {"tlv320aic23", 0}, | ||
655 | {} | ||
656 | }; | ||
657 | |||
658 | MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); | ||
659 | |||
660 | static struct i2c_driver tlv320aic23_i2c_driver = { | ||
661 | .driver = { | ||
662 | .name = "tlv320aic23-codec", | ||
663 | }, | ||
664 | .probe = tlv320aic23_codec_probe, | ||
665 | .remove = __exit_p(tlv320aic23_i2c_remove), | ||
666 | .id_table = tlv320aic23_id, | ||
667 | }; | ||
668 | |||
669 | module_i2c_driver(tlv320aic23_i2c_driver); | ||
670 | 639 | ||
671 | MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); | 640 | MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); |
672 | MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); | 641 | MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); |
diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h index e804120bd3da..3a7235a04a89 100644 --- a/sound/soc/codecs/tlv320aic23.h +++ b/sound/soc/codecs/tlv320aic23.h | |||
@@ -12,6 +12,12 @@ | |||
12 | #ifndef _TLV320AIC23_H | 12 | #ifndef _TLV320AIC23_H |
13 | #define _TLV320AIC23_H | 13 | #define _TLV320AIC23_H |
14 | 14 | ||
15 | struct device; | ||
16 | struct regmap_config; | ||
17 | |||
18 | extern const struct regmap_config tlv320aic23_regmap; | ||
19 | int tlv320aic23_probe(struct device *dev, struct regmap *regmap); | ||
20 | |||
15 | /* Codec TLV320AIC23 */ | 21 | /* Codec TLV320AIC23 */ |
16 | #define TLV320AIC23_LINVOL 0x00 | 22 | #define TLV320AIC23_LINVOL 0x00 |
17 | #define TLV320AIC23_RINVOL 0x01 | 23 | #define TLV320AIC23_RINVOL 0x01 |
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 688151ba309a..c6bd7e75352d 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c | |||
@@ -29,9 +29,12 @@ | |||
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/pm.h> | 30 | #include <linux/pm.h> |
31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
32 | #include <linux/of_gpio.h> | ||
32 | #include <linux/i2c.h> | 33 | #include <linux/i2c.h> |
33 | #include <linux/cdev.h> | 34 | #include <linux/cdev.h> |
34 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/clk.h> | ||
37 | #include <linux/regulator/consumer.h> | ||
35 | 38 | ||
36 | #include <sound/tlv320aic32x4.h> | 39 | #include <sound/tlv320aic32x4.h> |
37 | #include <sound/core.h> | 40 | #include <sound/core.h> |
@@ -66,20 +69,32 @@ struct aic32x4_priv { | |||
66 | u32 micpga_routing; | 69 | u32 micpga_routing; |
67 | bool swapdacs; | 70 | bool swapdacs; |
68 | int rstn_gpio; | 71 | int rstn_gpio; |
72 | struct clk *mclk; | ||
73 | |||
74 | struct regulator *supply_ldo; | ||
75 | struct regulator *supply_iov; | ||
76 | struct regulator *supply_dv; | ||
77 | struct regulator *supply_av; | ||
69 | }; | 78 | }; |
70 | 79 | ||
71 | /* 0dB min, 1dB steps */ | ||
72 | static DECLARE_TLV_DB_SCALE(tlv_step_1, 0, 100, 0); | ||
73 | /* 0dB min, 0.5dB steps */ | 80 | /* 0dB min, 0.5dB steps */ |
74 | static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0); | 81 | static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0); |
82 | /* -63.5dB min, 0.5dB steps */ | ||
83 | static DECLARE_TLV_DB_SCALE(tlv_pcm, -6350, 50, 0); | ||
84 | /* -6dB min, 1dB steps */ | ||
85 | static DECLARE_TLV_DB_SCALE(tlv_driver_gain, -600, 100, 0); | ||
86 | /* -12dB min, 0.5dB steps */ | ||
87 | static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0); | ||
75 | 88 | ||
76 | static const struct snd_kcontrol_new aic32x4_snd_controls[] = { | 89 | static const struct snd_kcontrol_new aic32x4_snd_controls[] = { |
77 | SOC_DOUBLE_R_TLV("PCM Playback Volume", AIC32X4_LDACVOL, | 90 | SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL, |
78 | AIC32X4_RDACVOL, 0, 0x30, 0, tlv_step_0_5), | 91 | AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm), |
79 | SOC_DOUBLE_R_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, | 92 | SOC_DOUBLE_R_S_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, |
80 | AIC32X4_HPRGAIN, 0, 0x1D, 0, tlv_step_1), | 93 | AIC32X4_HPRGAIN, 0, -0x6, 0x1d, 5, 0, |
81 | SOC_DOUBLE_R_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, | 94 | tlv_driver_gain), |
82 | AIC32X4_LORGAIN, 0, 0x1D, 0, tlv_step_1), | 95 | SOC_DOUBLE_R_S_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, |
96 | AIC32X4_LORGAIN, 0, -0x6, 0x1d, 5, 0, | ||
97 | tlv_driver_gain), | ||
83 | SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN, | 98 | SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN, |
84 | AIC32X4_HPRGAIN, 6, 0x01, 1), | 99 | AIC32X4_HPRGAIN, 6, 0x01, 1), |
85 | SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN, | 100 | SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN, |
@@ -90,8 +105,8 @@ static const struct snd_kcontrol_new aic32x4_snd_controls[] = { | |||
90 | SOC_SINGLE("ADCFGA Left Mute Switch", AIC32X4_ADCFGA, 7, 1, 0), | 105 | SOC_SINGLE("ADCFGA Left Mute Switch", AIC32X4_ADCFGA, 7, 1, 0), |
91 | SOC_SINGLE("ADCFGA Right Mute Switch", AIC32X4_ADCFGA, 3, 1, 0), | 106 | SOC_SINGLE("ADCFGA Right Mute Switch", AIC32X4_ADCFGA, 3, 1, 0), |
92 | 107 | ||
93 | SOC_DOUBLE_R_TLV("ADC Level Volume", AIC32X4_LADCVOL, | 108 | SOC_DOUBLE_R_S_TLV("ADC Level Volume", AIC32X4_LADCVOL, |
94 | AIC32X4_RADCVOL, 0, 0x28, 0, tlv_step_0_5), | 109 | AIC32X4_RADCVOL, 0, -0x18, 0x28, 6, 0, tlv_adc_vol), |
95 | SOC_DOUBLE_R_TLV("PGA Level Volume", AIC32X4_LMICPGAVOL, | 110 | SOC_DOUBLE_R_TLV("PGA Level Volume", AIC32X4_LMICPGAVOL, |
96 | AIC32X4_RMICPGAVOL, 0, 0x5f, 0, tlv_step_0_5), | 111 | AIC32X4_RMICPGAVOL, 0, 0x5f, 0, tlv_step_0_5), |
97 | 112 | ||
@@ -480,8 +495,18 @@ static int aic32x4_mute(struct snd_soc_dai *dai, int mute) | |||
480 | static int aic32x4_set_bias_level(struct snd_soc_codec *codec, | 495 | static int aic32x4_set_bias_level(struct snd_soc_codec *codec, |
481 | enum snd_soc_bias_level level) | 496 | enum snd_soc_bias_level level) |
482 | { | 497 | { |
498 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); | ||
499 | int ret; | ||
500 | |||
483 | switch (level) { | 501 | switch (level) { |
484 | case SND_SOC_BIAS_ON: | 502 | case SND_SOC_BIAS_ON: |
503 | /* Switch on master clock */ | ||
504 | ret = clk_prepare_enable(aic32x4->mclk); | ||
505 | if (ret) { | ||
506 | dev_err(codec->dev, "Failed to enable master clock\n"); | ||
507 | return ret; | ||
508 | } | ||
509 | |||
485 | /* Switch on PLL */ | 510 | /* Switch on PLL */ |
486 | snd_soc_update_bits(codec, AIC32X4_PLLPR, | 511 | snd_soc_update_bits(codec, AIC32X4_PLLPR, |
487 | AIC32X4_PLLEN, AIC32X4_PLLEN); | 512 | AIC32X4_PLLEN, AIC32X4_PLLEN); |
@@ -509,29 +534,32 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec, | |||
509 | case SND_SOC_BIAS_PREPARE: | 534 | case SND_SOC_BIAS_PREPARE: |
510 | break; | 535 | break; |
511 | case SND_SOC_BIAS_STANDBY: | 536 | case SND_SOC_BIAS_STANDBY: |
512 | /* Switch off PLL */ | 537 | /* Switch off BCLK_N Divider */ |
513 | snd_soc_update_bits(codec, AIC32X4_PLLPR, | 538 | snd_soc_update_bits(codec, AIC32X4_BCLKN, |
514 | AIC32X4_PLLEN, 0); | 539 | AIC32X4_BCLKEN, 0); |
515 | 540 | ||
516 | /* Switch off NDAC Divider */ | 541 | /* Switch off MADC Divider */ |
517 | snd_soc_update_bits(codec, AIC32X4_NDAC, | 542 | snd_soc_update_bits(codec, AIC32X4_MADC, |
518 | AIC32X4_NDACEN, 0); | 543 | AIC32X4_MADCEN, 0); |
544 | |||
545 | /* Switch off NADC Divider */ | ||
546 | snd_soc_update_bits(codec, AIC32X4_NADC, | ||
547 | AIC32X4_NADCEN, 0); | ||
519 | 548 | ||
520 | /* Switch off MDAC Divider */ | 549 | /* Switch off MDAC Divider */ |
521 | snd_soc_update_bits(codec, AIC32X4_MDAC, | 550 | snd_soc_update_bits(codec, AIC32X4_MDAC, |
522 | AIC32X4_MDACEN, 0); | 551 | AIC32X4_MDACEN, 0); |
523 | 552 | ||
524 | /* Switch off NADC Divider */ | 553 | /* Switch off NDAC Divider */ |
525 | snd_soc_update_bits(codec, AIC32X4_NADC, | 554 | snd_soc_update_bits(codec, AIC32X4_NDAC, |
526 | AIC32X4_NADCEN, 0); | 555 | AIC32X4_NDACEN, 0); |
527 | 556 | ||
528 | /* Switch off MADC Divider */ | 557 | /* Switch off PLL */ |
529 | snd_soc_update_bits(codec, AIC32X4_MADC, | 558 | snd_soc_update_bits(codec, AIC32X4_PLLPR, |
530 | AIC32X4_MADCEN, 0); | 559 | AIC32X4_PLLEN, 0); |
531 | 560 | ||
532 | /* Switch off BCLK_N Divider */ | 561 | /* Switch off master clock */ |
533 | snd_soc_update_bits(codec, AIC32X4_BCLKN, | 562 | clk_disable_unprepare(aic32x4->mclk); |
534 | AIC32X4_BCLKEN, 0); | ||
535 | break; | 563 | break; |
536 | case SND_SOC_BIAS_OFF: | 564 | case SND_SOC_BIAS_OFF: |
537 | break; | 565 | break; |
@@ -588,7 +616,7 @@ static int aic32x4_probe(struct snd_soc_codec *codec) | |||
588 | 616 | ||
589 | snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | 617 | snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); |
590 | 618 | ||
591 | if (aic32x4->rstn_gpio >= 0) { | 619 | if (gpio_is_valid(aic32x4->rstn_gpio)) { |
592 | ndelay(10); | 620 | ndelay(10); |
593 | gpio_set_value(aic32x4->rstn_gpio, 1); | 621 | gpio_set_value(aic32x4->rstn_gpio, 1); |
594 | } | 622 | } |
@@ -663,11 +691,122 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { | |||
663 | .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), | 691 | .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), |
664 | }; | 692 | }; |
665 | 693 | ||
694 | static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4, | ||
695 | struct device_node *np) | ||
696 | { | ||
697 | aic32x4->swapdacs = false; | ||
698 | aic32x4->micpga_routing = 0; | ||
699 | aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0); | ||
700 | |||
701 | return 0; | ||
702 | } | ||
703 | |||
704 | static void aic32x4_disable_regulators(struct aic32x4_priv *aic32x4) | ||
705 | { | ||
706 | regulator_disable(aic32x4->supply_iov); | ||
707 | |||
708 | if (!IS_ERR(aic32x4->supply_ldo)) | ||
709 | regulator_disable(aic32x4->supply_ldo); | ||
710 | |||
711 | if (!IS_ERR(aic32x4->supply_dv)) | ||
712 | regulator_disable(aic32x4->supply_dv); | ||
713 | |||
714 | if (!IS_ERR(aic32x4->supply_av)) | ||
715 | regulator_disable(aic32x4->supply_av); | ||
716 | } | ||
717 | |||
718 | static int aic32x4_setup_regulators(struct device *dev, | ||
719 | struct aic32x4_priv *aic32x4) | ||
720 | { | ||
721 | int ret = 0; | ||
722 | |||
723 | aic32x4->supply_ldo = devm_regulator_get_optional(dev, "ldoin"); | ||
724 | aic32x4->supply_iov = devm_regulator_get(dev, "iov"); | ||
725 | aic32x4->supply_dv = devm_regulator_get_optional(dev, "dv"); | ||
726 | aic32x4->supply_av = devm_regulator_get_optional(dev, "av"); | ||
727 | |||
728 | /* Check if the regulator requirements are fulfilled */ | ||
729 | |||
730 | if (IS_ERR(aic32x4->supply_iov)) { | ||
731 | dev_err(dev, "Missing supply 'iov'\n"); | ||
732 | return PTR_ERR(aic32x4->supply_iov); | ||
733 | } | ||
734 | |||
735 | if (IS_ERR(aic32x4->supply_ldo)) { | ||
736 | if (PTR_ERR(aic32x4->supply_ldo) == -EPROBE_DEFER) | ||
737 | return -EPROBE_DEFER; | ||
738 | |||
739 | if (IS_ERR(aic32x4->supply_dv)) { | ||
740 | dev_err(dev, "Missing supply 'dv' or 'ldoin'\n"); | ||
741 | return PTR_ERR(aic32x4->supply_dv); | ||
742 | } | ||
743 | if (IS_ERR(aic32x4->supply_av)) { | ||
744 | dev_err(dev, "Missing supply 'av' or 'ldoin'\n"); | ||
745 | return PTR_ERR(aic32x4->supply_av); | ||
746 | } | ||
747 | } else { | ||
748 | if (IS_ERR(aic32x4->supply_dv) && | ||
749 | PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER) | ||
750 | return -EPROBE_DEFER; | ||
751 | if (IS_ERR(aic32x4->supply_av) && | ||
752 | PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER) | ||
753 | return -EPROBE_DEFER; | ||
754 | } | ||
755 | |||
756 | ret = regulator_enable(aic32x4->supply_iov); | ||
757 | if (ret) { | ||
758 | dev_err(dev, "Failed to enable regulator iov\n"); | ||
759 | return ret; | ||
760 | } | ||
761 | |||
762 | if (!IS_ERR(aic32x4->supply_ldo)) { | ||
763 | ret = regulator_enable(aic32x4->supply_ldo); | ||
764 | if (ret) { | ||
765 | dev_err(dev, "Failed to enable regulator ldo\n"); | ||
766 | goto error_ldo; | ||
767 | } | ||
768 | } | ||
769 | |||
770 | if (!IS_ERR(aic32x4->supply_dv)) { | ||
771 | ret = regulator_enable(aic32x4->supply_dv); | ||
772 | if (ret) { | ||
773 | dev_err(dev, "Failed to enable regulator dv\n"); | ||
774 | goto error_dv; | ||
775 | } | ||
776 | } | ||
777 | |||
778 | if (!IS_ERR(aic32x4->supply_av)) { | ||
779 | ret = regulator_enable(aic32x4->supply_av); | ||
780 | if (ret) { | ||
781 | dev_err(dev, "Failed to enable regulator av\n"); | ||
782 | goto error_av; | ||
783 | } | ||
784 | } | ||
785 | |||
786 | if (!IS_ERR(aic32x4->supply_ldo) && IS_ERR(aic32x4->supply_av)) | ||
787 | aic32x4->power_cfg |= AIC32X4_PWR_AIC32X4_LDO_ENABLE; | ||
788 | |||
789 | return 0; | ||
790 | |||
791 | error_av: | ||
792 | if (!IS_ERR(aic32x4->supply_dv)) | ||
793 | regulator_disable(aic32x4->supply_dv); | ||
794 | |||
795 | error_dv: | ||
796 | if (!IS_ERR(aic32x4->supply_ldo)) | ||
797 | regulator_disable(aic32x4->supply_ldo); | ||
798 | |||
799 | error_ldo: | ||
800 | regulator_disable(aic32x4->supply_iov); | ||
801 | return ret; | ||
802 | } | ||
803 | |||
666 | static int aic32x4_i2c_probe(struct i2c_client *i2c, | 804 | static int aic32x4_i2c_probe(struct i2c_client *i2c, |
667 | const struct i2c_device_id *id) | 805 | const struct i2c_device_id *id) |
668 | { | 806 | { |
669 | struct aic32x4_pdata *pdata = i2c->dev.platform_data; | 807 | struct aic32x4_pdata *pdata = i2c->dev.platform_data; |
670 | struct aic32x4_priv *aic32x4; | 808 | struct aic32x4_priv *aic32x4; |
809 | struct device_node *np = i2c->dev.of_node; | ||
671 | int ret; | 810 | int ret; |
672 | 811 | ||
673 | aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv), | 812 | aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv), |
@@ -686,6 +825,12 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, | |||
686 | aic32x4->swapdacs = pdata->swapdacs; | 825 | aic32x4->swapdacs = pdata->swapdacs; |
687 | aic32x4->micpga_routing = pdata->micpga_routing; | 826 | aic32x4->micpga_routing = pdata->micpga_routing; |
688 | aic32x4->rstn_gpio = pdata->rstn_gpio; | 827 | aic32x4->rstn_gpio = pdata->rstn_gpio; |
828 | } else if (np) { | ||
829 | ret = aic32x4_parse_dt(aic32x4, np); | ||
830 | if (ret) { | ||
831 | dev_err(&i2c->dev, "Failed to parse DT node\n"); | ||
832 | return ret; | ||
833 | } | ||
689 | } else { | 834 | } else { |
690 | aic32x4->power_cfg = 0; | 835 | aic32x4->power_cfg = 0; |
691 | aic32x4->swapdacs = false; | 836 | aic32x4->swapdacs = false; |
@@ -693,20 +838,44 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, | |||
693 | aic32x4->rstn_gpio = -1; | 838 | aic32x4->rstn_gpio = -1; |
694 | } | 839 | } |
695 | 840 | ||
696 | if (aic32x4->rstn_gpio >= 0) { | 841 | aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk"); |
842 | if (IS_ERR(aic32x4->mclk)) { | ||
843 | dev_err(&i2c->dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n"); | ||
844 | return PTR_ERR(aic32x4->mclk); | ||
845 | } | ||
846 | |||
847 | if (gpio_is_valid(aic32x4->rstn_gpio)) { | ||
697 | ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, | 848 | ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, |
698 | GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); | 849 | GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); |
699 | if (ret != 0) | 850 | if (ret != 0) |
700 | return ret; | 851 | return ret; |
701 | } | 852 | } |
702 | 853 | ||
854 | ret = aic32x4_setup_regulators(&i2c->dev, aic32x4); | ||
855 | if (ret) { | ||
856 | dev_err(&i2c->dev, "Failed to setup regulators\n"); | ||
857 | return ret; | ||
858 | } | ||
859 | |||
703 | ret = snd_soc_register_codec(&i2c->dev, | 860 | ret = snd_soc_register_codec(&i2c->dev, |
704 | &soc_codec_dev_aic32x4, &aic32x4_dai, 1); | 861 | &soc_codec_dev_aic32x4, &aic32x4_dai, 1); |
705 | return ret; | 862 | if (ret) { |
863 | dev_err(&i2c->dev, "Failed to register codec\n"); | ||
864 | aic32x4_disable_regulators(aic32x4); | ||
865 | return ret; | ||
866 | } | ||
867 | |||
868 | i2c_set_clientdata(i2c, aic32x4); | ||
869 | |||
870 | return 0; | ||
706 | } | 871 | } |
707 | 872 | ||
708 | static int aic32x4_i2c_remove(struct i2c_client *client) | 873 | static int aic32x4_i2c_remove(struct i2c_client *client) |
709 | { | 874 | { |
875 | struct aic32x4_priv *aic32x4 = i2c_get_clientdata(client); | ||
876 | |||
877 | aic32x4_disable_regulators(aic32x4); | ||
878 | |||
710 | snd_soc_unregister_codec(&client->dev); | 879 | snd_soc_unregister_codec(&client->dev); |
711 | return 0; | 880 | return 0; |
712 | } | 881 | } |
@@ -717,10 +886,17 @@ static const struct i2c_device_id aic32x4_i2c_id[] = { | |||
717 | }; | 886 | }; |
718 | MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); | 887 | MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); |
719 | 888 | ||
889 | static const struct of_device_id aic32x4_of_id[] = { | ||
890 | { .compatible = "ti,tlv320aic32x4", }, | ||
891 | { /* senitel */ } | ||
892 | }; | ||
893 | MODULE_DEVICE_TABLE(of, aic32x4_of_id); | ||
894 | |||
720 | static struct i2c_driver aic32x4_i2c_driver = { | 895 | static struct i2c_driver aic32x4_i2c_driver = { |
721 | .driver = { | 896 | .driver = { |
722 | .name = "tlv320aic32x4", | 897 | .name = "tlv320aic32x4", |
723 | .owner = THIS_MODULE, | 898 | .owner = THIS_MODULE, |
899 | .of_match_table = aic32x4_of_id, | ||
724 | }, | 900 | }, |
725 | .probe = aic32x4_i2c_probe, | 901 | .probe = aic32x4_i2c_probe, |
726 | .remove = aic32x4_i2c_remove, | 902 | .remove = aic32x4_i2c_remove, |
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index dba0306c42a5..32d219570cca 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c | |||
@@ -171,26 +171,23 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, | |||
171 | static const char *wm8991_digital_sidetone[] = | 171 | static const char *wm8991_digital_sidetone[] = |
172 | {"None", "Left ADC", "Right ADC", "Reserved"}; | 172 | {"None", "Left ADC", "Right ADC", "Reserved"}; |
173 | 173 | ||
174 | static const struct soc_enum wm8991_left_digital_sidetone_enum = | 174 | static SOC_ENUM_SINGLE_DECL(wm8991_left_digital_sidetone_enum, |
175 | SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, | 175 | WM8991_DIGITAL_SIDE_TONE, |
176 | WM8991_ADC_TO_DACL_SHIFT, | 176 | WM8991_ADC_TO_DACL_SHIFT, |
177 | WM8991_ADC_TO_DACL_MASK, | 177 | wm8991_digital_sidetone); |
178 | wm8991_digital_sidetone); | 178 | |
179 | 179 | static SOC_ENUM_SINGLE_DECL(wm8991_right_digital_sidetone_enum, | |
180 | static const struct soc_enum wm8991_right_digital_sidetone_enum = | 180 | WM8991_DIGITAL_SIDE_TONE, |
181 | SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, | 181 | WM8991_ADC_TO_DACR_SHIFT, |
182 | WM8991_ADC_TO_DACR_SHIFT, | 182 | wm8991_digital_sidetone); |
183 | WM8991_ADC_TO_DACR_MASK, | ||
184 | wm8991_digital_sidetone); | ||
185 | 183 | ||
186 | static const char *wm8991_adcmode[] = | 184 | static const char *wm8991_adcmode[] = |
187 | {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; | 185 | {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; |
188 | 186 | ||
189 | static const struct soc_enum wm8991_right_adcmode_enum = | 187 | static SOC_ENUM_SINGLE_DECL(wm8991_right_adcmode_enum, |
190 | SOC_ENUM_SINGLE(WM8991_ADC_CTRL, | 188 | WM8991_ADC_CTRL, |
191 | WM8991_ADC_HPF_CUT_SHIFT, | 189 | WM8991_ADC_HPF_CUT_SHIFT, |
192 | WM8991_ADC_HPF_CUT_MASK, | 190 | wm8991_adcmode); |
193 | wm8991_adcmode); | ||
194 | 191 | ||
195 | static const struct snd_kcontrol_new wm8991_snd_controls[] = { | 192 | static const struct snd_kcontrol_new wm8991_snd_controls[] = { |
196 | /* INMIXL */ | 193 | /* INMIXL */ |
@@ -486,9 +483,9 @@ static const struct snd_kcontrol_new wm8991_dapm_inmixr_controls[] = { | |||
486 | static const char *wm8991_ainlmux[] = | 483 | static const char *wm8991_ainlmux[] = |
487 | {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; | 484 | {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; |
488 | 485 | ||
489 | static const struct soc_enum wm8991_ainlmux_enum = | 486 | static SOC_ENUM_SINGLE_DECL(wm8991_ainlmux_enum, |
490 | SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, | 487 | WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, |
491 | ARRAY_SIZE(wm8991_ainlmux), wm8991_ainlmux); | 488 | wm8991_ainlmux); |
492 | 489 | ||
493 | static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = | 490 | static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = |
494 | SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum); | 491 | SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum); |
@@ -499,9 +496,9 @@ static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = | |||
499 | static const char *wm8991_ainrmux[] = | 496 | static const char *wm8991_ainrmux[] = |
500 | {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; | 497 | {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; |
501 | 498 | ||
502 | static const struct soc_enum wm8991_ainrmux_enum = | 499 | static SOC_ENUM_SINGLE_DECL(wm8991_ainrmux_enum, |
503 | SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, | 500 | WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, |
504 | ARRAY_SIZE(wm8991_ainrmux), wm8991_ainrmux); | 501 | wm8991_ainrmux); |
505 | 502 | ||
506 | static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls = | 503 | static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls = |
507 | SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum); | 504 | SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum); |
@@ -1251,11 +1248,8 @@ static int wm8991_remove(struct snd_soc_codec *codec) | |||
1251 | 1248 | ||
1252 | static int wm8991_probe(struct snd_soc_codec *codec) | 1249 | static int wm8991_probe(struct snd_soc_codec *codec) |
1253 | { | 1250 | { |
1254 | struct wm8991_priv *wm8991; | ||
1255 | int ret; | 1251 | int ret; |
1256 | 1252 | ||
1257 | wm8991 = snd_soc_codec_get_drvdata(codec); | ||
1258 | |||
1259 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | 1253 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); |
1260 | if (ret < 0) { | 1254 | if (ret < 0) { |
1261 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); | 1255 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); |
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 07f8f141727d..19a18a4f133a 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -170,7 +170,7 @@ config SND_SOC_EUKREA_TLV320 | |||
170 | || MACH_EUKREA_MBIMXSD35_BASEBOARD \ | 170 | || MACH_EUKREA_MBIMXSD35_BASEBOARD \ |
171 | || MACH_EUKREA_MBIMXSD51_BASEBOARD | 171 | || MACH_EUKREA_MBIMXSD51_BASEBOARD |
172 | depends on I2C | 172 | depends on I2C |
173 | select SND_SOC_TLV320AIC23 | 173 | select SND_SOC_TLV320AIC23_I2C |
174 | select SND_SOC_IMX_PCM_FIQ | 174 | select SND_SOC_IMX_PCM_FIQ |
175 | select SND_SOC_IMX_AUDMUX | 175 | select SND_SOC_IMX_AUDMUX |
176 | select SND_SOC_IMX_SSI | 176 | select SND_SOC_IMX_SSI |
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 22ad9c5654b5..e00659351a4e 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig | |||
@@ -58,7 +58,7 @@ config SND_OMAP_SOC_OSK5912 | |||
58 | tristate "SoC Audio support for omap osk5912" | 58 | tristate "SoC Audio support for omap osk5912" |
59 | depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C | 59 | depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C |
60 | select SND_OMAP_SOC_MCBSP | 60 | select SND_OMAP_SOC_MCBSP |
61 | select SND_SOC_TLV320AIC23 | 61 | select SND_SOC_TLV320AIC23_I2C |
62 | help | 62 | help |
63 | Say Y if you want to add support for SoC audio on osk5912. | 63 | Say Y if you want to add support for SoC audio on osk5912. |
64 | 64 | ||
@@ -66,7 +66,7 @@ config SND_OMAP_SOC_AM3517EVM | |||
66 | tristate "SoC Audio support for OMAP3517 / AM3517 EVM" | 66 | tristate "SoC Audio support for OMAP3517 / AM3517 EVM" |
67 | depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C | 67 | depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C |
68 | select SND_OMAP_SOC_MCBSP | 68 | select SND_OMAP_SOC_MCBSP |
69 | select SND_SOC_TLV320AIC23 | 69 | select SND_SOC_TLV320AIC23_I2C |
70 | help | 70 | help |
71 | Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517 | 71 | Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517 |
72 | EVM. | 72 | EVM. |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 454f41cfc828..47a7a1b633ae 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -117,7 +117,7 @@ config SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23 | |||
117 | tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" | 117 | tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" |
118 | depends on SND_SOC_SAMSUNG && ARCH_S3C24XX | 118 | depends on SND_SOC_SAMSUNG && ARCH_S3C24XX |
119 | select SND_S3C24XX_I2S | 119 | select SND_S3C24XX_I2S |
120 | select SND_SOC_TLV320AIC23 | 120 | select SND_SOC_TLV320AIC23_I2C |
121 | select SND_SOC_SAMSUNG_SIMTEC | 121 | select SND_SOC_SAMSUNG_SIMTEC |
122 | 122 | ||
123 | config SND_SOC_SAMSUNG_SIMTEC_HERMES | 123 | config SND_SOC_SAMSUNG_SIMTEC_HERMES |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 93854f031523..ad2dd14f0e3e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -2716,6 +2716,48 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
2716 | EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); | 2716 | EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); |
2717 | 2717 | ||
2718 | /** | 2718 | /** |
2719 | * snd_soc_read_signed - Read a codec register and interprete as signed value | ||
2720 | * @codec: codec | ||
2721 | * @reg: Register to read | ||
2722 | * @mask: Mask to use after shifting the register value | ||
2723 | * @shift: Right shift of register value | ||
2724 | * @sign_bit: Bit that describes if a number is negative or not. | ||
2725 | * | ||
2726 | * This functions reads a codec register. The register value is shifted right | ||
2727 | * by 'shift' bits and masked with the given 'mask'. Afterwards it translates | ||
2728 | * the given registervalue into a signed integer if sign_bit is non-zero. | ||
2729 | * | ||
2730 | * Returns the register value as signed int. | ||
2731 | */ | ||
2732 | static int snd_soc_read_signed(struct snd_soc_codec *codec, unsigned int reg, | ||
2733 | unsigned int mask, unsigned int shift, unsigned int sign_bit) | ||
2734 | { | ||
2735 | int ret; | ||
2736 | unsigned int val; | ||
2737 | |||
2738 | val = (snd_soc_read(codec, reg) >> shift) & mask; | ||
2739 | |||
2740 | if (!sign_bit) | ||
2741 | return val; | ||
2742 | |||
2743 | /* non-negative number */ | ||
2744 | if (!(val & BIT(sign_bit))) | ||
2745 | return val; | ||
2746 | |||
2747 | ret = val; | ||
2748 | |||
2749 | /* | ||
2750 | * The register most probably does not contain a full-sized int. | ||
2751 | * Instead we have an arbitrary number of bits in a signed | ||
2752 | * representation which has to be translated into a full-sized int. | ||
2753 | * This is done by filling up all bits above the sign-bit. | ||
2754 | */ | ||
2755 | ret |= ~((int)(BIT(sign_bit) - 1)); | ||
2756 | |||
2757 | return ret; | ||
2758 | } | ||
2759 | |||
2760 | /** | ||
2719 | * snd_soc_info_volsw - single mixer info callback | 2761 | * snd_soc_info_volsw - single mixer info callback |
2720 | * @kcontrol: mixer control | 2762 | * @kcontrol: mixer control |
2721 | * @uinfo: control element information | 2763 | * @uinfo: control element information |
@@ -2743,7 +2785,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, | |||
2743 | 2785 | ||
2744 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; | 2786 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; |
2745 | uinfo->value.integer.min = 0; | 2787 | uinfo->value.integer.min = 0; |
2746 | uinfo->value.integer.max = platform_max; | 2788 | uinfo->value.integer.max = platform_max - mc->min; |
2747 | return 0; | 2789 | return 0; |
2748 | } | 2790 | } |
2749 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); | 2791 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); |
@@ -2769,11 +2811,16 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | |||
2769 | unsigned int shift = mc->shift; | 2811 | unsigned int shift = mc->shift; |
2770 | unsigned int rshift = mc->rshift; | 2812 | unsigned int rshift = mc->rshift; |
2771 | int max = mc->max; | 2813 | int max = mc->max; |
2814 | int min = mc->min; | ||
2815 | int sign_bit = mc->sign_bit; | ||
2772 | unsigned int mask = (1 << fls(max)) - 1; | 2816 | unsigned int mask = (1 << fls(max)) - 1; |
2773 | unsigned int invert = mc->invert; | 2817 | unsigned int invert = mc->invert; |
2774 | 2818 | ||
2775 | ucontrol->value.integer.value[0] = | 2819 | if (sign_bit) |
2776 | (snd_soc_read(codec, reg) >> shift) & mask; | 2820 | mask = BIT(sign_bit + 1) - 1; |
2821 | |||
2822 | ucontrol->value.integer.value[0] = snd_soc_read_signed(codec, reg, mask, | ||
2823 | shift, sign_bit) - min; | ||
2777 | if (invert) | 2824 | if (invert) |
2778 | ucontrol->value.integer.value[0] = | 2825 | ucontrol->value.integer.value[0] = |
2779 | max - ucontrol->value.integer.value[0]; | 2826 | max - ucontrol->value.integer.value[0]; |
@@ -2781,10 +2828,12 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | |||
2781 | if (snd_soc_volsw_is_stereo(mc)) { | 2828 | if (snd_soc_volsw_is_stereo(mc)) { |
2782 | if (reg == reg2) | 2829 | if (reg == reg2) |
2783 | ucontrol->value.integer.value[1] = | 2830 | ucontrol->value.integer.value[1] = |
2784 | (snd_soc_read(codec, reg) >> rshift) & mask; | 2831 | snd_soc_read_signed(codec, reg, mask, rshift, |
2832 | sign_bit) - min; | ||
2785 | else | 2833 | else |
2786 | ucontrol->value.integer.value[1] = | 2834 | ucontrol->value.integer.value[1] = |
2787 | (snd_soc_read(codec, reg2) >> shift) & mask; | 2835 | snd_soc_read_signed(codec, reg2, mask, shift, |
2836 | sign_bit) - min; | ||
2788 | if (invert) | 2837 | if (invert) |
2789 | ucontrol->value.integer.value[1] = | 2838 | ucontrol->value.integer.value[1] = |
2790 | max - ucontrol->value.integer.value[1]; | 2839 | max - ucontrol->value.integer.value[1]; |
@@ -2815,6 +2864,8 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, | |||
2815 | unsigned int shift = mc->shift; | 2864 | unsigned int shift = mc->shift; |
2816 | unsigned int rshift = mc->rshift; | 2865 | unsigned int rshift = mc->rshift; |
2817 | int max = mc->max; | 2866 | int max = mc->max; |
2867 | int min = mc->min; | ||
2868 | unsigned int sign_bit = mc->sign_bit; | ||
2818 | unsigned int mask = (1 << fls(max)) - 1; | 2869 | unsigned int mask = (1 << fls(max)) - 1; |
2819 | unsigned int invert = mc->invert; | 2870 | unsigned int invert = mc->invert; |
2820 | int err; | 2871 | int err; |
@@ -2822,13 +2873,16 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, | |||
2822 | unsigned int val2 = 0; | 2873 | unsigned int val2 = 0; |
2823 | unsigned int val, val_mask; | 2874 | unsigned int val, val_mask; |
2824 | 2875 | ||
2825 | val = (ucontrol->value.integer.value[0] & mask); | 2876 | if (sign_bit) |
2877 | mask = BIT(sign_bit + 1) - 1; | ||
2878 | |||
2879 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
2826 | if (invert) | 2880 | if (invert) |
2827 | val = max - val; | 2881 | val = max - val; |
2828 | val_mask = mask << shift; | 2882 | val_mask = mask << shift; |
2829 | val = val << shift; | 2883 | val = val << shift; |
2830 | if (snd_soc_volsw_is_stereo(mc)) { | 2884 | if (snd_soc_volsw_is_stereo(mc)) { |
2831 | val2 = (ucontrol->value.integer.value[1] & mask); | 2885 | val2 = ((ucontrol->value.integer.value[1] + min) & mask); |
2832 | if (invert) | 2886 | if (invert) |
2833 | val2 = max - val2; | 2887 | val2 = max - val2; |
2834 | if (reg == reg2) { | 2888 | if (reg == reg2) { |
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 9f9c1856f822..31198cf7f88d 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig | |||
@@ -105,7 +105,7 @@ config SND_SOC_TEGRA_TRIMSLICE | |||
105 | tristate "SoC Audio support for TrimSlice board" | 105 | tristate "SoC Audio support for TrimSlice board" |
106 | depends on SND_SOC_TEGRA && I2C | 106 | depends on SND_SOC_TEGRA && I2C |
107 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC | 107 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC |
108 | select SND_SOC_TLV320AIC23 | 108 | select SND_SOC_TLV320AIC23_I2C |
109 | help | 109 | help |
110 | Say Y or M here if you want to add support for SoC audio on the | 110 | Say Y or M here if you want to add support for SoC audio on the |
111 | TrimSlice platform. | 111 | TrimSlice platform. |