diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-07-22 02:43:19 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-07-22 02:43:19 -0400 |
commit | 13b137ef0367237909bb2dc38babfb8305154676 (patch) | |
tree | a5d756fcc6603da970ef8c5e263244c6166a2fba /sound/soc/codecs | |
parent | e8fd86efaa09445ca1afc1aea08d4666c966ed03 (diff) | |
parent | 440085598672c0e3fde8a48495f61fea418b06d1 (diff) |
Merge branch 'topic/asoc' into for-linus
Diffstat (limited to 'sound/soc/codecs')
30 files changed, 5643 insertions, 320 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 98175a096df2..36a030f1d1f5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -17,6 +17,7 @@ config SND_SOC_ALL_CODECS | |||
17 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI | 17 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI |
18 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS | 18 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS |
19 | select SND_SOC_AD73311 | 19 | select SND_SOC_AD73311 |
20 | select SND_SOC_ADAV80X | ||
20 | select SND_SOC_ADS117X | 21 | select SND_SOC_ADS117X |
21 | select SND_SOC_AK4104 if SPI_MASTER | 22 | select SND_SOC_AK4104 if SPI_MASTER |
22 | select SND_SOC_AK4535 if I2C | 23 | select SND_SOC_AK4535 if I2C |
@@ -42,6 +43,7 @@ config SND_SOC_ALL_CODECS | |||
42 | select SND_SOC_SN95031 if INTEL_SCU_IPC | 43 | select SND_SOC_SN95031 if INTEL_SCU_IPC |
43 | select SND_SOC_SPDIF | 44 | select SND_SOC_SPDIF |
44 | select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI | 45 | select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI |
46 | select SND_SOC_STA32X if I2C | ||
45 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS | 47 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS |
46 | select SND_SOC_TLV320AIC23 if I2C | 48 | select SND_SOC_TLV320AIC23 if I2C |
47 | select SND_SOC_TLV320AIC26 if SPI_MASTER | 49 | select SND_SOC_TLV320AIC26 if SPI_MASTER |
@@ -71,6 +73,7 @@ config SND_SOC_ALL_CODECS | |||
71 | select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI | 73 | select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI |
72 | select SND_SOC_WM8770 if SPI_MASTER | 74 | select SND_SOC_WM8770 if SPI_MASTER |
73 | select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI | 75 | select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI |
76 | select SND_SOC_WM8782 | ||
74 | select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI | 77 | select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI |
75 | select SND_SOC_WM8900 if I2C | 78 | select SND_SOC_WM8900 if I2C |
76 | select SND_SOC_WM8903 if I2C | 79 | select SND_SOC_WM8903 if I2C |
@@ -84,6 +87,7 @@ config SND_SOC_ALL_CODECS | |||
84 | select SND_SOC_WM8971 if I2C | 87 | select SND_SOC_WM8971 if I2C |
85 | select SND_SOC_WM8974 if I2C | 88 | select SND_SOC_WM8974 if I2C |
86 | select SND_SOC_WM8978 if I2C | 89 | select SND_SOC_WM8978 if I2C |
90 | select SND_SOC_WM8983 if SND_SOC_I2C_AND_SPI | ||
87 | select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI | 91 | select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI |
88 | select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI | 92 | select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI |
89 | select SND_SOC_WM8990 if I2C | 93 | select SND_SOC_WM8990 if I2C |
@@ -130,7 +134,14 @@ config SND_SOC_AD1980 | |||
130 | 134 | ||
131 | config SND_SOC_AD73311 | 135 | config SND_SOC_AD73311 |
132 | tristate | 136 | tristate |
133 | 137 | ||
138 | config SND_SOC_ADAU1701 | ||
139 | select SIGMA | ||
140 | tristate | ||
141 | |||
142 | config SND_SOC_ADAV80X | ||
143 | tristate | ||
144 | |||
134 | config SND_SOC_ADS117X | 145 | config SND_SOC_ADS117X |
135 | tristate | 146 | tristate |
136 | 147 | ||
@@ -216,6 +227,9 @@ config SND_SOC_SPDIF | |||
216 | config SND_SOC_SSM2602 | 227 | config SND_SOC_SSM2602 |
217 | tristate | 228 | tristate |
218 | 229 | ||
230 | config SND_SOC_STA32X | ||
231 | tristate | ||
232 | |||
219 | config SND_SOC_STAC9766 | 233 | config SND_SOC_STAC9766 |
220 | tristate | 234 | tristate |
221 | 235 | ||
@@ -299,6 +313,9 @@ config SND_SOC_WM8770 | |||
299 | config SND_SOC_WM8776 | 313 | config SND_SOC_WM8776 |
300 | tristate | 314 | tristate |
301 | 315 | ||
316 | config SND_SOC_WM8782 | ||
317 | tristate | ||
318 | |||
302 | config SND_SOC_WM8804 | 319 | config SND_SOC_WM8804 |
303 | tristate | 320 | tristate |
304 | 321 | ||
@@ -338,6 +355,9 @@ config SND_SOC_WM8974 | |||
338 | config SND_SOC_WM8978 | 355 | config SND_SOC_WM8978 |
339 | tristate | 356 | tristate |
340 | 357 | ||
358 | config SND_SOC_WM8983 | ||
359 | tristate | ||
360 | |||
341 | config SND_SOC_WM8985 | 361 | config SND_SOC_WM8985 |
342 | tristate | 362 | tristate |
343 | 363 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index fd8558406ef0..da9990fb8569 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -4,6 +4,8 @@ snd-soc-ad1836-objs := ad1836.o | |||
4 | snd-soc-ad193x-objs := ad193x.o | 4 | snd-soc-ad193x-objs := ad193x.o |
5 | snd-soc-ad1980-objs := ad1980.o | 5 | snd-soc-ad1980-objs := ad1980.o |
6 | snd-soc-ad73311-objs := ad73311.o | 6 | snd-soc-ad73311-objs := ad73311.o |
7 | snd-soc-adau1701-objs := adau1701.o | ||
8 | snd-soc-adav80x-objs := adav80x.o | ||
7 | snd-soc-ads117x-objs := ads117x.o | 9 | snd-soc-ads117x-objs := ads117x.o |
8 | snd-soc-ak4104-objs := ak4104.o | 10 | snd-soc-ak4104-objs := ak4104.o |
9 | snd-soc-ak4535-objs := ak4535.o | 11 | snd-soc-ak4535-objs := ak4535.o |
@@ -28,6 +30,7 @@ snd-soc-alc5623-objs := alc5623.o | |||
28 | snd-soc-sn95031-objs := sn95031.o | 30 | snd-soc-sn95031-objs := sn95031.o |
29 | snd-soc-spdif-objs := spdif_transciever.o | 31 | snd-soc-spdif-objs := spdif_transciever.o |
30 | snd-soc-ssm2602-objs := ssm2602.o | 32 | snd-soc-ssm2602-objs := ssm2602.o |
33 | snd-soc-sta32x-objs := sta32x.o | ||
31 | snd-soc-stac9766-objs := stac9766.o | 34 | snd-soc-stac9766-objs := stac9766.o |
32 | snd-soc-tlv320aic23-objs := tlv320aic23.o | 35 | snd-soc-tlv320aic23-objs := tlv320aic23.o |
33 | snd-soc-tlv320aic26-objs := tlv320aic26.o | 36 | snd-soc-tlv320aic26-objs := tlv320aic26.o |
@@ -55,6 +58,7 @@ snd-soc-wm8750-objs := wm8750.o | |||
55 | snd-soc-wm8753-objs := wm8753.o | 58 | snd-soc-wm8753-objs := wm8753.o |
56 | snd-soc-wm8770-objs := wm8770.o | 59 | snd-soc-wm8770-objs := wm8770.o |
57 | snd-soc-wm8776-objs := wm8776.o | 60 | snd-soc-wm8776-objs := wm8776.o |
61 | snd-soc-wm8782-objs := wm8782.o | ||
58 | snd-soc-wm8804-objs := wm8804.o | 62 | snd-soc-wm8804-objs := wm8804.o |
59 | snd-soc-wm8900-objs := wm8900.o | 63 | snd-soc-wm8900-objs := wm8900.o |
60 | snd-soc-wm8903-objs := wm8903.o | 64 | snd-soc-wm8903-objs := wm8903.o |
@@ -68,6 +72,7 @@ snd-soc-wm8962-objs := wm8962.o | |||
68 | snd-soc-wm8971-objs := wm8971.o | 72 | snd-soc-wm8971-objs := wm8971.o |
69 | snd-soc-wm8974-objs := wm8974.o | 73 | snd-soc-wm8974-objs := wm8974.o |
70 | snd-soc-wm8978-objs := wm8978.o | 74 | snd-soc-wm8978-objs := wm8978.o |
75 | snd-soc-wm8983-objs := wm8983.o | ||
71 | snd-soc-wm8985-objs := wm8985.o | 76 | snd-soc-wm8985-objs := wm8985.o |
72 | snd-soc-wm8988-objs := wm8988.o | 77 | snd-soc-wm8988-objs := wm8988.o |
73 | snd-soc-wm8990-objs := wm8990.o | 78 | snd-soc-wm8990-objs := wm8990.o |
@@ -95,6 +100,8 @@ obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o | |||
95 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o | 100 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o |
96 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o | 101 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o |
97 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o | 102 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o |
103 | obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o | ||
104 | obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o | ||
98 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o | 105 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o |
99 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o | 106 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o |
100 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o | 107 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o |
@@ -120,6 +127,7 @@ obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o | |||
120 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o | 127 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o |
121 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o | 128 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o |
122 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o | 129 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o |
130 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o | ||
123 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o | 131 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o |
124 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o | 132 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o |
125 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o | 133 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o |
@@ -147,6 +155,7 @@ obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o | |||
147 | obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o | 155 | obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o |
148 | obj-$(CONFIG_SND_SOC_WM8770) += snd-soc-wm8770.o | 156 | obj-$(CONFIG_SND_SOC_WM8770) += snd-soc-wm8770.o |
149 | obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o | 157 | obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o |
158 | obj-$(CONFIG_SND_SOC_WM8782) += snd-soc-wm8782.o | ||
150 | obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o | 159 | obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o |
151 | obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o | 160 | obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o |
152 | obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o | 161 | obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o |
@@ -160,6 +169,7 @@ obj-$(CONFIG_SND_SOC_WM8962) += snd-soc-wm8962.o | |||
160 | obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o | 169 | obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o |
161 | obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o | 170 | obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o |
162 | obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o | 171 | obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o |
172 | obj-$(CONFIG_SND_SOC_WM8983) += snd-soc-wm8983.o | ||
163 | obj-$(CONFIG_SND_SOC_WM8985) += snd-soc-wm8985.o | 173 | obj-$(CONFIG_SND_SOC_WM8985) += snd-soc-wm8985.o |
164 | obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o | 174 | obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o |
165 | obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o | 175 | obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o |
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 754c496412bd..4e5c5726366b 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
@@ -1,19 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * File: sound/soc/codecs/ad1836.c | 2 | * Audio Codec driver supporting: |
3 | * Author: Barry Song <Barry.Song@analog.com> | 3 | * AD1835A, AD1836, AD1837A, AD1838A, AD1839A |
4 | * | ||
5 | * Created: Aug 04 2009 | ||
6 | * Description: Driver for AD1836 sound chip | ||
7 | * | ||
8 | * Modified: | ||
9 | * Copyright 2009 Analog Devices Inc. | ||
10 | * | 4 | * |
11 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 5 | * Copyright 2009-2011 Analog Devices Inc. |
12 | * | 6 | * |
13 | * This program is free software; you can redistribute it and/or modify | 7 | * Licensed under the GPL-2 or later. |
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | */ | 8 | */ |
18 | 9 | ||
19 | #include <linux/init.h> | 10 | #include <linux/init.h> |
@@ -30,10 +21,15 @@ | |||
30 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
31 | #include "ad1836.h" | 22 | #include "ad1836.h" |
32 | 23 | ||
24 | enum ad1836_type { | ||
25 | AD1835, | ||
26 | AD1836, | ||
27 | AD1838, | ||
28 | }; | ||
29 | |||
33 | /* codec private data */ | 30 | /* codec private data */ |
34 | struct ad1836_priv { | 31 | struct ad1836_priv { |
35 | enum snd_soc_control_type control_type; | 32 | enum ad1836_type type; |
36 | void *control_data; | ||
37 | }; | 33 | }; |
38 | 34 | ||
39 | /* | 35 | /* |
@@ -44,29 +40,60 @@ static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"}; | |||
44 | static const struct soc_enum ad1836_deemp_enum = | 40 | static const struct soc_enum ad1836_deemp_enum = |
45 | SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp); | 41 | SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp); |
46 | 42 | ||
47 | static const struct snd_kcontrol_new ad1836_snd_controls[] = { | 43 | #define AD1836_DAC_VOLUME(x) \ |
48 | /* DAC volume control */ | 44 | SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \ |
49 | SOC_DOUBLE_R("DAC1 Volume", AD1836_DAC_L1_VOL, | 45 | AD1836_DAC_R_VOL(x), 0, 0x3FF, 0) |
50 | AD1836_DAC_R1_VOL, 0, 0x3FF, 0), | 46 | |
51 | SOC_DOUBLE_R("DAC2 Volume", AD1836_DAC_L2_VOL, | 47 | #define AD1836_DAC_SWITCH(x) \ |
52 | AD1836_DAC_R2_VOL, 0, 0x3FF, 0), | 48 | SOC_DOUBLE("DAC" #x " Playback Switch", AD1836_DAC_CTRL2, \ |
53 | SOC_DOUBLE_R("DAC3 Volume", AD1836_DAC_L3_VOL, | 49 | AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1) |
54 | AD1836_DAC_R3_VOL, 0, 0x3FF, 0), | 50 | |
55 | 51 | #define AD1836_ADC_SWITCH(x) \ | |
56 | /* ADC switch control */ | 52 | SOC_DOUBLE("ADC" #x " Capture Switch", AD1836_ADC_CTRL2, \ |
57 | SOC_DOUBLE("ADC1 Switch", AD1836_ADC_CTRL2, AD1836_ADCL1_MUTE, | 53 | AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1) |
58 | AD1836_ADCR1_MUTE, 1, 1), | 54 | |
59 | SOC_DOUBLE("ADC2 Switch", AD1836_ADC_CTRL2, AD1836_ADCL2_MUTE, | 55 | static const struct snd_kcontrol_new ad183x_dac_controls[] = { |
60 | AD1836_ADCR2_MUTE, 1, 1), | 56 | AD1836_DAC_VOLUME(1), |
61 | 57 | AD1836_DAC_SWITCH(1), | |
62 | /* DAC switch control */ | 58 | AD1836_DAC_VOLUME(2), |
63 | SOC_DOUBLE("DAC1 Switch", AD1836_DAC_CTRL2, AD1836_DACL1_MUTE, | 59 | AD1836_DAC_SWITCH(2), |
64 | AD1836_DACR1_MUTE, 1, 1), | 60 | AD1836_DAC_VOLUME(3), |
65 | SOC_DOUBLE("DAC2 Switch", AD1836_DAC_CTRL2, AD1836_DACL2_MUTE, | 61 | AD1836_DAC_SWITCH(3), |
66 | AD1836_DACR2_MUTE, 1, 1), | 62 | AD1836_DAC_VOLUME(4), |
67 | SOC_DOUBLE("DAC3 Switch", AD1836_DAC_CTRL2, AD1836_DACL3_MUTE, | 63 | AD1836_DAC_SWITCH(4), |
68 | AD1836_DACR3_MUTE, 1, 1), | 64 | }; |
65 | |||
66 | static const struct snd_soc_dapm_widget ad183x_dac_dapm_widgets[] = { | ||
67 | SND_SOC_DAPM_OUTPUT("DAC1OUT"), | ||
68 | SND_SOC_DAPM_OUTPUT("DAC2OUT"), | ||
69 | SND_SOC_DAPM_OUTPUT("DAC3OUT"), | ||
70 | SND_SOC_DAPM_OUTPUT("DAC4OUT"), | ||
71 | }; | ||
72 | |||
73 | static const struct snd_soc_dapm_route ad183x_dac_routes[] = { | ||
74 | { "DAC1OUT", NULL, "DAC" }, | ||
75 | { "DAC2OUT", NULL, "DAC" }, | ||
76 | { "DAC3OUT", NULL, "DAC" }, | ||
77 | { "DAC4OUT", NULL, "DAC" }, | ||
78 | }; | ||
79 | |||
80 | static const struct snd_kcontrol_new ad183x_adc_controls[] = { | ||
81 | AD1836_ADC_SWITCH(1), | ||
82 | AD1836_ADC_SWITCH(2), | ||
83 | AD1836_ADC_SWITCH(3), | ||
84 | }; | ||
85 | |||
86 | static const struct snd_soc_dapm_widget ad183x_adc_dapm_widgets[] = { | ||
87 | SND_SOC_DAPM_INPUT("ADC1IN"), | ||
88 | SND_SOC_DAPM_INPUT("ADC2IN"), | ||
89 | }; | ||
90 | |||
91 | static const struct snd_soc_dapm_route ad183x_adc_routes[] = { | ||
92 | { "ADC", NULL, "ADC1IN" }, | ||
93 | { "ADC", NULL, "ADC2IN" }, | ||
94 | }; | ||
69 | 95 | ||
96 | static const struct snd_kcontrol_new ad183x_controls[] = { | ||
70 | /* ADC high-pass filter */ | 97 | /* ADC high-pass filter */ |
71 | SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1, | 98 | SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1, |
72 | AD1836_ADC_HIGHPASS_FILTER, 1, 0), | 99 | AD1836_ADC_HIGHPASS_FILTER, 1, 0), |
@@ -75,27 +102,24 @@ static const struct snd_kcontrol_new ad1836_snd_controls[] = { | |||
75 | SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum), | 102 | SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum), |
76 | }; | 103 | }; |
77 | 104 | ||
78 | static const struct snd_soc_dapm_widget ad1836_dapm_widgets[] = { | 105 | static const struct snd_soc_dapm_widget ad183x_dapm_widgets[] = { |
79 | SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1, | 106 | SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1, |
80 | AD1836_DAC_POWERDOWN, 1), | 107 | AD1836_DAC_POWERDOWN, 1), |
81 | SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), | 108 | SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), |
82 | SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1, | 109 | SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1, |
83 | AD1836_ADC_POWERDOWN, 1, NULL, 0), | 110 | AD1836_ADC_POWERDOWN, 1, NULL, 0), |
84 | SND_SOC_DAPM_OUTPUT("DAC1OUT"), | ||
85 | SND_SOC_DAPM_OUTPUT("DAC2OUT"), | ||
86 | SND_SOC_DAPM_OUTPUT("DAC3OUT"), | ||
87 | SND_SOC_DAPM_INPUT("ADC1IN"), | ||
88 | SND_SOC_DAPM_INPUT("ADC2IN"), | ||
89 | }; | 111 | }; |
90 | 112 | ||
91 | static const struct snd_soc_dapm_route audio_paths[] = { | 113 | static const struct snd_soc_dapm_route ad183x_dapm_routes[] = { |
92 | { "DAC", NULL, "ADC_PWR" }, | 114 | { "DAC", NULL, "ADC_PWR" }, |
93 | { "ADC", NULL, "ADC_PWR" }, | 115 | { "ADC", NULL, "ADC_PWR" }, |
94 | { "DAC1OUT", "DAC1 Switch", "DAC" }, | 116 | }; |
95 | { "DAC2OUT", "DAC2 Switch", "DAC" }, | 117 | |
96 | { "DAC3OUT", "DAC3 Switch", "DAC" }, | 118 | static const DECLARE_TLV_DB_SCALE(ad1836_in_tlv, 0, 300, 0); |
97 | { "ADC", "ADC1 Switch", "ADC1IN" }, | 119 | |
98 | { "ADC", "ADC2 Switch", "ADC2IN" }, | 120 | static const struct snd_kcontrol_new ad1836_controls[] = { |
121 | SOC_DOUBLE_TLV("ADC2 Capture Volume", AD1836_ADC_CTRL1, 3, 0, 4, 0, | ||
122 | ad1836_in_tlv), | ||
99 | }; | 123 | }; |
100 | 124 | ||
101 | /* | 125 | /* |
@@ -165,64 +189,69 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
165 | return 0; | 189 | return 0; |
166 | } | 190 | } |
167 | 191 | ||
192 | static struct snd_soc_dai_ops ad1836_dai_ops = { | ||
193 | .hw_params = ad1836_hw_params, | ||
194 | .set_fmt = ad1836_set_dai_fmt, | ||
195 | }; | ||
196 | |||
197 | #define AD183X_DAI(_name, num_dacs, num_adcs) \ | ||
198 | { \ | ||
199 | .name = _name "-hifi", \ | ||
200 | .playback = { \ | ||
201 | .stream_name = "Playback", \ | ||
202 | .channels_min = 2, \ | ||
203 | .channels_max = (num_dacs) * 2, \ | ||
204 | .rates = SNDRV_PCM_RATE_48000, \ | ||
205 | .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
206 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \ | ||
207 | }, \ | ||
208 | .capture = { \ | ||
209 | .stream_name = "Capture", \ | ||
210 | .channels_min = 2, \ | ||
211 | .channels_max = (num_adcs) * 2, \ | ||
212 | .rates = SNDRV_PCM_RATE_48000, \ | ||
213 | .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
214 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \ | ||
215 | }, \ | ||
216 | .ops = &ad1836_dai_ops, \ | ||
217 | } | ||
218 | |||
219 | static struct snd_soc_dai_driver ad183x_dais[] = { | ||
220 | [AD1835] = AD183X_DAI("ad1835", 4, 1), | ||
221 | [AD1836] = AD183X_DAI("ad1836", 3, 2), | ||
222 | [AD1838] = AD183X_DAI("ad1838", 3, 1), | ||
223 | }; | ||
224 | |||
168 | #ifdef CONFIG_PM | 225 | #ifdef CONFIG_PM |
169 | static int ad1836_soc_suspend(struct snd_soc_codec *codec, | 226 | static int ad1836_suspend(struct snd_soc_codec *codec, pm_message_t state) |
170 | pm_message_t state) | ||
171 | { | 227 | { |
172 | /* reset clock control mode */ | 228 | /* reset clock control mode */ |
173 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); | 229 | return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, |
174 | adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; | 230 | AD1836_ADC_SERFMT_MASK, 0); |
175 | |||
176 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); | ||
177 | } | 231 | } |
178 | 232 | ||
179 | static int ad1836_soc_resume(struct snd_soc_codec *codec) | 233 | static int ad1836_resume(struct snd_soc_codec *codec) |
180 | { | 234 | { |
181 | /* restore clock control mode */ | 235 | /* restore clock control mode */ |
182 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); | 236 | return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, |
183 | adc_ctrl2 |= AD1836_ADC_AUX; | 237 | AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX); |
184 | |||
185 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); | ||
186 | } | 238 | } |
187 | #else | 239 | #else |
188 | #define ad1836_soc_suspend NULL | 240 | #define ad1836_suspend NULL |
189 | #define ad1836_soc_resume NULL | 241 | #define ad1836_resume NULL |
190 | #endif | 242 | #endif |
191 | 243 | ||
192 | static struct snd_soc_dai_ops ad1836_dai_ops = { | ||
193 | .hw_params = ad1836_hw_params, | ||
194 | .set_fmt = ad1836_set_dai_fmt, | ||
195 | }; | ||
196 | |||
197 | /* codec DAI instance */ | ||
198 | static struct snd_soc_dai_driver ad1836_dai = { | ||
199 | .name = "ad1836-hifi", | ||
200 | .playback = { | ||
201 | .stream_name = "Playback", | ||
202 | .channels_min = 2, | ||
203 | .channels_max = 6, | ||
204 | .rates = SNDRV_PCM_RATE_48000, | ||
205 | .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | | ||
206 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, | ||
207 | }, | ||
208 | .capture = { | ||
209 | .stream_name = "Capture", | ||
210 | .channels_min = 2, | ||
211 | .channels_max = 4, | ||
212 | .rates = SNDRV_PCM_RATE_48000, | ||
213 | .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | | ||
214 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, | ||
215 | }, | ||
216 | .ops = &ad1836_dai_ops, | ||
217 | }; | ||
218 | |||
219 | static int ad1836_probe(struct snd_soc_codec *codec) | 244 | static int ad1836_probe(struct snd_soc_codec *codec) |
220 | { | 245 | { |
221 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); | 246 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); |
222 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 247 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
248 | int num_dacs, num_adcs; | ||
223 | int ret = 0; | 249 | int ret = 0; |
250 | int i; | ||
251 | |||
252 | num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2; | ||
253 | num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2; | ||
224 | 254 | ||
225 | codec->control_data = ad1836->control_data; | ||
226 | ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); | 255 | ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); |
227 | if (ret < 0) { | 256 | if (ret < 0) { |
228 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | 257 | dev_err(codec->dev, "failed to set cache I/O: %d\n", |
@@ -239,21 +268,46 @@ static int ad1836_probe(struct snd_soc_codec *codec) | |||
239 | snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100); | 268 | snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100); |
240 | /* unmute adc channles, adc aux mode */ | 269 | /* unmute adc channles, adc aux mode */ |
241 | snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180); | 270 | snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180); |
242 | /* left/right diff:PGA/MUX */ | ||
243 | snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); | ||
244 | /* volume */ | 271 | /* volume */ |
245 | snd_soc_write(codec, AD1836_DAC_L1_VOL, 0x3FF); | 272 | for (i = 1; i <= num_dacs; ++i) { |
246 | snd_soc_write(codec, AD1836_DAC_R1_VOL, 0x3FF); | 273 | snd_soc_write(codec, AD1836_DAC_L_VOL(i), 0x3FF); |
247 | snd_soc_write(codec, AD1836_DAC_L2_VOL, 0x3FF); | 274 | snd_soc_write(codec, AD1836_DAC_R_VOL(i), 0x3FF); |
248 | snd_soc_write(codec, AD1836_DAC_R2_VOL, 0x3FF); | 275 | } |
249 | snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); | 276 | |
250 | snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); | 277 | if (ad1836->type == AD1836) { |
251 | 278 | /* left/right diff:PGA/MUX */ | |
252 | snd_soc_add_controls(codec, ad1836_snd_controls, | 279 | snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); |
253 | ARRAY_SIZE(ad1836_snd_controls)); | 280 | ret = snd_soc_add_controls(codec, ad1836_controls, |
254 | snd_soc_dapm_new_controls(dapm, ad1836_dapm_widgets, | 281 | ARRAY_SIZE(ad1836_controls)); |
255 | ARRAY_SIZE(ad1836_dapm_widgets)); | 282 | if (ret) |
256 | snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths)); | 283 | return ret; |
284 | } else { | ||
285 | snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00); | ||
286 | } | ||
287 | |||
288 | ret = snd_soc_add_controls(codec, ad183x_dac_controls, num_dacs * 2); | ||
289 | if (ret) | ||
290 | return ret; | ||
291 | |||
292 | ret = snd_soc_add_controls(codec, ad183x_adc_controls, num_adcs); | ||
293 | if (ret) | ||
294 | return ret; | ||
295 | |||
296 | ret = snd_soc_dapm_new_controls(dapm, ad183x_dac_dapm_widgets, num_dacs); | ||
297 | if (ret) | ||
298 | return ret; | ||
299 | |||
300 | ret = snd_soc_dapm_new_controls(dapm, ad183x_adc_dapm_widgets, num_adcs); | ||
301 | if (ret) | ||
302 | return ret; | ||
303 | |||
304 | ret = snd_soc_dapm_add_routes(dapm, ad183x_dac_routes, num_dacs); | ||
305 | if (ret) | ||
306 | return ret; | ||
307 | |||
308 | ret = snd_soc_dapm_add_routes(dapm, ad183x_adc_routes, num_adcs); | ||
309 | if (ret) | ||
310 | return ret; | ||
257 | 311 | ||
258 | return ret; | 312 | return ret; |
259 | } | 313 | } |
@@ -262,19 +316,24 @@ static int ad1836_probe(struct snd_soc_codec *codec) | |||
262 | static int ad1836_remove(struct snd_soc_codec *codec) | 316 | static int ad1836_remove(struct snd_soc_codec *codec) |
263 | { | 317 | { |
264 | /* reset clock control mode */ | 318 | /* reset clock control mode */ |
265 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); | 319 | return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, |
266 | adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; | 320 | AD1836_ADC_SERFMT_MASK, 0); |
267 | |||
268 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); | ||
269 | } | 321 | } |
270 | 322 | ||
271 | static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { | 323 | static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { |
272 | .probe = ad1836_probe, | 324 | .probe = ad1836_probe, |
273 | .remove = ad1836_remove, | 325 | .remove = ad1836_remove, |
274 | .suspend = ad1836_soc_suspend, | 326 | .suspend = ad1836_suspend, |
275 | .resume = ad1836_soc_resume, | 327 | .resume = ad1836_resume, |
276 | .reg_cache_size = AD1836_NUM_REGS, | 328 | .reg_cache_size = AD1836_NUM_REGS, |
277 | .reg_word_size = sizeof(u16), | 329 | .reg_word_size = sizeof(u16), |
330 | |||
331 | .controls = ad183x_controls, | ||
332 | .num_controls = ARRAY_SIZE(ad183x_controls), | ||
333 | .dapm_widgets = ad183x_dapm_widgets, | ||
334 | .num_dapm_widgets = ARRAY_SIZE(ad183x_dapm_widgets), | ||
335 | .dapm_routes = ad183x_dapm_routes, | ||
336 | .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), | ||
278 | }; | 337 | }; |
279 | 338 | ||
280 | static int __devinit ad1836_spi_probe(struct spi_device *spi) | 339 | static int __devinit ad1836_spi_probe(struct spi_device *spi) |
@@ -286,12 +345,12 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi) | |||
286 | if (ad1836 == NULL) | 345 | if (ad1836 == NULL) |
287 | return -ENOMEM; | 346 | return -ENOMEM; |
288 | 347 | ||
348 | ad1836->type = spi_get_device_id(spi)->driver_data; | ||
349 | |||
289 | spi_set_drvdata(spi, ad1836); | 350 | spi_set_drvdata(spi, ad1836); |
290 | ad1836->control_data = spi; | ||
291 | ad1836->control_type = SND_SOC_SPI; | ||
292 | 351 | ||
293 | ret = snd_soc_register_codec(&spi->dev, | 352 | ret = snd_soc_register_codec(&spi->dev, |
294 | &soc_codec_dev_ad1836, &ad1836_dai, 1); | 353 | &soc_codec_dev_ad1836, &ad183x_dais[ad1836->type], 1); |
295 | if (ret < 0) | 354 | if (ret < 0) |
296 | kfree(ad1836); | 355 | kfree(ad1836); |
297 | return ret; | 356 | return ret; |
@@ -303,27 +362,29 @@ static int __devexit ad1836_spi_remove(struct spi_device *spi) | |||
303 | kfree(spi_get_drvdata(spi)); | 362 | kfree(spi_get_drvdata(spi)); |
304 | return 0; | 363 | return 0; |
305 | } | 364 | } |
365 | static const struct spi_device_id ad1836_ids[] = { | ||
366 | { "ad1835", AD1835 }, | ||
367 | { "ad1836", AD1836 }, | ||
368 | { "ad1837", AD1835 }, | ||
369 | { "ad1838", AD1838 }, | ||
370 | { "ad1839", AD1838 }, | ||
371 | { }, | ||
372 | }; | ||
373 | MODULE_DEVICE_TABLE(spi, ad1836_ids); | ||
306 | 374 | ||
307 | static struct spi_driver ad1836_spi_driver = { | 375 | static struct spi_driver ad1836_spi_driver = { |
308 | .driver = { | 376 | .driver = { |
309 | .name = "ad1836-codec", | 377 | .name = "ad1836", |
310 | .owner = THIS_MODULE, | 378 | .owner = THIS_MODULE, |
311 | }, | 379 | }, |
312 | .probe = ad1836_spi_probe, | 380 | .probe = ad1836_spi_probe, |
313 | .remove = __devexit_p(ad1836_spi_remove), | 381 | .remove = __devexit_p(ad1836_spi_remove), |
382 | .id_table = ad1836_ids, | ||
314 | }; | 383 | }; |
315 | 384 | ||
316 | static int __init ad1836_init(void) | 385 | static int __init ad1836_init(void) |
317 | { | 386 | { |
318 | int ret; | 387 | return spi_register_driver(&ad1836_spi_driver); |
319 | |||
320 | ret = spi_register_driver(&ad1836_spi_driver); | ||
321 | if (ret != 0) { | ||
322 | printk(KERN_ERR "Failed to register ad1836 SPI driver: %d\n", | ||
323 | ret); | ||
324 | } | ||
325 | |||
326 | return ret; | ||
327 | } | 388 | } |
328 | module_init(ad1836_init); | 389 | module_init(ad1836_init); |
329 | 390 | ||
diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index 9d6a3f8f8aaf..444747f0db26 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h | |||
@@ -1,19 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * File: sound/soc/codecs/ad1836.h | 2 | * Audio Codec driver supporting: |
3 | * Based on: | 3 | * AD1835A, AD1836, AD1837A, AD1838A, AD1839A |
4 | * Author: Barry Song <Barry.Song@analog.com> | ||
5 | * | 4 | * |
6 | * Created: Aug 04, 2009 | 5 | * Copyright 2009-2011 Analog Devices Inc. |
7 | * Description: definitions for AD1836 registers | ||
8 | * | 6 | * |
9 | * Modified: | 7 | * Licensed under the GPL-2 or later. |
10 | * | ||
11 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | */ | 8 | */ |
18 | 9 | ||
19 | #ifndef __AD1836_H__ | 10 | #ifndef __AD1836_H__ |
@@ -21,39 +12,30 @@ | |||
21 | 12 | ||
22 | #define AD1836_DAC_CTRL1 0 | 13 | #define AD1836_DAC_CTRL1 0 |
23 | #define AD1836_DAC_POWERDOWN 2 | 14 | #define AD1836_DAC_POWERDOWN 2 |
24 | #define AD1836_DAC_SERFMT_MASK 0xE0 | 15 | #define AD1836_DAC_SERFMT_MASK 0xE0 |
25 | #define AD1836_DAC_SERFMT_PCK256 (0x4 << 5) | 16 | #define AD1836_DAC_SERFMT_PCK256 (0x4 << 5) |
26 | #define AD1836_DAC_SERFMT_PCK128 (0x5 << 5) | 17 | #define AD1836_DAC_SERFMT_PCK128 (0x5 << 5) |
27 | #define AD1836_DAC_WORD_LEN_MASK 0x18 | 18 | #define AD1836_DAC_WORD_LEN_MASK 0x18 |
28 | #define AD1836_DAC_WORD_LEN_OFFSET 3 | 19 | #define AD1836_DAC_WORD_LEN_OFFSET 3 |
29 | 20 | ||
30 | #define AD1836_DAC_CTRL2 1 | 21 | #define AD1836_DAC_CTRL2 1 |
31 | #define AD1836_DACL1_MUTE 0 | ||
32 | #define AD1836_DACR1_MUTE 1 | ||
33 | #define AD1836_DACL2_MUTE 2 | ||
34 | #define AD1836_DACR2_MUTE 3 | ||
35 | #define AD1836_DACL3_MUTE 4 | ||
36 | #define AD1836_DACR3_MUTE 5 | ||
37 | 22 | ||
38 | #define AD1836_DAC_L1_VOL 2 | 23 | /* These macros are one-based. So AD183X_MUTE_LEFT(1) will return the mute bit |
39 | #define AD1836_DAC_R1_VOL 3 | 24 | * for the first ADC/DAC */ |
40 | #define AD1836_DAC_L2_VOL 4 | 25 | #define AD1836_MUTE_LEFT(x) (((x) * 2) - 2) |
41 | #define AD1836_DAC_R2_VOL 5 | 26 | #define AD1836_MUTE_RIGHT(x) (((x) * 2) - 1) |
42 | #define AD1836_DAC_L3_VOL 6 | 27 | |
43 | #define AD1836_DAC_R3_VOL 7 | 28 | #define AD1836_DAC_L_VOL(x) ((x) * 2) |
29 | #define AD1836_DAC_R_VOL(x) (1 + ((x) * 2)) | ||
44 | 30 | ||
45 | #define AD1836_ADC_CTRL1 12 | 31 | #define AD1836_ADC_CTRL1 12 |
46 | #define AD1836_ADC_POWERDOWN 7 | 32 | #define AD1836_ADC_POWERDOWN 7 |
47 | #define AD1836_ADC_HIGHPASS_FILTER 8 | 33 | #define AD1836_ADC_HIGHPASS_FILTER 8 |
48 | 34 | ||
49 | #define AD1836_ADC_CTRL2 13 | 35 | #define AD1836_ADC_CTRL2 13 |
50 | #define AD1836_ADCL1_MUTE 0 | ||
51 | #define AD1836_ADCR1_MUTE 1 | ||
52 | #define AD1836_ADCL2_MUTE 2 | ||
53 | #define AD1836_ADCR2_MUTE 3 | ||
54 | #define AD1836_ADC_WORD_LEN_MASK 0x30 | 36 | #define AD1836_ADC_WORD_LEN_MASK 0x30 |
55 | #define AD1836_ADC_WORD_OFFSET 5 | 37 | #define AD1836_ADC_WORD_OFFSET 5 |
56 | #define AD1836_ADC_SERFMT_MASK (7 << 6) | 38 | #define AD1836_ADC_SERFMT_MASK (7 << 6) |
57 | #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) | 39 | #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) |
58 | #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) | 40 | #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) |
59 | #define AD1836_ADC_AUX (0x6 << 6) | 41 | #define AD1836_ADC_AUX (0x6 << 6) |
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c new file mode 100644 index 000000000000..2758d5fc60d6 --- /dev/null +++ b/sound/soc/codecs/adau1701.c | |||
@@ -0,0 +1,549 @@ | |||
1 | /* | ||
2 | * Driver for ADAU1701 SigmaDSP processor | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * based on an inital version by Cliff Cai <cliff.cai@analog.com> | ||
7 | * | ||
8 | * Licensed under the GPL-2 or later. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/sigma.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | ||
21 | |||
22 | #include "adau1701.h" | ||
23 | |||
24 | #define ADAU1701_DSPCTRL 0x1c | ||
25 | #define ADAU1701_SEROCTL 0x1e | ||
26 | #define ADAU1701_SERICTL 0x1f | ||
27 | |||
28 | #define ADAU1701_AUXNPOW 0x22 | ||
29 | |||
30 | #define ADAU1701_OSCIPOW 0x26 | ||
31 | #define ADAU1701_DACSET 0x27 | ||
32 | |||
33 | #define ADAU1701_NUM_REGS 0x28 | ||
34 | |||
35 | #define ADAU1701_DSPCTRL_CR (1 << 2) | ||
36 | #define ADAU1701_DSPCTRL_DAM (1 << 3) | ||
37 | #define ADAU1701_DSPCTRL_ADM (1 << 4) | ||
38 | #define ADAU1701_DSPCTRL_SR_48 0x00 | ||
39 | #define ADAU1701_DSPCTRL_SR_96 0x01 | ||
40 | #define ADAU1701_DSPCTRL_SR_192 0x02 | ||
41 | #define ADAU1701_DSPCTRL_SR_MASK 0x03 | ||
42 | |||
43 | #define ADAU1701_SEROCTL_INV_LRCLK 0x2000 | ||
44 | #define ADAU1701_SEROCTL_INV_BCLK 0x1000 | ||
45 | #define ADAU1701_SEROCTL_MASTER 0x0800 | ||
46 | |||
47 | #define ADAU1701_SEROCTL_OBF16 0x0000 | ||
48 | #define ADAU1701_SEROCTL_OBF8 0x0200 | ||
49 | #define ADAU1701_SEROCTL_OBF4 0x0400 | ||
50 | #define ADAU1701_SEROCTL_OBF2 0x0600 | ||
51 | #define ADAU1701_SEROCTL_OBF_MASK 0x0600 | ||
52 | |||
53 | #define ADAU1701_SEROCTL_OLF1024 0x0000 | ||
54 | #define ADAU1701_SEROCTL_OLF512 0x0080 | ||
55 | #define ADAU1701_SEROCTL_OLF256 0x0100 | ||
56 | #define ADAU1701_SEROCTL_OLF_MASK 0x0180 | ||
57 | |||
58 | #define ADAU1701_SEROCTL_MSB_DEALY1 0x0000 | ||
59 | #define ADAU1701_SEROCTL_MSB_DEALY0 0x0004 | ||
60 | #define ADAU1701_SEROCTL_MSB_DEALY8 0x0008 | ||
61 | #define ADAU1701_SEROCTL_MSB_DEALY12 0x000c | ||
62 | #define ADAU1701_SEROCTL_MSB_DEALY16 0x0010 | ||
63 | #define ADAU1701_SEROCTL_MSB_DEALY_MASK 0x001c | ||
64 | |||
65 | #define ADAU1701_SEROCTL_WORD_LEN_24 0x0000 | ||
66 | #define ADAU1701_SEROCTL_WORD_LEN_20 0x0001 | ||
67 | #define ADAU1701_SEROCTL_WORD_LEN_16 0x0010 | ||
68 | #define ADAU1701_SEROCTL_WORD_LEN_MASK 0x0003 | ||
69 | |||
70 | #define ADAU1701_AUXNPOW_VBPD 0x40 | ||
71 | #define ADAU1701_AUXNPOW_VRPD 0x20 | ||
72 | |||
73 | #define ADAU1701_SERICTL_I2S 0 | ||
74 | #define ADAU1701_SERICTL_LEFTJ 1 | ||
75 | #define ADAU1701_SERICTL_TDM 2 | ||
76 | #define ADAU1701_SERICTL_RIGHTJ_24 3 | ||
77 | #define ADAU1701_SERICTL_RIGHTJ_20 4 | ||
78 | #define ADAU1701_SERICTL_RIGHTJ_18 5 | ||
79 | #define ADAU1701_SERICTL_RIGHTJ_16 6 | ||
80 | #define ADAU1701_SERICTL_MODE_MASK 7 | ||
81 | #define ADAU1701_SERICTL_INV_BCLK BIT(3) | ||
82 | #define ADAU1701_SERICTL_INV_LRCLK BIT(4) | ||
83 | |||
84 | #define ADAU1701_OSCIPOW_OPD 0x04 | ||
85 | #define ADAU1701_DACSET_DACINIT 1 | ||
86 | |||
87 | #define ADAU1701_FIRMWARE "adau1701.bin" | ||
88 | |||
89 | struct adau1701 { | ||
90 | unsigned int dai_fmt; | ||
91 | }; | ||
92 | |||
93 | static const struct snd_kcontrol_new adau1701_controls[] = { | ||
94 | SOC_SINGLE("Master Capture Switch", ADAU1701_DSPCTRL, 4, 1, 0), | ||
95 | }; | ||
96 | |||
97 | static const struct snd_soc_dapm_widget adau1701_dapm_widgets[] = { | ||
98 | SND_SOC_DAPM_DAC("DAC0", "Playback", ADAU1701_AUXNPOW, 3, 1), | ||
99 | SND_SOC_DAPM_DAC("DAC1", "Playback", ADAU1701_AUXNPOW, 2, 1), | ||
100 | SND_SOC_DAPM_DAC("DAC2", "Playback", ADAU1701_AUXNPOW, 1, 1), | ||
101 | SND_SOC_DAPM_DAC("DAC3", "Playback", ADAU1701_AUXNPOW, 0, 1), | ||
102 | SND_SOC_DAPM_ADC("ADC", "Capture", ADAU1701_AUXNPOW, 7, 1), | ||
103 | |||
104 | SND_SOC_DAPM_OUTPUT("OUT0"), | ||
105 | SND_SOC_DAPM_OUTPUT("OUT1"), | ||
106 | SND_SOC_DAPM_OUTPUT("OUT2"), | ||
107 | SND_SOC_DAPM_OUTPUT("OUT3"), | ||
108 | SND_SOC_DAPM_INPUT("IN0"), | ||
109 | SND_SOC_DAPM_INPUT("IN1"), | ||
110 | }; | ||
111 | |||
112 | static const struct snd_soc_dapm_route adau1701_dapm_routes[] = { | ||
113 | { "OUT0", NULL, "DAC0" }, | ||
114 | { "OUT1", NULL, "DAC1" }, | ||
115 | { "OUT2", NULL, "DAC2" }, | ||
116 | { "OUT3", NULL, "DAC3" }, | ||
117 | |||
118 | { "ADC", NULL, "IN0" }, | ||
119 | { "ADC", NULL, "IN1" }, | ||
120 | }; | ||
121 | |||
122 | static unsigned int adau1701_register_size(struct snd_soc_codec *codec, | ||
123 | unsigned int reg) | ||
124 | { | ||
125 | switch (reg) { | ||
126 | case ADAU1701_DSPCTRL: | ||
127 | case ADAU1701_SEROCTL: | ||
128 | case ADAU1701_AUXNPOW: | ||
129 | case ADAU1701_OSCIPOW: | ||
130 | case ADAU1701_DACSET: | ||
131 | return 2; | ||
132 | case ADAU1701_SERICTL: | ||
133 | return 1; | ||
134 | } | ||
135 | |||
136 | dev_err(codec->dev, "Unsupported register address: %d\n", reg); | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static int adau1701_write(struct snd_soc_codec *codec, unsigned int reg, | ||
141 | unsigned int value) | ||
142 | { | ||
143 | unsigned int i; | ||
144 | unsigned int size; | ||
145 | uint8_t buf[4]; | ||
146 | int ret; | ||
147 | |||
148 | size = adau1701_register_size(codec, reg); | ||
149 | if (size == 0) | ||
150 | return -EINVAL; | ||
151 | |||
152 | snd_soc_cache_write(codec, reg, value); | ||
153 | |||
154 | buf[0] = 0x08; | ||
155 | buf[1] = reg; | ||
156 | |||
157 | for (i = size + 1; i >= 2; --i) { | ||
158 | buf[i] = value; | ||
159 | value >>= 8; | ||
160 | } | ||
161 | |||
162 | ret = i2c_master_send(to_i2c_client(codec->dev), buf, size + 2); | ||
163 | if (ret == size + 2) | ||
164 | return 0; | ||
165 | else if (ret < 0) | ||
166 | return ret; | ||
167 | else | ||
168 | return -EIO; | ||
169 | } | ||
170 | |||
171 | static unsigned int adau1701_read(struct snd_soc_codec *codec, unsigned int reg) | ||
172 | { | ||
173 | unsigned int value; | ||
174 | unsigned int ret; | ||
175 | |||
176 | ret = snd_soc_cache_read(codec, reg, &value); | ||
177 | if (ret) | ||
178 | return ret; | ||
179 | |||
180 | return value; | ||
181 | } | ||
182 | |||
183 | static int adau1701_load_firmware(struct snd_soc_codec *codec) | ||
184 | { | ||
185 | return process_sigma_firmware(codec->control_data, ADAU1701_FIRMWARE); | ||
186 | } | ||
187 | |||
188 | static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, | ||
189 | snd_pcm_format_t format) | ||
190 | { | ||
191 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
192 | unsigned int mask = ADAU1701_SEROCTL_WORD_LEN_MASK; | ||
193 | unsigned int val; | ||
194 | |||
195 | switch (format) { | ||
196 | case SNDRV_PCM_FORMAT_S16_LE: | ||
197 | val = ADAU1701_SEROCTL_WORD_LEN_16; | ||
198 | break; | ||
199 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
200 | val = ADAU1701_SEROCTL_WORD_LEN_20; | ||
201 | break; | ||
202 | case SNDRV_PCM_FORMAT_S24_LE: | ||
203 | val = ADAU1701_SEROCTL_WORD_LEN_24; | ||
204 | break; | ||
205 | default: | ||
206 | return -EINVAL; | ||
207 | } | ||
208 | |||
209 | if (adau1701->dai_fmt == SND_SOC_DAIFMT_RIGHT_J) { | ||
210 | switch (format) { | ||
211 | case SNDRV_PCM_FORMAT_S16_LE: | ||
212 | val |= ADAU1701_SEROCTL_MSB_DEALY16; | ||
213 | break; | ||
214 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
215 | val |= ADAU1701_SEROCTL_MSB_DEALY12; | ||
216 | break; | ||
217 | case SNDRV_PCM_FORMAT_S24_LE: | ||
218 | val |= ADAU1701_SEROCTL_MSB_DEALY8; | ||
219 | break; | ||
220 | } | ||
221 | mask |= ADAU1701_SEROCTL_MSB_DEALY_MASK; | ||
222 | } | ||
223 | |||
224 | snd_soc_update_bits(codec, ADAU1701_SEROCTL, mask, val); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static int adau1701_set_playback_pcm_format(struct snd_soc_codec *codec, | ||
230 | snd_pcm_format_t format) | ||
231 | { | ||
232 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
233 | unsigned int val; | ||
234 | |||
235 | if (adau1701->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) | ||
236 | return 0; | ||
237 | |||
238 | switch (format) { | ||
239 | case SNDRV_PCM_FORMAT_S16_LE: | ||
240 | val = ADAU1701_SERICTL_RIGHTJ_16; | ||
241 | break; | ||
242 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
243 | val = ADAU1701_SERICTL_RIGHTJ_20; | ||
244 | break; | ||
245 | case SNDRV_PCM_FORMAT_S24_LE: | ||
246 | val = ADAU1701_SERICTL_RIGHTJ_24; | ||
247 | break; | ||
248 | default: | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | |||
252 | snd_soc_update_bits(codec, ADAU1701_SERICTL, | ||
253 | ADAU1701_SERICTL_MODE_MASK, val); | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int adau1701_hw_params(struct snd_pcm_substream *substream, | ||
259 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
260 | { | ||
261 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
262 | struct snd_soc_codec *codec = rtd->codec; | ||
263 | snd_pcm_format_t format; | ||
264 | unsigned int val; | ||
265 | |||
266 | switch (params_rate(params)) { | ||
267 | case 192000: | ||
268 | val = ADAU1701_DSPCTRL_SR_192; | ||
269 | break; | ||
270 | case 96000: | ||
271 | val = ADAU1701_DSPCTRL_SR_96; | ||
272 | break; | ||
273 | case 48000: | ||
274 | val = ADAU1701_DSPCTRL_SR_48; | ||
275 | break; | ||
276 | default: | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | |||
280 | snd_soc_update_bits(codec, ADAU1701_DSPCTRL, | ||
281 | ADAU1701_DSPCTRL_SR_MASK, val); | ||
282 | |||
283 | format = params_format(params); | ||
284 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
285 | return adau1701_set_playback_pcm_format(codec, format); | ||
286 | else | ||
287 | return adau1701_set_capture_pcm_format(codec, format); | ||
288 | } | ||
289 | |||
290 | static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
291 | unsigned int fmt) | ||
292 | { | ||
293 | struct snd_soc_codec *codec = codec_dai->codec; | ||
294 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
295 | unsigned int serictl = 0x00, seroctl = 0x00; | ||
296 | bool invert_lrclk; | ||
297 | |||
298 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
299 | case SND_SOC_DAIFMT_CBM_CFM: | ||
300 | /* master, 64-bits per sample, 1 frame per sample */ | ||
301 | seroctl |= ADAU1701_SEROCTL_MASTER | ADAU1701_SEROCTL_OBF16 | ||
302 | | ADAU1701_SEROCTL_OLF1024; | ||
303 | break; | ||
304 | case SND_SOC_DAIFMT_CBS_CFS: | ||
305 | break; | ||
306 | default: | ||
307 | return -EINVAL; | ||
308 | } | ||
309 | |||
310 | /* clock inversion */ | ||
311 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
312 | case SND_SOC_DAIFMT_NB_NF: | ||
313 | invert_lrclk = false; | ||
314 | break; | ||
315 | case SND_SOC_DAIFMT_NB_IF: | ||
316 | invert_lrclk = true; | ||
317 | break; | ||
318 | case SND_SOC_DAIFMT_IB_NF: | ||
319 | invert_lrclk = false; | ||
320 | serictl |= ADAU1701_SERICTL_INV_BCLK; | ||
321 | seroctl |= ADAU1701_SEROCTL_INV_BCLK; | ||
322 | break; | ||
323 | case SND_SOC_DAIFMT_IB_IF: | ||
324 | invert_lrclk = true; | ||
325 | serictl |= ADAU1701_SERICTL_INV_BCLK; | ||
326 | seroctl |= ADAU1701_SEROCTL_INV_BCLK; | ||
327 | break; | ||
328 | default: | ||
329 | return -EINVAL; | ||
330 | } | ||
331 | |||
332 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
333 | case SND_SOC_DAIFMT_I2S: | ||
334 | break; | ||
335 | case SND_SOC_DAIFMT_LEFT_J: | ||
336 | serictl |= ADAU1701_SERICTL_LEFTJ; | ||
337 | seroctl |= ADAU1701_SEROCTL_MSB_DEALY0; | ||
338 | invert_lrclk = !invert_lrclk; | ||
339 | break; | ||
340 | case SND_SOC_DAIFMT_RIGHT_J: | ||
341 | serictl |= ADAU1701_SERICTL_RIGHTJ_24; | ||
342 | seroctl |= ADAU1701_SEROCTL_MSB_DEALY8; | ||
343 | invert_lrclk = !invert_lrclk; | ||
344 | break; | ||
345 | default: | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | if (invert_lrclk) { | ||
350 | seroctl |= ADAU1701_SEROCTL_INV_LRCLK; | ||
351 | serictl |= ADAU1701_SERICTL_INV_LRCLK; | ||
352 | } | ||
353 | |||
354 | adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | ||
355 | |||
356 | snd_soc_write(codec, ADAU1701_SERICTL, serictl); | ||
357 | snd_soc_update_bits(codec, ADAU1701_SEROCTL, | ||
358 | ~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl); | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int adau1701_set_bias_level(struct snd_soc_codec *codec, | ||
364 | enum snd_soc_bias_level level) | ||
365 | { | ||
366 | unsigned int mask = ADAU1701_AUXNPOW_VBPD | ADAU1701_AUXNPOW_VRPD; | ||
367 | |||
368 | switch (level) { | ||
369 | case SND_SOC_BIAS_ON: | ||
370 | break; | ||
371 | case SND_SOC_BIAS_PREPARE: | ||
372 | break; | ||
373 | case SND_SOC_BIAS_STANDBY: | ||
374 | /* Enable VREF and VREF buffer */ | ||
375 | snd_soc_update_bits(codec, ADAU1701_AUXNPOW, mask, 0x00); | ||
376 | break; | ||
377 | case SND_SOC_BIAS_OFF: | ||
378 | /* Disable VREF and VREF buffer */ | ||
379 | snd_soc_update_bits(codec, ADAU1701_AUXNPOW, mask, mask); | ||
380 | break; | ||
381 | } | ||
382 | |||
383 | codec->dapm.bias_level = level; | ||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute) | ||
388 | { | ||
389 | struct snd_soc_codec *codec = dai->codec; | ||
390 | unsigned int mask = ADAU1701_DSPCTRL_DAM; | ||
391 | unsigned int val; | ||
392 | |||
393 | if (mute) | ||
394 | val = 0; | ||
395 | else | ||
396 | val = mask; | ||
397 | |||
398 | snd_soc_update_bits(codec, ADAU1701_DSPCTRL, mask, val); | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id, | ||
404 | unsigned int freq, int dir) | ||
405 | { | ||
406 | unsigned int val; | ||
407 | |||
408 | switch (clk_id) { | ||
409 | case ADAU1701_CLK_SRC_OSC: | ||
410 | val = 0x0; | ||
411 | break; | ||
412 | case ADAU1701_CLK_SRC_MCLK: | ||
413 | val = ADAU1701_OSCIPOW_OPD; | ||
414 | break; | ||
415 | default: | ||
416 | return -EINVAL; | ||
417 | } | ||
418 | |||
419 | snd_soc_update_bits(codec, ADAU1701_OSCIPOW, ADAU1701_OSCIPOW_OPD, val); | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | #define ADAU1701_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \ | ||
425 | SNDRV_PCM_RATE_192000) | ||
426 | |||
427 | #define ADAU1701_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
428 | SNDRV_PCM_FMTBIT_S24_LE) | ||
429 | |||
430 | static const struct snd_soc_dai_ops adau1701_dai_ops = { | ||
431 | .set_fmt = adau1701_set_dai_fmt, | ||
432 | .hw_params = adau1701_hw_params, | ||
433 | .digital_mute = adau1701_digital_mute, | ||
434 | }; | ||
435 | |||
436 | static struct snd_soc_dai_driver adau1701_dai = { | ||
437 | .name = "adau1701", | ||
438 | .playback = { | ||
439 | .stream_name = "Playback", | ||
440 | .channels_min = 2, | ||
441 | .channels_max = 8, | ||
442 | .rates = ADAU1701_RATES, | ||
443 | .formats = ADAU1701_FORMATS, | ||
444 | }, | ||
445 | .capture = { | ||
446 | .stream_name = "Capture", | ||
447 | .channels_min = 2, | ||
448 | .channels_max = 8, | ||
449 | .rates = ADAU1701_RATES, | ||
450 | .formats = ADAU1701_FORMATS, | ||
451 | }, | ||
452 | .ops = &adau1701_dai_ops, | ||
453 | .symmetric_rates = 1, | ||
454 | }; | ||
455 | |||
456 | static int adau1701_probe(struct snd_soc_codec *codec) | ||
457 | { | ||
458 | int ret; | ||
459 | |||
460 | codec->dapm.idle_bias_off = 1; | ||
461 | |||
462 | ret = adau1701_load_firmware(codec); | ||
463 | if (ret) | ||
464 | dev_warn(codec->dev, "Failed to load firmware\n"); | ||
465 | |||
466 | snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT); | ||
467 | snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR); | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | static struct snd_soc_codec_driver adau1701_codec_drv = { | ||
473 | .probe = adau1701_probe, | ||
474 | .set_bias_level = adau1701_set_bias_level, | ||
475 | |||
476 | .reg_cache_size = ADAU1701_NUM_REGS, | ||
477 | .reg_word_size = sizeof(u16), | ||
478 | |||
479 | .controls = adau1701_controls, | ||
480 | .num_controls = ARRAY_SIZE(adau1701_controls), | ||
481 | .dapm_widgets = adau1701_dapm_widgets, | ||
482 | .num_dapm_widgets = ARRAY_SIZE(adau1701_dapm_widgets), | ||
483 | .dapm_routes = adau1701_dapm_routes, | ||
484 | .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), | ||
485 | |||
486 | .write = adau1701_write, | ||
487 | .read = adau1701_read, | ||
488 | |||
489 | .set_sysclk = adau1701_set_sysclk, | ||
490 | }; | ||
491 | |||
492 | static __devinit int adau1701_i2c_probe(struct i2c_client *client, | ||
493 | const struct i2c_device_id *id) | ||
494 | { | ||
495 | struct adau1701 *adau1701; | ||
496 | int ret; | ||
497 | |||
498 | adau1701 = kzalloc(sizeof(*adau1701), GFP_KERNEL); | ||
499 | if (!adau1701) | ||
500 | return -ENOMEM; | ||
501 | |||
502 | i2c_set_clientdata(client, adau1701); | ||
503 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, | ||
504 | &adau1701_dai, 1); | ||
505 | if (ret < 0) | ||
506 | kfree(adau1701); | ||
507 | |||
508 | return ret; | ||
509 | } | ||
510 | |||
511 | static __devexit int adau1701_i2c_remove(struct i2c_client *client) | ||
512 | { | ||
513 | snd_soc_unregister_codec(&client->dev); | ||
514 | kfree(i2c_get_clientdata(client)); | ||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | static const struct i2c_device_id adau1701_i2c_id[] = { | ||
519 | { "adau1701", 0 }, | ||
520 | { } | ||
521 | }; | ||
522 | MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id); | ||
523 | |||
524 | static struct i2c_driver adau1701_i2c_driver = { | ||
525 | .driver = { | ||
526 | .name = "adau1701", | ||
527 | .owner = THIS_MODULE, | ||
528 | }, | ||
529 | .probe = adau1701_i2c_probe, | ||
530 | .remove = __devexit_p(adau1701_i2c_remove), | ||
531 | .id_table = adau1701_i2c_id, | ||
532 | }; | ||
533 | |||
534 | static int __init adau1701_init(void) | ||
535 | { | ||
536 | return i2c_add_driver(&adau1701_i2c_driver); | ||
537 | } | ||
538 | module_init(adau1701_init); | ||
539 | |||
540 | static void __exit adau1701_exit(void) | ||
541 | { | ||
542 | i2c_del_driver(&adau1701_i2c_driver); | ||
543 | } | ||
544 | module_exit(adau1701_exit); | ||
545 | |||
546 | MODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver"); | ||
547 | MODULE_AUTHOR("Cliff Cai <cliff.cai@analog.com>"); | ||
548 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
549 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/adau1701.h b/sound/soc/codecs/adau1701.h new file mode 100644 index 000000000000..8d0949a2aec9 --- /dev/null +++ b/sound/soc/codecs/adau1701.h | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * header file for ADAU1701 SigmaDSP processor | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #ifndef _ADAU1701_H | ||
10 | #define _ADAU1701_H | ||
11 | |||
12 | enum adau1701_clk_src { | ||
13 | ADAU1701_CLK_SRC_OSC, | ||
14 | ADAU1701_CLK_SRC_MCLK, | ||
15 | }; | ||
16 | |||
17 | #endif | ||
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c new file mode 100644 index 000000000000..300c04b70e71 --- /dev/null +++ b/sound/soc/codecs/adav80x.c | |||
@@ -0,0 +1,951 @@ | |||
1 | /* | ||
2 | * ADAV80X Audio Codec driver supporting ADAV801, ADAV803 | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * Author: Yi Li <yi.li@analog.com> | ||
6 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
7 | * | ||
8 | * Licensed under the GPL-2 or later. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/spi/spi.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/tlv.h> | ||
21 | #include <sound/soc.h> | ||
22 | |||
23 | #include "adav80x.h" | ||
24 | |||
25 | #define ADAV80X_PLAYBACK_CTRL 0x04 | ||
26 | #define ADAV80X_AUX_IN_CTRL 0x05 | ||
27 | #define ADAV80X_REC_CTRL 0x06 | ||
28 | #define ADAV80X_AUX_OUT_CTRL 0x07 | ||
29 | #define ADAV80X_DPATH_CTRL1 0x62 | ||
30 | #define ADAV80X_DPATH_CTRL2 0x63 | ||
31 | #define ADAV80X_DAC_CTRL1 0x64 | ||
32 | #define ADAV80X_DAC_CTRL2 0x65 | ||
33 | #define ADAV80X_DAC_CTRL3 0x66 | ||
34 | #define ADAV80X_DAC_L_VOL 0x68 | ||
35 | #define ADAV80X_DAC_R_VOL 0x69 | ||
36 | #define ADAV80X_PGA_L_VOL 0x6c | ||
37 | #define ADAV80X_PGA_R_VOL 0x6d | ||
38 | #define ADAV80X_ADC_CTRL1 0x6e | ||
39 | #define ADAV80X_ADC_CTRL2 0x6f | ||
40 | #define ADAV80X_ADC_L_VOL 0x70 | ||
41 | #define ADAV80X_ADC_R_VOL 0x71 | ||
42 | #define ADAV80X_PLL_CTRL1 0x74 | ||
43 | #define ADAV80X_PLL_CTRL2 0x75 | ||
44 | #define ADAV80X_ICLK_CTRL1 0x76 | ||
45 | #define ADAV80X_ICLK_CTRL2 0x77 | ||
46 | #define ADAV80X_PLL_CLK_SRC 0x78 | ||
47 | #define ADAV80X_PLL_OUTE 0x7a | ||
48 | |||
49 | #define ADAV80X_PLL_CLK_SRC_PLL_XIN(pll) 0x00 | ||
50 | #define ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll) (0x40 << (pll)) | ||
51 | #define ADAV80X_PLL_CLK_SRC_PLL_MASK(pll) (0x40 << (pll)) | ||
52 | |||
53 | #define ADAV80X_ICLK_CTRL1_DAC_SRC(src) ((src) << 5) | ||
54 | #define ADAV80X_ICLK_CTRL1_ADC_SRC(src) ((src) << 2) | ||
55 | #define ADAV80X_ICLK_CTRL1_ICLK2_SRC(src) (src) | ||
56 | #define ADAV80X_ICLK_CTRL2_ICLK1_SRC(src) ((src) << 3) | ||
57 | |||
58 | #define ADAV80X_PLL_CTRL1_PLLDIV 0x10 | ||
59 | #define ADAV80X_PLL_CTRL1_PLLPD(pll) (0x04 << (pll)) | ||
60 | #define ADAV80X_PLL_CTRL1_XTLPD 0x02 | ||
61 | |||
62 | #define ADAV80X_PLL_CTRL2_FIELD(pll, x) ((x) << ((pll) * 4)) | ||
63 | |||
64 | #define ADAV80X_PLL_CTRL2_FS_48(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x00) | ||
65 | #define ADAV80X_PLL_CTRL2_FS_32(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x08) | ||
66 | #define ADAV80X_PLL_CTRL2_FS_44(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0c) | ||
67 | |||
68 | #define ADAV80X_PLL_CTRL2_SEL(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x02) | ||
69 | #define ADAV80X_PLL_CTRL2_DOUB(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x01) | ||
70 | #define ADAV80X_PLL_CTRL2_PLL_MASK(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0f) | ||
71 | |||
72 | #define ADAV80X_ADC_CTRL1_MODULATOR_MASK 0x80 | ||
73 | #define ADAV80X_ADC_CTRL1_MODULATOR_128FS 0x00 | ||
74 | #define ADAV80X_ADC_CTRL1_MODULATOR_64FS 0x80 | ||
75 | |||
76 | #define ADAV80X_DAC_CTRL1_PD 0x80 | ||
77 | |||
78 | #define ADAV80X_DAC_CTRL2_DIV1 0x00 | ||
79 | #define ADAV80X_DAC_CTRL2_DIV1_5 0x10 | ||
80 | #define ADAV80X_DAC_CTRL2_DIV2 0x20 | ||
81 | #define ADAV80X_DAC_CTRL2_DIV3 0x30 | ||
82 | #define ADAV80X_DAC_CTRL2_DIV_MASK 0x30 | ||
83 | |||
84 | #define ADAV80X_DAC_CTRL2_INTERPOL_256FS 0x00 | ||
85 | #define ADAV80X_DAC_CTRL2_INTERPOL_128FS 0x40 | ||
86 | #define ADAV80X_DAC_CTRL2_INTERPOL_64FS 0x80 | ||
87 | #define ADAV80X_DAC_CTRL2_INTERPOL_MASK 0xc0 | ||
88 | |||
89 | #define ADAV80X_DAC_CTRL2_DEEMPH_NONE 0x00 | ||
90 | #define ADAV80X_DAC_CTRL2_DEEMPH_44 0x01 | ||
91 | #define ADAV80X_DAC_CTRL2_DEEMPH_32 0x02 | ||
92 | #define ADAV80X_DAC_CTRL2_DEEMPH_48 0x03 | ||
93 | #define ADAV80X_DAC_CTRL2_DEEMPH_MASK 0x01 | ||
94 | |||
95 | #define ADAV80X_CAPTURE_MODE_MASTER 0x20 | ||
96 | #define ADAV80X_CAPTURE_WORD_LEN24 0x00 | ||
97 | #define ADAV80X_CAPTURE_WORD_LEN20 0x04 | ||
98 | #define ADAV80X_CAPTRUE_WORD_LEN18 0x08 | ||
99 | #define ADAV80X_CAPTURE_WORD_LEN16 0x0c | ||
100 | #define ADAV80X_CAPTURE_WORD_LEN_MASK 0x0c | ||
101 | |||
102 | #define ADAV80X_CAPTURE_MODE_LEFT_J 0x00 | ||
103 | #define ADAV80X_CAPTURE_MODE_I2S 0x01 | ||
104 | #define ADAV80X_CAPTURE_MODE_RIGHT_J 0x03 | ||
105 | #define ADAV80X_CAPTURE_MODE_MASK 0x03 | ||
106 | |||
107 | #define ADAV80X_PLAYBACK_MODE_MASTER 0x10 | ||
108 | #define ADAV80X_PLAYBACK_MODE_LEFT_J 0x00 | ||
109 | #define ADAV80X_PLAYBACK_MODE_I2S 0x01 | ||
110 | #define ADAV80X_PLAYBACK_MODE_RIGHT_J_24 0x04 | ||
111 | #define ADAV80X_PLAYBACK_MODE_RIGHT_J_20 0x05 | ||
112 | #define ADAV80X_PLAYBACK_MODE_RIGHT_J_18 0x06 | ||
113 | #define ADAV80X_PLAYBACK_MODE_RIGHT_J_16 0x07 | ||
114 | #define ADAV80X_PLAYBACK_MODE_MASK 0x07 | ||
115 | |||
116 | #define ADAV80X_PLL_OUTE_SYSCLKPD(x) BIT(2 - (x)) | ||
117 | |||
118 | static u8 adav80x_default_regs[] = { | ||
119 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x01, 0x80, 0x26, 0x00, 0x00, | ||
120 | 0x02, 0x40, 0x20, 0x00, 0x09, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
121 | 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x92, 0xb1, 0x37, | ||
122 | 0x48, 0xd2, 0xfb, 0xca, 0xd2, 0x15, 0xe8, 0x29, 0xb9, 0x6a, 0xda, 0x2b, | ||
123 | 0xb7, 0xc0, 0x11, 0x65, 0x5c, 0xf6, 0xff, 0x8d, 0x00, 0x00, 0x00, 0x00, | ||
124 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
125 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, | ||
126 | 0x00, 0xe8, 0x46, 0xe1, 0x5b, 0xd3, 0x43, 0x77, 0x93, 0xa7, 0x44, 0xee, | ||
127 | 0x32, 0x12, 0xc0, 0x11, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x3f, | ||
128 | 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, | ||
129 | 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, | ||
130 | }; | ||
131 | |||
132 | struct adav80x { | ||
133 | enum snd_soc_control_type control_type; | ||
134 | |||
135 | enum adav80x_clk_src clk_src; | ||
136 | unsigned int sysclk; | ||
137 | enum adav80x_pll_src pll_src; | ||
138 | |||
139 | unsigned int dai_fmt[2]; | ||
140 | unsigned int rate; | ||
141 | bool deemph; | ||
142 | bool sysclk_pd[3]; | ||
143 | }; | ||
144 | |||
145 | static const char *adav80x_mux_text[] = { | ||
146 | "ADC", | ||
147 | "Playback", | ||
148 | "Aux Playback", | ||
149 | }; | ||
150 | |||
151 | static const unsigned int adav80x_mux_values[] = { | ||
152 | 0, 2, 3, | ||
153 | }; | ||
154 | |||
155 | #define ADAV80X_MUX_ENUM_DECL(name, reg, shift) \ | ||
156 | SOC_VALUE_ENUM_DOUBLE_DECL(name, reg, shift, 7, \ | ||
157 | ARRAY_SIZE(adav80x_mux_text), adav80x_mux_text, \ | ||
158 | adav80x_mux_values) | ||
159 | |||
160 | static ADAV80X_MUX_ENUM_DECL(adav80x_aux_capture_enum, ADAV80X_DPATH_CTRL1, 0); | ||
161 | static ADAV80X_MUX_ENUM_DECL(adav80x_capture_enum, ADAV80X_DPATH_CTRL1, 3); | ||
162 | static ADAV80X_MUX_ENUM_DECL(adav80x_dac_enum, ADAV80X_DPATH_CTRL2, 3); | ||
163 | |||
164 | static const struct snd_kcontrol_new adav80x_aux_capture_mux_ctrl = | ||
165 | SOC_DAPM_VALUE_ENUM("Route", adav80x_aux_capture_enum); | ||
166 | static const struct snd_kcontrol_new adav80x_capture_mux_ctrl = | ||
167 | SOC_DAPM_VALUE_ENUM("Route", adav80x_capture_enum); | ||
168 | static const struct snd_kcontrol_new adav80x_dac_mux_ctrl = | ||
169 | SOC_DAPM_VALUE_ENUM("Route", adav80x_dac_enum); | ||
170 | |||
171 | #define ADAV80X_MUX(name, ctrl) \ | ||
172 | SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) | ||
173 | |||
174 | static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = { | ||
175 | SND_SOC_DAPM_DAC("DAC", NULL, ADAV80X_DAC_CTRL1, 7, 1), | ||
176 | SND_SOC_DAPM_ADC("ADC", NULL, ADAV80X_ADC_CTRL1, 5, 1), | ||
177 | |||
178 | SND_SOC_DAPM_PGA("Right PGA", ADAV80X_ADC_CTRL1, 0, 1, NULL, 0), | ||
179 | SND_SOC_DAPM_PGA("Left PGA", ADAV80X_ADC_CTRL1, 1, 1, NULL, 0), | ||
180 | |||
181 | SND_SOC_DAPM_AIF_OUT("AIFOUT", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0), | ||
182 | SND_SOC_DAPM_AIF_IN("AIFIN", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), | ||
183 | |||
184 | SND_SOC_DAPM_AIF_OUT("AIFAUXOUT", "Aux Capture", 0, SND_SOC_NOPM, 0, 0), | ||
185 | SND_SOC_DAPM_AIF_IN("AIFAUXIN", "Aux Playback", 0, SND_SOC_NOPM, 0, 0), | ||
186 | |||
187 | ADAV80X_MUX("Aux Capture Select", &adav80x_aux_capture_mux_ctrl), | ||
188 | ADAV80X_MUX("Capture Select", &adav80x_capture_mux_ctrl), | ||
189 | ADAV80X_MUX("DAC Select", &adav80x_dac_mux_ctrl), | ||
190 | |||
191 | SND_SOC_DAPM_INPUT("VINR"), | ||
192 | SND_SOC_DAPM_INPUT("VINL"), | ||
193 | SND_SOC_DAPM_OUTPUT("VOUTR"), | ||
194 | SND_SOC_DAPM_OUTPUT("VOUTL"), | ||
195 | |||
196 | SND_SOC_DAPM_SUPPLY("SYSCLK", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
197 | SND_SOC_DAPM_SUPPLY("PLL1", ADAV80X_PLL_CTRL1, 2, 1, NULL, 0), | ||
198 | SND_SOC_DAPM_SUPPLY("PLL2", ADAV80X_PLL_CTRL1, 3, 1, NULL, 0), | ||
199 | SND_SOC_DAPM_SUPPLY("OSC", ADAV80X_PLL_CTRL1, 1, 1, NULL, 0), | ||
200 | }; | ||
201 | |||
202 | static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, | ||
203 | struct snd_soc_dapm_widget *sink) | ||
204 | { | ||
205 | struct snd_soc_codec *codec = source->codec; | ||
206 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
207 | const char *clk; | ||
208 | |||
209 | switch (adav80x->clk_src) { | ||
210 | case ADAV80X_CLK_PLL1: | ||
211 | clk = "PLL1"; | ||
212 | break; | ||
213 | case ADAV80X_CLK_PLL2: | ||
214 | clk = "PLL2"; | ||
215 | break; | ||
216 | case ADAV80X_CLK_XTAL: | ||
217 | clk = "OSC"; | ||
218 | break; | ||
219 | default: | ||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | return strcmp(source->name, clk) == 0; | ||
224 | } | ||
225 | |||
226 | static int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source, | ||
227 | struct snd_soc_dapm_widget *sink) | ||
228 | { | ||
229 | struct snd_soc_codec *codec = source->codec; | ||
230 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
231 | |||
232 | return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL; | ||
233 | } | ||
234 | |||
235 | |||
236 | static const struct snd_soc_dapm_route adav80x_dapm_routes[] = { | ||
237 | { "DAC Select", "ADC", "ADC" }, | ||
238 | { "DAC Select", "Playback", "AIFIN" }, | ||
239 | { "DAC Select", "Aux Playback", "AIFAUXIN" }, | ||
240 | { "DAC", NULL, "DAC Select" }, | ||
241 | |||
242 | { "Capture Select", "ADC", "ADC" }, | ||
243 | { "Capture Select", "Playback", "AIFIN" }, | ||
244 | { "Capture Select", "Aux Playback", "AIFAUXIN" }, | ||
245 | { "AIFOUT", NULL, "Capture Select" }, | ||
246 | |||
247 | { "Aux Capture Select", "ADC", "ADC" }, | ||
248 | { "Aux Capture Select", "Playback", "AIFIN" }, | ||
249 | { "Aux Capture Select", "Aux Playback", "AIFAUXIN" }, | ||
250 | { "AIFAUXOUT", NULL, "Aux Capture Select" }, | ||
251 | |||
252 | { "VOUTR", NULL, "DAC" }, | ||
253 | { "VOUTL", NULL, "DAC" }, | ||
254 | |||
255 | { "Left PGA", NULL, "VINL" }, | ||
256 | { "Right PGA", NULL, "VINR" }, | ||
257 | { "ADC", NULL, "Left PGA" }, | ||
258 | { "ADC", NULL, "Right PGA" }, | ||
259 | |||
260 | { "SYSCLK", NULL, "PLL1", adav80x_dapm_sysclk_check }, | ||
261 | { "SYSCLK", NULL, "PLL2", adav80x_dapm_sysclk_check }, | ||
262 | { "SYSCLK", NULL, "OSC", adav80x_dapm_sysclk_check }, | ||
263 | { "PLL1", NULL, "OSC", adav80x_dapm_pll_check }, | ||
264 | { "PLL2", NULL, "OSC", adav80x_dapm_pll_check }, | ||
265 | |||
266 | { "ADC", NULL, "SYSCLK" }, | ||
267 | { "DAC", NULL, "SYSCLK" }, | ||
268 | { "AIFOUT", NULL, "SYSCLK" }, | ||
269 | { "AIFAUXOUT", NULL, "SYSCLK" }, | ||
270 | { "AIFIN", NULL, "SYSCLK" }, | ||
271 | { "AIFAUXIN", NULL, "SYSCLK" }, | ||
272 | }; | ||
273 | |||
274 | static int adav80x_set_deemph(struct snd_soc_codec *codec) | ||
275 | { | ||
276 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
277 | unsigned int val; | ||
278 | |||
279 | if (adav80x->deemph) { | ||
280 | switch (adav80x->rate) { | ||
281 | case 32000: | ||
282 | val = ADAV80X_DAC_CTRL2_DEEMPH_32; | ||
283 | break; | ||
284 | case 44100: | ||
285 | val = ADAV80X_DAC_CTRL2_DEEMPH_44; | ||
286 | break; | ||
287 | case 48000: | ||
288 | case 64000: | ||
289 | case 88200: | ||
290 | case 96000: | ||
291 | val = ADAV80X_DAC_CTRL2_DEEMPH_48; | ||
292 | break; | ||
293 | default: | ||
294 | val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; | ||
295 | break; | ||
296 | } | ||
297 | } else { | ||
298 | val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; | ||
299 | } | ||
300 | |||
301 | return snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2, | ||
302 | ADAV80X_DAC_CTRL2_DEEMPH_MASK, val); | ||
303 | } | ||
304 | |||
305 | static int adav80x_put_deemph(struct snd_kcontrol *kcontrol, | ||
306 | struct snd_ctl_elem_value *ucontrol) | ||
307 | { | ||
308 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
309 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
310 | unsigned int deemph = ucontrol->value.enumerated.item[0]; | ||
311 | |||
312 | if (deemph > 1) | ||
313 | return -EINVAL; | ||
314 | |||
315 | adav80x->deemph = deemph; | ||
316 | |||
317 | return adav80x_set_deemph(codec); | ||
318 | } | ||
319 | |||
320 | static int adav80x_get_deemph(struct snd_kcontrol *kcontrol, | ||
321 | struct snd_ctl_elem_value *ucontrol) | ||
322 | { | ||
323 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
324 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
325 | |||
326 | ucontrol->value.enumerated.item[0] = adav80x->deemph; | ||
327 | return 0; | ||
328 | }; | ||
329 | |||
330 | static const DECLARE_TLV_DB_SCALE(adav80x_inpga_tlv, 0, 50, 0); | ||
331 | static const DECLARE_TLV_DB_MINMAX(adav80x_digital_tlv, -9563, 0); | ||
332 | |||
333 | static const struct snd_kcontrol_new adav80x_controls[] = { | ||
334 | SOC_DOUBLE_R_TLV("Master Playback Volume", ADAV80X_DAC_L_VOL, | ||
335 | ADAV80X_DAC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), | ||
336 | SOC_DOUBLE_R_TLV("Master Capture Volume", ADAV80X_ADC_L_VOL, | ||
337 | ADAV80X_ADC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), | ||
338 | |||
339 | SOC_DOUBLE_R_TLV("PGA Capture Volume", ADAV80X_PGA_L_VOL, | ||
340 | ADAV80X_PGA_R_VOL, 0, 0x30, 0, adav80x_inpga_tlv), | ||
341 | |||
342 | SOC_DOUBLE("Master Playback Switch", ADAV80X_DAC_CTRL1, 0, 1, 1, 0), | ||
343 | SOC_DOUBLE("Master Capture Switch", ADAV80X_ADC_CTRL1, 2, 3, 1, 1), | ||
344 | |||
345 | SOC_SINGLE("ADC High Pass Filter Switch", ADAV80X_ADC_CTRL1, 6, 1, 0), | ||
346 | |||
347 | SOC_SINGLE_BOOL_EXT("Playback De-emphasis Switch", 0, | ||
348 | adav80x_get_deemph, adav80x_put_deemph), | ||
349 | }; | ||
350 | |||
351 | static unsigned int adav80x_port_ctrl_regs[2][2] = { | ||
352 | { ADAV80X_REC_CTRL, ADAV80X_PLAYBACK_CTRL, }, | ||
353 | { ADAV80X_AUX_OUT_CTRL, ADAV80X_AUX_IN_CTRL }, | ||
354 | }; | ||
355 | |||
356 | static int adav80x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
357 | { | ||
358 | struct snd_soc_codec *codec = dai->codec; | ||
359 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
360 | unsigned int capture = 0x00; | ||
361 | unsigned int playback = 0x00; | ||
362 | |||
363 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
364 | case SND_SOC_DAIFMT_CBM_CFM: | ||
365 | capture |= ADAV80X_CAPTURE_MODE_MASTER; | ||
366 | playback |= ADAV80X_PLAYBACK_MODE_MASTER; | ||
367 | case SND_SOC_DAIFMT_CBS_CFS: | ||
368 | break; | ||
369 | default: | ||
370 | return -EINVAL; | ||
371 | } | ||
372 | |||
373 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
374 | case SND_SOC_DAIFMT_I2S: | ||
375 | capture |= ADAV80X_CAPTURE_MODE_I2S; | ||
376 | playback |= ADAV80X_PLAYBACK_MODE_I2S; | ||
377 | break; | ||
378 | case SND_SOC_DAIFMT_LEFT_J: | ||
379 | capture |= ADAV80X_CAPTURE_MODE_LEFT_J; | ||
380 | playback |= ADAV80X_PLAYBACK_MODE_LEFT_J; | ||
381 | break; | ||
382 | case SND_SOC_DAIFMT_RIGHT_J: | ||
383 | capture |= ADAV80X_CAPTURE_MODE_RIGHT_J; | ||
384 | playback |= ADAV80X_PLAYBACK_MODE_RIGHT_J_24; | ||
385 | break; | ||
386 | default: | ||
387 | return -EINVAL; | ||
388 | } | ||
389 | |||
390 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
391 | case SND_SOC_DAIFMT_NB_NF: | ||
392 | break; | ||
393 | default: | ||
394 | return -EINVAL; | ||
395 | } | ||
396 | |||
397 | snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0], | ||
398 | ADAV80X_CAPTURE_MODE_MASK | ADAV80X_CAPTURE_MODE_MASTER, | ||
399 | capture); | ||
400 | snd_soc_write(codec, adav80x_port_ctrl_regs[dai->id][1], playback); | ||
401 | |||
402 | adav80x->dai_fmt[dai->id] = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | ||
403 | |||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | static int adav80x_set_adc_clock(struct snd_soc_codec *codec, | ||
408 | unsigned int sample_rate) | ||
409 | { | ||
410 | unsigned int val; | ||
411 | |||
412 | if (sample_rate <= 48000) | ||
413 | val = ADAV80X_ADC_CTRL1_MODULATOR_128FS; | ||
414 | else | ||
415 | val = ADAV80X_ADC_CTRL1_MODULATOR_64FS; | ||
416 | |||
417 | snd_soc_update_bits(codec, ADAV80X_ADC_CTRL1, | ||
418 | ADAV80X_ADC_CTRL1_MODULATOR_MASK, val); | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int adav80x_set_dac_clock(struct snd_soc_codec *codec, | ||
424 | unsigned int sample_rate) | ||
425 | { | ||
426 | unsigned int val; | ||
427 | |||
428 | if (sample_rate <= 48000) | ||
429 | val = ADAV80X_DAC_CTRL2_DIV1 | ADAV80X_DAC_CTRL2_INTERPOL_256FS; | ||
430 | else | ||
431 | val = ADAV80X_DAC_CTRL2_DIV2 | ADAV80X_DAC_CTRL2_INTERPOL_128FS; | ||
432 | |||
433 | snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2, | ||
434 | ADAV80X_DAC_CTRL2_DIV_MASK | ADAV80X_DAC_CTRL2_INTERPOL_MASK, | ||
435 | val); | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec, | ||
441 | struct snd_soc_dai *dai, snd_pcm_format_t format) | ||
442 | { | ||
443 | unsigned int val; | ||
444 | |||
445 | switch (format) { | ||
446 | case SNDRV_PCM_FORMAT_S16_LE: | ||
447 | val = ADAV80X_CAPTURE_WORD_LEN16; | ||
448 | break; | ||
449 | case SNDRV_PCM_FORMAT_S18_3LE: | ||
450 | val = ADAV80X_CAPTRUE_WORD_LEN18; | ||
451 | break; | ||
452 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
453 | val = ADAV80X_CAPTURE_WORD_LEN20; | ||
454 | break; | ||
455 | case SNDRV_PCM_FORMAT_S24_LE: | ||
456 | val = ADAV80X_CAPTURE_WORD_LEN24; | ||
457 | break; | ||
458 | default: | ||
459 | return -EINVAL; | ||
460 | } | ||
461 | |||
462 | snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0], | ||
463 | ADAV80X_CAPTURE_WORD_LEN_MASK, val); | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec, | ||
469 | struct snd_soc_dai *dai, snd_pcm_format_t format) | ||
470 | { | ||
471 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
472 | unsigned int val; | ||
473 | |||
474 | if (adav80x->dai_fmt[dai->id] != SND_SOC_DAIFMT_RIGHT_J) | ||
475 | return 0; | ||
476 | |||
477 | switch (format) { | ||
478 | case SNDRV_PCM_FORMAT_S16_LE: | ||
479 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_16; | ||
480 | break; | ||
481 | case SNDRV_PCM_FORMAT_S18_3LE: | ||
482 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_18; | ||
483 | break; | ||
484 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
485 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_20; | ||
486 | break; | ||
487 | case SNDRV_PCM_FORMAT_S24_LE: | ||
488 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_24; | ||
489 | break; | ||
490 | default: | ||
491 | return -EINVAL; | ||
492 | } | ||
493 | |||
494 | snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][1], | ||
495 | ADAV80X_PLAYBACK_MODE_MASK, val); | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | static int adav80x_hw_params(struct snd_pcm_substream *substream, | ||
501 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
502 | { | ||
503 | struct snd_soc_codec *codec = dai->codec; | ||
504 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
505 | unsigned int rate = params_rate(params); | ||
506 | |||
507 | if (rate * 256 != adav80x->sysclk) | ||
508 | return -EINVAL; | ||
509 | |||
510 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
511 | adav80x_set_playback_pcm_format(codec, dai, | ||
512 | params_format(params)); | ||
513 | adav80x_set_dac_clock(codec, rate); | ||
514 | } else { | ||
515 | adav80x_set_capture_pcm_format(codec, dai, | ||
516 | params_format(params)); | ||
517 | adav80x_set_adc_clock(codec, rate); | ||
518 | } | ||
519 | adav80x->rate = rate; | ||
520 | adav80x_set_deemph(codec); | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int adav80x_set_sysclk(struct snd_soc_codec *codec, | ||
526 | int clk_id, unsigned int freq, int dir) | ||
527 | { | ||
528 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
529 | |||
530 | if (dir == SND_SOC_CLOCK_IN) { | ||
531 | switch (clk_id) { | ||
532 | case ADAV80X_CLK_XIN: | ||
533 | case ADAV80X_CLK_XTAL: | ||
534 | case ADAV80X_CLK_MCLKI: | ||
535 | case ADAV80X_CLK_PLL1: | ||
536 | case ADAV80X_CLK_PLL2: | ||
537 | break; | ||
538 | default: | ||
539 | return -EINVAL; | ||
540 | } | ||
541 | |||
542 | adav80x->sysclk = freq; | ||
543 | |||
544 | if (adav80x->clk_src != clk_id) { | ||
545 | unsigned int iclk_ctrl1, iclk_ctrl2; | ||
546 | |||
547 | adav80x->clk_src = clk_id; | ||
548 | if (clk_id == ADAV80X_CLK_XTAL) | ||
549 | clk_id = ADAV80X_CLK_XIN; | ||
550 | |||
551 | iclk_ctrl1 = ADAV80X_ICLK_CTRL1_DAC_SRC(clk_id) | | ||
552 | ADAV80X_ICLK_CTRL1_ADC_SRC(clk_id) | | ||
553 | ADAV80X_ICLK_CTRL1_ICLK2_SRC(clk_id); | ||
554 | iclk_ctrl2 = ADAV80X_ICLK_CTRL2_ICLK1_SRC(clk_id); | ||
555 | |||
556 | snd_soc_write(codec, ADAV80X_ICLK_CTRL1, iclk_ctrl1); | ||
557 | snd_soc_write(codec, ADAV80X_ICLK_CTRL2, iclk_ctrl2); | ||
558 | |||
559 | snd_soc_dapm_sync(&codec->dapm); | ||
560 | } | ||
561 | } else { | ||
562 | unsigned int mask; | ||
563 | |||
564 | switch (clk_id) { | ||
565 | case ADAV80X_CLK_SYSCLK1: | ||
566 | case ADAV80X_CLK_SYSCLK2: | ||
567 | case ADAV80X_CLK_SYSCLK3: | ||
568 | break; | ||
569 | default: | ||
570 | return -EINVAL; | ||
571 | } | ||
572 | |||
573 | clk_id -= ADAV80X_CLK_SYSCLK1; | ||
574 | mask = ADAV80X_PLL_OUTE_SYSCLKPD(clk_id); | ||
575 | |||
576 | if (freq == 0) { | ||
577 | snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, mask); | ||
578 | adav80x->sysclk_pd[clk_id] = true; | ||
579 | } else { | ||
580 | snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, 0); | ||
581 | adav80x->sysclk_pd[clk_id] = false; | ||
582 | } | ||
583 | |||
584 | if (adav80x->sysclk_pd[0]) | ||
585 | snd_soc_dapm_disable_pin(&codec->dapm, "PLL1"); | ||
586 | else | ||
587 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); | ||
588 | |||
589 | if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) | ||
590 | snd_soc_dapm_disable_pin(&codec->dapm, "PLL2"); | ||
591 | else | ||
592 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); | ||
593 | |||
594 | snd_soc_dapm_sync(&codec->dapm); | ||
595 | } | ||
596 | |||
597 | return 0; | ||
598 | } | ||
599 | |||
600 | static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id, | ||
601 | int source, unsigned int freq_in, unsigned int freq_out) | ||
602 | { | ||
603 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
604 | unsigned int pll_ctrl1 = 0; | ||
605 | unsigned int pll_ctrl2 = 0; | ||
606 | unsigned int pll_src; | ||
607 | |||
608 | switch (source) { | ||
609 | case ADAV80X_PLL_SRC_XTAL: | ||
610 | case ADAV80X_PLL_SRC_XIN: | ||
611 | case ADAV80X_PLL_SRC_MCLKI: | ||
612 | break; | ||
613 | default: | ||
614 | return -EINVAL; | ||
615 | } | ||
616 | |||
617 | if (!freq_out) | ||
618 | return 0; | ||
619 | |||
620 | switch (freq_in) { | ||
621 | case 27000000: | ||
622 | break; | ||
623 | case 54000000: | ||
624 | if (source == ADAV80X_PLL_SRC_XIN) { | ||
625 | pll_ctrl1 |= ADAV80X_PLL_CTRL1_PLLDIV; | ||
626 | break; | ||
627 | } | ||
628 | default: | ||
629 | return -EINVAL; | ||
630 | } | ||
631 | |||
632 | if (freq_out > 12288000) { | ||
633 | pll_ctrl2 |= ADAV80X_PLL_CTRL2_DOUB(pll_id); | ||
634 | freq_out /= 2; | ||
635 | } | ||
636 | |||
637 | /* freq_out = sample_rate * 256 */ | ||
638 | switch (freq_out) { | ||
639 | case 8192000: | ||
640 | pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_32(pll_id); | ||
641 | break; | ||
642 | case 11289600: | ||
643 | pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_44(pll_id); | ||
644 | break; | ||
645 | case 12288000: | ||
646 | pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_48(pll_id); | ||
647 | break; | ||
648 | default: | ||
649 | return -EINVAL; | ||
650 | } | ||
651 | |||
652 | snd_soc_update_bits(codec, ADAV80X_PLL_CTRL1, ADAV80X_PLL_CTRL1_PLLDIV, | ||
653 | pll_ctrl1); | ||
654 | snd_soc_update_bits(codec, ADAV80X_PLL_CTRL2, | ||
655 | ADAV80X_PLL_CTRL2_PLL_MASK(pll_id), pll_ctrl2); | ||
656 | |||
657 | if (source != adav80x->pll_src) { | ||
658 | if (source == ADAV80X_PLL_SRC_MCLKI) | ||
659 | pll_src = ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll_id); | ||
660 | else | ||
661 | pll_src = ADAV80X_PLL_CLK_SRC_PLL_XIN(pll_id); | ||
662 | |||
663 | snd_soc_update_bits(codec, ADAV80X_PLL_CLK_SRC, | ||
664 | ADAV80X_PLL_CLK_SRC_PLL_MASK(pll_id), pll_src); | ||
665 | |||
666 | adav80x->pll_src = source; | ||
667 | |||
668 | snd_soc_dapm_sync(&codec->dapm); | ||
669 | } | ||
670 | |||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | static int adav80x_set_bias_level(struct snd_soc_codec *codec, | ||
675 | enum snd_soc_bias_level level) | ||
676 | { | ||
677 | unsigned int mask = ADAV80X_DAC_CTRL1_PD; | ||
678 | |||
679 | switch (level) { | ||
680 | case SND_SOC_BIAS_ON: | ||
681 | break; | ||
682 | case SND_SOC_BIAS_PREPARE: | ||
683 | break; | ||
684 | case SND_SOC_BIAS_STANDBY: | ||
685 | snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, 0x00); | ||
686 | break; | ||
687 | case SND_SOC_BIAS_OFF: | ||
688 | snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, mask); | ||
689 | break; | ||
690 | } | ||
691 | |||
692 | codec->dapm.bias_level = level; | ||
693 | return 0; | ||
694 | } | ||
695 | |||
696 | /* Enforce the same sample rate on all audio interfaces */ | ||
697 | static int adav80x_dai_startup(struct snd_pcm_substream *substream, | ||
698 | struct snd_soc_dai *dai) | ||
699 | { | ||
700 | struct snd_soc_codec *codec = dai->codec; | ||
701 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
702 | |||
703 | if (!codec->active || !adav80x->rate) | ||
704 | return 0; | ||
705 | |||
706 | return snd_pcm_hw_constraint_minmax(substream->runtime, | ||
707 | SNDRV_PCM_HW_PARAM_RATE, adav80x->rate, adav80x->rate); | ||
708 | } | ||
709 | |||
710 | static void adav80x_dai_shutdown(struct snd_pcm_substream *substream, | ||
711 | struct snd_soc_dai *dai) | ||
712 | { | ||
713 | struct snd_soc_codec *codec = dai->codec; | ||
714 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
715 | |||
716 | if (!codec->active) | ||
717 | adav80x->rate = 0; | ||
718 | } | ||
719 | |||
720 | static const struct snd_soc_dai_ops adav80x_dai_ops = { | ||
721 | .set_fmt = adav80x_set_dai_fmt, | ||
722 | .hw_params = adav80x_hw_params, | ||
723 | .startup = adav80x_dai_startup, | ||
724 | .shutdown = adav80x_dai_shutdown, | ||
725 | }; | ||
726 | |||
727 | #define ADAV80X_PLAYBACK_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
728 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | \ | ||
729 | SNDRV_PCM_RATE_96000) | ||
730 | |||
731 | #define ADAV80X_CAPTURE_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) | ||
732 | |||
733 | #define ADAV80X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ | ||
734 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) | ||
735 | |||
736 | static struct snd_soc_dai_driver adav80x_dais[] = { | ||
737 | { | ||
738 | .name = "adav80x-hifi", | ||
739 | .id = 0, | ||
740 | .playback = { | ||
741 | .stream_name = "HiFi Playback", | ||
742 | .channels_min = 2, | ||
743 | .channels_max = 2, | ||
744 | .rates = ADAV80X_PLAYBACK_RATES, | ||
745 | .formats = ADAV80X_FORMATS, | ||
746 | }, | ||
747 | .capture = { | ||
748 | .stream_name = "HiFi Capture", | ||
749 | .channels_min = 2, | ||
750 | .channels_max = 2, | ||
751 | .rates = ADAV80X_CAPTURE_RATES, | ||
752 | .formats = ADAV80X_FORMATS, | ||
753 | }, | ||
754 | .ops = &adav80x_dai_ops, | ||
755 | }, | ||
756 | { | ||
757 | .name = "adav80x-aux", | ||
758 | .id = 1, | ||
759 | .playback = { | ||
760 | .stream_name = "Aux Playback", | ||
761 | .channels_min = 2, | ||
762 | .channels_max = 2, | ||
763 | .rates = ADAV80X_PLAYBACK_RATES, | ||
764 | .formats = ADAV80X_FORMATS, | ||
765 | }, | ||
766 | .capture = { | ||
767 | .stream_name = "Aux Capture", | ||
768 | .channels_min = 2, | ||
769 | .channels_max = 2, | ||
770 | .rates = ADAV80X_CAPTURE_RATES, | ||
771 | .formats = ADAV80X_FORMATS, | ||
772 | }, | ||
773 | .ops = &adav80x_dai_ops, | ||
774 | }, | ||
775 | }; | ||
776 | |||
777 | static int adav80x_probe(struct snd_soc_codec *codec) | ||
778 | { | ||
779 | int ret; | ||
780 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
781 | |||
782 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, adav80x->control_type); | ||
783 | if (ret) { | ||
784 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); | ||
785 | return ret; | ||
786 | } | ||
787 | |||
788 | /* Force PLLs on for SYSCLK output */ | ||
789 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); | ||
790 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); | ||
791 | |||
792 | /* Power down S/PDIF receiver, since it is currently not supported */ | ||
793 | snd_soc_write(codec, ADAV80X_PLL_OUTE, 0x20); | ||
794 | /* Disable DAC zero flag */ | ||
795 | snd_soc_write(codec, ADAV80X_DAC_CTRL3, 0x6); | ||
796 | |||
797 | return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
798 | } | ||
799 | |||
800 | static int adav80x_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
801 | { | ||
802 | return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
803 | } | ||
804 | |||
805 | static int adav80x_resume(struct snd_soc_codec *codec) | ||
806 | { | ||
807 | adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
808 | codec->cache_sync = 1; | ||
809 | snd_soc_cache_sync(codec); | ||
810 | |||
811 | return 0; | ||
812 | } | ||
813 | |||
814 | static int adav80x_remove(struct snd_soc_codec *codec) | ||
815 | { | ||
816 | return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
817 | } | ||
818 | |||
819 | static struct snd_soc_codec_driver adav80x_codec_driver = { | ||
820 | .probe = adav80x_probe, | ||
821 | .remove = adav80x_remove, | ||
822 | .suspend = adav80x_suspend, | ||
823 | .resume = adav80x_resume, | ||
824 | .set_bias_level = adav80x_set_bias_level, | ||
825 | |||
826 | .set_pll = adav80x_set_pll, | ||
827 | .set_sysclk = adav80x_set_sysclk, | ||
828 | |||
829 | .reg_word_size = sizeof(u8), | ||
830 | .reg_cache_size = ARRAY_SIZE(adav80x_default_regs), | ||
831 | .reg_cache_default = adav80x_default_regs, | ||
832 | |||
833 | .controls = adav80x_controls, | ||
834 | .num_controls = ARRAY_SIZE(adav80x_controls), | ||
835 | .dapm_widgets = adav80x_dapm_widgets, | ||
836 | .num_dapm_widgets = ARRAY_SIZE(adav80x_dapm_widgets), | ||
837 | .dapm_routes = adav80x_dapm_routes, | ||
838 | .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), | ||
839 | }; | ||
840 | |||
841 | static int __devinit adav80x_bus_probe(struct device *dev, | ||
842 | enum snd_soc_control_type control_type) | ||
843 | { | ||
844 | struct adav80x *adav80x; | ||
845 | int ret; | ||
846 | |||
847 | adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL); | ||
848 | if (!adav80x) | ||
849 | return -ENOMEM; | ||
850 | |||
851 | dev_set_drvdata(dev, adav80x); | ||
852 | adav80x->control_type = control_type; | ||
853 | |||
854 | ret = snd_soc_register_codec(dev, &adav80x_codec_driver, | ||
855 | adav80x_dais, ARRAY_SIZE(adav80x_dais)); | ||
856 | if (ret) | ||
857 | kfree(adav80x); | ||
858 | |||
859 | return ret; | ||
860 | } | ||
861 | |||
862 | static int __devexit adav80x_bus_remove(struct device *dev) | ||
863 | { | ||
864 | snd_soc_unregister_codec(dev); | ||
865 | kfree(dev_get_drvdata(dev)); | ||
866 | return 0; | ||
867 | } | ||
868 | |||
869 | #if defined(CONFIG_SPI_MASTER) | ||
870 | static int __devinit adav80x_spi_probe(struct spi_device *spi) | ||
871 | { | ||
872 | return adav80x_bus_probe(&spi->dev, SND_SOC_SPI); | ||
873 | } | ||
874 | |||
875 | static int __devexit adav80x_spi_remove(struct spi_device *spi) | ||
876 | { | ||
877 | return adav80x_bus_remove(&spi->dev); | ||
878 | } | ||
879 | |||
880 | static struct spi_driver adav80x_spi_driver = { | ||
881 | .driver = { | ||
882 | .name = "adav801", | ||
883 | .owner = THIS_MODULE, | ||
884 | }, | ||
885 | .probe = adav80x_spi_probe, | ||
886 | .remove = __devexit_p(adav80x_spi_remove), | ||
887 | }; | ||
888 | #endif | ||
889 | |||
890 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
891 | static const struct i2c_device_id adav80x_id[] = { | ||
892 | { "adav803", 0 }, | ||
893 | { } | ||
894 | }; | ||
895 | MODULE_DEVICE_TABLE(i2c, adav80x_id); | ||
896 | |||
897 | static int __devinit adav80x_i2c_probe(struct i2c_client *client, | ||
898 | const struct i2c_device_id *id) | ||
899 | { | ||
900 | return adav80x_bus_probe(&client->dev, SND_SOC_I2C); | ||
901 | } | ||
902 | |||
903 | static int __devexit adav80x_i2c_remove(struct i2c_client *client) | ||
904 | { | ||
905 | return adav80x_bus_remove(&client->dev); | ||
906 | } | ||
907 | |||
908 | static struct i2c_driver adav80x_i2c_driver = { | ||
909 | .driver = { | ||
910 | .name = "adav803", | ||
911 | .owner = THIS_MODULE, | ||
912 | }, | ||
913 | .probe = adav80x_i2c_probe, | ||
914 | .remove = __devexit_p(adav80x_i2c_remove), | ||
915 | .id_table = adav80x_id, | ||
916 | }; | ||
917 | #endif | ||
918 | |||
919 | static int __init adav80x_init(void) | ||
920 | { | ||
921 | int ret = 0; | ||
922 | |||
923 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
924 | ret = i2c_add_driver(&adav80x_i2c_driver); | ||
925 | if (ret) | ||
926 | return ret; | ||
927 | #endif | ||
928 | |||
929 | #if defined(CONFIG_SPI_MASTER) | ||
930 | ret = spi_register_driver(&adav80x_spi_driver); | ||
931 | #endif | ||
932 | |||
933 | return ret; | ||
934 | } | ||
935 | module_init(adav80x_init); | ||
936 | |||
937 | static void __exit adav80x_exit(void) | ||
938 | { | ||
939 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
940 | i2c_del_driver(&adav80x_i2c_driver); | ||
941 | #endif | ||
942 | #if defined(CONFIG_SPI_MASTER) | ||
943 | spi_unregister_driver(&adav80x_spi_driver); | ||
944 | #endif | ||
945 | } | ||
946 | module_exit(adav80x_exit); | ||
947 | |||
948 | MODULE_DESCRIPTION("ASoC ADAV80x driver"); | ||
949 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
950 | MODULE_AUTHOR("Yi Li <yi.li@analog.com>>"); | ||
951 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/adav80x.h b/sound/soc/codecs/adav80x.h new file mode 100644 index 000000000000..adb0fc76d4e3 --- /dev/null +++ b/sound/soc/codecs/adav80x.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * header file for ADAV80X parts | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #ifndef _ADAV80X_H | ||
10 | #define _ADAV80X_H | ||
11 | |||
12 | enum adav80x_pll_src { | ||
13 | ADAV80X_PLL_SRC_XIN, | ||
14 | ADAV80X_PLL_SRC_XTAL, | ||
15 | ADAV80X_PLL_SRC_MCLKI, | ||
16 | }; | ||
17 | |||
18 | enum adav80x_pll { | ||
19 | ADAV80X_PLL1 = 0, | ||
20 | ADAV80X_PLL2 = 1, | ||
21 | }; | ||
22 | |||
23 | enum adav80x_clk_src { | ||
24 | ADAV80X_CLK_XIN = 0, | ||
25 | ADAV80X_CLK_MCLKI = 1, | ||
26 | ADAV80X_CLK_PLL1 = 2, | ||
27 | ADAV80X_CLK_PLL2 = 3, | ||
28 | ADAV80X_CLK_XTAL = 6, | ||
29 | |||
30 | ADAV80X_CLK_SYSCLK1 = 6, | ||
31 | ADAV80X_CLK_SYSCLK2 = 7, | ||
32 | ADAV80X_CLK_SYSCLK3 = 8, | ||
33 | }; | ||
34 | |||
35 | #endif | ||
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index ed96f247c2da..7a64e58cddc4 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c | |||
@@ -457,7 +457,7 @@ static struct snd_soc_dai_ops ak4641_pcm_dai_ops = { | |||
457 | .set_sysclk = ak4641_set_dai_sysclk, | 457 | .set_sysclk = ak4641_set_dai_sysclk, |
458 | }; | 458 | }; |
459 | 459 | ||
460 | struct snd_soc_dai_driver ak4641_dai[] = { | 460 | static struct snd_soc_dai_driver ak4641_dai[] = { |
461 | { | 461 | { |
462 | .name = "ak4641-hifi", | 462 | .name = "ak4641-hifi", |
463 | .id = 1, | 463 | .id = 1, |
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 0206a17d7283..6cc8678f49f3 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -636,10 +636,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec) | |||
636 | #endif /* CONFIG_PM */ | 636 | #endif /* CONFIG_PM */ |
637 | 637 | ||
638 | /* | 638 | /* |
639 | * ASoC codec device structure | 639 | * ASoC codec driver structure |
640 | * | ||
641 | * Assign this variable to the codec_dev field of the machine driver's | ||
642 | * snd_soc_device structure. | ||
643 | */ | 640 | */ |
644 | static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { | 641 | static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { |
645 | .probe = cs4270_probe, | 642 | .probe = cs4270_probe, |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 4173b67c94d1..ac65a2d36408 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -1397,8 +1397,6 @@ static int max98088_dai_set_sysclk(struct snd_soc_dai *dai, | |||
1397 | if (freq == max98088->sysclk) | 1397 | if (freq == max98088->sysclk) |
1398 | return 0; | 1398 | return 0; |
1399 | 1399 | ||
1400 | max98088->sysclk = freq; /* remember current sysclk */ | ||
1401 | |||
1402 | /* Setup clocks for slave mode, and using the PLL | 1400 | /* Setup clocks for slave mode, and using the PLL |
1403 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) | 1401 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) |
1404 | * 0x02 (when master clk is 20MHz to 30MHz).. | 1402 | * 0x02 (when master clk is 20MHz to 30MHz).. |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index e1d282d477da..668434d44303 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c | |||
@@ -1517,8 +1517,6 @@ static int max98095_dai_set_sysclk(struct snd_soc_dai *dai, | |||
1517 | if (freq == max98095->sysclk) | 1517 | if (freq == max98095->sysclk) |
1518 | return 0; | 1518 | return 0; |
1519 | 1519 | ||
1520 | max98095->sysclk = freq; /* remember current sysclk */ | ||
1521 | |||
1522 | /* Setup clocks for slave mode, and using the PLL | 1520 | /* Setup clocks for slave mode, and using the PLL |
1523 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) | 1521 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) |
1524 | * 0x02 (when master clk is 20MHz to 40MHz).. | 1522 | * 0x02 (when master clk is 20MHz to 40MHz).. |
@@ -2261,11 +2259,11 @@ static int max98095_probe(struct snd_soc_codec *codec) | |||
2261 | 2259 | ||
2262 | ret = snd_soc_read(codec, M98095_0FF_REV_ID); | 2260 | ret = snd_soc_read(codec, M98095_0FF_REV_ID); |
2263 | if (ret < 0) { | 2261 | if (ret < 0) { |
2264 | dev_err(codec->dev, "Failed to read device revision: %d\n", | 2262 | dev_err(codec->dev, "Failure reading hardware revision: %d\n", |
2265 | ret); | 2263 | ret); |
2266 | goto err_access; | 2264 | goto err_access; |
2267 | } | 2265 | } |
2268 | dev_info(codec->dev, "revision %c\n", ret + 'A'); | 2266 | dev_info(codec->dev, "Hardware revision: %c\n", ret - 0x40 + 'A'); |
2269 | 2267 | ||
2270 | snd_soc_write(codec, M98095_097_PWR_SYS, M98095_PWRSV); | 2268 | snd_soc_write(codec, M98095_097_PWR_SYS, M98095_PWRSV); |
2271 | 2269 | ||
@@ -2342,8 +2340,8 @@ static int max98095_i2c_probe(struct i2c_client *i2c, | |||
2342 | max98095->control_data = i2c; | 2340 | max98095->control_data = i2c; |
2343 | max98095->pdata = i2c->dev.platform_data; | 2341 | max98095->pdata = i2c->dev.platform_data; |
2344 | 2342 | ||
2345 | ret = snd_soc_register_codec(&i2c->dev, | 2343 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98095, |
2346 | &soc_codec_dev_max98095, &max98095_dai[0], 3); | 2344 | max98095_dai, ARRAY_SIZE(max98095_dai)); |
2347 | if (ret < 0) | 2345 | if (ret < 0) |
2348 | kfree(max98095); | 2346 | kfree(max98095); |
2349 | return ret; | 2347 | return ret; |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c new file mode 100644 index 000000000000..409d89d1f34c --- /dev/null +++ b/sound/soc/codecs/sta32x.c | |||
@@ -0,0 +1,917 @@ | |||
1 | /* | ||
2 | * Codec driver for ST STA32x 2.1-channel high-efficiency digital audio system | ||
3 | * | ||
4 | * Copyright: 2011 Raumfeld GmbH | ||
5 | * Author: Johannes Stezenbach <js@sig21.net> | ||
6 | * | ||
7 | * based on code from: | ||
8 | * Wolfson Microelectronics PLC. | ||
9 | * Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
10 | * Freescale Semiconductor, Inc. | ||
11 | * Timur Tabi <timur@freescale.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the | ||
15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
16 | * option) any later version. | ||
17 | */ | ||
18 | |||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s:%d: " fmt, __func__, __LINE__ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/pm.h> | ||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/regulator/consumer.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <sound/core.h> | ||
31 | #include <sound/pcm.h> | ||
32 | #include <sound/pcm_params.h> | ||
33 | #include <sound/soc.h> | ||
34 | #include <sound/soc-dapm.h> | ||
35 | #include <sound/initval.h> | ||
36 | #include <sound/tlv.h> | ||
37 | |||
38 | #include "sta32x.h" | ||
39 | |||
40 | #define STA32X_RATES (SNDRV_PCM_RATE_32000 | \ | ||
41 | SNDRV_PCM_RATE_44100 | \ | ||
42 | SNDRV_PCM_RATE_48000 | \ | ||
43 | SNDRV_PCM_RATE_88200 | \ | ||
44 | SNDRV_PCM_RATE_96000 | \ | ||
45 | SNDRV_PCM_RATE_176400 | \ | ||
46 | SNDRV_PCM_RATE_192000) | ||
47 | |||
48 | #define STA32X_FORMATS \ | ||
49 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ | ||
50 | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ | ||
51 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ | ||
52 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \ | ||
53 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \ | ||
54 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) | ||
55 | |||
56 | /* Power-up register defaults */ | ||
57 | static const u8 sta32x_regs[STA32X_REGISTER_COUNT] = { | ||
58 | 0x63, 0x80, 0xc2, 0x40, 0xc2, 0x5c, 0x10, 0xff, 0x60, 0x60, | ||
59 | 0x60, 0x80, 0x00, 0x00, 0x00, 0x40, 0x80, 0x77, 0x6a, 0x69, | ||
60 | 0x6a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, | ||
62 | 0xc0, 0xf3, 0x33, 0x00, 0x0c, | ||
63 | }; | ||
64 | |||
65 | /* regulator power supply names */ | ||
66 | static const char *sta32x_supply_names[] = { | ||
67 | "Vdda", /* analog supply, 3.3VV */ | ||
68 | "Vdd3", /* digital supply, 3.3V */ | ||
69 | "Vcc" /* power amp spply, 10V - 36V */ | ||
70 | }; | ||
71 | |||
72 | /* codec private data */ | ||
73 | struct sta32x_priv { | ||
74 | struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)]; | ||
75 | struct snd_soc_codec *codec; | ||
76 | |||
77 | unsigned int mclk; | ||
78 | unsigned int format; | ||
79 | }; | ||
80 | |||
81 | static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1); | ||
82 | static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1); | ||
83 | static const DECLARE_TLV_DB_SCALE(tone_tlv, -120, 200, 0); | ||
84 | |||
85 | static const char *sta32x_drc_ac[] = { | ||
86 | "Anti-Clipping", "Dynamic Range Compression" }; | ||
87 | static const char *sta32x_auto_eq_mode[] = { | ||
88 | "User", "Preset", "Loudness" }; | ||
89 | static const char *sta32x_auto_gc_mode[] = { | ||
90 | "User", "AC no clipping", "AC limited clipping (10%)", | ||
91 | "DRC nighttime listening mode" }; | ||
92 | static const char *sta32x_auto_xo_mode[] = { | ||
93 | "User", "80Hz", "100Hz", "120Hz", "140Hz", "160Hz", "180Hz", "200Hz", | ||
94 | "220Hz", "240Hz", "260Hz", "280Hz", "300Hz", "320Hz", "340Hz", "360Hz" }; | ||
95 | static const char *sta32x_preset_eq_mode[] = { | ||
96 | "Flat", "Rock", "Soft Rock", "Jazz", "Classical", "Dance", "Pop", "Soft", | ||
97 | "Hard", "Party", "Vocal", "Hip-Hop", "Dialog", "Bass-boost #1", | ||
98 | "Bass-boost #2", "Bass-boost #3", "Loudness 1", "Loudness 2", | ||
99 | "Loudness 3", "Loudness 4", "Loudness 5", "Loudness 6", "Loudness 7", | ||
100 | "Loudness 8", "Loudness 9", "Loudness 10", "Loudness 11", "Loudness 12", | ||
101 | "Loudness 13", "Loudness 14", "Loudness 15", "Loudness 16" }; | ||
102 | static const char *sta32x_limiter_select[] = { | ||
103 | "Limiter Disabled", "Limiter #1", "Limiter #2" }; | ||
104 | static const char *sta32x_limiter_attack_rate[] = { | ||
105 | "3.1584", "2.7072", "2.2560", "1.8048", "1.3536", "0.9024", | ||
106 | "0.4512", "0.2256", "0.1504", "0.1123", "0.0902", "0.0752", | ||
107 | "0.0645", "0.0564", "0.0501", "0.0451" }; | ||
108 | static const char *sta32x_limiter_release_rate[] = { | ||
109 | "0.5116", "0.1370", "0.0744", "0.0499", "0.0360", "0.0299", | ||
110 | "0.0264", "0.0208", "0.0198", "0.0172", "0.0147", "0.0137", | ||
111 | "0.0134", "0.0117", "0.0110", "0.0104" }; | ||
112 | |||
113 | static const unsigned int sta32x_limiter_ac_attack_tlv[] = { | ||
114 | TLV_DB_RANGE_HEAD(2), | ||
115 | 0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0), | ||
116 | 8, 16, TLV_DB_SCALE_ITEM(300, 100, 0), | ||
117 | }; | ||
118 | |||
119 | static const unsigned int sta32x_limiter_ac_release_tlv[] = { | ||
120 | TLV_DB_RANGE_HEAD(5), | ||
121 | 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), | ||
122 | 1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0), | ||
123 | 2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0), | ||
124 | 3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0), | ||
125 | 8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0), | ||
126 | }; | ||
127 | |||
128 | static const unsigned int sta32x_limiter_drc_attack_tlv[] = { | ||
129 | TLV_DB_RANGE_HEAD(3), | ||
130 | 0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0), | ||
131 | 8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0), | ||
132 | 14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0), | ||
133 | }; | ||
134 | |||
135 | static const unsigned int sta32x_limiter_drc_release_tlv[] = { | ||
136 | TLV_DB_RANGE_HEAD(5), | ||
137 | 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), | ||
138 | 1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0), | ||
139 | 3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0), | ||
140 | 5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0), | ||
141 | 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0), | ||
142 | }; | ||
143 | |||
144 | static const struct soc_enum sta32x_drc_ac_enum = | ||
145 | SOC_ENUM_SINGLE(STA32X_CONFD, STA32X_CONFD_DRC_SHIFT, | ||
146 | 2, sta32x_drc_ac); | ||
147 | static const struct soc_enum sta32x_auto_eq_enum = | ||
148 | SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT, | ||
149 | 3, sta32x_auto_eq_mode); | ||
150 | static const struct soc_enum sta32x_auto_gc_enum = | ||
151 | SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT, | ||
152 | 4, sta32x_auto_gc_mode); | ||
153 | static const struct soc_enum sta32x_auto_xo_enum = | ||
154 | SOC_ENUM_SINGLE(STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT, | ||
155 | 16, sta32x_auto_xo_mode); | ||
156 | static const struct soc_enum sta32x_preset_eq_enum = | ||
157 | SOC_ENUM_SINGLE(STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT, | ||
158 | 32, sta32x_preset_eq_mode); | ||
159 | static const struct soc_enum sta32x_limiter_ch1_enum = | ||
160 | SOC_ENUM_SINGLE(STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT, | ||
161 | 3, sta32x_limiter_select); | ||
162 | static const struct soc_enum sta32x_limiter_ch2_enum = | ||
163 | SOC_ENUM_SINGLE(STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT, | ||
164 | 3, sta32x_limiter_select); | ||
165 | static const struct soc_enum sta32x_limiter_ch3_enum = | ||
166 | SOC_ENUM_SINGLE(STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT, | ||
167 | 3, sta32x_limiter_select); | ||
168 | static const struct soc_enum sta32x_limiter1_attack_rate_enum = | ||
169 | SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxA_SHIFT, | ||
170 | 16, sta32x_limiter_attack_rate); | ||
171 | static const struct soc_enum sta32x_limiter2_attack_rate_enum = | ||
172 | SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxA_SHIFT, | ||
173 | 16, sta32x_limiter_attack_rate); | ||
174 | static const struct soc_enum sta32x_limiter1_release_rate_enum = | ||
175 | SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxR_SHIFT, | ||
176 | 16, sta32x_limiter_release_rate); | ||
177 | static const struct soc_enum sta32x_limiter2_release_rate_enum = | ||
178 | SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxR_SHIFT, | ||
179 | 16, sta32x_limiter_release_rate); | ||
180 | |||
181 | /* byte array controls for setting biquad, mixer, scaling coefficients; | ||
182 | * for biquads all five coefficients need to be set in one go, | ||
183 | * mixer and pre/postscale coefs can be set individually; | ||
184 | * each coef is 24bit, the bytes are ordered in the same way | ||
185 | * as given in the STA32x data sheet (big endian; b1, b2, a1, a2, b0) | ||
186 | */ | ||
187 | |||
188 | static int sta32x_coefficient_info(struct snd_kcontrol *kcontrol, | ||
189 | struct snd_ctl_elem_info *uinfo) | ||
190 | { | ||
191 | int numcoef = kcontrol->private_value >> 16; | ||
192 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
193 | uinfo->count = 3 * numcoef; | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static int sta32x_coefficient_get(struct snd_kcontrol *kcontrol, | ||
198 | struct snd_ctl_elem_value *ucontrol) | ||
199 | { | ||
200 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
201 | int numcoef = kcontrol->private_value >> 16; | ||
202 | int index = kcontrol->private_value & 0xffff; | ||
203 | unsigned int cfud; | ||
204 | int i; | ||
205 | |||
206 | /* preserve reserved bits in STA32X_CFUD */ | ||
207 | cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0; | ||
208 | /* chip documentation does not say if the bits are self clearing, | ||
209 | * so do it explicitly */ | ||
210 | snd_soc_write(codec, STA32X_CFUD, cfud); | ||
211 | |||
212 | snd_soc_write(codec, STA32X_CFADDR2, index); | ||
213 | if (numcoef == 1) | ||
214 | snd_soc_write(codec, STA32X_CFUD, cfud | 0x04); | ||
215 | else if (numcoef == 5) | ||
216 | snd_soc_write(codec, STA32X_CFUD, cfud | 0x08); | ||
217 | else | ||
218 | return -EINVAL; | ||
219 | for (i = 0; i < 3 * numcoef; i++) | ||
220 | ucontrol->value.bytes.data[i] = | ||
221 | snd_soc_read(codec, STA32X_B1CF1 + i); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol, | ||
227 | struct snd_ctl_elem_value *ucontrol) | ||
228 | { | ||
229 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
230 | int numcoef = kcontrol->private_value >> 16; | ||
231 | int index = kcontrol->private_value & 0xffff; | ||
232 | unsigned int cfud; | ||
233 | int i; | ||
234 | |||
235 | /* preserve reserved bits in STA32X_CFUD */ | ||
236 | cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0; | ||
237 | /* chip documentation does not say if the bits are self clearing, | ||
238 | * so do it explicitly */ | ||
239 | snd_soc_write(codec, STA32X_CFUD, cfud); | ||
240 | |||
241 | snd_soc_write(codec, STA32X_CFADDR2, index); | ||
242 | for (i = 0; i < 3 * numcoef; i++) | ||
243 | snd_soc_write(codec, STA32X_B1CF1 + i, | ||
244 | ucontrol->value.bytes.data[i]); | ||
245 | if (numcoef == 1) | ||
246 | snd_soc_write(codec, STA32X_CFUD, cfud | 0x01); | ||
247 | else if (numcoef == 5) | ||
248 | snd_soc_write(codec, STA32X_CFUD, cfud | 0x02); | ||
249 | else | ||
250 | return -EINVAL; | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | #define SINGLE_COEF(xname, index) \ | ||
256 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
257 | .info = sta32x_coefficient_info, \ | ||
258 | .get = sta32x_coefficient_get,\ | ||
259 | .put = sta32x_coefficient_put, \ | ||
260 | .private_value = index | (1 << 16) } | ||
261 | |||
262 | #define BIQUAD_COEFS(xname, index) \ | ||
263 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
264 | .info = sta32x_coefficient_info, \ | ||
265 | .get = sta32x_coefficient_get,\ | ||
266 | .put = sta32x_coefficient_put, \ | ||
267 | .private_value = index | (5 << 16) } | ||
268 | |||
269 | static const struct snd_kcontrol_new sta32x_snd_controls[] = { | ||
270 | SOC_SINGLE_TLV("Master Volume", STA32X_MVOL, 0, 0xff, 1, mvol_tlv), | ||
271 | SOC_SINGLE("Master Switch", STA32X_MMUTE, 0, 1, 1), | ||
272 | SOC_SINGLE("Ch1 Switch", STA32X_MMUTE, 1, 1, 1), | ||
273 | SOC_SINGLE("Ch2 Switch", STA32X_MMUTE, 2, 1, 1), | ||
274 | SOC_SINGLE("Ch3 Switch", STA32X_MMUTE, 3, 1, 1), | ||
275 | SOC_SINGLE_TLV("Ch1 Volume", STA32X_C1VOL, 0, 0xff, 1, chvol_tlv), | ||
276 | SOC_SINGLE_TLV("Ch2 Volume", STA32X_C2VOL, 0, 0xff, 1, chvol_tlv), | ||
277 | SOC_SINGLE_TLV("Ch3 Volume", STA32X_C3VOL, 0, 0xff, 1, chvol_tlv), | ||
278 | SOC_SINGLE("De-emphasis Filter Switch", STA32X_CONFD, STA32X_CONFD_DEMP_SHIFT, 1, 0), | ||
279 | SOC_ENUM("Compressor/Limiter Switch", sta32x_drc_ac_enum), | ||
280 | SOC_SINGLE("Miami Mode Switch", STA32X_CONFD, STA32X_CONFD_MME_SHIFT, 1, 0), | ||
281 | SOC_SINGLE("Zero Cross Switch", STA32X_CONFE, STA32X_CONFE_ZCE_SHIFT, 1, 0), | ||
282 | SOC_SINGLE("Soft Ramp Switch", STA32X_CONFE, STA32X_CONFE_SVE_SHIFT, 1, 0), | ||
283 | SOC_SINGLE("Auto-Mute Switch", STA32X_CONFF, STA32X_CONFF_IDE_SHIFT, 1, 0), | ||
284 | SOC_ENUM("Automode EQ", sta32x_auto_eq_enum), | ||
285 | SOC_ENUM("Automode GC", sta32x_auto_gc_enum), | ||
286 | SOC_ENUM("Automode XO", sta32x_auto_xo_enum), | ||
287 | SOC_ENUM("Preset EQ", sta32x_preset_eq_enum), | ||
288 | SOC_SINGLE("Ch1 Tone Control Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0), | ||
289 | SOC_SINGLE("Ch2 Tone Control Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0), | ||
290 | SOC_SINGLE("Ch1 EQ Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0), | ||
291 | SOC_SINGLE("Ch2 EQ Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0), | ||
292 | SOC_SINGLE("Ch1 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0), | ||
293 | SOC_SINGLE("Ch2 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0), | ||
294 | SOC_SINGLE("Ch3 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0), | ||
295 | SOC_ENUM("Ch1 Limiter Select", sta32x_limiter_ch1_enum), | ||
296 | SOC_ENUM("Ch2 Limiter Select", sta32x_limiter_ch2_enum), | ||
297 | SOC_ENUM("Ch3 Limiter Select", sta32x_limiter_ch3_enum), | ||
298 | SOC_SINGLE_TLV("Bass Tone Control", STA32X_TONE, STA32X_TONE_BTC_SHIFT, 15, 0, tone_tlv), | ||
299 | SOC_SINGLE_TLV("Treble Tone Control", STA32X_TONE, STA32X_TONE_TTC_SHIFT, 15, 0, tone_tlv), | ||
300 | SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum), | ||
301 | SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum), | ||
302 | SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum), | ||
303 | SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum), | ||
304 | |||
305 | /* depending on mode, the attack/release thresholds have | ||
306 | * two different enum definitions; provide both | ||
307 | */ | ||
308 | SOC_SINGLE_TLV("Limiter1 Attack Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT, | ||
309 | 16, 0, sta32x_limiter_ac_attack_tlv), | ||
310 | SOC_SINGLE_TLV("Limiter2 Attack Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT, | ||
311 | 16, 0, sta32x_limiter_ac_attack_tlv), | ||
312 | SOC_SINGLE_TLV("Limiter1 Release Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT, | ||
313 | 16, 0, sta32x_limiter_ac_release_tlv), | ||
314 | SOC_SINGLE_TLV("Limiter2 Release Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT, | ||
315 | 16, 0, sta32x_limiter_ac_release_tlv), | ||
316 | SOC_SINGLE_TLV("Limiter1 Attack Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT, | ||
317 | 16, 0, sta32x_limiter_drc_attack_tlv), | ||
318 | SOC_SINGLE_TLV("Limiter2 Attack Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT, | ||
319 | 16, 0, sta32x_limiter_drc_attack_tlv), | ||
320 | SOC_SINGLE_TLV("Limiter1 Release Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT, | ||
321 | 16, 0, sta32x_limiter_drc_release_tlv), | ||
322 | SOC_SINGLE_TLV("Limiter2 Release Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT, | ||
323 | 16, 0, sta32x_limiter_drc_release_tlv), | ||
324 | |||
325 | BIQUAD_COEFS("Ch1 - Biquad 1", 0), | ||
326 | BIQUAD_COEFS("Ch1 - Biquad 2", 5), | ||
327 | BIQUAD_COEFS("Ch1 - Biquad 3", 10), | ||
328 | BIQUAD_COEFS("Ch1 - Biquad 4", 15), | ||
329 | BIQUAD_COEFS("Ch2 - Biquad 1", 20), | ||
330 | BIQUAD_COEFS("Ch2 - Biquad 2", 25), | ||
331 | BIQUAD_COEFS("Ch2 - Biquad 3", 30), | ||
332 | BIQUAD_COEFS("Ch2 - Biquad 4", 35), | ||
333 | BIQUAD_COEFS("High-pass", 40), | ||
334 | BIQUAD_COEFS("Low-pass", 45), | ||
335 | SINGLE_COEF("Ch1 - Prescale", 50), | ||
336 | SINGLE_COEF("Ch2 - Prescale", 51), | ||
337 | SINGLE_COEF("Ch1 - Postscale", 52), | ||
338 | SINGLE_COEF("Ch2 - Postscale", 53), | ||
339 | SINGLE_COEF("Ch3 - Postscale", 54), | ||
340 | SINGLE_COEF("Thermal warning - Postscale", 55), | ||
341 | SINGLE_COEF("Ch1 - Mix 1", 56), | ||
342 | SINGLE_COEF("Ch1 - Mix 2", 57), | ||
343 | SINGLE_COEF("Ch2 - Mix 1", 58), | ||
344 | SINGLE_COEF("Ch2 - Mix 2", 59), | ||
345 | SINGLE_COEF("Ch3 - Mix 1", 60), | ||
346 | SINGLE_COEF("Ch3 - Mix 2", 61), | ||
347 | }; | ||
348 | |||
349 | static const struct snd_soc_dapm_widget sta32x_dapm_widgets[] = { | ||
350 | SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), | ||
351 | SND_SOC_DAPM_OUTPUT("LEFT"), | ||
352 | SND_SOC_DAPM_OUTPUT("RIGHT"), | ||
353 | SND_SOC_DAPM_OUTPUT("SUB"), | ||
354 | }; | ||
355 | |||
356 | static const struct snd_soc_dapm_route sta32x_dapm_routes[] = { | ||
357 | { "LEFT", NULL, "DAC" }, | ||
358 | { "RIGHT", NULL, "DAC" }, | ||
359 | { "SUB", NULL, "DAC" }, | ||
360 | }; | ||
361 | |||
362 | /* MCLK interpolation ratio per fs */ | ||
363 | static struct { | ||
364 | int fs; | ||
365 | int ir; | ||
366 | } interpolation_ratios[] = { | ||
367 | { 32000, 0 }, | ||
368 | { 44100, 0 }, | ||
369 | { 48000, 0 }, | ||
370 | { 88200, 1 }, | ||
371 | { 96000, 1 }, | ||
372 | { 176400, 2 }, | ||
373 | { 192000, 2 }, | ||
374 | }; | ||
375 | |||
376 | /* MCLK to fs clock ratios */ | ||
377 | static struct { | ||
378 | int ratio; | ||
379 | int mcs; | ||
380 | } mclk_ratios[3][7] = { | ||
381 | { { 768, 0 }, { 512, 1 }, { 384, 2 }, { 256, 3 }, | ||
382 | { 128, 4 }, { 576, 5 }, { 0, 0 } }, | ||
383 | { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } }, | ||
384 | { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } }, | ||
385 | }; | ||
386 | |||
387 | |||
388 | /** | ||
389 | * sta32x_set_dai_sysclk - configure MCLK | ||
390 | * @codec_dai: the codec DAI | ||
391 | * @clk_id: the clock ID (ignored) | ||
392 | * @freq: the MCLK input frequency | ||
393 | * @dir: the clock direction (ignored) | ||
394 | * | ||
395 | * The value of MCLK is used to determine which sample rates are supported | ||
396 | * by the STA32X, based on the mclk_ratios table. | ||
397 | * | ||
398 | * This function must be called by the machine driver's 'startup' function, | ||
399 | * otherwise the list of supported sample rates will not be available in | ||
400 | * time for ALSA. | ||
401 | * | ||
402 | * For setups with variable MCLKs, pass 0 as 'freq' argument. This will cause | ||
403 | * theoretically possible sample rates to be enabled. Call it again with a | ||
404 | * proper value set one the external clock is set (most probably you would do | ||
405 | * that from a machine's driver 'hw_param' hook. | ||
406 | */ | ||
407 | static int sta32x_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
408 | int clk_id, unsigned int freq, int dir) | ||
409 | { | ||
410 | struct snd_soc_codec *codec = codec_dai->codec; | ||
411 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | ||
412 | int i, j, ir, fs; | ||
413 | unsigned int rates = 0; | ||
414 | unsigned int rate_min = -1; | ||
415 | unsigned int rate_max = 0; | ||
416 | |||
417 | pr_debug("mclk=%u\n", freq); | ||
418 | sta32x->mclk = freq; | ||
419 | |||
420 | if (sta32x->mclk) { | ||
421 | for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) { | ||
422 | ir = interpolation_ratios[i].ir; | ||
423 | fs = interpolation_ratios[i].fs; | ||
424 | for (j = 0; mclk_ratios[ir][j].ratio; j++) { | ||
425 | if (mclk_ratios[ir][j].ratio * fs == freq) { | ||
426 | rates |= snd_pcm_rate_to_rate_bit(fs); | ||
427 | if (fs < rate_min) | ||
428 | rate_min = fs; | ||
429 | if (fs > rate_max) | ||
430 | rate_max = fs; | ||
431 | } | ||
432 | } | ||
433 | } | ||
434 | /* FIXME: soc should support a rate list */ | ||
435 | rates &= ~SNDRV_PCM_RATE_KNOT; | ||
436 | |||
437 | if (!rates) { | ||
438 | dev_err(codec->dev, "could not find a valid sample rate\n"); | ||
439 | return -EINVAL; | ||
440 | } | ||
441 | } else { | ||
442 | /* enable all possible rates */ | ||
443 | rates = STA32X_RATES; | ||
444 | rate_min = 32000; | ||
445 | rate_max = 192000; | ||
446 | } | ||
447 | |||
448 | codec_dai->driver->playback.rates = rates; | ||
449 | codec_dai->driver->playback.rate_min = rate_min; | ||
450 | codec_dai->driver->playback.rate_max = rate_max; | ||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | /** | ||
455 | * sta32x_set_dai_fmt - configure the codec for the selected audio format | ||
456 | * @codec_dai: the codec DAI | ||
457 | * @fmt: a SND_SOC_DAIFMT_x value indicating the data format | ||
458 | * | ||
459 | * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the | ||
460 | * codec accordingly. | ||
461 | */ | ||
462 | static int sta32x_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
463 | unsigned int fmt) | ||
464 | { | ||
465 | struct snd_soc_codec *codec = codec_dai->codec; | ||
466 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | ||
467 | u8 confb = snd_soc_read(codec, STA32X_CONFB); | ||
468 | |||
469 | pr_debug("\n"); | ||
470 | confb &= ~(STA32X_CONFB_C1IM | STA32X_CONFB_C2IM); | ||
471 | |||
472 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
473 | case SND_SOC_DAIFMT_CBS_CFS: | ||
474 | break; | ||
475 | default: | ||
476 | return -EINVAL; | ||
477 | } | ||
478 | |||
479 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
480 | case SND_SOC_DAIFMT_I2S: | ||
481 | case SND_SOC_DAIFMT_RIGHT_J: | ||
482 | case SND_SOC_DAIFMT_LEFT_J: | ||
483 | sta32x->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | ||
484 | break; | ||
485 | default: | ||
486 | return -EINVAL; | ||
487 | } | ||
488 | |||
489 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
490 | case SND_SOC_DAIFMT_NB_NF: | ||
491 | confb |= STA32X_CONFB_C2IM; | ||
492 | break; | ||
493 | case SND_SOC_DAIFMT_NB_IF: | ||
494 | confb |= STA32X_CONFB_C1IM; | ||
495 | break; | ||
496 | default: | ||
497 | return -EINVAL; | ||
498 | } | ||
499 | |||
500 | snd_soc_write(codec, STA32X_CONFB, confb); | ||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | /** | ||
505 | * sta32x_hw_params - program the STA32X with the given hardware parameters. | ||
506 | * @substream: the audio stream | ||
507 | * @params: the hardware parameters to set | ||
508 | * @dai: the SOC DAI (ignored) | ||
509 | * | ||
510 | * This function programs the hardware with the values provided. | ||
511 | * Specifically, the sample rate and the data format. | ||
512 | */ | ||
513 | static int sta32x_hw_params(struct snd_pcm_substream *substream, | ||
514 | struct snd_pcm_hw_params *params, | ||
515 | struct snd_soc_dai *dai) | ||
516 | { | ||
517 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
518 | struct snd_soc_codec *codec = rtd->codec; | ||
519 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | ||
520 | unsigned int rate; | ||
521 | int i, mcs = -1, ir = -1; | ||
522 | u8 confa, confb; | ||
523 | |||
524 | rate = params_rate(params); | ||
525 | pr_debug("rate: %u\n", rate); | ||
526 | for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) | ||
527 | if (interpolation_ratios[i].fs == rate) | ||
528 | ir = interpolation_ratios[i].ir; | ||
529 | if (ir < 0) | ||
530 | return -EINVAL; | ||
531 | for (i = 0; mclk_ratios[ir][i].ratio; i++) | ||
532 | if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) | ||
533 | mcs = mclk_ratios[ir][i].mcs; | ||
534 | if (mcs < 0) | ||
535 | return -EINVAL; | ||
536 | |||
537 | confa = snd_soc_read(codec, STA32X_CONFA); | ||
538 | confa &= ~(STA32X_CONFA_MCS_MASK | STA32X_CONFA_IR_MASK); | ||
539 | confa |= (ir << STA32X_CONFA_IR_SHIFT) | (mcs << STA32X_CONFA_MCS_SHIFT); | ||
540 | |||
541 | confb = snd_soc_read(codec, STA32X_CONFB); | ||
542 | confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB); | ||
543 | switch (params_format(params)) { | ||
544 | case SNDRV_PCM_FORMAT_S24_LE: | ||
545 | case SNDRV_PCM_FORMAT_S24_BE: | ||
546 | case SNDRV_PCM_FORMAT_S24_3LE: | ||
547 | case SNDRV_PCM_FORMAT_S24_3BE: | ||
548 | pr_debug("24bit\n"); | ||
549 | /* fall through */ | ||
550 | case SNDRV_PCM_FORMAT_S32_LE: | ||
551 | case SNDRV_PCM_FORMAT_S32_BE: | ||
552 | pr_debug("24bit or 32bit\n"); | ||
553 | switch (sta32x->format) { | ||
554 | case SND_SOC_DAIFMT_I2S: | ||
555 | confb |= 0x0; | ||
556 | break; | ||
557 | case SND_SOC_DAIFMT_LEFT_J: | ||
558 | confb |= 0x1; | ||
559 | break; | ||
560 | case SND_SOC_DAIFMT_RIGHT_J: | ||
561 | confb |= 0x2; | ||
562 | break; | ||
563 | } | ||
564 | |||
565 | break; | ||
566 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
567 | case SNDRV_PCM_FORMAT_S20_3BE: | ||
568 | pr_debug("20bit\n"); | ||
569 | switch (sta32x->format) { | ||
570 | case SND_SOC_DAIFMT_I2S: | ||
571 | confb |= 0x4; | ||
572 | break; | ||
573 | case SND_SOC_DAIFMT_LEFT_J: | ||
574 | confb |= 0x5; | ||
575 | break; | ||
576 | case SND_SOC_DAIFMT_RIGHT_J: | ||
577 | confb |= 0x6; | ||
578 | break; | ||
579 | } | ||
580 | |||
581 | break; | ||
582 | case SNDRV_PCM_FORMAT_S18_3LE: | ||
583 | case SNDRV_PCM_FORMAT_S18_3BE: | ||
584 | pr_debug("18bit\n"); | ||
585 | switch (sta32x->format) { | ||
586 | case SND_SOC_DAIFMT_I2S: | ||
587 | confb |= 0x8; | ||
588 | break; | ||
589 | case SND_SOC_DAIFMT_LEFT_J: | ||
590 | confb |= 0x9; | ||
591 | break; | ||
592 | case SND_SOC_DAIFMT_RIGHT_J: | ||
593 | confb |= 0xa; | ||
594 | break; | ||
595 | } | ||
596 | |||
597 | break; | ||
598 | case SNDRV_PCM_FORMAT_S16_LE: | ||
599 | case SNDRV_PCM_FORMAT_S16_BE: | ||
600 | pr_debug("16bit\n"); | ||
601 | switch (sta32x->format) { | ||
602 | case SND_SOC_DAIFMT_I2S: | ||
603 | confb |= 0x0; | ||
604 | break; | ||
605 | case SND_SOC_DAIFMT_LEFT_J: | ||
606 | confb |= 0xd; | ||
607 | break; | ||
608 | case SND_SOC_DAIFMT_RIGHT_J: | ||
609 | confb |= 0xe; | ||
610 | break; | ||
611 | } | ||
612 | |||
613 | break; | ||
614 | default: | ||
615 | return -EINVAL; | ||
616 | } | ||
617 | |||
618 | snd_soc_write(codec, STA32X_CONFA, confa); | ||
619 | snd_soc_write(codec, STA32X_CONFB, confb); | ||
620 | return 0; | ||
621 | } | ||
622 | |||
623 | /** | ||
624 | * sta32x_set_bias_level - DAPM callback | ||
625 | * @codec: the codec device | ||
626 | * @level: DAPM power level | ||
627 | * | ||
628 | * This is called by ALSA to put the codec into low power mode | ||
629 | * or to wake it up. If the codec is powered off completely | ||
630 | * all registers must be restored after power on. | ||
631 | */ | ||
632 | static int sta32x_set_bias_level(struct snd_soc_codec *codec, | ||
633 | enum snd_soc_bias_level level) | ||
634 | { | ||
635 | int ret; | ||
636 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | ||
637 | |||
638 | pr_debug("level = %d\n", level); | ||
639 | switch (level) { | ||
640 | case SND_SOC_BIAS_ON: | ||
641 | break; | ||
642 | |||
643 | case SND_SOC_BIAS_PREPARE: | ||
644 | /* Full power on */ | ||
645 | snd_soc_update_bits(codec, STA32X_CONFF, | ||
646 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, | ||
647 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD); | ||
648 | break; | ||
649 | |||
650 | case SND_SOC_BIAS_STANDBY: | ||
651 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
652 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), | ||
653 | sta32x->supplies); | ||
654 | if (ret != 0) { | ||
655 | dev_err(codec->dev, | ||
656 | "Failed to enable supplies: %d\n", ret); | ||
657 | return ret; | ||
658 | } | ||
659 | |||
660 | snd_soc_cache_sync(codec); | ||
661 | } | ||
662 | |||
663 | /* Power up to mute */ | ||
664 | /* FIXME */ | ||
665 | snd_soc_update_bits(codec, STA32X_CONFF, | ||
666 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, | ||
667 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD); | ||
668 | |||
669 | break; | ||
670 | |||
671 | case SND_SOC_BIAS_OFF: | ||
672 | /* The chip runs through the power down sequence for us. */ | ||
673 | snd_soc_update_bits(codec, STA32X_CONFF, | ||
674 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, | ||
675 | STA32X_CONFF_PWDN); | ||
676 | msleep(300); | ||
677 | |||
678 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), | ||
679 | sta32x->supplies); | ||
680 | break; | ||
681 | } | ||
682 | codec->dapm.bias_level = level; | ||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | static struct snd_soc_dai_ops sta32x_dai_ops = { | ||
687 | .hw_params = sta32x_hw_params, | ||
688 | .set_sysclk = sta32x_set_dai_sysclk, | ||
689 | .set_fmt = sta32x_set_dai_fmt, | ||
690 | }; | ||
691 | |||
692 | static struct snd_soc_dai_driver sta32x_dai = { | ||
693 | .name = "STA32X", | ||
694 | .playback = { | ||
695 | .stream_name = "Playback", | ||
696 | .channels_min = 2, | ||
697 | .channels_max = 2, | ||
698 | .rates = STA32X_RATES, | ||
699 | .formats = STA32X_FORMATS, | ||
700 | }, | ||
701 | .ops = &sta32x_dai_ops, | ||
702 | }; | ||
703 | |||
704 | #ifdef CONFIG_PM | ||
705 | static int sta32x_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
706 | { | ||
707 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | static int sta32x_resume(struct snd_soc_codec *codec) | ||
712 | { | ||
713 | sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
714 | return 0; | ||
715 | } | ||
716 | #else | ||
717 | #define sta32x_suspend NULL | ||
718 | #define sta32x_resume NULL | ||
719 | #endif | ||
720 | |||
721 | static int sta32x_probe(struct snd_soc_codec *codec) | ||
722 | { | ||
723 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | ||
724 | int i, ret = 0; | ||
725 | |||
726 | sta32x->codec = codec; | ||
727 | |||
728 | /* regulators */ | ||
729 | for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) | ||
730 | sta32x->supplies[i].supply = sta32x_supply_names[i]; | ||
731 | |||
732 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sta32x->supplies), | ||
733 | sta32x->supplies); | ||
734 | if (ret != 0) { | ||
735 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
736 | goto err; | ||
737 | } | ||
738 | |||
739 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), | ||
740 | sta32x->supplies); | ||
741 | if (ret != 0) { | ||
742 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
743 | goto err_get; | ||
744 | } | ||
745 | |||
746 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will | ||
747 | * then do the I2C transactions itself. | ||
748 | */ | ||
749 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | ||
750 | if (ret < 0) { | ||
751 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); | ||
752 | return ret; | ||
753 | } | ||
754 | |||
755 | /* read reg reset values into cache */ | ||
756 | for (i = 0; i < STA32X_REGISTER_COUNT; i++) | ||
757 | snd_soc_cache_write(codec, i, sta32x_regs[i]); | ||
758 | |||
759 | /* preserve reset values of reserved register bits */ | ||
760 | snd_soc_cache_write(codec, STA32X_CONFC, | ||
761 | codec->hw_read(codec, STA32X_CONFC)); | ||
762 | snd_soc_cache_write(codec, STA32X_CONFE, | ||
763 | codec->hw_read(codec, STA32X_CONFE)); | ||
764 | snd_soc_cache_write(codec, STA32X_CONFF, | ||
765 | codec->hw_read(codec, STA32X_CONFF)); | ||
766 | snd_soc_cache_write(codec, STA32X_MMUTE, | ||
767 | codec->hw_read(codec, STA32X_MMUTE)); | ||
768 | snd_soc_cache_write(codec, STA32X_AUTO1, | ||
769 | codec->hw_read(codec, STA32X_AUTO1)); | ||
770 | snd_soc_cache_write(codec, STA32X_AUTO3, | ||
771 | codec->hw_read(codec, STA32X_AUTO3)); | ||
772 | snd_soc_cache_write(codec, STA32X_C3CFG, | ||
773 | codec->hw_read(codec, STA32X_C3CFG)); | ||
774 | |||
775 | /* FIXME enable thermal warning adjustment and recovery */ | ||
776 | snd_soc_update_bits(codec, STA32X_CONFA, | ||
777 | STA32X_CONFA_TWAB | STA32X_CONFA_TWRB, 0); | ||
778 | |||
779 | /* FIXME select 2.1 mode */ | ||
780 | snd_soc_update_bits(codec, STA32X_CONFF, | ||
781 | STA32X_CONFF_OCFG_MASK, | ||
782 | 1 << STA32X_CONFF_OCFG_SHIFT); | ||
783 | |||
784 | /* FIXME channel to output mapping */ | ||
785 | snd_soc_update_bits(codec, STA32X_C1CFG, | ||
786 | STA32X_CxCFG_OM_MASK, | ||
787 | 0 << STA32X_CxCFG_OM_SHIFT); | ||
788 | snd_soc_update_bits(codec, STA32X_C2CFG, | ||
789 | STA32X_CxCFG_OM_MASK, | ||
790 | 1 << STA32X_CxCFG_OM_SHIFT); | ||
791 | snd_soc_update_bits(codec, STA32X_C3CFG, | ||
792 | STA32X_CxCFG_OM_MASK, | ||
793 | 2 << STA32X_CxCFG_OM_SHIFT); | ||
794 | |||
795 | sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
796 | /* Bias level configuration will have done an extra enable */ | ||
797 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
798 | |||
799 | return 0; | ||
800 | |||
801 | err_get: | ||
802 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
803 | err: | ||
804 | return ret; | ||
805 | } | ||
806 | |||
807 | static int sta32x_remove(struct snd_soc_codec *codec) | ||
808 | { | ||
809 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | ||
810 | |||
811 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
812 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
813 | |||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | static int sta32x_reg_is_volatile(struct snd_soc_codec *codec, | ||
818 | unsigned int reg) | ||
819 | { | ||
820 | switch (reg) { | ||
821 | case STA32X_CONFA ... STA32X_L2ATRT: | ||
822 | case STA32X_MPCC1 ... STA32X_FDRC2: | ||
823 | return 0; | ||
824 | } | ||
825 | return 1; | ||
826 | } | ||
827 | |||
828 | static const struct snd_soc_codec_driver sta32x_codec = { | ||
829 | .probe = sta32x_probe, | ||
830 | .remove = sta32x_remove, | ||
831 | .suspend = sta32x_suspend, | ||
832 | .resume = sta32x_resume, | ||
833 | .reg_cache_size = STA32X_REGISTER_COUNT, | ||
834 | .reg_word_size = sizeof(u8), | ||
835 | .volatile_register = sta32x_reg_is_volatile, | ||
836 | .set_bias_level = sta32x_set_bias_level, | ||
837 | .controls = sta32x_snd_controls, | ||
838 | .num_controls = ARRAY_SIZE(sta32x_snd_controls), | ||
839 | .dapm_widgets = sta32x_dapm_widgets, | ||
840 | .num_dapm_widgets = ARRAY_SIZE(sta32x_dapm_widgets), | ||
841 | .dapm_routes = sta32x_dapm_routes, | ||
842 | .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), | ||
843 | }; | ||
844 | |||
845 | static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, | ||
846 | const struct i2c_device_id *id) | ||
847 | { | ||
848 | struct sta32x_priv *sta32x; | ||
849 | int ret; | ||
850 | |||
851 | sta32x = kzalloc(sizeof(struct sta32x_priv), GFP_KERNEL); | ||
852 | if (!sta32x) | ||
853 | return -ENOMEM; | ||
854 | |||
855 | i2c_set_clientdata(i2c, sta32x); | ||
856 | |||
857 | ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); | ||
858 | if (ret != 0) { | ||
859 | dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret); | ||
860 | return ret; | ||
861 | } | ||
862 | |||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | static __devexit int sta32x_i2c_remove(struct i2c_client *client) | ||
867 | { | ||
868 | struct sta32x_priv *sta32x = i2c_get_clientdata(client); | ||
869 | struct snd_soc_codec *codec = sta32x->codec; | ||
870 | |||
871 | if (codec) | ||
872 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
873 | |||
874 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
875 | |||
876 | if (codec) { | ||
877 | snd_soc_unregister_codec(&client->dev); | ||
878 | snd_soc_codec_set_drvdata(codec, NULL); | ||
879 | } | ||
880 | |||
881 | kfree(sta32x); | ||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | static const struct i2c_device_id sta32x_i2c_id[] = { | ||
886 | { "sta326", 0 }, | ||
887 | { "sta328", 0 }, | ||
888 | { "sta329", 0 }, | ||
889 | { } | ||
890 | }; | ||
891 | MODULE_DEVICE_TABLE(i2c, sta32x_i2c_id); | ||
892 | |||
893 | static struct i2c_driver sta32x_i2c_driver = { | ||
894 | .driver = { | ||
895 | .name = "sta32x", | ||
896 | .owner = THIS_MODULE, | ||
897 | }, | ||
898 | .probe = sta32x_i2c_probe, | ||
899 | .remove = __devexit_p(sta32x_i2c_remove), | ||
900 | .id_table = sta32x_i2c_id, | ||
901 | }; | ||
902 | |||
903 | static int __init sta32x_init(void) | ||
904 | { | ||
905 | return i2c_add_driver(&sta32x_i2c_driver); | ||
906 | } | ||
907 | module_init(sta32x_init); | ||
908 | |||
909 | static void __exit sta32x_exit(void) | ||
910 | { | ||
911 | i2c_del_driver(&sta32x_i2c_driver); | ||
912 | } | ||
913 | module_exit(sta32x_exit); | ||
914 | |||
915 | MODULE_DESCRIPTION("ASoC STA32X driver"); | ||
916 | MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>"); | ||
917 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/sta32x.h b/sound/soc/codecs/sta32x.h new file mode 100644 index 000000000000..b97ee5a75667 --- /dev/null +++ b/sound/soc/codecs/sta32x.h | |||
@@ -0,0 +1,210 @@ | |||
1 | /* | ||
2 | * Codec driver for ST STA32x 2.1-channel high-efficiency digital audio system | ||
3 | * | ||
4 | * Copyright: 2011 Raumfeld GmbH | ||
5 | * Author: Johannes Stezenbach <js@sig21.net> | ||
6 | * | ||
7 | * based on code from: | ||
8 | * Wolfson Microelectronics PLC. | ||
9 | * Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | #ifndef _ASOC_STA_32X_H | ||
17 | #define _ASOC_STA_32X_H | ||
18 | |||
19 | /* STA326 register addresses */ | ||
20 | |||
21 | #define STA32X_REGISTER_COUNT 0x2d | ||
22 | |||
23 | #define STA32X_CONFA 0x00 | ||
24 | #define STA32X_CONFB 0x01 | ||
25 | #define STA32X_CONFC 0x02 | ||
26 | #define STA32X_CONFD 0x03 | ||
27 | #define STA32X_CONFE 0x04 | ||
28 | #define STA32X_CONFF 0x05 | ||
29 | #define STA32X_MMUTE 0x06 | ||
30 | #define STA32X_MVOL 0x07 | ||
31 | #define STA32X_C1VOL 0x08 | ||
32 | #define STA32X_C2VOL 0x09 | ||
33 | #define STA32X_C3VOL 0x0a | ||
34 | #define STA32X_AUTO1 0x0b | ||
35 | #define STA32X_AUTO2 0x0c | ||
36 | #define STA32X_AUTO3 0x0d | ||
37 | #define STA32X_C1CFG 0x0e | ||
38 | #define STA32X_C2CFG 0x0f | ||
39 | #define STA32X_C3CFG 0x10 | ||
40 | #define STA32X_TONE 0x11 | ||
41 | #define STA32X_L1AR 0x12 | ||
42 | #define STA32X_L1ATRT 0x13 | ||
43 | #define STA32X_L2AR 0x14 | ||
44 | #define STA32X_L2ATRT 0x15 | ||
45 | #define STA32X_CFADDR2 0x16 | ||
46 | #define STA32X_B1CF1 0x17 | ||
47 | #define STA32X_B1CF2 0x18 | ||
48 | #define STA32X_B1CF3 0x19 | ||
49 | #define STA32X_B2CF1 0x1a | ||
50 | #define STA32X_B2CF2 0x1b | ||
51 | #define STA32X_B2CF3 0x1c | ||
52 | #define STA32X_A1CF1 0x1d | ||
53 | #define STA32X_A1CF2 0x1e | ||
54 | #define STA32X_A1CF3 0x1f | ||
55 | #define STA32X_A2CF1 0x20 | ||
56 | #define STA32X_A2CF2 0x21 | ||
57 | #define STA32X_A2CF3 0x22 | ||
58 | #define STA32X_B0CF1 0x23 | ||
59 | #define STA32X_B0CF2 0x24 | ||
60 | #define STA32X_B0CF3 0x25 | ||
61 | #define STA32X_CFUD 0x26 | ||
62 | #define STA32X_MPCC1 0x27 | ||
63 | #define STA32X_MPCC2 0x28 | ||
64 | /* Reserved 0x29 */ | ||
65 | /* Reserved 0x2a */ | ||
66 | #define STA32X_Reserved 0x2a | ||
67 | #define STA32X_FDRC1 0x2b | ||
68 | #define STA32X_FDRC2 0x2c | ||
69 | /* Reserved 0x2d */ | ||
70 | |||
71 | |||
72 | /* STA326 register field definitions */ | ||
73 | |||
74 | /* 0x00 CONFA */ | ||
75 | #define STA32X_CONFA_MCS_MASK 0x03 | ||
76 | #define STA32X_CONFA_MCS_SHIFT 0 | ||
77 | #define STA32X_CONFA_IR_MASK 0x18 | ||
78 | #define STA32X_CONFA_IR_SHIFT 3 | ||
79 | #define STA32X_CONFA_TWRB 0x20 | ||
80 | #define STA32X_CONFA_TWAB 0x40 | ||
81 | #define STA32X_CONFA_FDRB 0x80 | ||
82 | |||
83 | /* 0x01 CONFB */ | ||
84 | #define STA32X_CONFB_SAI_MASK 0x0f | ||
85 | #define STA32X_CONFB_SAI_SHIFT 0 | ||
86 | #define STA32X_CONFB_SAIFB 0x10 | ||
87 | #define STA32X_CONFB_DSCKE 0x20 | ||
88 | #define STA32X_CONFB_C1IM 0x40 | ||
89 | #define STA32X_CONFB_C2IM 0x80 | ||
90 | |||
91 | /* 0x02 CONFC */ | ||
92 | #define STA32X_CONFC_OM_MASK 0x03 | ||
93 | #define STA32X_CONFC_OM_SHIFT 0 | ||
94 | #define STA32X_CONFC_CSZ_MASK 0x7c | ||
95 | #define STA32X_CONFC_CSZ_SHIFT 2 | ||
96 | |||
97 | /* 0x03 CONFD */ | ||
98 | #define STA32X_CONFD_HPB 0x01 | ||
99 | #define STA32X_CONFD_HPB_SHIFT 0 | ||
100 | #define STA32X_CONFD_DEMP 0x02 | ||
101 | #define STA32X_CONFD_DEMP_SHIFT 1 | ||
102 | #define STA32X_CONFD_DSPB 0x04 | ||
103 | #define STA32X_CONFD_DSPB_SHIFT 2 | ||
104 | #define STA32X_CONFD_PSL 0x08 | ||
105 | #define STA32X_CONFD_PSL_SHIFT 3 | ||
106 | #define STA32X_CONFD_BQL 0x10 | ||
107 | #define STA32X_CONFD_BQL_SHIFT 4 | ||
108 | #define STA32X_CONFD_DRC 0x20 | ||
109 | #define STA32X_CONFD_DRC_SHIFT 5 | ||
110 | #define STA32X_CONFD_ZDE 0x40 | ||
111 | #define STA32X_CONFD_ZDE_SHIFT 6 | ||
112 | #define STA32X_CONFD_MME 0x80 | ||
113 | #define STA32X_CONFD_MME_SHIFT 7 | ||
114 | |||
115 | /* 0x04 CONFE */ | ||
116 | #define STA32X_CONFE_MPCV 0x01 | ||
117 | #define STA32X_CONFE_MPCV_SHIFT 0 | ||
118 | #define STA32X_CONFE_MPC 0x02 | ||
119 | #define STA32X_CONFE_MPC_SHIFT 1 | ||
120 | #define STA32X_CONFE_AME 0x08 | ||
121 | #define STA32X_CONFE_AME_SHIFT 3 | ||
122 | #define STA32X_CONFE_PWMS 0x10 | ||
123 | #define STA32X_CONFE_PWMS_SHIFT 4 | ||
124 | #define STA32X_CONFE_ZCE 0x40 | ||
125 | #define STA32X_CONFE_ZCE_SHIFT 6 | ||
126 | #define STA32X_CONFE_SVE 0x80 | ||
127 | #define STA32X_CONFE_SVE_SHIFT 7 | ||
128 | |||
129 | /* 0x05 CONFF */ | ||
130 | #define STA32X_CONFF_OCFG_MASK 0x03 | ||
131 | #define STA32X_CONFF_OCFG_SHIFT 0 | ||
132 | #define STA32X_CONFF_IDE 0x04 | ||
133 | #define STA32X_CONFF_IDE_SHIFT 3 | ||
134 | #define STA32X_CONFF_BCLE 0x08 | ||
135 | #define STA32X_CONFF_ECLE 0x20 | ||
136 | #define STA32X_CONFF_PWDN 0x40 | ||
137 | #define STA32X_CONFF_EAPD 0x80 | ||
138 | |||
139 | /* 0x06 MMUTE */ | ||
140 | #define STA32X_MMUTE_MMUTE 0x01 | ||
141 | |||
142 | /* 0x0b AUTO1 */ | ||
143 | #define STA32X_AUTO1_AMEQ_MASK 0x03 | ||
144 | #define STA32X_AUTO1_AMEQ_SHIFT 0 | ||
145 | #define STA32X_AUTO1_AMV_MASK 0xc0 | ||
146 | #define STA32X_AUTO1_AMV_SHIFT 2 | ||
147 | #define STA32X_AUTO1_AMGC_MASK 0x30 | ||
148 | #define STA32X_AUTO1_AMGC_SHIFT 4 | ||
149 | #define STA32X_AUTO1_AMPS 0x80 | ||
150 | |||
151 | /* 0x0c AUTO2 */ | ||
152 | #define STA32X_AUTO2_AMAME 0x01 | ||
153 | #define STA32X_AUTO2_AMAM_MASK 0x0e | ||
154 | #define STA32X_AUTO2_AMAM_SHIFT 1 | ||
155 | #define STA32X_AUTO2_XO_MASK 0xf0 | ||
156 | #define STA32X_AUTO2_XO_SHIFT 4 | ||
157 | |||
158 | /* 0x0d AUTO3 */ | ||
159 | #define STA32X_AUTO3_PEQ_MASK 0x1f | ||
160 | #define STA32X_AUTO3_PEQ_SHIFT 0 | ||
161 | |||
162 | /* 0x0e 0x0f 0x10 CxCFG */ | ||
163 | #define STA32X_CxCFG_TCB 0x01 /* only C1 and C2 */ | ||
164 | #define STA32X_CxCFG_TCB_SHIFT 0 | ||
165 | #define STA32X_CxCFG_EQBP 0x02 /* only C1 and C2 */ | ||
166 | #define STA32X_CxCFG_EQBP_SHIFT 1 | ||
167 | #define STA32X_CxCFG_VBP 0x03 | ||
168 | #define STA32X_CxCFG_VBP_SHIFT 2 | ||
169 | #define STA32X_CxCFG_BO 0x04 | ||
170 | #define STA32X_CxCFG_LS_MASK 0x30 | ||
171 | #define STA32X_CxCFG_LS_SHIFT 4 | ||
172 | #define STA32X_CxCFG_OM_MASK 0xc0 | ||
173 | #define STA32X_CxCFG_OM_SHIFT 6 | ||
174 | |||
175 | /* 0x11 TONE */ | ||
176 | #define STA32X_TONE_BTC_SHIFT 0 | ||
177 | #define STA32X_TONE_TTC_SHIFT 4 | ||
178 | |||
179 | /* 0x12 0x13 0x14 0x15 limiter attack/release */ | ||
180 | #define STA32X_LxA_SHIFT 0 | ||
181 | #define STA32X_LxR_SHIFT 4 | ||
182 | |||
183 | /* 0x26 CFUD */ | ||
184 | #define STA32X_CFUD_W1 0x01 | ||
185 | #define STA32X_CFUD_WA 0x02 | ||
186 | #define STA32X_CFUD_R1 0x04 | ||
187 | #define STA32X_CFUD_RA 0x08 | ||
188 | |||
189 | |||
190 | /* biquad filter coefficient table offsets */ | ||
191 | #define STA32X_C1_BQ_BASE 0 | ||
192 | #define STA32X_C2_BQ_BASE 20 | ||
193 | #define STA32X_CH_BQ_NUM 4 | ||
194 | #define STA32X_BQ_NUM_COEF 5 | ||
195 | #define STA32X_XO_HP_BQ_BASE 40 | ||
196 | #define STA32X_XO_LP_BQ_BASE 45 | ||
197 | #define STA32X_C1_PRESCALE 50 | ||
198 | #define STA32X_C2_PRESCALE 51 | ||
199 | #define STA32X_C1_POSTSCALE 52 | ||
200 | #define STA32X_C2_POSTSCALE 53 | ||
201 | #define STA32X_C3_POSTSCALE 54 | ||
202 | #define STA32X_TW_POSTSCALE 55 | ||
203 | #define STA32X_C1_MIX1 56 | ||
204 | #define STA32X_C1_MIX2 57 | ||
205 | #define STA32X_C2_MIX1 58 | ||
206 | #define STA32X_C2_MIX2 59 | ||
207 | #define STA32X_C3_MIX1 60 | ||
208 | #define STA32X_C3_MIX2 61 | ||
209 | |||
210 | #endif /* _ASOC_STA_32X_H */ | ||
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 789453d44ec5..0963c4c7a83f 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -226,11 +226,13 @@ static const char *aic3x_adc_hpf[] = | |||
226 | #define RDAC_ENUM 1 | 226 | #define RDAC_ENUM 1 |
227 | #define LHPCOM_ENUM 2 | 227 | #define LHPCOM_ENUM 2 |
228 | #define RHPCOM_ENUM 3 | 228 | #define RHPCOM_ENUM 3 |
229 | #define LINE1L_ENUM 4 | 229 | #define LINE1L_2_L_ENUM 4 |
230 | #define LINE1R_ENUM 5 | 230 | #define LINE1L_2_R_ENUM 5 |
231 | #define LINE2L_ENUM 6 | 231 | #define LINE1R_2_L_ENUM 6 |
232 | #define LINE2R_ENUM 7 | 232 | #define LINE1R_2_R_ENUM 7 |
233 | #define ADC_HPF_ENUM 8 | 233 | #define LINE2L_ENUM 8 |
234 | #define LINE2R_ENUM 9 | ||
235 | #define ADC_HPF_ENUM 10 | ||
234 | 236 | ||
235 | static const struct soc_enum aic3x_enum[] = { | 237 | static const struct soc_enum aic3x_enum[] = { |
236 | SOC_ENUM_SINGLE(DAC_LINE_MUX, 6, 3, aic3x_left_dac_mux), | 238 | SOC_ENUM_SINGLE(DAC_LINE_MUX, 6, 3, aic3x_left_dac_mux), |
@@ -238,6 +240,8 @@ static const struct soc_enum aic3x_enum[] = { | |||
238 | SOC_ENUM_SINGLE(HPLCOM_CFG, 4, 3, aic3x_left_hpcom_mux), | 240 | SOC_ENUM_SINGLE(HPLCOM_CFG, 4, 3, aic3x_left_hpcom_mux), |
239 | SOC_ENUM_SINGLE(HPRCOM_CFG, 3, 5, aic3x_right_hpcom_mux), | 241 | SOC_ENUM_SINGLE(HPRCOM_CFG, 3, 5, aic3x_right_hpcom_mux), |
240 | SOC_ENUM_SINGLE(LINE1L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 242 | SOC_ENUM_SINGLE(LINE1L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), |
243 | SOC_ENUM_SINGLE(LINE1L_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), | ||
244 | SOC_ENUM_SINGLE(LINE1R_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), | ||
241 | SOC_ENUM_SINGLE(LINE1R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 245 | SOC_ENUM_SINGLE(LINE1R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), |
242 | SOC_ENUM_SINGLE(LINE2L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 246 | SOC_ENUM_SINGLE(LINE2L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), |
243 | SOC_ENUM_SINGLE(LINE2R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 247 | SOC_ENUM_SINGLE(LINE2R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), |
@@ -490,12 +494,16 @@ static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = { | |||
490 | }; | 494 | }; |
491 | 495 | ||
492 | /* Left Line1 Mux */ | 496 | /* Left Line1 Mux */ |
493 | static const struct snd_kcontrol_new aic3x_left_line1_mux_controls = | 497 | static const struct snd_kcontrol_new aic3x_left_line1l_mux_controls = |
494 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1L_ENUM]); | 498 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1L_2_L_ENUM]); |
499 | static const struct snd_kcontrol_new aic3x_right_line1l_mux_controls = | ||
500 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1L_2_R_ENUM]); | ||
495 | 501 | ||
496 | /* Right Line1 Mux */ | 502 | /* Right Line1 Mux */ |
497 | static const struct snd_kcontrol_new aic3x_right_line1_mux_controls = | 503 | static const struct snd_kcontrol_new aic3x_right_line1r_mux_controls = |
498 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1R_ENUM]); | 504 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1R_2_R_ENUM]); |
505 | static const struct snd_kcontrol_new aic3x_left_line1r_mux_controls = | ||
506 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1R_2_L_ENUM]); | ||
499 | 507 | ||
500 | /* Left Line2 Mux */ | 508 | /* Left Line2 Mux */ |
501 | static const struct snd_kcontrol_new aic3x_left_line2_mux_controls = | 509 | static const struct snd_kcontrol_new aic3x_left_line2_mux_controls = |
@@ -535,9 +543,9 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | |||
535 | &aic3x_left_pga_mixer_controls[0], | 543 | &aic3x_left_pga_mixer_controls[0], |
536 | ARRAY_SIZE(aic3x_left_pga_mixer_controls)), | 544 | ARRAY_SIZE(aic3x_left_pga_mixer_controls)), |
537 | SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0, | 545 | SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0, |
538 | &aic3x_left_line1_mux_controls), | 546 | &aic3x_left_line1l_mux_controls), |
539 | SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0, | 547 | SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0, |
540 | &aic3x_left_line1_mux_controls), | 548 | &aic3x_left_line1r_mux_controls), |
541 | SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0, | 549 | SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0, |
542 | &aic3x_left_line2_mux_controls), | 550 | &aic3x_left_line2_mux_controls), |
543 | 551 | ||
@@ -548,9 +556,9 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | |||
548 | &aic3x_right_pga_mixer_controls[0], | 556 | &aic3x_right_pga_mixer_controls[0], |
549 | ARRAY_SIZE(aic3x_right_pga_mixer_controls)), | 557 | ARRAY_SIZE(aic3x_right_pga_mixer_controls)), |
550 | SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0, | 558 | SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0, |
551 | &aic3x_right_line1_mux_controls), | 559 | &aic3x_right_line1l_mux_controls), |
552 | SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0, | 560 | SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0, |
553 | &aic3x_right_line1_mux_controls), | 561 | &aic3x_right_line1r_mux_controls), |
554 | SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0, | 562 | SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0, |
555 | &aic3x_right_line2_mux_controls), | 563 | &aic3x_right_line2_mux_controls), |
556 | 564 | ||
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 4c336636d4f5..cd63bba623df 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -954,9 +954,9 @@ static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0); | |||
954 | 954 | ||
955 | /* | 955 | /* |
956 | * MICGAIN volume control: | 956 | * MICGAIN volume control: |
957 | * from -6 to 30 dB in 6 dB steps | 957 | * from 6 to 30 dB in 6 dB steps |
958 | */ | 958 | */ |
959 | static DECLARE_TLV_DB_SCALE(mic_amp_tlv, -600, 600, 0); | 959 | static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0); |
960 | 960 | ||
961 | /* | 961 | /* |
962 | * AFMGAIN volume control: | 962 | * AFMGAIN volume control: |
diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c new file mode 100644 index 000000000000..a2a09f85ea99 --- /dev/null +++ b/sound/soc/codecs/wm8782.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * sound/soc/codecs/wm8782.c | ||
3 | * simple, strap-pin configured 24bit 2ch ADC | ||
4 | * | ||
5 | * Copyright: 2011 Raumfeld GmbH | ||
6 | * Author: Johannes Stezenbach <js@sig21.net> | ||
7 | * | ||
8 | * based on ad73311.c | ||
9 | * Copyright: Analog Device Inc. | ||
10 | * Author: Cliff Cai <cliff.cai@analog.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/init.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/device.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/ac97_codec.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/soc.h> | ||
28 | |||
29 | static struct snd_soc_dai_driver wm8782_dai = { | ||
30 | .name = "wm8782", | ||
31 | .capture = { | ||
32 | .stream_name = "Capture", | ||
33 | .channels_min = 2, | ||
34 | .channels_max = 2, | ||
35 | /* For configurations with FSAMPEN=0 */ | ||
36 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
37 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
38 | SNDRV_PCM_FMTBIT_S20_3LE | | ||
39 | SNDRV_PCM_FMTBIT_S24_LE, | ||
40 | }, | ||
41 | }; | ||
42 | |||
43 | static struct snd_soc_codec_driver soc_codec_dev_wm8782; | ||
44 | |||
45 | static __devinit int wm8782_probe(struct platform_device *pdev) | ||
46 | { | ||
47 | return snd_soc_register_codec(&pdev->dev, | ||
48 | &soc_codec_dev_wm8782, &wm8782_dai, 1); | ||
49 | } | ||
50 | |||
51 | static int __devexit wm8782_remove(struct platform_device *pdev) | ||
52 | { | ||
53 | snd_soc_unregister_codec(&pdev->dev); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static struct platform_driver wm8782_codec_driver = { | ||
58 | .driver = { | ||
59 | .name = "wm8782", | ||
60 | .owner = THIS_MODULE, | ||
61 | }, | ||
62 | .probe = wm8782_probe, | ||
63 | .remove = wm8782_remove, | ||
64 | }; | ||
65 | |||
66 | static int __init wm8782_init(void) | ||
67 | { | ||
68 | return platform_driver_register(&wm8782_codec_driver); | ||
69 | } | ||
70 | module_init(wm8782_init); | ||
71 | |||
72 | static void __exit wm8782_exit(void) | ||
73 | { | ||
74 | platform_driver_unregister(&wm8782_codec_driver); | ||
75 | } | ||
76 | module_exit(wm8782_exit); | ||
77 | |||
78 | MODULE_DESCRIPTION("ASoC WM8782 driver"); | ||
79 | MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>"); | ||
80 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 449ea09a193d..082040eda8a2 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -1167,6 +1167,7 @@ static int wm8900_resume(struct snd_soc_codec *codec) | |||
1167 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); | 1167 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); |
1168 | if (ret != 0) { | 1168 | if (ret != 0) { |
1169 | dev_err(codec->dev, "Failed to restart FLL\n"); | 1169 | dev_err(codec->dev, "Failed to restart FLL\n"); |
1170 | kfree(cache); | ||
1170 | return ret; | 1171 | return ret; |
1171 | } | 1172 | } |
1172 | } | 1173 | } |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 9b3bba4df5b3..b085575d4aa5 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -2560,6 +2560,7 @@ static __devexit int wm8904_i2c_remove(struct i2c_client *client) | |||
2560 | static const struct i2c_device_id wm8904_i2c_id[] = { | 2560 | static const struct i2c_device_id wm8904_i2c_id[] = { |
2561 | { "wm8904", WM8904 }, | 2561 | { "wm8904", WM8904 }, |
2562 | { "wm8912", WM8912 }, | 2562 | { "wm8912", WM8912 }, |
2563 | { "wm8918", WM8904 }, /* Actually a subset, updates to follow */ | ||
2563 | { } | 2564 | { } |
2564 | }; | 2565 | }; |
2565 | MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id); | 2566 | MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id); |
diff --git a/sound/soc/codecs/wm8915.c b/sound/soc/codecs/wm8915.c index e2ab4fac2819..423baa9be241 100644 --- a/sound/soc/codecs/wm8915.c +++ b/sound/soc/codecs/wm8915.c | |||
@@ -41,14 +41,12 @@ | |||
41 | #define HPOUT2L 4 | 41 | #define HPOUT2L 4 |
42 | #define HPOUT2R 8 | 42 | #define HPOUT2R 8 |
43 | 43 | ||
44 | #define WM8915_NUM_SUPPLIES 6 | 44 | #define WM8915_NUM_SUPPLIES 4 |
45 | static const char *wm8915_supply_names[WM8915_NUM_SUPPLIES] = { | 45 | static const char *wm8915_supply_names[WM8915_NUM_SUPPLIES] = { |
46 | "DCVDD", | ||
47 | "DBVDD", | 46 | "DBVDD", |
48 | "AVDD1", | 47 | "AVDD1", |
49 | "AVDD2", | 48 | "AVDD2", |
50 | "CPVDD", | 49 | "CPVDD", |
51 | "MICVDD", | ||
52 | }; | 50 | }; |
53 | 51 | ||
54 | struct wm8915_priv { | 52 | struct wm8915_priv { |
@@ -57,6 +55,7 @@ struct wm8915_priv { | |||
57 | int ldo1ena; | 55 | int ldo1ena; |
58 | 56 | ||
59 | int sysclk; | 57 | int sysclk; |
58 | int sysclk_src; | ||
60 | 59 | ||
61 | int fll_src; | 60 | int fll_src; |
62 | int fll_fref; | 61 | int fll_fref; |
@@ -76,6 +75,7 @@ struct wm8915_priv { | |||
76 | struct wm8915_pdata pdata; | 75 | struct wm8915_pdata pdata; |
77 | 76 | ||
78 | int rx_rate[WM8915_AIFS]; | 77 | int rx_rate[WM8915_AIFS]; |
78 | int bclk_rate[WM8915_AIFS]; | ||
79 | 79 | ||
80 | /* Platform dependant ReTune mobile configuration */ | 80 | /* Platform dependant ReTune mobile configuration */ |
81 | int num_retune_mobile_texts; | 81 | int num_retune_mobile_texts; |
@@ -113,8 +113,6 @@ WM8915_REGULATOR_EVENT(0) | |||
113 | WM8915_REGULATOR_EVENT(1) | 113 | WM8915_REGULATOR_EVENT(1) |
114 | WM8915_REGULATOR_EVENT(2) | 114 | WM8915_REGULATOR_EVENT(2) |
115 | WM8915_REGULATOR_EVENT(3) | 115 | WM8915_REGULATOR_EVENT(3) |
116 | WM8915_REGULATOR_EVENT(4) | ||
117 | WM8915_REGULATOR_EVENT(5) | ||
118 | 116 | ||
119 | static const u16 wm8915_reg[WM8915_MAX_REGISTER] = { | 117 | static const u16 wm8915_reg[WM8915_MAX_REGISTER] = { |
120 | [WM8915_SOFTWARE_RESET] = 0x8915, | 118 | [WM8915_SOFTWARE_RESET] = 0x8915, |
@@ -1565,6 +1563,50 @@ static int wm8915_reset(struct snd_soc_codec *codec) | |||
1565 | return snd_soc_write(codec, WM8915_SOFTWARE_RESET, 0x8915); | 1563 | return snd_soc_write(codec, WM8915_SOFTWARE_RESET, 0x8915); |
1566 | } | 1564 | } |
1567 | 1565 | ||
1566 | static const int bclk_divs[] = { | ||
1567 | 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96 | ||
1568 | }; | ||
1569 | |||
1570 | static void wm8915_update_bclk(struct snd_soc_codec *codec) | ||
1571 | { | ||
1572 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
1573 | int aif, best, cur_val, bclk_rate, bclk_reg, i; | ||
1574 | |||
1575 | /* Don't bother if we're in a low frequency idle mode that | ||
1576 | * can't support audio. | ||
1577 | */ | ||
1578 | if (wm8915->sysclk < 64000) | ||
1579 | return; | ||
1580 | |||
1581 | for (aif = 0; aif < WM8915_AIFS; aif++) { | ||
1582 | switch (aif) { | ||
1583 | case 0: | ||
1584 | bclk_reg = WM8915_AIF1_BCLK; | ||
1585 | break; | ||
1586 | case 1: | ||
1587 | bclk_reg = WM8915_AIF2_BCLK; | ||
1588 | break; | ||
1589 | } | ||
1590 | |||
1591 | bclk_rate = wm8915->bclk_rate[aif]; | ||
1592 | |||
1593 | /* Pick a divisor for BCLK as close as we can get to ideal */ | ||
1594 | best = 0; | ||
1595 | for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { | ||
1596 | cur_val = (wm8915->sysclk / bclk_divs[i]) - bclk_rate; | ||
1597 | if (cur_val < 0) /* BCLK table is sorted */ | ||
1598 | break; | ||
1599 | best = i; | ||
1600 | } | ||
1601 | bclk_rate = wm8915->sysclk / bclk_divs[best]; | ||
1602 | dev_dbg(codec->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n", | ||
1603 | bclk_divs[best], bclk_rate); | ||
1604 | |||
1605 | snd_soc_update_bits(codec, bclk_reg, | ||
1606 | WM8915_AIF1_BCLK_DIV_MASK, best); | ||
1607 | } | ||
1608 | } | ||
1609 | |||
1568 | static int wm8915_set_bias_level(struct snd_soc_codec *codec, | 1610 | static int wm8915_set_bias_level(struct snd_soc_codec *codec, |
1569 | enum snd_soc_bias_level level) | 1611 | enum snd_soc_bias_level level) |
1570 | { | 1612 | { |
@@ -1717,10 +1759,6 @@ static int wm8915_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
1717 | return 0; | 1759 | return 0; |
1718 | } | 1760 | } |
1719 | 1761 | ||
1720 | static const int bclk_divs[] = { | ||
1721 | 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96 | ||
1722 | }; | ||
1723 | |||
1724 | static const int dsp_divs[] = { | 1762 | static const int dsp_divs[] = { |
1725 | 48000, 32000, 16000, 8000 | 1763 | 48000, 32000, 16000, 8000 |
1726 | }; | 1764 | }; |
@@ -1731,17 +1769,11 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream, | |||
1731 | { | 1769 | { |
1732 | struct snd_soc_codec *codec = dai->codec; | 1770 | struct snd_soc_codec *codec = dai->codec; |
1733 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | 1771 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); |
1734 | int bits, i, bclk_rate, best, cur_val; | 1772 | int bits, i, bclk_rate; |
1735 | int aifdata = 0; | 1773 | int aifdata = 0; |
1736 | int bclk = 0; | ||
1737 | int lrclk = 0; | 1774 | int lrclk = 0; |
1738 | int dsp = 0; | 1775 | int dsp = 0; |
1739 | int aifdata_reg, bclk_reg, lrclk_reg, dsp_shift; | 1776 | int aifdata_reg, lrclk_reg, dsp_shift; |
1740 | |||
1741 | if (!wm8915->sysclk) { | ||
1742 | dev_err(codec->dev, "SYSCLK not configured\n"); | ||
1743 | return -EINVAL; | ||
1744 | } | ||
1745 | 1777 | ||
1746 | switch (dai->id) { | 1778 | switch (dai->id) { |
1747 | case 0: | 1779 | case 0: |
@@ -1753,7 +1785,6 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream, | |||
1753 | aifdata_reg = WM8915_AIF1TX_DATA_CONFIGURATION_1; | 1785 | aifdata_reg = WM8915_AIF1TX_DATA_CONFIGURATION_1; |
1754 | lrclk_reg = WM8915_AIF1_TX_LRCLK_1; | 1786 | lrclk_reg = WM8915_AIF1_TX_LRCLK_1; |
1755 | } | 1787 | } |
1756 | bclk_reg = WM8915_AIF1_BCLK; | ||
1757 | dsp_shift = 0; | 1788 | dsp_shift = 0; |
1758 | break; | 1789 | break; |
1759 | case 1: | 1790 | case 1: |
@@ -1765,7 +1796,6 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream, | |||
1765 | aifdata_reg = WM8915_AIF2TX_DATA_CONFIGURATION_1; | 1796 | aifdata_reg = WM8915_AIF2TX_DATA_CONFIGURATION_1; |
1766 | lrclk_reg = WM8915_AIF2_TX_LRCLK_1; | 1797 | lrclk_reg = WM8915_AIF2_TX_LRCLK_1; |
1767 | } | 1798 | } |
1768 | bclk_reg = WM8915_AIF2_BCLK; | ||
1769 | dsp_shift = WM8915_DSP2_DIV_SHIFT; | 1799 | dsp_shift = WM8915_DSP2_DIV_SHIFT; |
1770 | break; | 1800 | break; |
1771 | default: | 1801 | default: |
@@ -1779,6 +1809,9 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream, | |||
1779 | return bclk_rate; | 1809 | return bclk_rate; |
1780 | } | 1810 | } |
1781 | 1811 | ||
1812 | wm8915->bclk_rate[dai->id] = bclk_rate; | ||
1813 | wm8915->rx_rate[dai->id] = params_rate(params); | ||
1814 | |||
1782 | /* Needs looking at for TDM */ | 1815 | /* Needs looking at for TDM */ |
1783 | bits = snd_pcm_format_width(params_format(params)); | 1816 | bits = snd_pcm_format_width(params_format(params)); |
1784 | if (bits < 0) | 1817 | if (bits < 0) |
@@ -1796,18 +1829,7 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream, | |||
1796 | } | 1829 | } |
1797 | dsp |= i << dsp_shift; | 1830 | dsp |= i << dsp_shift; |
1798 | 1831 | ||
1799 | /* Pick a divisor for BCLK as close as we can get to ideal */ | 1832 | wm8915_update_bclk(codec); |
1800 | best = 0; | ||
1801 | for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { | ||
1802 | cur_val = (wm8915->sysclk / bclk_divs[i]) - bclk_rate; | ||
1803 | if (cur_val < 0) /* BCLK table is sorted */ | ||
1804 | break; | ||
1805 | best = i; | ||
1806 | } | ||
1807 | bclk_rate = wm8915->sysclk / bclk_divs[best]; | ||
1808 | dev_dbg(dai->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n", | ||
1809 | bclk_divs[best], bclk_rate); | ||
1810 | bclk |= best; | ||
1811 | 1833 | ||
1812 | lrclk = bclk_rate / params_rate(params); | 1834 | lrclk = bclk_rate / params_rate(params); |
1813 | dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", | 1835 | dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", |
@@ -1817,14 +1839,11 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream, | |||
1817 | WM8915_AIF1TX_WL_MASK | | 1839 | WM8915_AIF1TX_WL_MASK | |
1818 | WM8915_AIF1TX_SLOT_LEN_MASK, | 1840 | WM8915_AIF1TX_SLOT_LEN_MASK, |
1819 | aifdata); | 1841 | aifdata); |
1820 | snd_soc_update_bits(codec, bclk_reg, WM8915_AIF1_BCLK_DIV_MASK, bclk); | ||
1821 | snd_soc_update_bits(codec, lrclk_reg, WM8915_AIF1RX_RATE_MASK, | 1842 | snd_soc_update_bits(codec, lrclk_reg, WM8915_AIF1RX_RATE_MASK, |
1822 | lrclk); | 1843 | lrclk); |
1823 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_2, | 1844 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_2, |
1824 | WM8915_DSP1_DIV_SHIFT << dsp_shift, dsp); | 1845 | WM8915_DSP1_DIV_SHIFT << dsp_shift, dsp); |
1825 | 1846 | ||
1826 | wm8915->rx_rate[dai->id] = params_rate(params); | ||
1827 | |||
1828 | return 0; | 1847 | return 0; |
1829 | } | 1848 | } |
1830 | 1849 | ||
@@ -1838,6 +1857,9 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai, | |||
1838 | int src; | 1857 | int src; |
1839 | int old; | 1858 | int old; |
1840 | 1859 | ||
1860 | if (freq == wm8915->sysclk && clk_id == wm8915->sysclk_src) | ||
1861 | return 0; | ||
1862 | |||
1841 | /* Disable SYSCLK while we reconfigure */ | 1863 | /* Disable SYSCLK while we reconfigure */ |
1842 | old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1) & WM8915_SYSCLK_ENA; | 1864 | old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1) & WM8915_SYSCLK_ENA; |
1843 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, | 1865 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, |
@@ -1882,6 +1904,8 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai, | |||
1882 | return -EINVAL; | 1904 | return -EINVAL; |
1883 | } | 1905 | } |
1884 | 1906 | ||
1907 | wm8915_update_bclk(codec); | ||
1908 | |||
1885 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, | 1909 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, |
1886 | WM8915_SYSCLK_SRC_MASK | WM8915_SYSCLK_DIV_MASK, | 1910 | WM8915_SYSCLK_SRC_MASK | WM8915_SYSCLK_DIV_MASK, |
1887 | src << WM8915_SYSCLK_SRC_SHIFT | ratediv); | 1911 | src << WM8915_SYSCLK_SRC_SHIFT | ratediv); |
@@ -1889,6 +1913,8 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai, | |||
1889 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, | 1913 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, |
1890 | WM8915_SYSCLK_ENA, old); | 1914 | WM8915_SYSCLK_ENA, old); |
1891 | 1915 | ||
1916 | wm8915->sysclk_src = clk_id; | ||
1917 | |||
1892 | return 0; | 1918 | return 0; |
1893 | } | 1919 | } |
1894 | 1920 | ||
@@ -2007,6 +2033,7 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2007 | unsigned int Fref, unsigned int Fout) | 2033 | unsigned int Fref, unsigned int Fout) |
2008 | { | 2034 | { |
2009 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | 2035 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); |
2036 | struct i2c_client *i2c = to_i2c_client(codec->dev); | ||
2010 | struct _fll_div fll_div; | 2037 | struct _fll_div fll_div; |
2011 | unsigned long timeout; | 2038 | unsigned long timeout; |
2012 | int ret, reg; | 2039 | int ret, reg; |
@@ -2093,7 +2120,18 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2093 | else | 2120 | else |
2094 | timeout = msecs_to_jiffies(2); | 2121 | timeout = msecs_to_jiffies(2); |
2095 | 2122 | ||
2096 | wait_for_completion_timeout(&wm8915->fll_lock, timeout); | 2123 | /* Allow substantially longer if we've actually got the IRQ */ |
2124 | if (i2c->irq) | ||
2125 | timeout *= 1000; | ||
2126 | |||
2127 | ret = wait_for_completion_timeout(&wm8915->fll_lock, timeout); | ||
2128 | |||
2129 | if (ret == 0 && i2c->irq) { | ||
2130 | dev_err(codec->dev, "Timed out waiting for FLL\n"); | ||
2131 | ret = -ETIMEDOUT; | ||
2132 | } else { | ||
2133 | ret = 0; | ||
2134 | } | ||
2097 | 2135 | ||
2098 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); | 2136 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); |
2099 | 2137 | ||
@@ -2101,7 +2139,7 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2101 | wm8915->fll_fout = Fout; | 2139 | wm8915->fll_fout = Fout; |
2102 | wm8915->fll_src = source; | 2140 | wm8915->fll_src = source; |
2103 | 2141 | ||
2104 | return 0; | 2142 | return ret; |
2105 | } | 2143 | } |
2106 | 2144 | ||
2107 | #ifdef CONFIG_GPIOLIB | 2145 | #ifdef CONFIG_GPIOLIB |
@@ -2293,6 +2331,12 @@ static void wm8915_micd(struct snd_soc_codec *codec) | |||
2293 | SND_JACK_HEADSET | SND_JACK_BTN_0); | 2331 | SND_JACK_HEADSET | SND_JACK_BTN_0); |
2294 | wm8915->jack_mic = true; | 2332 | wm8915->jack_mic = true; |
2295 | wm8915->detecting = false; | 2333 | wm8915->detecting = false; |
2334 | |||
2335 | /* Increase poll rate to give better responsiveness | ||
2336 | * for buttons */ | ||
2337 | snd_soc_update_bits(codec, WM8915_MIC_DETECT_1, | ||
2338 | WM8915_MICD_RATE_MASK, | ||
2339 | 5 << WM8915_MICD_RATE_SHIFT); | ||
2296 | } | 2340 | } |
2297 | 2341 | ||
2298 | /* If we detected a lower impedence during initial startup | 2342 | /* If we detected a lower impedence during initial startup |
@@ -2333,15 +2377,17 @@ static void wm8915_micd(struct snd_soc_codec *codec) | |||
2333 | SND_JACK_HEADPHONE, | 2377 | SND_JACK_HEADPHONE, |
2334 | SND_JACK_HEADSET | | 2378 | SND_JACK_HEADSET | |
2335 | SND_JACK_BTN_0); | 2379 | SND_JACK_BTN_0); |
2380 | |||
2381 | /* Increase the detection rate a bit for | ||
2382 | * responsiveness. | ||
2383 | */ | ||
2384 | snd_soc_update_bits(codec, WM8915_MIC_DETECT_1, | ||
2385 | WM8915_MICD_RATE_MASK, | ||
2386 | 7 << WM8915_MICD_RATE_SHIFT); | ||
2387 | |||
2336 | wm8915->detecting = false; | 2388 | wm8915->detecting = false; |
2337 | } | 2389 | } |
2338 | } | 2390 | } |
2339 | |||
2340 | /* Increase poll rate to give better responsiveness for buttons */ | ||
2341 | if (!wm8915->detecting) | ||
2342 | snd_soc_update_bits(codec, WM8915_MIC_DETECT_1, | ||
2343 | WM8915_MICD_RATE_MASK, | ||
2344 | 5 << WM8915_MICD_RATE_SHIFT); | ||
2345 | } | 2391 | } |
2346 | 2392 | ||
2347 | static irqreturn_t wm8915_irq(int irq, void *data) | 2393 | static irqreturn_t wm8915_irq(int irq, void *data) |
@@ -2383,6 +2429,20 @@ static irqreturn_t wm8915_irq(int irq, void *data) | |||
2383 | } | 2429 | } |
2384 | } | 2430 | } |
2385 | 2431 | ||
2432 | static irqreturn_t wm8915_edge_irq(int irq, void *data) | ||
2433 | { | ||
2434 | irqreturn_t ret = IRQ_NONE; | ||
2435 | irqreturn_t val; | ||
2436 | |||
2437 | do { | ||
2438 | val = wm8915_irq(irq, data); | ||
2439 | if (val != IRQ_NONE) | ||
2440 | ret = val; | ||
2441 | } while (val != IRQ_NONE); | ||
2442 | |||
2443 | return ret; | ||
2444 | } | ||
2445 | |||
2386 | static void wm8915_retune_mobile_pdata(struct snd_soc_codec *codec) | 2446 | static void wm8915_retune_mobile_pdata(struct snd_soc_codec *codec) |
2387 | { | 2447 | { |
2388 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | 2448 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); |
@@ -2482,8 +2542,6 @@ static int wm8915_probe(struct snd_soc_codec *codec) | |||
2482 | wm8915->disable_nb[1].notifier_call = wm8915_regulator_event_1; | 2542 | wm8915->disable_nb[1].notifier_call = wm8915_regulator_event_1; |
2483 | wm8915->disable_nb[2].notifier_call = wm8915_regulator_event_2; | 2543 | wm8915->disable_nb[2].notifier_call = wm8915_regulator_event_2; |
2484 | wm8915->disable_nb[3].notifier_call = wm8915_regulator_event_3; | 2544 | wm8915->disable_nb[3].notifier_call = wm8915_regulator_event_3; |
2485 | wm8915->disable_nb[4].notifier_call = wm8915_regulator_event_4; | ||
2486 | wm8915->disable_nb[5].notifier_call = wm8915_regulator_event_5; | ||
2487 | 2545 | ||
2488 | /* This should really be moved into the regulator core */ | 2546 | /* This should really be moved into the regulator core */ |
2489 | for (i = 0; i < ARRAY_SIZE(wm8915->supplies); i++) { | 2547 | for (i = 0; i < ARRAY_SIZE(wm8915->supplies); i++) { |
@@ -2709,8 +2767,14 @@ static int wm8915_probe(struct snd_soc_codec *codec) | |||
2709 | 2767 | ||
2710 | irq_flags |= IRQF_ONESHOT; | 2768 | irq_flags |= IRQF_ONESHOT; |
2711 | 2769 | ||
2712 | ret = request_threaded_irq(i2c->irq, NULL, wm8915_irq, | 2770 | if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) |
2713 | irq_flags, "wm8915", codec); | 2771 | ret = request_threaded_irq(i2c->irq, NULL, |
2772 | wm8915_edge_irq, | ||
2773 | irq_flags, "wm8915", codec); | ||
2774 | else | ||
2775 | ret = request_threaded_irq(i2c->irq, NULL, wm8915_irq, | ||
2776 | irq_flags, "wm8915", codec); | ||
2777 | |||
2714 | if (ret == 0) { | 2778 | if (ret == 0) { |
2715 | /* Unmask the interrupt */ | 2779 | /* Unmask the interrupt */ |
2716 | snd_soc_update_bits(codec, WM8915_INTERRUPT_CONTROL, | 2780 | snd_soc_update_bits(codec, WM8915_INTERRUPT_CONTROL, |
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 25580e3ee7c4..056daa0010f9 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -297,8 +297,6 @@ static int wm8940_add_widgets(struct snd_soc_codec *codec) | |||
297 | if (ret) | 297 | if (ret) |
298 | goto error_ret; | 298 | goto error_ret; |
299 | ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | 299 | ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); |
300 | if (ret) | ||
301 | goto error_ret; | ||
302 | 300 | ||
303 | error_ret: | 301 | error_ret: |
304 | return ret; | 302 | return ret; |
@@ -683,8 +681,6 @@ static int wm8940_resume(struct snd_soc_codec *codec) | |||
683 | } | 681 | } |
684 | } | 682 | } |
685 | ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 683 | ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
686 | if (ret) | ||
687 | goto error_ret; | ||
688 | 684 | ||
689 | error_ret: | 685 | error_ret: |
690 | return ret; | 686 | return ret; |
@@ -730,9 +726,6 @@ static int wm8940_probe(struct snd_soc_codec *codec) | |||
730 | if (ret) | 726 | if (ret) |
731 | return ret; | 727 | return ret; |
732 | ret = wm8940_add_widgets(codec); | 728 | ret = wm8940_add_widgets(codec); |
733 | if (ret) | ||
734 | return ret; | ||
735 | |||
736 | return ret; | 729 | return ret; |
737 | } | 730 | } |
738 | 731 | ||
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 5e05eed96c38..8499c563a9b5 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -78,6 +78,8 @@ struct wm8962_priv { | |||
78 | #ifdef CONFIG_GPIOLIB | 78 | #ifdef CONFIG_GPIOLIB |
79 | struct gpio_chip gpio_chip; | 79 | struct gpio_chip gpio_chip; |
80 | #endif | 80 | #endif |
81 | |||
82 | int irq; | ||
81 | }; | 83 | }; |
82 | 84 | ||
83 | /* We can't use the same notifier block for more than one supply and | 85 | /* We can't use the same notifier block for more than one supply and |
@@ -1982,6 +1984,7 @@ static const unsigned int classd_tlv[] = { | |||
1982 | 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), | 1984 | 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), |
1983 | 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), | 1985 | 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), |
1984 | }; | 1986 | }; |
1987 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | ||
1985 | 1988 | ||
1986 | /* The VU bits for the headphones are in a different register to the mute | 1989 | /* The VU bits for the headphones are in a different register to the mute |
1987 | * bits and only take effect on the PGA if it is actually powered. | 1990 | * bits and only take effect on the PGA if it is actually powered. |
@@ -2119,6 +2122,18 @@ SOC_SINGLE_TLV("HPMIXR MIXINR Volume", WM8962_HEADPHONE_MIXER_4, | |||
2119 | 2122 | ||
2120 | SOC_SINGLE_TLV("Speaker Boost Volume", WM8962_CLASS_D_CONTROL_2, 0, 7, 0, | 2123 | SOC_SINGLE_TLV("Speaker Boost Volume", WM8962_CLASS_D_CONTROL_2, 0, 7, 0, |
2121 | classd_tlv), | 2124 | classd_tlv), |
2125 | |||
2126 | SOC_SINGLE("EQ Switch", WM8962_EQ1, WM8962_EQ_ENA_SHIFT, 1, 0), | ||
2127 | SOC_DOUBLE_R_TLV("EQ1 Volume", WM8962_EQ2, WM8962_EQ22, | ||
2128 | WM8962_EQL_B1_GAIN_SHIFT, 31, 0, eq_tlv), | ||
2129 | SOC_DOUBLE_R_TLV("EQ2 Volume", WM8962_EQ2, WM8962_EQ22, | ||
2130 | WM8962_EQL_B2_GAIN_SHIFT, 31, 0, eq_tlv), | ||
2131 | SOC_DOUBLE_R_TLV("EQ3 Volume", WM8962_EQ2, WM8962_EQ22, | ||
2132 | WM8962_EQL_B3_GAIN_SHIFT, 31, 0, eq_tlv), | ||
2133 | SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23, | ||
2134 | WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv), | ||
2135 | SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23, | ||
2136 | WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv), | ||
2122 | }; | 2137 | }; |
2123 | 2138 | ||
2124 | static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { | 2139 | static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { |
@@ -2184,6 +2199,8 @@ static int sysclk_event(struct snd_soc_dapm_widget *w, | |||
2184 | struct snd_kcontrol *kcontrol, int event) | 2199 | struct snd_kcontrol *kcontrol, int event) |
2185 | { | 2200 | { |
2186 | struct snd_soc_codec *codec = w->codec; | 2201 | struct snd_soc_codec *codec = w->codec; |
2202 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2203 | unsigned long timeout; | ||
2187 | int src; | 2204 | int src; |
2188 | int fll; | 2205 | int fll; |
2189 | 2206 | ||
@@ -2203,9 +2220,19 @@ static int sysclk_event(struct snd_soc_dapm_widget *w, | |||
2203 | 2220 | ||
2204 | switch (event) { | 2221 | switch (event) { |
2205 | case SND_SOC_DAPM_PRE_PMU: | 2222 | case SND_SOC_DAPM_PRE_PMU: |
2206 | if (fll) | 2223 | if (fll) { |
2207 | snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, | 2224 | snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, |
2208 | WM8962_FLL_ENA, WM8962_FLL_ENA); | 2225 | WM8962_FLL_ENA, WM8962_FLL_ENA); |
2226 | if (wm8962->irq) { | ||
2227 | timeout = msecs_to_jiffies(5); | ||
2228 | timeout = wait_for_completion_timeout(&wm8962->fll_lock, | ||
2229 | timeout); | ||
2230 | |||
2231 | if (timeout == 0) | ||
2232 | dev_err(codec->dev, | ||
2233 | "Timed out starting FLL\n"); | ||
2234 | } | ||
2235 | } | ||
2209 | break; | 2236 | break; |
2210 | 2237 | ||
2211 | case SND_SOC_DAPM_POST_PMD: | 2238 | case SND_SOC_DAPM_POST_PMD: |
@@ -2763,18 +2790,44 @@ static const int bclk_divs[] = { | |||
2763 | 1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32 | 2790 | 1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32 |
2764 | }; | 2791 | }; |
2765 | 2792 | ||
2793 | static const int sysclk_rates[] = { | ||
2794 | 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536, | ||
2795 | }; | ||
2796 | |||
2766 | static void wm8962_configure_bclk(struct snd_soc_codec *codec) | 2797 | static void wm8962_configure_bclk(struct snd_soc_codec *codec) |
2767 | { | 2798 | { |
2768 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 2799 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
2769 | int dspclk, i; | 2800 | int dspclk, i; |
2770 | int clocking2 = 0; | 2801 | int clocking2 = 0; |
2802 | int clocking4 = 0; | ||
2771 | int aif2 = 0; | 2803 | int aif2 = 0; |
2772 | 2804 | ||
2773 | if (!wm8962->bclk) { | 2805 | if (!wm8962->sysclk_rate) { |
2774 | dev_dbg(codec->dev, "No BCLK rate configured\n"); | 2806 | dev_dbg(codec->dev, "No SYSCLK configured\n"); |
2807 | return; | ||
2808 | } | ||
2809 | |||
2810 | if (!wm8962->bclk || !wm8962->lrclk) { | ||
2811 | dev_dbg(codec->dev, "No audio clocks configured\n"); | ||
2775 | return; | 2812 | return; |
2776 | } | 2813 | } |
2777 | 2814 | ||
2815 | for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) { | ||
2816 | if (sysclk_rates[i] == wm8962->sysclk_rate / wm8962->lrclk) { | ||
2817 | clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT; | ||
2818 | break; | ||
2819 | } | ||
2820 | } | ||
2821 | |||
2822 | if (i == ARRAY_SIZE(sysclk_rates)) { | ||
2823 | dev_err(codec->dev, "Unsupported sysclk ratio %d\n", | ||
2824 | wm8962->sysclk_rate / wm8962->lrclk); | ||
2825 | return; | ||
2826 | } | ||
2827 | |||
2828 | snd_soc_update_bits(codec, WM8962_CLOCKING_4, | ||
2829 | WM8962_SYSCLK_RATE_MASK, clocking4); | ||
2830 | |||
2778 | dspclk = snd_soc_read(codec, WM8962_CLOCKING1); | 2831 | dspclk = snd_soc_read(codec, WM8962_CLOCKING1); |
2779 | if (dspclk < 0) { | 2832 | if (dspclk < 0) { |
2780 | dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk); | 2833 | dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk); |
@@ -2844,6 +2897,8 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec, | |||
2844 | /* VMID 2*50k */ | 2897 | /* VMID 2*50k */ |
2845 | snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, | 2898 | snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, |
2846 | WM8962_VMID_SEL_MASK, 0x80); | 2899 | WM8962_VMID_SEL_MASK, 0x80); |
2900 | |||
2901 | wm8962_configure_bclk(codec); | ||
2847 | break; | 2902 | break; |
2848 | 2903 | ||
2849 | case SND_SOC_BIAS_STANDBY: | 2904 | case SND_SOC_BIAS_STANDBY: |
@@ -2876,8 +2931,6 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec, | |||
2876 | snd_soc_update_bits(codec, WM8962_CLOCKING2, | 2931 | snd_soc_update_bits(codec, WM8962_CLOCKING2, |
2877 | WM8962_CLKREG_OVD, | 2932 | WM8962_CLKREG_OVD, |
2878 | WM8962_CLKREG_OVD); | 2933 | WM8962_CLKREG_OVD); |
2879 | |||
2880 | wm8962_configure_bclk(codec); | ||
2881 | } | 2934 | } |
2882 | 2935 | ||
2883 | /* VMID 2*250k */ | 2936 | /* VMID 2*250k */ |
@@ -2918,10 +2971,6 @@ static const struct { | |||
2918 | { 96000, 6 }, | 2971 | { 96000, 6 }, |
2919 | }; | 2972 | }; |
2920 | 2973 | ||
2921 | static const int sysclk_rates[] = { | ||
2922 | 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536, | ||
2923 | }; | ||
2924 | |||
2925 | static int wm8962_hw_params(struct snd_pcm_substream *substream, | 2974 | static int wm8962_hw_params(struct snd_pcm_substream *substream, |
2926 | struct snd_pcm_hw_params *params, | 2975 | struct snd_pcm_hw_params *params, |
2927 | struct snd_soc_dai *dai) | 2976 | struct snd_soc_dai *dai) |
@@ -2929,41 +2978,27 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream, | |||
2929 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 2978 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
2930 | struct snd_soc_codec *codec = rtd->codec; | 2979 | struct snd_soc_codec *codec = rtd->codec; |
2931 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 2980 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
2932 | int rate = params_rate(params); | ||
2933 | int i; | 2981 | int i; |
2934 | int aif0 = 0; | 2982 | int aif0 = 0; |
2935 | int adctl3 = 0; | 2983 | int adctl3 = 0; |
2936 | int clocking4 = 0; | ||
2937 | 2984 | ||
2938 | wm8962->bclk = snd_soc_params_to_bclk(params); | 2985 | wm8962->bclk = snd_soc_params_to_bclk(params); |
2939 | wm8962->lrclk = params_rate(params); | 2986 | wm8962->lrclk = params_rate(params); |
2940 | 2987 | ||
2941 | for (i = 0; i < ARRAY_SIZE(sr_vals); i++) { | 2988 | for (i = 0; i < ARRAY_SIZE(sr_vals); i++) { |
2942 | if (sr_vals[i].rate == rate) { | 2989 | if (sr_vals[i].rate == wm8962->lrclk) { |
2943 | adctl3 |= sr_vals[i].reg; | 2990 | adctl3 |= sr_vals[i].reg; |
2944 | break; | 2991 | break; |
2945 | } | 2992 | } |
2946 | } | 2993 | } |
2947 | if (i == ARRAY_SIZE(sr_vals)) { | 2994 | if (i == ARRAY_SIZE(sr_vals)) { |
2948 | dev_err(codec->dev, "Unsupported rate %dHz\n", rate); | 2995 | dev_err(codec->dev, "Unsupported rate %dHz\n", wm8962->lrclk); |
2949 | return -EINVAL; | 2996 | return -EINVAL; |
2950 | } | 2997 | } |
2951 | 2998 | ||
2952 | if (rate % 8000 == 0) | 2999 | if (wm8962->lrclk % 8000 == 0) |
2953 | adctl3 |= WM8962_SAMPLE_RATE_INT_MODE; | 3000 | adctl3 |= WM8962_SAMPLE_RATE_INT_MODE; |
2954 | 3001 | ||
2955 | for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) { | ||
2956 | if (sysclk_rates[i] == wm8962->sysclk_rate / rate) { | ||
2957 | clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT; | ||
2958 | break; | ||
2959 | } | ||
2960 | } | ||
2961 | if (i == ARRAY_SIZE(sysclk_rates)) { | ||
2962 | dev_err(codec->dev, "Unsupported sysclk ratio %d\n", | ||
2963 | wm8962->sysclk_rate / rate); | ||
2964 | return -EINVAL; | ||
2965 | } | ||
2966 | |||
2967 | switch (params_format(params)) { | 3002 | switch (params_format(params)) { |
2968 | case SNDRV_PCM_FORMAT_S16_LE: | 3003 | case SNDRV_PCM_FORMAT_S16_LE: |
2969 | break; | 3004 | break; |
@@ -2985,8 +3020,6 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream, | |||
2985 | snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_3, | 3020 | snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_3, |
2986 | WM8962_SAMPLE_RATE_INT_MODE | | 3021 | WM8962_SAMPLE_RATE_INT_MODE | |
2987 | WM8962_SAMPLE_RATE_MASK, adctl3); | 3022 | WM8962_SAMPLE_RATE_MASK, adctl3); |
2988 | snd_soc_update_bits(codec, WM8962_CLOCKING_4, | ||
2989 | WM8962_SYSCLK_RATE_MASK, clocking4); | ||
2990 | 3023 | ||
2991 | wm8962_configure_bclk(codec); | 3024 | wm8962_configure_bclk(codec); |
2992 | 3025 | ||
@@ -3261,16 +3294,31 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
3261 | 3294 | ||
3262 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); | 3295 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); |
3263 | 3296 | ||
3264 | /* This should be a massive overestimate */ | 3297 | ret = 0; |
3265 | timeout = msecs_to_jiffies(1); | 3298 | |
3299 | if (fll1 & WM8962_FLL_ENA) { | ||
3300 | /* This should be a massive overestimate but go even | ||
3301 | * higher if we'll error out | ||
3302 | */ | ||
3303 | if (wm8962->irq) | ||
3304 | timeout = msecs_to_jiffies(5); | ||
3305 | else | ||
3306 | timeout = msecs_to_jiffies(1); | ||
3307 | |||
3308 | timeout = wait_for_completion_timeout(&wm8962->fll_lock, | ||
3309 | timeout); | ||
3266 | 3310 | ||
3267 | wait_for_completion_timeout(&wm8962->fll_lock, timeout); | 3311 | if (timeout == 0 && wm8962->irq) { |
3312 | dev_err(codec->dev, "FLL lock timed out"); | ||
3313 | ret = -ETIMEDOUT; | ||
3314 | } | ||
3315 | } | ||
3268 | 3316 | ||
3269 | wm8962->fll_fref = Fref; | 3317 | wm8962->fll_fref = Fref; |
3270 | wm8962->fll_fout = Fout; | 3318 | wm8962->fll_fout = Fout; |
3271 | wm8962->fll_src = source; | 3319 | wm8962->fll_src = source; |
3272 | 3320 | ||
3273 | return 0; | 3321 | return ret; |
3274 | } | 3322 | } |
3275 | 3323 | ||
3276 | static int wm8962_mute(struct snd_soc_dai *dai, int mute) | 3324 | static int wm8962_mute(struct snd_soc_dai *dai, int mute) |
@@ -3731,8 +3779,6 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3731 | int ret; | 3779 | int ret; |
3732 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3780 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3733 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); | 3781 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); |
3734 | struct i2c_client *i2c = container_of(codec->dev, struct i2c_client, | ||
3735 | dev); | ||
3736 | u16 *reg_cache = codec->reg_cache; | 3782 | u16 *reg_cache = codec->reg_cache; |
3737 | int i, trigger, irq_pol; | 3783 | int i, trigger, irq_pol; |
3738 | bool dmicclk, dmicdat; | 3784 | bool dmicclk, dmicdat; |
@@ -3871,6 +3917,9 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3871 | snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME, | 3917 | snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME, |
3872 | WM8962_HPOUT_VU, WM8962_HPOUT_VU); | 3918 | WM8962_HPOUT_VU, WM8962_HPOUT_VU); |
3873 | 3919 | ||
3920 | /* Stereo control for EQ */ | ||
3921 | snd_soc_update_bits(codec, WM8962_EQ1, WM8962_EQ_SHARED_COEFF, 0); | ||
3922 | |||
3874 | wm8962_add_widgets(codec); | 3923 | wm8962_add_widgets(codec); |
3875 | 3924 | ||
3876 | /* Save boards having to disable DMIC when not in use */ | 3925 | /* Save boards having to disable DMIC when not in use */ |
@@ -3899,7 +3948,7 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3899 | wm8962_init_beep(codec); | 3948 | wm8962_init_beep(codec); |
3900 | wm8962_init_gpio(codec); | 3949 | wm8962_init_gpio(codec); |
3901 | 3950 | ||
3902 | if (i2c->irq) { | 3951 | if (wm8962->irq) { |
3903 | if (pdata && pdata->irq_active_low) { | 3952 | if (pdata && pdata->irq_active_low) { |
3904 | trigger = IRQF_TRIGGER_LOW; | 3953 | trigger = IRQF_TRIGGER_LOW; |
3905 | irq_pol = WM8962_IRQ_POL; | 3954 | irq_pol = WM8962_IRQ_POL; |
@@ -3911,12 +3960,13 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3911 | snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL, | 3960 | snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL, |
3912 | WM8962_IRQ_POL, irq_pol); | 3961 | WM8962_IRQ_POL, irq_pol); |
3913 | 3962 | ||
3914 | ret = request_threaded_irq(i2c->irq, NULL, wm8962_irq, | 3963 | ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq, |
3915 | trigger | IRQF_ONESHOT, | 3964 | trigger | IRQF_ONESHOT, |
3916 | "wm8962", codec); | 3965 | "wm8962", codec); |
3917 | if (ret != 0) { | 3966 | if (ret != 0) { |
3918 | dev_err(codec->dev, "Failed to request IRQ %d: %d\n", | 3967 | dev_err(codec->dev, "Failed to request IRQ %d: %d\n", |
3919 | i2c->irq, ret); | 3968 | wm8962->irq, ret); |
3969 | wm8962->irq = 0; | ||
3920 | /* Non-fatal */ | 3970 | /* Non-fatal */ |
3921 | } else { | 3971 | } else { |
3922 | /* Enable some IRQs by default */ | 3972 | /* Enable some IRQs by default */ |
@@ -3941,12 +3991,10 @@ err: | |||
3941 | static int wm8962_remove(struct snd_soc_codec *codec) | 3991 | static int wm8962_remove(struct snd_soc_codec *codec) |
3942 | { | 3992 | { |
3943 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3993 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3944 | struct i2c_client *i2c = container_of(codec->dev, struct i2c_client, | ||
3945 | dev); | ||
3946 | int i; | 3994 | int i; |
3947 | 3995 | ||
3948 | if (i2c->irq) | 3996 | if (wm8962->irq) |
3949 | free_irq(i2c->irq, codec); | 3997 | free_irq(wm8962->irq, codec); |
3950 | 3998 | ||
3951 | cancel_delayed_work_sync(&wm8962->mic_work); | 3999 | cancel_delayed_work_sync(&wm8962->mic_work); |
3952 | 4000 | ||
@@ -3986,6 +4034,8 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3986 | 4034 | ||
3987 | i2c_set_clientdata(i2c, wm8962); | 4035 | i2c_set_clientdata(i2c, wm8962); |
3988 | 4036 | ||
4037 | wm8962->irq = i2c->irq; | ||
4038 | |||
3989 | ret = snd_soc_register_codec(&i2c->dev, | 4039 | ret = snd_soc_register_codec(&i2c->dev, |
3990 | &soc_codec_dev_wm8962, &wm8962_dai, 1); | 4040 | &soc_codec_dev_wm8962, &wm8962_dai, 1); |
3991 | if (ret < 0) | 4041 | if (ret < 0) |
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c new file mode 100644 index 000000000000..17f04ec2b940 --- /dev/null +++ b/sound/soc/codecs/wm8983.c | |||
@@ -0,0 +1,1203 @@ | |||
1 | /* | ||
2 | * wm8983.c -- WM8983 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2011 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/spi/spi.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/initval.h> | ||
26 | #include <sound/tlv.h> | ||
27 | |||
28 | #include "wm8983.h" | ||
29 | |||
30 | static const u16 wm8983_reg_defs[WM8983_MAX_REGISTER + 1] = { | ||
31 | [0x00] = 0x0000, /* R0 - Software Reset */ | ||
32 | [0x01] = 0x0000, /* R1 - Power management 1 */ | ||
33 | [0x02] = 0x0000, /* R2 - Power management 2 */ | ||
34 | [0x03] = 0x0000, /* R3 - Power management 3 */ | ||
35 | [0x04] = 0x0050, /* R4 - Audio Interface */ | ||
36 | [0x05] = 0x0000, /* R5 - Companding control */ | ||
37 | [0x06] = 0x0140, /* R6 - Clock Gen control */ | ||
38 | [0x07] = 0x0000, /* R7 - Additional control */ | ||
39 | [0x08] = 0x0000, /* R8 - GPIO Control */ | ||
40 | [0x09] = 0x0000, /* R9 - Jack Detect Control 1 */ | ||
41 | [0x0A] = 0x0000, /* R10 - DAC Control */ | ||
42 | [0x0B] = 0x00FF, /* R11 - Left DAC digital Vol */ | ||
43 | [0x0C] = 0x00FF, /* R12 - Right DAC digital vol */ | ||
44 | [0x0D] = 0x0000, /* R13 - Jack Detect Control 2 */ | ||
45 | [0x0E] = 0x0100, /* R14 - ADC Control */ | ||
46 | [0x0F] = 0x00FF, /* R15 - Left ADC Digital Vol */ | ||
47 | [0x10] = 0x00FF, /* R16 - Right ADC Digital Vol */ | ||
48 | [0x12] = 0x012C, /* R18 - EQ1 - low shelf */ | ||
49 | [0x13] = 0x002C, /* R19 - EQ2 - peak 1 */ | ||
50 | [0x14] = 0x002C, /* R20 - EQ3 - peak 2 */ | ||
51 | [0x15] = 0x002C, /* R21 - EQ4 - peak 3 */ | ||
52 | [0x16] = 0x002C, /* R22 - EQ5 - high shelf */ | ||
53 | [0x18] = 0x0032, /* R24 - DAC Limiter 1 */ | ||
54 | [0x19] = 0x0000, /* R25 - DAC Limiter 2 */ | ||
55 | [0x1B] = 0x0000, /* R27 - Notch Filter 1 */ | ||
56 | [0x1C] = 0x0000, /* R28 - Notch Filter 2 */ | ||
57 | [0x1D] = 0x0000, /* R29 - Notch Filter 3 */ | ||
58 | [0x1E] = 0x0000, /* R30 - Notch Filter 4 */ | ||
59 | [0x20] = 0x0038, /* R32 - ALC control 1 */ | ||
60 | [0x21] = 0x000B, /* R33 - ALC control 2 */ | ||
61 | [0x22] = 0x0032, /* R34 - ALC control 3 */ | ||
62 | [0x23] = 0x0000, /* R35 - Noise Gate */ | ||
63 | [0x24] = 0x0008, /* R36 - PLL N */ | ||
64 | [0x25] = 0x000C, /* R37 - PLL K 1 */ | ||
65 | [0x26] = 0x0093, /* R38 - PLL K 2 */ | ||
66 | [0x27] = 0x00E9, /* R39 - PLL K 3 */ | ||
67 | [0x29] = 0x0000, /* R41 - 3D control */ | ||
68 | [0x2A] = 0x0000, /* R42 - OUT4 to ADC */ | ||
69 | [0x2B] = 0x0000, /* R43 - Beep control */ | ||
70 | [0x2C] = 0x0033, /* R44 - Input ctrl */ | ||
71 | [0x2D] = 0x0010, /* R45 - Left INP PGA gain ctrl */ | ||
72 | [0x2E] = 0x0010, /* R46 - Right INP PGA gain ctrl */ | ||
73 | [0x2F] = 0x0100, /* R47 - Left ADC BOOST ctrl */ | ||
74 | [0x30] = 0x0100, /* R48 - Right ADC BOOST ctrl */ | ||
75 | [0x31] = 0x0002, /* R49 - Output ctrl */ | ||
76 | [0x32] = 0x0001, /* R50 - Left mixer ctrl */ | ||
77 | [0x33] = 0x0001, /* R51 - Right mixer ctrl */ | ||
78 | [0x34] = 0x0039, /* R52 - LOUT1 (HP) volume ctrl */ | ||
79 | [0x35] = 0x0039, /* R53 - ROUT1 (HP) volume ctrl */ | ||
80 | [0x36] = 0x0039, /* R54 - LOUT2 (SPK) volume ctrl */ | ||
81 | [0x37] = 0x0039, /* R55 - ROUT2 (SPK) volume ctrl */ | ||
82 | [0x38] = 0x0001, /* R56 - OUT3 mixer ctrl */ | ||
83 | [0x39] = 0x0001, /* R57 - OUT4 (MONO) mix ctrl */ | ||
84 | [0x3D] = 0x0000 /* R61 - BIAS CTRL */ | ||
85 | }; | ||
86 | |||
87 | static const struct wm8983_reg_access { | ||
88 | u16 read; /* Mask of readable bits */ | ||
89 | u16 write; /* Mask of writable bits */ | ||
90 | } wm8983_access_masks[WM8983_MAX_REGISTER + 1] = { | ||
91 | [0x00] = { 0x0000, 0x01FF }, /* R0 - Software Reset */ | ||
92 | [0x01] = { 0x0000, 0x01FF }, /* R1 - Power management 1 */ | ||
93 | [0x02] = { 0x0000, 0x01FF }, /* R2 - Power management 2 */ | ||
94 | [0x03] = { 0x0000, 0x01EF }, /* R3 - Power management 3 */ | ||
95 | [0x04] = { 0x0000, 0x01FF }, /* R4 - Audio Interface */ | ||
96 | [0x05] = { 0x0000, 0x003F }, /* R5 - Companding control */ | ||
97 | [0x06] = { 0x0000, 0x01FD }, /* R6 - Clock Gen control */ | ||
98 | [0x07] = { 0x0000, 0x000F }, /* R7 - Additional control */ | ||
99 | [0x08] = { 0x0000, 0x003F }, /* R8 - GPIO Control */ | ||
100 | [0x09] = { 0x0000, 0x0070 }, /* R9 - Jack Detect Control 1 */ | ||
101 | [0x0A] = { 0x0000, 0x004F }, /* R10 - DAC Control */ | ||
102 | [0x0B] = { 0x0000, 0x01FF }, /* R11 - Left DAC digital Vol */ | ||
103 | [0x0C] = { 0x0000, 0x01FF }, /* R12 - Right DAC digital vol */ | ||
104 | [0x0D] = { 0x0000, 0x00FF }, /* R13 - Jack Detect Control 2 */ | ||
105 | [0x0E] = { 0x0000, 0x01FB }, /* R14 - ADC Control */ | ||
106 | [0x0F] = { 0x0000, 0x01FF }, /* R15 - Left ADC Digital Vol */ | ||
107 | [0x10] = { 0x0000, 0x01FF }, /* R16 - Right ADC Digital Vol */ | ||
108 | [0x12] = { 0x0000, 0x017F }, /* R18 - EQ1 - low shelf */ | ||
109 | [0x13] = { 0x0000, 0x017F }, /* R19 - EQ2 - peak 1 */ | ||
110 | [0x14] = { 0x0000, 0x017F }, /* R20 - EQ3 - peak 2 */ | ||
111 | [0x15] = { 0x0000, 0x017F }, /* R21 - EQ4 - peak 3 */ | ||
112 | [0x16] = { 0x0000, 0x007F }, /* R22 - EQ5 - high shelf */ | ||
113 | [0x18] = { 0x0000, 0x01FF }, /* R24 - DAC Limiter 1 */ | ||
114 | [0x19] = { 0x0000, 0x007F }, /* R25 - DAC Limiter 2 */ | ||
115 | [0x1B] = { 0x0000, 0x01FF }, /* R27 - Notch Filter 1 */ | ||
116 | [0x1C] = { 0x0000, 0x017F }, /* R28 - Notch Filter 2 */ | ||
117 | [0x1D] = { 0x0000, 0x017F }, /* R29 - Notch Filter 3 */ | ||
118 | [0x1E] = { 0x0000, 0x017F }, /* R30 - Notch Filter 4 */ | ||
119 | [0x20] = { 0x0000, 0x01BF }, /* R32 - ALC control 1 */ | ||
120 | [0x21] = { 0x0000, 0x00FF }, /* R33 - ALC control 2 */ | ||
121 | [0x22] = { 0x0000, 0x01FF }, /* R34 - ALC control 3 */ | ||
122 | [0x23] = { 0x0000, 0x000F }, /* R35 - Noise Gate */ | ||
123 | [0x24] = { 0x0000, 0x001F }, /* R36 - PLL N */ | ||
124 | [0x25] = { 0x0000, 0x003F }, /* R37 - PLL K 1 */ | ||
125 | [0x26] = { 0x0000, 0x01FF }, /* R38 - PLL K 2 */ | ||
126 | [0x27] = { 0x0000, 0x01FF }, /* R39 - PLL K 3 */ | ||
127 | [0x29] = { 0x0000, 0x000F }, /* R41 - 3D control */ | ||
128 | [0x2A] = { 0x0000, 0x01E7 }, /* R42 - OUT4 to ADC */ | ||
129 | [0x2B] = { 0x0000, 0x01BF }, /* R43 - Beep control */ | ||
130 | [0x2C] = { 0x0000, 0x0177 }, /* R44 - Input ctrl */ | ||
131 | [0x2D] = { 0x0000, 0x01FF }, /* R45 - Left INP PGA gain ctrl */ | ||
132 | [0x2E] = { 0x0000, 0x01FF }, /* R46 - Right INP PGA gain ctrl */ | ||
133 | [0x2F] = { 0x0000, 0x0177 }, /* R47 - Left ADC BOOST ctrl */ | ||
134 | [0x30] = { 0x0000, 0x0177 }, /* R48 - Right ADC BOOST ctrl */ | ||
135 | [0x31] = { 0x0000, 0x007F }, /* R49 - Output ctrl */ | ||
136 | [0x32] = { 0x0000, 0x01FF }, /* R50 - Left mixer ctrl */ | ||
137 | [0x33] = { 0x0000, 0x01FF }, /* R51 - Right mixer ctrl */ | ||
138 | [0x34] = { 0x0000, 0x01FF }, /* R52 - LOUT1 (HP) volume ctrl */ | ||
139 | [0x35] = { 0x0000, 0x01FF }, /* R53 - ROUT1 (HP) volume ctrl */ | ||
140 | [0x36] = { 0x0000, 0x01FF }, /* R54 - LOUT2 (SPK) volume ctrl */ | ||
141 | [0x37] = { 0x0000, 0x01FF }, /* R55 - ROUT2 (SPK) volume ctrl */ | ||
142 | [0x38] = { 0x0000, 0x004F }, /* R56 - OUT3 mixer ctrl */ | ||
143 | [0x39] = { 0x0000, 0x00FF }, /* R57 - OUT4 (MONO) mix ctrl */ | ||
144 | [0x3D] = { 0x0000, 0x0100 } /* R61 - BIAS CTRL */ | ||
145 | }; | ||
146 | |||
147 | /* vol/gain update regs */ | ||
148 | static const int vol_update_regs[] = { | ||
149 | WM8983_LEFT_DAC_DIGITAL_VOL, | ||
150 | WM8983_RIGHT_DAC_DIGITAL_VOL, | ||
151 | WM8983_LEFT_ADC_DIGITAL_VOL, | ||
152 | WM8983_RIGHT_ADC_DIGITAL_VOL, | ||
153 | WM8983_LOUT1_HP_VOLUME_CTRL, | ||
154 | WM8983_ROUT1_HP_VOLUME_CTRL, | ||
155 | WM8983_LOUT2_SPK_VOLUME_CTRL, | ||
156 | WM8983_ROUT2_SPK_VOLUME_CTRL, | ||
157 | WM8983_LEFT_INP_PGA_GAIN_CTRL, | ||
158 | WM8983_RIGHT_INP_PGA_GAIN_CTRL | ||
159 | }; | ||
160 | |||
161 | struct wm8983_priv { | ||
162 | enum snd_soc_control_type control_type; | ||
163 | u32 sysclk; | ||
164 | u32 bclk; | ||
165 | }; | ||
166 | |||
167 | static const struct { | ||
168 | int div; | ||
169 | int ratio; | ||
170 | } fs_ratios[] = { | ||
171 | { 10, 128 }, | ||
172 | { 15, 192 }, | ||
173 | { 20, 256 }, | ||
174 | { 30, 384 }, | ||
175 | { 40, 512 }, | ||
176 | { 60, 768 }, | ||
177 | { 80, 1024 }, | ||
178 | { 120, 1536 } | ||
179 | }; | ||
180 | |||
181 | static const int srates[] = { 48000, 32000, 24000, 16000, 12000, 8000 }; | ||
182 | |||
183 | static const int bclk_divs[] = { | ||
184 | 1, 2, 4, 8, 16, 32 | ||
185 | }; | ||
186 | |||
187 | static int eqmode_get(struct snd_kcontrol *kcontrol, | ||
188 | struct snd_ctl_elem_value *ucontrol); | ||
189 | static int eqmode_put(struct snd_kcontrol *kcontrol, | ||
190 | struct snd_ctl_elem_value *ucontrol); | ||
191 | |||
192 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1); | ||
193 | static const DECLARE_TLV_DB_SCALE(adc_tlv, -12700, 50, 1); | ||
194 | static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); | ||
195 | static const DECLARE_TLV_DB_SCALE(lim_thresh_tlv, -600, 100, 0); | ||
196 | static const DECLARE_TLV_DB_SCALE(lim_boost_tlv, 0, 100, 0); | ||
197 | static const DECLARE_TLV_DB_SCALE(alc_min_tlv, -1200, 600, 0); | ||
198 | static const DECLARE_TLV_DB_SCALE(alc_max_tlv, -675, 600, 0); | ||
199 | static const DECLARE_TLV_DB_SCALE(alc_tar_tlv, -2250, 150, 0); | ||
200 | static const DECLARE_TLV_DB_SCALE(pga_vol_tlv, -1200, 75, 0); | ||
201 | static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1); | ||
202 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | ||
203 | static const DECLARE_TLV_DB_SCALE(aux_tlv, -1500, 300, 0); | ||
204 | static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); | ||
205 | static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); | ||
206 | |||
207 | static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" }; | ||
208 | static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7, | ||
209 | alc_sel_text); | ||
210 | |||
211 | static const char *alc_mode_text[] = { "ALC", "Limiter" }; | ||
212 | static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8, | ||
213 | alc_mode_text); | ||
214 | |||
215 | static const char *filter_mode_text[] = { "Audio", "Application" }; | ||
216 | static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7, | ||
217 | filter_mode_text); | ||
218 | |||
219 | static const char *eq_bw_text[] = { "Narrow", "Wide" }; | ||
220 | static const char *eqmode_text[] = { "Capture", "Playback" }; | ||
221 | static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); | ||
222 | |||
223 | static const char *eq1_cutoff_text[] = { | ||
224 | "80Hz", "105Hz", "135Hz", "175Hz" | ||
225 | }; | ||
226 | static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5, | ||
227 | eq1_cutoff_text); | ||
228 | static const char *eq2_cutoff_text[] = { | ||
229 | "230Hz", "300Hz", "385Hz", "500Hz" | ||
230 | }; | ||
231 | static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text); | ||
232 | static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5, | ||
233 | eq2_cutoff_text); | ||
234 | static const char *eq3_cutoff_text[] = { | ||
235 | "650Hz", "850Hz", "1.1kHz", "1.4kHz" | ||
236 | }; | ||
237 | static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text); | ||
238 | static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5, | ||
239 | eq3_cutoff_text); | ||
240 | static const char *eq4_cutoff_text[] = { | ||
241 | "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" | ||
242 | }; | ||
243 | static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text); | ||
244 | static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5, | ||
245 | eq4_cutoff_text); | ||
246 | static const char *eq5_cutoff_text[] = { | ||
247 | "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" | ||
248 | }; | ||
249 | static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5, | ||
250 | eq5_cutoff_text); | ||
251 | |||
252 | static const char *speaker_mode_text[] = { "Class A/B", "Class D" }; | ||
253 | static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text); | ||
254 | |||
255 | static const char *depth_3d_text[] = { | ||
256 | "Off", | ||
257 | "6.67%", | ||
258 | "13.3%", | ||
259 | "20%", | ||
260 | "26.7%", | ||
261 | "33.3%", | ||
262 | "40%", | ||
263 | "46.6%", | ||
264 | "53.3%", | ||
265 | "60%", | ||
266 | "66.7%", | ||
267 | "73.3%", | ||
268 | "80%", | ||
269 | "86.7%", | ||
270 | "93.3%", | ||
271 | "100%" | ||
272 | }; | ||
273 | static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0, | ||
274 | depth_3d_text); | ||
275 | |||
276 | static const struct snd_kcontrol_new wm8983_snd_controls[] = { | ||
277 | SOC_SINGLE("Digital Loopback Switch", WM8983_COMPANDING_CONTROL, | ||
278 | 0, 1, 0), | ||
279 | |||
280 | SOC_ENUM("ALC Capture Function", alc_sel), | ||
281 | SOC_SINGLE_TLV("ALC Capture Max Volume", WM8983_ALC_CONTROL_1, | ||
282 | 3, 7, 0, alc_max_tlv), | ||
283 | SOC_SINGLE_TLV("ALC Capture Min Volume", WM8983_ALC_CONTROL_1, | ||
284 | 0, 7, 0, alc_min_tlv), | ||
285 | SOC_SINGLE_TLV("ALC Capture Target Volume", WM8983_ALC_CONTROL_2, | ||
286 | 0, 15, 0, alc_tar_tlv), | ||
287 | SOC_SINGLE("ALC Capture Attack", WM8983_ALC_CONTROL_3, 0, 10, 0), | ||
288 | SOC_SINGLE("ALC Capture Hold", WM8983_ALC_CONTROL_2, 4, 10, 0), | ||
289 | SOC_SINGLE("ALC Capture Decay", WM8983_ALC_CONTROL_3, 4, 10, 0), | ||
290 | SOC_ENUM("ALC Mode", alc_mode), | ||
291 | SOC_SINGLE("ALC Capture NG Switch", WM8983_NOISE_GATE, | ||
292 | 3, 1, 0), | ||
293 | SOC_SINGLE("ALC Capture NG Threshold", WM8983_NOISE_GATE, | ||
294 | 0, 7, 1), | ||
295 | |||
296 | SOC_DOUBLE_R_TLV("Capture Volume", WM8983_LEFT_ADC_DIGITAL_VOL, | ||
297 | WM8983_RIGHT_ADC_DIGITAL_VOL, 0, 255, 0, adc_tlv), | ||
298 | SOC_DOUBLE_R("Capture PGA ZC Switch", WM8983_LEFT_INP_PGA_GAIN_CTRL, | ||
299 | WM8983_RIGHT_INP_PGA_GAIN_CTRL, 7, 1, 0), | ||
300 | SOC_DOUBLE_R_TLV("Capture PGA Volume", WM8983_LEFT_INP_PGA_GAIN_CTRL, | ||
301 | WM8983_RIGHT_INP_PGA_GAIN_CTRL, 0, 63, 0, pga_vol_tlv), | ||
302 | |||
303 | SOC_DOUBLE_R_TLV("Capture PGA Boost Volume", | ||
304 | WM8983_LEFT_ADC_BOOST_CTRL, WM8983_RIGHT_ADC_BOOST_CTRL, | ||
305 | 8, 1, 0, pga_boost_tlv), | ||
306 | |||
307 | SOC_DOUBLE("ADC Inversion Switch", WM8983_ADC_CONTROL, 0, 1, 1, 0), | ||
308 | SOC_SINGLE("ADC 128x Oversampling Switch", WM8983_ADC_CONTROL, 8, 1, 0), | ||
309 | |||
310 | SOC_DOUBLE_R_TLV("Playback Volume", WM8983_LEFT_DAC_DIGITAL_VOL, | ||
311 | WM8983_RIGHT_DAC_DIGITAL_VOL, 0, 255, 0, dac_tlv), | ||
312 | |||
313 | SOC_SINGLE("DAC Playback Limiter Switch", WM8983_DAC_LIMITER_1, 8, 1, 0), | ||
314 | SOC_SINGLE("DAC Playback Limiter Decay", WM8983_DAC_LIMITER_1, 4, 10, 0), | ||
315 | SOC_SINGLE("DAC Playback Limiter Attack", WM8983_DAC_LIMITER_1, 0, 11, 0), | ||
316 | SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8983_DAC_LIMITER_2, | ||
317 | 4, 7, 1, lim_thresh_tlv), | ||
318 | SOC_SINGLE_TLV("DAC Playback Limiter Boost Volume", WM8983_DAC_LIMITER_2, | ||
319 | 0, 12, 0, lim_boost_tlv), | ||
320 | SOC_DOUBLE("DAC Inversion Switch", WM8983_DAC_CONTROL, 0, 1, 1, 0), | ||
321 | SOC_SINGLE("DAC Auto Mute Switch", WM8983_DAC_CONTROL, 2, 1, 0), | ||
322 | SOC_SINGLE("DAC 128x Oversampling Switch", WM8983_DAC_CONTROL, 3, 1, 0), | ||
323 | |||
324 | SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8983_LOUT1_HP_VOLUME_CTRL, | ||
325 | WM8983_ROUT1_HP_VOLUME_CTRL, 0, 63, 0, out_tlv), | ||
326 | SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8983_LOUT1_HP_VOLUME_CTRL, | ||
327 | WM8983_ROUT1_HP_VOLUME_CTRL, 7, 1, 0), | ||
328 | SOC_DOUBLE_R("Headphone Switch", WM8983_LOUT1_HP_VOLUME_CTRL, | ||
329 | WM8983_ROUT1_HP_VOLUME_CTRL, 6, 1, 1), | ||
330 | |||
331 | SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8983_LOUT2_SPK_VOLUME_CTRL, | ||
332 | WM8983_ROUT2_SPK_VOLUME_CTRL, 0, 63, 0, out_tlv), | ||
333 | SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8983_LOUT2_SPK_VOLUME_CTRL, | ||
334 | WM8983_ROUT2_SPK_VOLUME_CTRL, 7, 1, 0), | ||
335 | SOC_DOUBLE_R("Speaker Switch", WM8983_LOUT2_SPK_VOLUME_CTRL, | ||
336 | WM8983_ROUT2_SPK_VOLUME_CTRL, 6, 1, 1), | ||
337 | |||
338 | SOC_SINGLE("OUT3 Switch", WM8983_OUT3_MIXER_CTRL, | ||
339 | 6, 1, 1), | ||
340 | |||
341 | SOC_SINGLE("OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, | ||
342 | 6, 1, 1), | ||
343 | |||
344 | SOC_SINGLE("High Pass Filter Switch", WM8983_ADC_CONTROL, 8, 1, 0), | ||
345 | SOC_ENUM("High Pass Filter Mode", filter_mode), | ||
346 | SOC_SINGLE("High Pass Filter Cutoff", WM8983_ADC_CONTROL, 4, 7, 0), | ||
347 | |||
348 | SOC_DOUBLE_R_TLV("Aux Bypass Volume", | ||
349 | WM8983_LEFT_MIXER_CTRL, WM8983_RIGHT_MIXER_CTRL, 6, 7, 0, | ||
350 | aux_tlv), | ||
351 | |||
352 | SOC_DOUBLE_R_TLV("Input PGA Bypass Volume", | ||
353 | WM8983_LEFT_MIXER_CTRL, WM8983_RIGHT_MIXER_CTRL, 2, 7, 0, | ||
354 | bypass_tlv), | ||
355 | |||
356 | SOC_ENUM_EXT("Equalizer Function", eqmode, eqmode_get, eqmode_put), | ||
357 | SOC_ENUM("EQ1 Cutoff", eq1_cutoff), | ||
358 | SOC_SINGLE_TLV("EQ1 Volume", WM8983_EQ1_LOW_SHELF, 0, 24, 1, eq_tlv), | ||
359 | SOC_ENUM("EQ2 Bandwith", eq2_bw), | ||
360 | SOC_ENUM("EQ2 Cutoff", eq2_cutoff), | ||
361 | SOC_SINGLE_TLV("EQ2 Volume", WM8983_EQ2_PEAK_1, 0, 24, 1, eq_tlv), | ||
362 | SOC_ENUM("EQ3 Bandwith", eq3_bw), | ||
363 | SOC_ENUM("EQ3 Cutoff", eq3_cutoff), | ||
364 | SOC_SINGLE_TLV("EQ3 Volume", WM8983_EQ3_PEAK_2, 0, 24, 1, eq_tlv), | ||
365 | SOC_ENUM("EQ4 Bandwith", eq4_bw), | ||
366 | SOC_ENUM("EQ4 Cutoff", eq4_cutoff), | ||
367 | SOC_SINGLE_TLV("EQ4 Volume", WM8983_EQ4_PEAK_3, 0, 24, 1, eq_tlv), | ||
368 | SOC_ENUM("EQ5 Cutoff", eq5_cutoff), | ||
369 | SOC_SINGLE_TLV("EQ5 Volume", WM8983_EQ5_HIGH_SHELF, 0, 24, 1, eq_tlv), | ||
370 | |||
371 | SOC_ENUM("3D Depth", depth_3d), | ||
372 | |||
373 | SOC_ENUM("Speaker Mode", speaker_mode) | ||
374 | }; | ||
375 | |||
376 | static const struct snd_kcontrol_new left_out_mixer[] = { | ||
377 | SOC_DAPM_SINGLE("Line Switch", WM8983_LEFT_MIXER_CTRL, 1, 1, 0), | ||
378 | SOC_DAPM_SINGLE("Aux Switch", WM8983_LEFT_MIXER_CTRL, 5, 1, 0), | ||
379 | SOC_DAPM_SINGLE("PCM Switch", WM8983_LEFT_MIXER_CTRL, 0, 1, 0), | ||
380 | }; | ||
381 | |||
382 | static const struct snd_kcontrol_new right_out_mixer[] = { | ||
383 | SOC_DAPM_SINGLE("Line Switch", WM8983_RIGHT_MIXER_CTRL, 1, 1, 0), | ||
384 | SOC_DAPM_SINGLE("Aux Switch", WM8983_RIGHT_MIXER_CTRL, 5, 1, 0), | ||
385 | SOC_DAPM_SINGLE("PCM Switch", WM8983_RIGHT_MIXER_CTRL, 0, 1, 0), | ||
386 | }; | ||
387 | |||
388 | static const struct snd_kcontrol_new left_input_mixer[] = { | ||
389 | SOC_DAPM_SINGLE("L2 Switch", WM8983_INPUT_CTRL, 2, 1, 0), | ||
390 | SOC_DAPM_SINGLE("MicN Switch", WM8983_INPUT_CTRL, 1, 1, 0), | ||
391 | SOC_DAPM_SINGLE("MicP Switch", WM8983_INPUT_CTRL, 0, 1, 0), | ||
392 | }; | ||
393 | |||
394 | static const struct snd_kcontrol_new right_input_mixer[] = { | ||
395 | SOC_DAPM_SINGLE("R2 Switch", WM8983_INPUT_CTRL, 6, 1, 0), | ||
396 | SOC_DAPM_SINGLE("MicN Switch", WM8983_INPUT_CTRL, 5, 1, 0), | ||
397 | SOC_DAPM_SINGLE("MicP Switch", WM8983_INPUT_CTRL, 4, 1, 0), | ||
398 | }; | ||
399 | |||
400 | static const struct snd_kcontrol_new left_boost_mixer[] = { | ||
401 | SOC_DAPM_SINGLE_TLV("L2 Volume", WM8983_LEFT_ADC_BOOST_CTRL, | ||
402 | 4, 7, 0, boost_tlv), | ||
403 | SOC_DAPM_SINGLE_TLV("AUXL Volume", WM8983_LEFT_ADC_BOOST_CTRL, | ||
404 | 0, 7, 0, boost_tlv) | ||
405 | }; | ||
406 | |||
407 | static const struct snd_kcontrol_new out3_mixer[] = { | ||
408 | SOC_DAPM_SINGLE("LMIX2OUT3 Switch", WM8983_OUT3_MIXER_CTRL, | ||
409 | 1, 1, 0), | ||
410 | SOC_DAPM_SINGLE("LDAC2OUT3 Switch", WM8983_OUT3_MIXER_CTRL, | ||
411 | 0, 1, 0), | ||
412 | }; | ||
413 | |||
414 | static const struct snd_kcontrol_new out4_mixer[] = { | ||
415 | SOC_DAPM_SINGLE("LMIX2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, | ||
416 | 4, 1, 0), | ||
417 | SOC_DAPM_SINGLE("RMIX2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, | ||
418 | 1, 1, 0), | ||
419 | SOC_DAPM_SINGLE("LDAC2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, | ||
420 | 3, 1, 0), | ||
421 | SOC_DAPM_SINGLE("RDAC2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, | ||
422 | 0, 1, 0), | ||
423 | }; | ||
424 | |||
425 | static const struct snd_kcontrol_new right_boost_mixer[] = { | ||
426 | SOC_DAPM_SINGLE_TLV("R2 Volume", WM8983_RIGHT_ADC_BOOST_CTRL, | ||
427 | 4, 7, 0, boost_tlv), | ||
428 | SOC_DAPM_SINGLE_TLV("AUXR Volume", WM8983_RIGHT_ADC_BOOST_CTRL, | ||
429 | 0, 7, 0, boost_tlv) | ||
430 | }; | ||
431 | |||
432 | static const struct snd_soc_dapm_widget wm8983_dapm_widgets[] = { | ||
433 | SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8983_POWER_MANAGEMENT_3, | ||
434 | 0, 0), | ||
435 | SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8983_POWER_MANAGEMENT_3, | ||
436 | 1, 0), | ||
437 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8983_POWER_MANAGEMENT_2, | ||
438 | 0, 0), | ||
439 | SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8983_POWER_MANAGEMENT_2, | ||
440 | 1, 0), | ||
441 | |||
442 | SND_SOC_DAPM_MIXER("Left Output Mixer", WM8983_POWER_MANAGEMENT_3, | ||
443 | 2, 0, left_out_mixer, ARRAY_SIZE(left_out_mixer)), | ||
444 | SND_SOC_DAPM_MIXER("Right Output Mixer", WM8983_POWER_MANAGEMENT_3, | ||
445 | 3, 0, right_out_mixer, ARRAY_SIZE(right_out_mixer)), | ||
446 | |||
447 | SND_SOC_DAPM_MIXER("Left Input Mixer", WM8983_POWER_MANAGEMENT_2, | ||
448 | 2, 0, left_input_mixer, ARRAY_SIZE(left_input_mixer)), | ||
449 | SND_SOC_DAPM_MIXER("Right Input Mixer", WM8983_POWER_MANAGEMENT_2, | ||
450 | 3, 0, right_input_mixer, ARRAY_SIZE(right_input_mixer)), | ||
451 | |||
452 | SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8983_POWER_MANAGEMENT_2, | ||
453 | 4, 0, left_boost_mixer, ARRAY_SIZE(left_boost_mixer)), | ||
454 | SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8983_POWER_MANAGEMENT_2, | ||
455 | 5, 0, right_boost_mixer, ARRAY_SIZE(right_boost_mixer)), | ||
456 | |||
457 | SND_SOC_DAPM_MIXER("OUT3 Mixer", WM8983_POWER_MANAGEMENT_1, | ||
458 | 6, 0, out3_mixer, ARRAY_SIZE(out3_mixer)), | ||
459 | |||
460 | SND_SOC_DAPM_MIXER("OUT4 Mixer", WM8983_POWER_MANAGEMENT_1, | ||
461 | 7, 0, out4_mixer, ARRAY_SIZE(out4_mixer)), | ||
462 | |||
463 | SND_SOC_DAPM_PGA("Left Capture PGA", WM8983_LEFT_INP_PGA_GAIN_CTRL, | ||
464 | 6, 1, NULL, 0), | ||
465 | SND_SOC_DAPM_PGA("Right Capture PGA", WM8983_RIGHT_INP_PGA_GAIN_CTRL, | ||
466 | 6, 1, NULL, 0), | ||
467 | |||
468 | SND_SOC_DAPM_PGA("Left Headphone Out", WM8983_POWER_MANAGEMENT_2, | ||
469 | 7, 0, NULL, 0), | ||
470 | SND_SOC_DAPM_PGA("Right Headphone Out", WM8983_POWER_MANAGEMENT_2, | ||
471 | 8, 0, NULL, 0), | ||
472 | |||
473 | SND_SOC_DAPM_PGA("Left Speaker Out", WM8983_POWER_MANAGEMENT_3, | ||
474 | 5, 0, NULL, 0), | ||
475 | SND_SOC_DAPM_PGA("Right Speaker Out", WM8983_POWER_MANAGEMENT_3, | ||
476 | 6, 0, NULL, 0), | ||
477 | |||
478 | SND_SOC_DAPM_PGA("OUT3 Out", WM8983_POWER_MANAGEMENT_3, | ||
479 | 7, 0, NULL, 0), | ||
480 | |||
481 | SND_SOC_DAPM_PGA("OUT4 Out", WM8983_POWER_MANAGEMENT_3, | ||
482 | 8, 0, NULL, 0), | ||
483 | |||
484 | SND_SOC_DAPM_MICBIAS("Mic Bias", WM8983_POWER_MANAGEMENT_1, 4, 0), | ||
485 | |||
486 | SND_SOC_DAPM_INPUT("LIN"), | ||
487 | SND_SOC_DAPM_INPUT("LIP"), | ||
488 | SND_SOC_DAPM_INPUT("RIN"), | ||
489 | SND_SOC_DAPM_INPUT("RIP"), | ||
490 | SND_SOC_DAPM_INPUT("AUXL"), | ||
491 | SND_SOC_DAPM_INPUT("AUXR"), | ||
492 | SND_SOC_DAPM_INPUT("L2"), | ||
493 | SND_SOC_DAPM_INPUT("R2"), | ||
494 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
495 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
496 | SND_SOC_DAPM_OUTPUT("SPKL"), | ||
497 | SND_SOC_DAPM_OUTPUT("SPKR"), | ||
498 | SND_SOC_DAPM_OUTPUT("OUT3"), | ||
499 | SND_SOC_DAPM_OUTPUT("OUT4") | ||
500 | }; | ||
501 | |||
502 | static const struct snd_soc_dapm_route wm8983_audio_map[] = { | ||
503 | { "OUT3 Mixer", "LMIX2OUT3 Switch", "Left Output Mixer" }, | ||
504 | { "OUT3 Mixer", "LDAC2OUT3 Switch", "Left DAC" }, | ||
505 | |||
506 | { "OUT3 Out", NULL, "OUT3 Mixer" }, | ||
507 | { "OUT3", NULL, "OUT3 Out" }, | ||
508 | |||
509 | { "OUT4 Mixer", "LMIX2OUT4 Switch", "Left Output Mixer" }, | ||
510 | { "OUT4 Mixer", "RMIX2OUT4 Switch", "Right Output Mixer" }, | ||
511 | { "OUT4 Mixer", "LDAC2OUT4 Switch", "Left DAC" }, | ||
512 | { "OUT4 Mixer", "RDAC2OUT4 Switch", "Right DAC" }, | ||
513 | |||
514 | { "OUT4 Out", NULL, "OUT4 Mixer" }, | ||
515 | { "OUT4", NULL, "OUT4 Out" }, | ||
516 | |||
517 | { "Right Output Mixer", "PCM Switch", "Right DAC" }, | ||
518 | { "Right Output Mixer", "Aux Switch", "AUXR" }, | ||
519 | { "Right Output Mixer", "Line Switch", "Right Boost Mixer" }, | ||
520 | |||
521 | { "Left Output Mixer", "PCM Switch", "Left DAC" }, | ||
522 | { "Left Output Mixer", "Aux Switch", "AUXL" }, | ||
523 | { "Left Output Mixer", "Line Switch", "Left Boost Mixer" }, | ||
524 | |||
525 | { "Right Headphone Out", NULL, "Right Output Mixer" }, | ||
526 | { "HPR", NULL, "Right Headphone Out" }, | ||
527 | |||
528 | { "Left Headphone Out", NULL, "Left Output Mixer" }, | ||
529 | { "HPL", NULL, "Left Headphone Out" }, | ||
530 | |||
531 | { "Right Speaker Out", NULL, "Right Output Mixer" }, | ||
532 | { "SPKR", NULL, "Right Speaker Out" }, | ||
533 | |||
534 | { "Left Speaker Out", NULL, "Left Output Mixer" }, | ||
535 | { "SPKL", NULL, "Left Speaker Out" }, | ||
536 | |||
537 | { "Right ADC", NULL, "Right Boost Mixer" }, | ||
538 | |||
539 | { "Right Boost Mixer", "AUXR Volume", "AUXR" }, | ||
540 | { "Right Boost Mixer", NULL, "Right Capture PGA" }, | ||
541 | { "Right Boost Mixer", "R2 Volume", "R2" }, | ||
542 | |||
543 | { "Left ADC", NULL, "Left Boost Mixer" }, | ||
544 | |||
545 | { "Left Boost Mixer", "AUXL Volume", "AUXL" }, | ||
546 | { "Left Boost Mixer", NULL, "Left Capture PGA" }, | ||
547 | { "Left Boost Mixer", "L2 Volume", "L2" }, | ||
548 | |||
549 | { "Right Capture PGA", NULL, "Right Input Mixer" }, | ||
550 | { "Left Capture PGA", NULL, "Left Input Mixer" }, | ||
551 | |||
552 | { "Right Input Mixer", "R2 Switch", "R2" }, | ||
553 | { "Right Input Mixer", "MicN Switch", "RIN" }, | ||
554 | { "Right Input Mixer", "MicP Switch", "RIP" }, | ||
555 | |||
556 | { "Left Input Mixer", "L2 Switch", "L2" }, | ||
557 | { "Left Input Mixer", "MicN Switch", "LIN" }, | ||
558 | { "Left Input Mixer", "MicP Switch", "LIP" }, | ||
559 | }; | ||
560 | |||
561 | static int eqmode_get(struct snd_kcontrol *kcontrol, | ||
562 | struct snd_ctl_elem_value *ucontrol) | ||
563 | { | ||
564 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
565 | unsigned int reg; | ||
566 | |||
567 | reg = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF); | ||
568 | if (reg & WM8983_EQ3DMODE) | ||
569 | ucontrol->value.integer.value[0] = 1; | ||
570 | else | ||
571 | ucontrol->value.integer.value[0] = 0; | ||
572 | |||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | static int eqmode_put(struct snd_kcontrol *kcontrol, | ||
577 | struct snd_ctl_elem_value *ucontrol) | ||
578 | { | ||
579 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
580 | unsigned int regpwr2, regpwr3; | ||
581 | unsigned int reg_eq; | ||
582 | |||
583 | if (ucontrol->value.integer.value[0] != 0 | ||
584 | && ucontrol->value.integer.value[0] != 1) | ||
585 | return -EINVAL; | ||
586 | |||
587 | reg_eq = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF); | ||
588 | switch ((reg_eq & WM8983_EQ3DMODE) >> WM8983_EQ3DMODE_SHIFT) { | ||
589 | case 0: | ||
590 | if (!ucontrol->value.integer.value[0]) | ||
591 | return 0; | ||
592 | break; | ||
593 | case 1: | ||
594 | if (ucontrol->value.integer.value[0]) | ||
595 | return 0; | ||
596 | break; | ||
597 | } | ||
598 | |||
599 | regpwr2 = snd_soc_read(codec, WM8983_POWER_MANAGEMENT_2); | ||
600 | regpwr3 = snd_soc_read(codec, WM8983_POWER_MANAGEMENT_3); | ||
601 | /* disable the DACs and ADCs */ | ||
602 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_2, | ||
603 | WM8983_ADCENR_MASK | WM8983_ADCENL_MASK, 0); | ||
604 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_3, | ||
605 | WM8983_DACENR_MASK | WM8983_DACENL_MASK, 0); | ||
606 | /* set the desired eqmode */ | ||
607 | snd_soc_update_bits(codec, WM8983_EQ1_LOW_SHELF, | ||
608 | WM8983_EQ3DMODE_MASK, | ||
609 | ucontrol->value.integer.value[0] | ||
610 | << WM8983_EQ3DMODE_SHIFT); | ||
611 | /* restore DAC/ADC configuration */ | ||
612 | snd_soc_write(codec, WM8983_POWER_MANAGEMENT_2, regpwr2); | ||
613 | snd_soc_write(codec, WM8983_POWER_MANAGEMENT_3, regpwr3); | ||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | static int wm8983_readable(struct snd_soc_codec *codec, unsigned int reg) | ||
618 | { | ||
619 | if (reg > WM8983_MAX_REGISTER) | ||
620 | return 0; | ||
621 | |||
622 | return wm8983_access_masks[reg].read != 0; | ||
623 | } | ||
624 | |||
625 | static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute) | ||
626 | { | ||
627 | struct snd_soc_codec *codec = dai->codec; | ||
628 | |||
629 | return snd_soc_update_bits(codec, WM8983_DAC_CONTROL, | ||
630 | WM8983_SOFTMUTE_MASK, | ||
631 | !!mute << WM8983_SOFTMUTE_SHIFT); | ||
632 | } | ||
633 | |||
634 | static int wm8983_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
635 | { | ||
636 | struct snd_soc_codec *codec = dai->codec; | ||
637 | u16 format, master, bcp, lrp; | ||
638 | |||
639 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
640 | case SND_SOC_DAIFMT_I2S: | ||
641 | format = 0x2; | ||
642 | break; | ||
643 | case SND_SOC_DAIFMT_RIGHT_J: | ||
644 | format = 0x0; | ||
645 | break; | ||
646 | case SND_SOC_DAIFMT_LEFT_J: | ||
647 | format = 0x1; | ||
648 | break; | ||
649 | case SND_SOC_DAIFMT_DSP_A: | ||
650 | case SND_SOC_DAIFMT_DSP_B: | ||
651 | format = 0x3; | ||
652 | break; | ||
653 | default: | ||
654 | dev_err(dai->dev, "Unknown dai format\n"); | ||
655 | return -EINVAL; | ||
656 | } | ||
657 | |||
658 | snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE, | ||
659 | WM8983_FMT_MASK, format << WM8983_FMT_SHIFT); | ||
660 | |||
661 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
662 | case SND_SOC_DAIFMT_CBM_CFM: | ||
663 | master = 1; | ||
664 | break; | ||
665 | case SND_SOC_DAIFMT_CBS_CFS: | ||
666 | master = 0; | ||
667 | break; | ||
668 | default: | ||
669 | dev_err(dai->dev, "Unknown master/slave configuration\n"); | ||
670 | return -EINVAL; | ||
671 | } | ||
672 | |||
673 | snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, | ||
674 | WM8983_MS_MASK, master << WM8983_MS_SHIFT); | ||
675 | |||
676 | /* FIXME: We don't currently support DSP A/B modes */ | ||
677 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
678 | case SND_SOC_DAIFMT_DSP_A: | ||
679 | case SND_SOC_DAIFMT_DSP_B: | ||
680 | dev_err(dai->dev, "DSP A/B modes are not supported\n"); | ||
681 | return -EINVAL; | ||
682 | default: | ||
683 | break; | ||
684 | } | ||
685 | |||
686 | bcp = lrp = 0; | ||
687 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
688 | case SND_SOC_DAIFMT_NB_NF: | ||
689 | break; | ||
690 | case SND_SOC_DAIFMT_IB_IF: | ||
691 | bcp = lrp = 1; | ||
692 | break; | ||
693 | case SND_SOC_DAIFMT_IB_NF: | ||
694 | bcp = 1; | ||
695 | break; | ||
696 | case SND_SOC_DAIFMT_NB_IF: | ||
697 | lrp = 1; | ||
698 | break; | ||
699 | default: | ||
700 | dev_err(dai->dev, "Unknown polarity configuration\n"); | ||
701 | return -EINVAL; | ||
702 | } | ||
703 | |||
704 | snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE, | ||
705 | WM8983_LRCP_MASK, lrp << WM8983_LRCP_SHIFT); | ||
706 | snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE, | ||
707 | WM8983_BCP_MASK, bcp << WM8983_BCP_SHIFT); | ||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | static int wm8983_hw_params(struct snd_pcm_substream *substream, | ||
712 | struct snd_pcm_hw_params *params, | ||
713 | struct snd_soc_dai *dai) | ||
714 | { | ||
715 | int i; | ||
716 | struct snd_soc_codec *codec = dai->codec; | ||
717 | struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); | ||
718 | u16 blen, srate_idx; | ||
719 | u32 tmp; | ||
720 | int srate_best; | ||
721 | int ret; | ||
722 | |||
723 | ret = snd_soc_params_to_bclk(params); | ||
724 | if (ret < 0) { | ||
725 | dev_err(codec->dev, "Failed to convert params to bclk: %d\n", ret); | ||
726 | return ret; | ||
727 | } | ||
728 | |||
729 | wm8983->bclk = ret; | ||
730 | |||
731 | switch (params_format(params)) { | ||
732 | case SNDRV_PCM_FORMAT_S16_LE: | ||
733 | blen = 0x0; | ||
734 | break; | ||
735 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
736 | blen = 0x1; | ||
737 | break; | ||
738 | case SNDRV_PCM_FORMAT_S24_LE: | ||
739 | blen = 0x2; | ||
740 | break; | ||
741 | case SNDRV_PCM_FORMAT_S32_LE: | ||
742 | blen = 0x3; | ||
743 | break; | ||
744 | default: | ||
745 | dev_err(dai->dev, "Unsupported word length %u\n", | ||
746 | params_format(params)); | ||
747 | return -EINVAL; | ||
748 | } | ||
749 | |||
750 | snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE, | ||
751 | WM8983_WL_MASK, blen << WM8983_WL_SHIFT); | ||
752 | |||
753 | /* | ||
754 | * match to the nearest possible sample rate and rely | ||
755 | * on the array index to configure the SR register | ||
756 | */ | ||
757 | srate_idx = 0; | ||
758 | srate_best = abs(srates[0] - params_rate(params)); | ||
759 | for (i = 1; i < ARRAY_SIZE(srates); ++i) { | ||
760 | if (abs(srates[i] - params_rate(params)) >= srate_best) | ||
761 | continue; | ||
762 | srate_idx = i; | ||
763 | srate_best = abs(srates[i] - params_rate(params)); | ||
764 | } | ||
765 | |||
766 | dev_dbg(dai->dev, "Selected SRATE = %d\n", srates[srate_idx]); | ||
767 | snd_soc_update_bits(codec, WM8983_ADDITIONAL_CONTROL, | ||
768 | WM8983_SR_MASK, srate_idx << WM8983_SR_SHIFT); | ||
769 | |||
770 | dev_dbg(dai->dev, "Target BCLK = %uHz\n", wm8983->bclk); | ||
771 | dev_dbg(dai->dev, "SYSCLK = %uHz\n", wm8983->sysclk); | ||
772 | |||
773 | for (i = 0; i < ARRAY_SIZE(fs_ratios); ++i) { | ||
774 | if (wm8983->sysclk / params_rate(params) | ||
775 | == fs_ratios[i].ratio) | ||
776 | break; | ||
777 | } | ||
778 | |||
779 | if (i == ARRAY_SIZE(fs_ratios)) { | ||
780 | dev_err(dai->dev, "Unable to configure MCLK ratio %u/%u\n", | ||
781 | wm8983->sysclk, params_rate(params)); | ||
782 | return -EINVAL; | ||
783 | } | ||
784 | |||
785 | dev_dbg(dai->dev, "MCLK ratio = %dfs\n", fs_ratios[i].ratio); | ||
786 | snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, | ||
787 | WM8983_MCLKDIV_MASK, i << WM8983_MCLKDIV_SHIFT); | ||
788 | |||
789 | /* select the appropriate bclk divider */ | ||
790 | tmp = (wm8983->sysclk / fs_ratios[i].div) * 10; | ||
791 | for (i = 0; i < ARRAY_SIZE(bclk_divs); ++i) { | ||
792 | if (wm8983->bclk == tmp / bclk_divs[i]) | ||
793 | break; | ||
794 | } | ||
795 | |||
796 | if (i == ARRAY_SIZE(bclk_divs)) { | ||
797 | dev_err(dai->dev, "No matching BCLK divider found\n"); | ||
798 | return -EINVAL; | ||
799 | } | ||
800 | |||
801 | dev_dbg(dai->dev, "BCLK div = %d\n", i); | ||
802 | snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, | ||
803 | WM8983_BCLKDIV_MASK, i << WM8983_BCLKDIV_SHIFT); | ||
804 | |||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | struct pll_div { | ||
809 | u32 div2:1; | ||
810 | u32 n:4; | ||
811 | u32 k:24; | ||
812 | }; | ||
813 | |||
814 | #define FIXED_PLL_SIZE ((1ULL << 24) * 10) | ||
815 | static int pll_factors(struct pll_div *pll_div, unsigned int target, | ||
816 | unsigned int source) | ||
817 | { | ||
818 | u64 Kpart; | ||
819 | unsigned long int K, Ndiv, Nmod; | ||
820 | |||
821 | pll_div->div2 = 0; | ||
822 | Ndiv = target / source; | ||
823 | if (Ndiv < 6) { | ||
824 | source >>= 1; | ||
825 | pll_div->div2 = 1; | ||
826 | Ndiv = target / source; | ||
827 | } | ||
828 | |||
829 | if (Ndiv < 6 || Ndiv > 12) { | ||
830 | printk(KERN_ERR "%s: WM8983 N value is not within" | ||
831 | " the recommended range: %lu\n", __func__, Ndiv); | ||
832 | return -EINVAL; | ||
833 | } | ||
834 | pll_div->n = Ndiv; | ||
835 | |||
836 | Nmod = target % source; | ||
837 | Kpart = FIXED_PLL_SIZE * (u64)Nmod; | ||
838 | |||
839 | do_div(Kpart, source); | ||
840 | |||
841 | K = Kpart & 0xffffffff; | ||
842 | if ((K % 10) >= 5) | ||
843 | K += 5; | ||
844 | K /= 10; | ||
845 | pll_div->k = K; | ||
846 | return 0; | ||
847 | } | ||
848 | |||
849 | static int wm8983_set_pll(struct snd_soc_dai *dai, int pll_id, | ||
850 | int source, unsigned int freq_in, | ||
851 | unsigned int freq_out) | ||
852 | { | ||
853 | int ret; | ||
854 | struct snd_soc_codec *codec; | ||
855 | struct pll_div pll_div; | ||
856 | |||
857 | codec = dai->codec; | ||
858 | if (freq_in && freq_out) { | ||
859 | ret = pll_factors(&pll_div, freq_out * 4 * 2, freq_in); | ||
860 | if (ret) | ||
861 | return ret; | ||
862 | } | ||
863 | |||
864 | /* disable the PLL before re-programming it */ | ||
865 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
866 | WM8983_PLLEN_MASK, 0); | ||
867 | |||
868 | if (!freq_in || !freq_out) | ||
869 | return 0; | ||
870 | |||
871 | /* set PLLN and PRESCALE */ | ||
872 | snd_soc_write(codec, WM8983_PLL_N, | ||
873 | (pll_div.div2 << WM8983_PLL_PRESCALE_SHIFT) | ||
874 | | pll_div.n); | ||
875 | /* set PLLK */ | ||
876 | snd_soc_write(codec, WM8983_PLL_K_3, pll_div.k & 0x1ff); | ||
877 | snd_soc_write(codec, WM8983_PLL_K_2, (pll_div.k >> 9) & 0x1ff); | ||
878 | snd_soc_write(codec, WM8983_PLL_K_1, (pll_div.k >> 18)); | ||
879 | /* enable the PLL */ | ||
880 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
881 | WM8983_PLLEN_MASK, WM8983_PLLEN); | ||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | static int wm8983_set_sysclk(struct snd_soc_dai *dai, | ||
886 | int clk_id, unsigned int freq, int dir) | ||
887 | { | ||
888 | struct snd_soc_codec *codec = dai->codec; | ||
889 | struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); | ||
890 | |||
891 | switch (clk_id) { | ||
892 | case WM8983_CLKSRC_MCLK: | ||
893 | snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, | ||
894 | WM8983_CLKSEL_MASK, 0); | ||
895 | break; | ||
896 | case WM8983_CLKSRC_PLL: | ||
897 | snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, | ||
898 | WM8983_CLKSEL_MASK, WM8983_CLKSEL); | ||
899 | break; | ||
900 | default: | ||
901 | dev_err(dai->dev, "Unknown clock source: %d\n", clk_id); | ||
902 | return -EINVAL; | ||
903 | } | ||
904 | |||
905 | wm8983->sysclk = freq; | ||
906 | return 0; | ||
907 | } | ||
908 | |||
909 | static int wm8983_set_bias_level(struct snd_soc_codec *codec, | ||
910 | enum snd_soc_bias_level level) | ||
911 | { | ||
912 | int ret; | ||
913 | |||
914 | switch (level) { | ||
915 | case SND_SOC_BIAS_ON: | ||
916 | case SND_SOC_BIAS_PREPARE: | ||
917 | /* VMID at 100k */ | ||
918 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
919 | WM8983_VMIDSEL_MASK, | ||
920 | 1 << WM8983_VMIDSEL_SHIFT); | ||
921 | break; | ||
922 | case SND_SOC_BIAS_STANDBY: | ||
923 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
924 | ret = snd_soc_cache_sync(codec); | ||
925 | if (ret < 0) { | ||
926 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); | ||
927 | return ret; | ||
928 | } | ||
929 | /* enable anti-pop features */ | ||
930 | snd_soc_update_bits(codec, WM8983_OUT4_TO_ADC, | ||
931 | WM8983_POBCTRL_MASK | WM8983_DELEN_MASK, | ||
932 | WM8983_POBCTRL | WM8983_DELEN); | ||
933 | /* enable thermal shutdown */ | ||
934 | snd_soc_update_bits(codec, WM8983_OUTPUT_CTRL, | ||
935 | WM8983_TSDEN_MASK, WM8983_TSDEN); | ||
936 | /* enable BIASEN */ | ||
937 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
938 | WM8983_BIASEN_MASK, WM8983_BIASEN); | ||
939 | /* VMID at 100k */ | ||
940 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
941 | WM8983_VMIDSEL_MASK, | ||
942 | 1 << WM8983_VMIDSEL_SHIFT); | ||
943 | msleep(250); | ||
944 | /* disable anti-pop features */ | ||
945 | snd_soc_update_bits(codec, WM8983_OUT4_TO_ADC, | ||
946 | WM8983_POBCTRL_MASK | | ||
947 | WM8983_DELEN_MASK, 0); | ||
948 | } | ||
949 | |||
950 | /* VMID at 500k */ | ||
951 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
952 | WM8983_VMIDSEL_MASK, | ||
953 | 2 << WM8983_VMIDSEL_SHIFT); | ||
954 | break; | ||
955 | case SND_SOC_BIAS_OFF: | ||
956 | /* disable thermal shutdown */ | ||
957 | snd_soc_update_bits(codec, WM8983_OUTPUT_CTRL, | ||
958 | WM8983_TSDEN_MASK, 0); | ||
959 | /* disable VMIDSEL and BIASEN */ | ||
960 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
961 | WM8983_VMIDSEL_MASK | WM8983_BIASEN_MASK, | ||
962 | 0); | ||
963 | /* wait for VMID to discharge */ | ||
964 | msleep(100); | ||
965 | snd_soc_write(codec, WM8983_POWER_MANAGEMENT_1, 0); | ||
966 | snd_soc_write(codec, WM8983_POWER_MANAGEMENT_2, 0); | ||
967 | snd_soc_write(codec, WM8983_POWER_MANAGEMENT_3, 0); | ||
968 | break; | ||
969 | } | ||
970 | |||
971 | codec->dapm.bias_level = level; | ||
972 | return 0; | ||
973 | } | ||
974 | |||
975 | #ifdef CONFIG_PM | ||
976 | static int wm8983_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
977 | { | ||
978 | wm8983_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
979 | return 0; | ||
980 | } | ||
981 | |||
982 | static int wm8983_resume(struct snd_soc_codec *codec) | ||
983 | { | ||
984 | wm8983_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
985 | return 0; | ||
986 | } | ||
987 | #else | ||
988 | #define wm8983_suspend NULL | ||
989 | #define wm8983_resume NULL | ||
990 | #endif | ||
991 | |||
992 | static int wm8983_remove(struct snd_soc_codec *codec) | ||
993 | { | ||
994 | wm8983_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
995 | return 0; | ||
996 | } | ||
997 | |||
998 | static int wm8983_probe(struct snd_soc_codec *codec) | ||
999 | { | ||
1000 | int ret; | ||
1001 | struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); | ||
1002 | int i; | ||
1003 | |||
1004 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8983->control_type); | ||
1005 | if (ret < 0) { | ||
1006 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); | ||
1007 | return ret; | ||
1008 | } | ||
1009 | |||
1010 | ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0x8983); | ||
1011 | if (ret < 0) { | ||
1012 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | ||
1013 | return ret; | ||
1014 | } | ||
1015 | |||
1016 | /* set the vol/gain update bits */ | ||
1017 | for (i = 0; i < ARRAY_SIZE(vol_update_regs); ++i) | ||
1018 | snd_soc_update_bits(codec, vol_update_regs[i], | ||
1019 | 0x100, 0x100); | ||
1020 | |||
1021 | /* mute all outputs and set PGAs to minimum gain */ | ||
1022 | for (i = WM8983_LOUT1_HP_VOLUME_CTRL; | ||
1023 | i <= WM8983_OUT4_MONO_MIX_CTRL; ++i) | ||
1024 | snd_soc_update_bits(codec, i, 0x40, 0x40); | ||
1025 | |||
1026 | /* enable soft mute */ | ||
1027 | snd_soc_update_bits(codec, WM8983_DAC_CONTROL, | ||
1028 | WM8983_SOFTMUTE_MASK, | ||
1029 | WM8983_SOFTMUTE); | ||
1030 | |||
1031 | /* enable BIASCUT */ | ||
1032 | snd_soc_update_bits(codec, WM8983_BIAS_CTRL, | ||
1033 | WM8983_BIASCUT, WM8983_BIASCUT); | ||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | static struct snd_soc_dai_ops wm8983_dai_ops = { | ||
1038 | .digital_mute = wm8983_dac_mute, | ||
1039 | .hw_params = wm8983_hw_params, | ||
1040 | .set_fmt = wm8983_set_fmt, | ||
1041 | .set_sysclk = wm8983_set_sysclk, | ||
1042 | .set_pll = wm8983_set_pll | ||
1043 | }; | ||
1044 | |||
1045 | #define WM8983_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
1046 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
1047 | |||
1048 | static struct snd_soc_dai_driver wm8983_dai = { | ||
1049 | .name = "wm8983-hifi", | ||
1050 | .playback = { | ||
1051 | .stream_name = "Playback", | ||
1052 | .channels_min = 2, | ||
1053 | .channels_max = 2, | ||
1054 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1055 | .formats = WM8983_FORMATS, | ||
1056 | }, | ||
1057 | .capture = { | ||
1058 | .stream_name = "Capture", | ||
1059 | .channels_min = 2, | ||
1060 | .channels_max = 2, | ||
1061 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1062 | .formats = WM8983_FORMATS, | ||
1063 | }, | ||
1064 | .ops = &wm8983_dai_ops, | ||
1065 | .symmetric_rates = 1 | ||
1066 | }; | ||
1067 | |||
1068 | static struct snd_soc_codec_driver soc_codec_dev_wm8983 = { | ||
1069 | .probe = wm8983_probe, | ||
1070 | .remove = wm8983_remove, | ||
1071 | .suspend = wm8983_suspend, | ||
1072 | .resume = wm8983_resume, | ||
1073 | .set_bias_level = wm8983_set_bias_level, | ||
1074 | .reg_cache_size = ARRAY_SIZE(wm8983_reg_defs), | ||
1075 | .reg_word_size = sizeof(u16), | ||
1076 | .reg_cache_default = wm8983_reg_defs, | ||
1077 | .controls = wm8983_snd_controls, | ||
1078 | .num_controls = ARRAY_SIZE(wm8983_snd_controls), | ||
1079 | .dapm_widgets = wm8983_dapm_widgets, | ||
1080 | .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), | ||
1081 | .dapm_routes = wm8983_audio_map, | ||
1082 | .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), | ||
1083 | .readable_register = wm8983_readable | ||
1084 | }; | ||
1085 | |||
1086 | #if defined(CONFIG_SPI_MASTER) | ||
1087 | static int __devinit wm8983_spi_probe(struct spi_device *spi) | ||
1088 | { | ||
1089 | struct wm8983_priv *wm8983; | ||
1090 | int ret; | ||
1091 | |||
1092 | wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); | ||
1093 | if (!wm8983) | ||
1094 | return -ENOMEM; | ||
1095 | |||
1096 | wm8983->control_type = SND_SOC_SPI; | ||
1097 | spi_set_drvdata(spi, wm8983); | ||
1098 | |||
1099 | ret = snd_soc_register_codec(&spi->dev, | ||
1100 | &soc_codec_dev_wm8983, &wm8983_dai, 1); | ||
1101 | if (ret < 0) | ||
1102 | kfree(wm8983); | ||
1103 | return ret; | ||
1104 | } | ||
1105 | |||
1106 | static int __devexit wm8983_spi_remove(struct spi_device *spi) | ||
1107 | { | ||
1108 | snd_soc_unregister_codec(&spi->dev); | ||
1109 | kfree(spi_get_drvdata(spi)); | ||
1110 | return 0; | ||
1111 | } | ||
1112 | |||
1113 | static struct spi_driver wm8983_spi_driver = { | ||
1114 | .driver = { | ||
1115 | .name = "wm8983", | ||
1116 | .owner = THIS_MODULE, | ||
1117 | }, | ||
1118 | .probe = wm8983_spi_probe, | ||
1119 | .remove = __devexit_p(wm8983_spi_remove) | ||
1120 | }; | ||
1121 | #endif | ||
1122 | |||
1123 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1124 | static __devinit int wm8983_i2c_probe(struct i2c_client *i2c, | ||
1125 | const struct i2c_device_id *id) | ||
1126 | { | ||
1127 | struct wm8983_priv *wm8983; | ||
1128 | int ret; | ||
1129 | |||
1130 | wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); | ||
1131 | if (!wm8983) | ||
1132 | return -ENOMEM; | ||
1133 | |||
1134 | wm8983->control_type = SND_SOC_I2C; | ||
1135 | i2c_set_clientdata(i2c, wm8983); | ||
1136 | |||
1137 | ret = snd_soc_register_codec(&i2c->dev, | ||
1138 | &soc_codec_dev_wm8983, &wm8983_dai, 1); | ||
1139 | if (ret < 0) | ||
1140 | kfree(wm8983); | ||
1141 | return ret; | ||
1142 | } | ||
1143 | |||
1144 | static __devexit int wm8983_i2c_remove(struct i2c_client *client) | ||
1145 | { | ||
1146 | snd_soc_unregister_codec(&client->dev); | ||
1147 | kfree(i2c_get_clientdata(client)); | ||
1148 | return 0; | ||
1149 | } | ||
1150 | |||
1151 | static const struct i2c_device_id wm8983_i2c_id[] = { | ||
1152 | { "wm8983", 0 }, | ||
1153 | { } | ||
1154 | }; | ||
1155 | MODULE_DEVICE_TABLE(i2c, wm8983_i2c_id); | ||
1156 | |||
1157 | static struct i2c_driver wm8983_i2c_driver = { | ||
1158 | .driver = { | ||
1159 | .name = "wm8983", | ||
1160 | .owner = THIS_MODULE, | ||
1161 | }, | ||
1162 | .probe = wm8983_i2c_probe, | ||
1163 | .remove = __devexit_p(wm8983_i2c_remove), | ||
1164 | .id_table = wm8983_i2c_id | ||
1165 | }; | ||
1166 | #endif | ||
1167 | |||
1168 | static int __init wm8983_modinit(void) | ||
1169 | { | ||
1170 | int ret = 0; | ||
1171 | |||
1172 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1173 | ret = i2c_add_driver(&wm8983_i2c_driver); | ||
1174 | if (ret) { | ||
1175 | printk(KERN_ERR "Failed to register wm8983 I2C driver: %d\n", | ||
1176 | ret); | ||
1177 | } | ||
1178 | #endif | ||
1179 | #if defined(CONFIG_SPI_MASTER) | ||
1180 | ret = spi_register_driver(&wm8983_spi_driver); | ||
1181 | if (ret != 0) { | ||
1182 | printk(KERN_ERR "Failed to register wm8983 SPI driver: %d\n", | ||
1183 | ret); | ||
1184 | } | ||
1185 | #endif | ||
1186 | return ret; | ||
1187 | } | ||
1188 | module_init(wm8983_modinit); | ||
1189 | |||
1190 | static void __exit wm8983_exit(void) | ||
1191 | { | ||
1192 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1193 | i2c_del_driver(&wm8983_i2c_driver); | ||
1194 | #endif | ||
1195 | #if defined(CONFIG_SPI_MASTER) | ||
1196 | spi_unregister_driver(&wm8983_spi_driver); | ||
1197 | #endif | ||
1198 | } | ||
1199 | module_exit(wm8983_exit); | ||
1200 | |||
1201 | MODULE_DESCRIPTION("ASoC WM8983 driver"); | ||
1202 | MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>"); | ||
1203 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm8983.h b/sound/soc/codecs/wm8983.h new file mode 100644 index 000000000000..71ee619c2742 --- /dev/null +++ b/sound/soc/codecs/wm8983.h | |||
@@ -0,0 +1,1029 @@ | |||
1 | /* | ||
2 | * wm8983.h -- WM8983 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2011 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef _WM8983_H | ||
14 | #define _WM8983_H | ||
15 | |||
16 | /* | ||
17 | * Register values. | ||
18 | */ | ||
19 | #define WM8983_SOFTWARE_RESET 0x00 | ||
20 | #define WM8983_POWER_MANAGEMENT_1 0x01 | ||
21 | #define WM8983_POWER_MANAGEMENT_2 0x02 | ||
22 | #define WM8983_POWER_MANAGEMENT_3 0x03 | ||
23 | #define WM8983_AUDIO_INTERFACE 0x04 | ||
24 | #define WM8983_COMPANDING_CONTROL 0x05 | ||
25 | #define WM8983_CLOCK_GEN_CONTROL 0x06 | ||
26 | #define WM8983_ADDITIONAL_CONTROL 0x07 | ||
27 | #define WM8983_GPIO_CONTROL 0x08 | ||
28 | #define WM8983_JACK_DETECT_CONTROL_1 0x09 | ||
29 | #define WM8983_DAC_CONTROL 0x0A | ||
30 | #define WM8983_LEFT_DAC_DIGITAL_VOL 0x0B | ||
31 | #define WM8983_RIGHT_DAC_DIGITAL_VOL 0x0C | ||
32 | #define WM8983_JACK_DETECT_CONTROL_2 0x0D | ||
33 | #define WM8983_ADC_CONTROL 0x0E | ||
34 | #define WM8983_LEFT_ADC_DIGITAL_VOL 0x0F | ||
35 | #define WM8983_RIGHT_ADC_DIGITAL_VOL 0x10 | ||
36 | #define WM8983_EQ1_LOW_SHELF 0x12 | ||
37 | #define WM8983_EQ2_PEAK_1 0x13 | ||
38 | #define WM8983_EQ3_PEAK_2 0x14 | ||
39 | #define WM8983_EQ4_PEAK_3 0x15 | ||
40 | #define WM8983_EQ5_HIGH_SHELF 0x16 | ||
41 | #define WM8983_DAC_LIMITER_1 0x18 | ||
42 | #define WM8983_DAC_LIMITER_2 0x19 | ||
43 | #define WM8983_NOTCH_FILTER_1 0x1B | ||
44 | #define WM8983_NOTCH_FILTER_2 0x1C | ||
45 | #define WM8983_NOTCH_FILTER_3 0x1D | ||
46 | #define WM8983_NOTCH_FILTER_4 0x1E | ||
47 | #define WM8983_ALC_CONTROL_1 0x20 | ||
48 | #define WM8983_ALC_CONTROL_2 0x21 | ||
49 | #define WM8983_ALC_CONTROL_3 0x22 | ||
50 | #define WM8983_NOISE_GATE 0x23 | ||
51 | #define WM8983_PLL_N 0x24 | ||
52 | #define WM8983_PLL_K_1 0x25 | ||
53 | #define WM8983_PLL_K_2 0x26 | ||
54 | #define WM8983_PLL_K_3 0x27 | ||
55 | #define WM8983_3D_CONTROL 0x29 | ||
56 | #define WM8983_OUT4_TO_ADC 0x2A | ||
57 | #define WM8983_BEEP_CONTROL 0x2B | ||
58 | #define WM8983_INPUT_CTRL 0x2C | ||
59 | #define WM8983_LEFT_INP_PGA_GAIN_CTRL 0x2D | ||
60 | #define WM8983_RIGHT_INP_PGA_GAIN_CTRL 0x2E | ||
61 | #define WM8983_LEFT_ADC_BOOST_CTRL 0x2F | ||
62 | #define WM8983_RIGHT_ADC_BOOST_CTRL 0x30 | ||
63 | #define WM8983_OUTPUT_CTRL 0x31 | ||
64 | #define WM8983_LEFT_MIXER_CTRL 0x32 | ||
65 | #define WM8983_RIGHT_MIXER_CTRL 0x33 | ||
66 | #define WM8983_LOUT1_HP_VOLUME_CTRL 0x34 | ||
67 | #define WM8983_ROUT1_HP_VOLUME_CTRL 0x35 | ||
68 | #define WM8983_LOUT2_SPK_VOLUME_CTRL 0x36 | ||
69 | #define WM8983_ROUT2_SPK_VOLUME_CTRL 0x37 | ||
70 | #define WM8983_OUT3_MIXER_CTRL 0x38 | ||
71 | #define WM8983_OUT4_MONO_MIX_CTRL 0x39 | ||
72 | #define WM8983_BIAS_CTRL 0x3D | ||
73 | |||
74 | #define WM8983_REGISTER_COUNT 59 | ||
75 | #define WM8983_MAX_REGISTER 0x3F | ||
76 | |||
77 | /* | ||
78 | * Field Definitions. | ||
79 | */ | ||
80 | |||
81 | /* | ||
82 | * R0 (0x00) - Software Reset | ||
83 | */ | ||
84 | #define WM8983_SOFTWARE_RESET_MASK 0x01FF /* SOFTWARE_RESET - [8:0] */ | ||
85 | #define WM8983_SOFTWARE_RESET_SHIFT 0 /* SOFTWARE_RESET - [8:0] */ | ||
86 | #define WM8983_SOFTWARE_RESET_WIDTH 9 /* SOFTWARE_RESET - [8:0] */ | ||
87 | |||
88 | /* | ||
89 | * R1 (0x01) - Power management 1 | ||
90 | */ | ||
91 | #define WM8983_BUFDCOPEN 0x0100 /* BUFDCOPEN */ | ||
92 | #define WM8983_BUFDCOPEN_MASK 0x0100 /* BUFDCOPEN */ | ||
93 | #define WM8983_BUFDCOPEN_SHIFT 8 /* BUFDCOPEN */ | ||
94 | #define WM8983_BUFDCOPEN_WIDTH 1 /* BUFDCOPEN */ | ||
95 | #define WM8983_OUT4MIXEN 0x0080 /* OUT4MIXEN */ | ||
96 | #define WM8983_OUT4MIXEN_MASK 0x0080 /* OUT4MIXEN */ | ||
97 | #define WM8983_OUT4MIXEN_SHIFT 7 /* OUT4MIXEN */ | ||
98 | #define WM8983_OUT4MIXEN_WIDTH 1 /* OUT4MIXEN */ | ||
99 | #define WM8983_OUT3MIXEN 0x0040 /* OUT3MIXEN */ | ||
100 | #define WM8983_OUT3MIXEN_MASK 0x0040 /* OUT3MIXEN */ | ||
101 | #define WM8983_OUT3MIXEN_SHIFT 6 /* OUT3MIXEN */ | ||
102 | #define WM8983_OUT3MIXEN_WIDTH 1 /* OUT3MIXEN */ | ||
103 | #define WM8983_PLLEN 0x0020 /* PLLEN */ | ||
104 | #define WM8983_PLLEN_MASK 0x0020 /* PLLEN */ | ||
105 | #define WM8983_PLLEN_SHIFT 5 /* PLLEN */ | ||
106 | #define WM8983_PLLEN_WIDTH 1 /* PLLEN */ | ||
107 | #define WM8983_MICBEN 0x0010 /* MICBEN */ | ||
108 | #define WM8983_MICBEN_MASK 0x0010 /* MICBEN */ | ||
109 | #define WM8983_MICBEN_SHIFT 4 /* MICBEN */ | ||
110 | #define WM8983_MICBEN_WIDTH 1 /* MICBEN */ | ||
111 | #define WM8983_BIASEN 0x0008 /* BIASEN */ | ||
112 | #define WM8983_BIASEN_MASK 0x0008 /* BIASEN */ | ||
113 | #define WM8983_BIASEN_SHIFT 3 /* BIASEN */ | ||
114 | #define WM8983_BIASEN_WIDTH 1 /* BIASEN */ | ||
115 | #define WM8983_BUFIOEN 0x0004 /* BUFIOEN */ | ||
116 | #define WM8983_BUFIOEN_MASK 0x0004 /* BUFIOEN */ | ||
117 | #define WM8983_BUFIOEN_SHIFT 2 /* BUFIOEN */ | ||
118 | #define WM8983_BUFIOEN_WIDTH 1 /* BUFIOEN */ | ||
119 | #define WM8983_VMIDSEL_MASK 0x0003 /* VMIDSEL - [1:0] */ | ||
120 | #define WM8983_VMIDSEL_SHIFT 0 /* VMIDSEL - [1:0] */ | ||
121 | #define WM8983_VMIDSEL_WIDTH 2 /* VMIDSEL - [1:0] */ | ||
122 | |||
123 | /* | ||
124 | * R2 (0x02) - Power management 2 | ||
125 | */ | ||
126 | #define WM8983_ROUT1EN 0x0100 /* ROUT1EN */ | ||
127 | #define WM8983_ROUT1EN_MASK 0x0100 /* ROUT1EN */ | ||
128 | #define WM8983_ROUT1EN_SHIFT 8 /* ROUT1EN */ | ||
129 | #define WM8983_ROUT1EN_WIDTH 1 /* ROUT1EN */ | ||
130 | #define WM8983_LOUT1EN 0x0080 /* LOUT1EN */ | ||
131 | #define WM8983_LOUT1EN_MASK 0x0080 /* LOUT1EN */ | ||
132 | #define WM8983_LOUT1EN_SHIFT 7 /* LOUT1EN */ | ||
133 | #define WM8983_LOUT1EN_WIDTH 1 /* LOUT1EN */ | ||
134 | #define WM8983_SLEEP 0x0040 /* SLEEP */ | ||
135 | #define WM8983_SLEEP_MASK 0x0040 /* SLEEP */ | ||
136 | #define WM8983_SLEEP_SHIFT 6 /* SLEEP */ | ||
137 | #define WM8983_SLEEP_WIDTH 1 /* SLEEP */ | ||
138 | #define WM8983_BOOSTENR 0x0020 /* BOOSTENR */ | ||
139 | #define WM8983_BOOSTENR_MASK 0x0020 /* BOOSTENR */ | ||
140 | #define WM8983_BOOSTENR_SHIFT 5 /* BOOSTENR */ | ||
141 | #define WM8983_BOOSTENR_WIDTH 1 /* BOOSTENR */ | ||
142 | #define WM8983_BOOSTENL 0x0010 /* BOOSTENL */ | ||
143 | #define WM8983_BOOSTENL_MASK 0x0010 /* BOOSTENL */ | ||
144 | #define WM8983_BOOSTENL_SHIFT 4 /* BOOSTENL */ | ||
145 | #define WM8983_BOOSTENL_WIDTH 1 /* BOOSTENL */ | ||
146 | #define WM8983_INPGAENR 0x0008 /* INPGAENR */ | ||
147 | #define WM8983_INPGAENR_MASK 0x0008 /* INPGAENR */ | ||
148 | #define WM8983_INPGAENR_SHIFT 3 /* INPGAENR */ | ||
149 | #define WM8983_INPGAENR_WIDTH 1 /* INPGAENR */ | ||
150 | #define WM8983_INPPGAENL 0x0004 /* INPPGAENL */ | ||
151 | #define WM8983_INPPGAENL_MASK 0x0004 /* INPPGAENL */ | ||
152 | #define WM8983_INPPGAENL_SHIFT 2 /* INPPGAENL */ | ||
153 | #define WM8983_INPPGAENL_WIDTH 1 /* INPPGAENL */ | ||
154 | #define WM8983_ADCENR 0x0002 /* ADCENR */ | ||
155 | #define WM8983_ADCENR_MASK 0x0002 /* ADCENR */ | ||
156 | #define WM8983_ADCENR_SHIFT 1 /* ADCENR */ | ||
157 | #define WM8983_ADCENR_WIDTH 1 /* ADCENR */ | ||
158 | #define WM8983_ADCENL 0x0001 /* ADCENL */ | ||
159 | #define WM8983_ADCENL_MASK 0x0001 /* ADCENL */ | ||
160 | #define WM8983_ADCENL_SHIFT 0 /* ADCENL */ | ||
161 | #define WM8983_ADCENL_WIDTH 1 /* ADCENL */ | ||
162 | |||
163 | /* | ||
164 | * R3 (0x03) - Power management 3 | ||
165 | */ | ||
166 | #define WM8983_OUT4EN 0x0100 /* OUT4EN */ | ||
167 | #define WM8983_OUT4EN_MASK 0x0100 /* OUT4EN */ | ||
168 | #define WM8983_OUT4EN_SHIFT 8 /* OUT4EN */ | ||
169 | #define WM8983_OUT4EN_WIDTH 1 /* OUT4EN */ | ||
170 | #define WM8983_OUT3EN 0x0080 /* OUT3EN */ | ||
171 | #define WM8983_OUT3EN_MASK 0x0080 /* OUT3EN */ | ||
172 | #define WM8983_OUT3EN_SHIFT 7 /* OUT3EN */ | ||
173 | #define WM8983_OUT3EN_WIDTH 1 /* OUT3EN */ | ||
174 | #define WM8983_LOUT2EN 0x0040 /* LOUT2EN */ | ||
175 | #define WM8983_LOUT2EN_MASK 0x0040 /* LOUT2EN */ | ||
176 | #define WM8983_LOUT2EN_SHIFT 6 /* LOUT2EN */ | ||
177 | #define WM8983_LOUT2EN_WIDTH 1 /* LOUT2EN */ | ||
178 | #define WM8983_ROUT2EN 0x0020 /* ROUT2EN */ | ||
179 | #define WM8983_ROUT2EN_MASK 0x0020 /* ROUT2EN */ | ||
180 | #define WM8983_ROUT2EN_SHIFT 5 /* ROUT2EN */ | ||
181 | #define WM8983_ROUT2EN_WIDTH 1 /* ROUT2EN */ | ||
182 | #define WM8983_RMIXEN 0x0008 /* RMIXEN */ | ||
183 | #define WM8983_RMIXEN_MASK 0x0008 /* RMIXEN */ | ||
184 | #define WM8983_RMIXEN_SHIFT 3 /* RMIXEN */ | ||
185 | #define WM8983_RMIXEN_WIDTH 1 /* RMIXEN */ | ||
186 | #define WM8983_LMIXEN 0x0004 /* LMIXEN */ | ||
187 | #define WM8983_LMIXEN_MASK 0x0004 /* LMIXEN */ | ||
188 | #define WM8983_LMIXEN_SHIFT 2 /* LMIXEN */ | ||
189 | #define WM8983_LMIXEN_WIDTH 1 /* LMIXEN */ | ||
190 | #define WM8983_DACENR 0x0002 /* DACENR */ | ||
191 | #define WM8983_DACENR_MASK 0x0002 /* DACENR */ | ||
192 | #define WM8983_DACENR_SHIFT 1 /* DACENR */ | ||
193 | #define WM8983_DACENR_WIDTH 1 /* DACENR */ | ||
194 | #define WM8983_DACENL 0x0001 /* DACENL */ | ||
195 | #define WM8983_DACENL_MASK 0x0001 /* DACENL */ | ||
196 | #define WM8983_DACENL_SHIFT 0 /* DACENL */ | ||
197 | #define WM8983_DACENL_WIDTH 1 /* DACENL */ | ||
198 | |||
199 | /* | ||
200 | * R4 (0x04) - Audio Interface | ||
201 | */ | ||
202 | #define WM8983_BCP 0x0100 /* BCP */ | ||
203 | #define WM8983_BCP_MASK 0x0100 /* BCP */ | ||
204 | #define WM8983_BCP_SHIFT 8 /* BCP */ | ||
205 | #define WM8983_BCP_WIDTH 1 /* BCP */ | ||
206 | #define WM8983_LRCP 0x0080 /* LRCP */ | ||
207 | #define WM8983_LRCP_MASK 0x0080 /* LRCP */ | ||
208 | #define WM8983_LRCP_SHIFT 7 /* LRCP */ | ||
209 | #define WM8983_LRCP_WIDTH 1 /* LRCP */ | ||
210 | #define WM8983_WL_MASK 0x0060 /* WL - [6:5] */ | ||
211 | #define WM8983_WL_SHIFT 5 /* WL - [6:5] */ | ||
212 | #define WM8983_WL_WIDTH 2 /* WL - [6:5] */ | ||
213 | #define WM8983_FMT_MASK 0x0018 /* FMT - [4:3] */ | ||
214 | #define WM8983_FMT_SHIFT 3 /* FMT - [4:3] */ | ||
215 | #define WM8983_FMT_WIDTH 2 /* FMT - [4:3] */ | ||
216 | #define WM8983_DLRSWAP 0x0004 /* DLRSWAP */ | ||
217 | #define WM8983_DLRSWAP_MASK 0x0004 /* DLRSWAP */ | ||
218 | #define WM8983_DLRSWAP_SHIFT 2 /* DLRSWAP */ | ||
219 | #define WM8983_DLRSWAP_WIDTH 1 /* DLRSWAP */ | ||
220 | #define WM8983_ALRSWAP 0x0002 /* ALRSWAP */ | ||
221 | #define WM8983_ALRSWAP_MASK 0x0002 /* ALRSWAP */ | ||
222 | #define WM8983_ALRSWAP_SHIFT 1 /* ALRSWAP */ | ||
223 | #define WM8983_ALRSWAP_WIDTH 1 /* ALRSWAP */ | ||
224 | #define WM8983_MONO 0x0001 /* MONO */ | ||
225 | #define WM8983_MONO_MASK 0x0001 /* MONO */ | ||
226 | #define WM8983_MONO_SHIFT 0 /* MONO */ | ||
227 | #define WM8983_MONO_WIDTH 1 /* MONO */ | ||
228 | |||
229 | /* | ||
230 | * R5 (0x05) - Companding control | ||
231 | */ | ||
232 | #define WM8983_WL8 0x0020 /* WL8 */ | ||
233 | #define WM8983_WL8_MASK 0x0020 /* WL8 */ | ||
234 | #define WM8983_WL8_SHIFT 5 /* WL8 */ | ||
235 | #define WM8983_WL8_WIDTH 1 /* WL8 */ | ||
236 | #define WM8983_DAC_COMP_MASK 0x0018 /* DAC_COMP - [4:3] */ | ||
237 | #define WM8983_DAC_COMP_SHIFT 3 /* DAC_COMP - [4:3] */ | ||
238 | #define WM8983_DAC_COMP_WIDTH 2 /* DAC_COMP - [4:3] */ | ||
239 | #define WM8983_ADC_COMP_MASK 0x0006 /* ADC_COMP - [2:1] */ | ||
240 | #define WM8983_ADC_COMP_SHIFT 1 /* ADC_COMP - [2:1] */ | ||
241 | #define WM8983_ADC_COMP_WIDTH 2 /* ADC_COMP - [2:1] */ | ||
242 | #define WM8983_LOOPBACK 0x0001 /* LOOPBACK */ | ||
243 | #define WM8983_LOOPBACK_MASK 0x0001 /* LOOPBACK */ | ||
244 | #define WM8983_LOOPBACK_SHIFT 0 /* LOOPBACK */ | ||
245 | #define WM8983_LOOPBACK_WIDTH 1 /* LOOPBACK */ | ||
246 | |||
247 | /* | ||
248 | * R6 (0x06) - Clock Gen control | ||
249 | */ | ||
250 | #define WM8983_CLKSEL 0x0100 /* CLKSEL */ | ||
251 | #define WM8983_CLKSEL_MASK 0x0100 /* CLKSEL */ | ||
252 | #define WM8983_CLKSEL_SHIFT 8 /* CLKSEL */ | ||
253 | #define WM8983_CLKSEL_WIDTH 1 /* CLKSEL */ | ||
254 | #define WM8983_MCLKDIV_MASK 0x00E0 /* MCLKDIV - [7:5] */ | ||
255 | #define WM8983_MCLKDIV_SHIFT 5 /* MCLKDIV - [7:5] */ | ||
256 | #define WM8983_MCLKDIV_WIDTH 3 /* MCLKDIV - [7:5] */ | ||
257 | #define WM8983_BCLKDIV_MASK 0x001C /* BCLKDIV - [4:2] */ | ||
258 | #define WM8983_BCLKDIV_SHIFT 2 /* BCLKDIV - [4:2] */ | ||
259 | #define WM8983_BCLKDIV_WIDTH 3 /* BCLKDIV - [4:2] */ | ||
260 | #define WM8983_MS 0x0001 /* MS */ | ||
261 | #define WM8983_MS_MASK 0x0001 /* MS */ | ||
262 | #define WM8983_MS_SHIFT 0 /* MS */ | ||
263 | #define WM8983_MS_WIDTH 1 /* MS */ | ||
264 | |||
265 | /* | ||
266 | * R7 (0x07) - Additional control | ||
267 | */ | ||
268 | #define WM8983_SR_MASK 0x000E /* SR - [3:1] */ | ||
269 | #define WM8983_SR_SHIFT 1 /* SR - [3:1] */ | ||
270 | #define WM8983_SR_WIDTH 3 /* SR - [3:1] */ | ||
271 | #define WM8983_SLOWCLKEN 0x0001 /* SLOWCLKEN */ | ||
272 | #define WM8983_SLOWCLKEN_MASK 0x0001 /* SLOWCLKEN */ | ||
273 | #define WM8983_SLOWCLKEN_SHIFT 0 /* SLOWCLKEN */ | ||
274 | #define WM8983_SLOWCLKEN_WIDTH 1 /* SLOWCLKEN */ | ||
275 | |||
276 | /* | ||
277 | * R8 (0x08) - GPIO Control | ||
278 | */ | ||
279 | #define WM8983_OPCLKDIV_MASK 0x0030 /* OPCLKDIV - [5:4] */ | ||
280 | #define WM8983_OPCLKDIV_SHIFT 4 /* OPCLKDIV - [5:4] */ | ||
281 | #define WM8983_OPCLKDIV_WIDTH 2 /* OPCLKDIV - [5:4] */ | ||
282 | #define WM8983_GPIO1POL 0x0008 /* GPIO1POL */ | ||
283 | #define WM8983_GPIO1POL_MASK 0x0008 /* GPIO1POL */ | ||
284 | #define WM8983_GPIO1POL_SHIFT 3 /* GPIO1POL */ | ||
285 | #define WM8983_GPIO1POL_WIDTH 1 /* GPIO1POL */ | ||
286 | #define WM8983_GPIO1SEL_MASK 0x0007 /* GPIO1SEL - [2:0] */ | ||
287 | #define WM8983_GPIO1SEL_SHIFT 0 /* GPIO1SEL - [2:0] */ | ||
288 | #define WM8983_GPIO1SEL_WIDTH 3 /* GPIO1SEL - [2:0] */ | ||
289 | |||
290 | /* | ||
291 | * R9 (0x09) - Jack Detect Control 1 | ||
292 | */ | ||
293 | #define WM8983_JD_VMID1 0x0100 /* JD_VMID1 */ | ||
294 | #define WM8983_JD_VMID1_MASK 0x0100 /* JD_VMID1 */ | ||
295 | #define WM8983_JD_VMID1_SHIFT 8 /* JD_VMID1 */ | ||
296 | #define WM8983_JD_VMID1_WIDTH 1 /* JD_VMID1 */ | ||
297 | #define WM8983_JD_VMID0 0x0080 /* JD_VMID0 */ | ||
298 | #define WM8983_JD_VMID0_MASK 0x0080 /* JD_VMID0 */ | ||
299 | #define WM8983_JD_VMID0_SHIFT 7 /* JD_VMID0 */ | ||
300 | #define WM8983_JD_VMID0_WIDTH 1 /* JD_VMID0 */ | ||
301 | #define WM8983_JD_EN 0x0040 /* JD_EN */ | ||
302 | #define WM8983_JD_EN_MASK 0x0040 /* JD_EN */ | ||
303 | #define WM8983_JD_EN_SHIFT 6 /* JD_EN */ | ||
304 | #define WM8983_JD_EN_WIDTH 1 /* JD_EN */ | ||
305 | #define WM8983_JD_SEL_MASK 0x0030 /* JD_SEL - [5:4] */ | ||
306 | #define WM8983_JD_SEL_SHIFT 4 /* JD_SEL - [5:4] */ | ||
307 | #define WM8983_JD_SEL_WIDTH 2 /* JD_SEL - [5:4] */ | ||
308 | |||
309 | /* | ||
310 | * R10 (0x0A) - DAC Control | ||
311 | */ | ||
312 | #define WM8983_SOFTMUTE 0x0040 /* SOFTMUTE */ | ||
313 | #define WM8983_SOFTMUTE_MASK 0x0040 /* SOFTMUTE */ | ||
314 | #define WM8983_SOFTMUTE_SHIFT 6 /* SOFTMUTE */ | ||
315 | #define WM8983_SOFTMUTE_WIDTH 1 /* SOFTMUTE */ | ||
316 | #define WM8983_DACOSR128 0x0008 /* DACOSR128 */ | ||
317 | #define WM8983_DACOSR128_MASK 0x0008 /* DACOSR128 */ | ||
318 | #define WM8983_DACOSR128_SHIFT 3 /* DACOSR128 */ | ||
319 | #define WM8983_DACOSR128_WIDTH 1 /* DACOSR128 */ | ||
320 | #define WM8983_AMUTE 0x0004 /* AMUTE */ | ||
321 | #define WM8983_AMUTE_MASK 0x0004 /* AMUTE */ | ||
322 | #define WM8983_AMUTE_SHIFT 2 /* AMUTE */ | ||
323 | #define WM8983_AMUTE_WIDTH 1 /* AMUTE */ | ||
324 | #define WM8983_DACRPOL 0x0002 /* DACRPOL */ | ||
325 | #define WM8983_DACRPOL_MASK 0x0002 /* DACRPOL */ | ||
326 | #define WM8983_DACRPOL_SHIFT 1 /* DACRPOL */ | ||
327 | #define WM8983_DACRPOL_WIDTH 1 /* DACRPOL */ | ||
328 | #define WM8983_DACLPOL 0x0001 /* DACLPOL */ | ||
329 | #define WM8983_DACLPOL_MASK 0x0001 /* DACLPOL */ | ||
330 | #define WM8983_DACLPOL_SHIFT 0 /* DACLPOL */ | ||
331 | #define WM8983_DACLPOL_WIDTH 1 /* DACLPOL */ | ||
332 | |||
333 | /* | ||
334 | * R11 (0x0B) - Left DAC digital Vol | ||
335 | */ | ||
336 | #define WM8983_DACVU 0x0100 /* DACVU */ | ||
337 | #define WM8983_DACVU_MASK 0x0100 /* DACVU */ | ||
338 | #define WM8983_DACVU_SHIFT 8 /* DACVU */ | ||
339 | #define WM8983_DACVU_WIDTH 1 /* DACVU */ | ||
340 | #define WM8983_DACLVOL_MASK 0x00FF /* DACLVOL - [7:0] */ | ||
341 | #define WM8983_DACLVOL_SHIFT 0 /* DACLVOL - [7:0] */ | ||
342 | #define WM8983_DACLVOL_WIDTH 8 /* DACLVOL - [7:0] */ | ||
343 | |||
344 | /* | ||
345 | * R12 (0x0C) - Right DAC digital vol | ||
346 | */ | ||
347 | #define WM8983_DACVU 0x0100 /* DACVU */ | ||
348 | #define WM8983_DACVU_MASK 0x0100 /* DACVU */ | ||
349 | #define WM8983_DACVU_SHIFT 8 /* DACVU */ | ||
350 | #define WM8983_DACVU_WIDTH 1 /* DACVU */ | ||
351 | #define WM8983_DACRVOL_MASK 0x00FF /* DACRVOL - [7:0] */ | ||
352 | #define WM8983_DACRVOL_SHIFT 0 /* DACRVOL - [7:0] */ | ||
353 | #define WM8983_DACRVOL_WIDTH 8 /* DACRVOL - [7:0] */ | ||
354 | |||
355 | /* | ||
356 | * R13 (0x0D) - Jack Detect Control 2 | ||
357 | */ | ||
358 | #define WM8983_JD_EN1_MASK 0x00F0 /* JD_EN1 - [7:4] */ | ||
359 | #define WM8983_JD_EN1_SHIFT 4 /* JD_EN1 - [7:4] */ | ||
360 | #define WM8983_JD_EN1_WIDTH 4 /* JD_EN1 - [7:4] */ | ||
361 | #define WM8983_JD_EN0_MASK 0x000F /* JD_EN0 - [3:0] */ | ||
362 | #define WM8983_JD_EN0_SHIFT 0 /* JD_EN0 - [3:0] */ | ||
363 | #define WM8983_JD_EN0_WIDTH 4 /* JD_EN0 - [3:0] */ | ||
364 | |||
365 | /* | ||
366 | * R14 (0x0E) - ADC Control | ||
367 | */ | ||
368 | #define WM8983_HPFEN 0x0100 /* HPFEN */ | ||
369 | #define WM8983_HPFEN_MASK 0x0100 /* HPFEN */ | ||
370 | #define WM8983_HPFEN_SHIFT 8 /* HPFEN */ | ||
371 | #define WM8983_HPFEN_WIDTH 1 /* HPFEN */ | ||
372 | #define WM8983_HPFAPP 0x0080 /* HPFAPP */ | ||
373 | #define WM8983_HPFAPP_MASK 0x0080 /* HPFAPP */ | ||
374 | #define WM8983_HPFAPP_SHIFT 7 /* HPFAPP */ | ||
375 | #define WM8983_HPFAPP_WIDTH 1 /* HPFAPP */ | ||
376 | #define WM8983_HPFCUT_MASK 0x0070 /* HPFCUT - [6:4] */ | ||
377 | #define WM8983_HPFCUT_SHIFT 4 /* HPFCUT - [6:4] */ | ||
378 | #define WM8983_HPFCUT_WIDTH 3 /* HPFCUT - [6:4] */ | ||
379 | #define WM8983_ADCOSR128 0x0008 /* ADCOSR128 */ | ||
380 | #define WM8983_ADCOSR128_MASK 0x0008 /* ADCOSR128 */ | ||
381 | #define WM8983_ADCOSR128_SHIFT 3 /* ADCOSR128 */ | ||
382 | #define WM8983_ADCOSR128_WIDTH 1 /* ADCOSR128 */ | ||
383 | #define WM8983_ADCRPOL 0x0002 /* ADCRPOL */ | ||
384 | #define WM8983_ADCRPOL_MASK 0x0002 /* ADCRPOL */ | ||
385 | #define WM8983_ADCRPOL_SHIFT 1 /* ADCRPOL */ | ||
386 | #define WM8983_ADCRPOL_WIDTH 1 /* ADCRPOL */ | ||
387 | #define WM8983_ADCLPOL 0x0001 /* ADCLPOL */ | ||
388 | #define WM8983_ADCLPOL_MASK 0x0001 /* ADCLPOL */ | ||
389 | #define WM8983_ADCLPOL_SHIFT 0 /* ADCLPOL */ | ||
390 | #define WM8983_ADCLPOL_WIDTH 1 /* ADCLPOL */ | ||
391 | |||
392 | /* | ||
393 | * R15 (0x0F) - Left ADC Digital Vol | ||
394 | */ | ||
395 | #define WM8983_ADCVU 0x0100 /* ADCVU */ | ||
396 | #define WM8983_ADCVU_MASK 0x0100 /* ADCVU */ | ||
397 | #define WM8983_ADCVU_SHIFT 8 /* ADCVU */ | ||
398 | #define WM8983_ADCVU_WIDTH 1 /* ADCVU */ | ||
399 | #define WM8983_ADCLVOL_MASK 0x00FF /* ADCLVOL - [7:0] */ | ||
400 | #define WM8983_ADCLVOL_SHIFT 0 /* ADCLVOL - [7:0] */ | ||
401 | #define WM8983_ADCLVOL_WIDTH 8 /* ADCLVOL - [7:0] */ | ||
402 | |||
403 | /* | ||
404 | * R16 (0x10) - Right ADC Digital Vol | ||
405 | */ | ||
406 | #define WM8983_ADCVU 0x0100 /* ADCVU */ | ||
407 | #define WM8983_ADCVU_MASK 0x0100 /* ADCVU */ | ||
408 | #define WM8983_ADCVU_SHIFT 8 /* ADCVU */ | ||
409 | #define WM8983_ADCVU_WIDTH 1 /* ADCVU */ | ||
410 | #define WM8983_ADCRVOL_MASK 0x00FF /* ADCRVOL - [7:0] */ | ||
411 | #define WM8983_ADCRVOL_SHIFT 0 /* ADCRVOL - [7:0] */ | ||
412 | #define WM8983_ADCRVOL_WIDTH 8 /* ADCRVOL - [7:0] */ | ||
413 | |||
414 | /* | ||
415 | * R18 (0x12) - EQ1 - low shelf | ||
416 | */ | ||
417 | #define WM8983_EQ3DMODE 0x0100 /* EQ3DMODE */ | ||
418 | #define WM8983_EQ3DMODE_MASK 0x0100 /* EQ3DMODE */ | ||
419 | #define WM8983_EQ3DMODE_SHIFT 8 /* EQ3DMODE */ | ||
420 | #define WM8983_EQ3DMODE_WIDTH 1 /* EQ3DMODE */ | ||
421 | #define WM8983_EQ1C_MASK 0x0060 /* EQ1C - [6:5] */ | ||
422 | #define WM8983_EQ1C_SHIFT 5 /* EQ1C - [6:5] */ | ||
423 | #define WM8983_EQ1C_WIDTH 2 /* EQ1C - [6:5] */ | ||
424 | #define WM8983_EQ1G_MASK 0x001F /* EQ1G - [4:0] */ | ||
425 | #define WM8983_EQ1G_SHIFT 0 /* EQ1G - [4:0] */ | ||
426 | #define WM8983_EQ1G_WIDTH 5 /* EQ1G - [4:0] */ | ||
427 | |||
428 | /* | ||
429 | * R19 (0x13) - EQ2 - peak 1 | ||
430 | */ | ||
431 | #define WM8983_EQ2BW 0x0100 /* EQ2BW */ | ||
432 | #define WM8983_EQ2BW_MASK 0x0100 /* EQ2BW */ | ||
433 | #define WM8983_EQ2BW_SHIFT 8 /* EQ2BW */ | ||
434 | #define WM8983_EQ2BW_WIDTH 1 /* EQ2BW */ | ||
435 | #define WM8983_EQ2C_MASK 0x0060 /* EQ2C - [6:5] */ | ||
436 | #define WM8983_EQ2C_SHIFT 5 /* EQ2C - [6:5] */ | ||
437 | #define WM8983_EQ2C_WIDTH 2 /* EQ2C - [6:5] */ | ||
438 | #define WM8983_EQ2G_MASK 0x001F /* EQ2G - [4:0] */ | ||
439 | #define WM8983_EQ2G_SHIFT 0 /* EQ2G - [4:0] */ | ||
440 | #define WM8983_EQ2G_WIDTH 5 /* EQ2G - [4:0] */ | ||
441 | |||
442 | /* | ||
443 | * R20 (0x14) - EQ3 - peak 2 | ||
444 | */ | ||
445 | #define WM8983_EQ3BW 0x0100 /* EQ3BW */ | ||
446 | #define WM8983_EQ3BW_MASK 0x0100 /* EQ3BW */ | ||
447 | #define WM8983_EQ3BW_SHIFT 8 /* EQ3BW */ | ||
448 | #define WM8983_EQ3BW_WIDTH 1 /* EQ3BW */ | ||
449 | #define WM8983_EQ3C_MASK 0x0060 /* EQ3C - [6:5] */ | ||
450 | #define WM8983_EQ3C_SHIFT 5 /* EQ3C - [6:5] */ | ||
451 | #define WM8983_EQ3C_WIDTH 2 /* EQ3C - [6:5] */ | ||
452 | #define WM8983_EQ3G_MASK 0x001F /* EQ3G - [4:0] */ | ||
453 | #define WM8983_EQ3G_SHIFT 0 /* EQ3G - [4:0] */ | ||
454 | #define WM8983_EQ3G_WIDTH 5 /* EQ3G - [4:0] */ | ||
455 | |||
456 | /* | ||
457 | * R21 (0x15) - EQ4 - peak 3 | ||
458 | */ | ||
459 | #define WM8983_EQ4BW 0x0100 /* EQ4BW */ | ||
460 | #define WM8983_EQ4BW_MASK 0x0100 /* EQ4BW */ | ||
461 | #define WM8983_EQ4BW_SHIFT 8 /* EQ4BW */ | ||
462 | #define WM8983_EQ4BW_WIDTH 1 /* EQ4BW */ | ||
463 | #define WM8983_EQ4C_MASK 0x0060 /* EQ4C - [6:5] */ | ||
464 | #define WM8983_EQ4C_SHIFT 5 /* EQ4C - [6:5] */ | ||
465 | #define WM8983_EQ4C_WIDTH 2 /* EQ4C - [6:5] */ | ||
466 | #define WM8983_EQ4G_MASK 0x001F /* EQ4G - [4:0] */ | ||
467 | #define WM8983_EQ4G_SHIFT 0 /* EQ4G - [4:0] */ | ||
468 | #define WM8983_EQ4G_WIDTH 5 /* EQ4G - [4:0] */ | ||
469 | |||
470 | /* | ||
471 | * R22 (0x16) - EQ5 - high shelf | ||
472 | */ | ||
473 | #define WM8983_EQ5C_MASK 0x0060 /* EQ5C - [6:5] */ | ||
474 | #define WM8983_EQ5C_SHIFT 5 /* EQ5C - [6:5] */ | ||
475 | #define WM8983_EQ5C_WIDTH 2 /* EQ5C - [6:5] */ | ||
476 | #define WM8983_EQ5G_MASK 0x001F /* EQ5G - [4:0] */ | ||
477 | #define WM8983_EQ5G_SHIFT 0 /* EQ5G - [4:0] */ | ||
478 | #define WM8983_EQ5G_WIDTH 5 /* EQ5G - [4:0] */ | ||
479 | |||
480 | /* | ||
481 | * R24 (0x18) - DAC Limiter 1 | ||
482 | */ | ||
483 | #define WM8983_LIMEN 0x0100 /* LIMEN */ | ||
484 | #define WM8983_LIMEN_MASK 0x0100 /* LIMEN */ | ||
485 | #define WM8983_LIMEN_SHIFT 8 /* LIMEN */ | ||
486 | #define WM8983_LIMEN_WIDTH 1 /* LIMEN */ | ||
487 | #define WM8983_LIMDCY_MASK 0x00F0 /* LIMDCY - [7:4] */ | ||
488 | #define WM8983_LIMDCY_SHIFT 4 /* LIMDCY - [7:4] */ | ||
489 | #define WM8983_LIMDCY_WIDTH 4 /* LIMDCY - [7:4] */ | ||
490 | #define WM8983_LIMATK_MASK 0x000F /* LIMATK - [3:0] */ | ||
491 | #define WM8983_LIMATK_SHIFT 0 /* LIMATK - [3:0] */ | ||
492 | #define WM8983_LIMATK_WIDTH 4 /* LIMATK - [3:0] */ | ||
493 | |||
494 | /* | ||
495 | * R25 (0x19) - DAC Limiter 2 | ||
496 | */ | ||
497 | #define WM8983_LIMLVL_MASK 0x0070 /* LIMLVL - [6:4] */ | ||
498 | #define WM8983_LIMLVL_SHIFT 4 /* LIMLVL - [6:4] */ | ||
499 | #define WM8983_LIMLVL_WIDTH 3 /* LIMLVL - [6:4] */ | ||
500 | #define WM8983_LIMBOOST_MASK 0x000F /* LIMBOOST - [3:0] */ | ||
501 | #define WM8983_LIMBOOST_SHIFT 0 /* LIMBOOST - [3:0] */ | ||
502 | #define WM8983_LIMBOOST_WIDTH 4 /* LIMBOOST - [3:0] */ | ||
503 | |||
504 | /* | ||
505 | * R27 (0x1B) - Notch Filter 1 | ||
506 | */ | ||
507 | #define WM8983_NFU 0x0100 /* NFU */ | ||
508 | #define WM8983_NFU_MASK 0x0100 /* NFU */ | ||
509 | #define WM8983_NFU_SHIFT 8 /* NFU */ | ||
510 | #define WM8983_NFU_WIDTH 1 /* NFU */ | ||
511 | #define WM8983_NFEN 0x0080 /* NFEN */ | ||
512 | #define WM8983_NFEN_MASK 0x0080 /* NFEN */ | ||
513 | #define WM8983_NFEN_SHIFT 7 /* NFEN */ | ||
514 | #define WM8983_NFEN_WIDTH 1 /* NFEN */ | ||
515 | #define WM8983_NFA0_13_7_MASK 0x007F /* NFA0(13:7) - [6:0] */ | ||
516 | #define WM8983_NFA0_13_7_SHIFT 0 /* NFA0(13:7) - [6:0] */ | ||
517 | #define WM8983_NFA0_13_7_WIDTH 7 /* NFA0(13:7) - [6:0] */ | ||
518 | |||
519 | /* | ||
520 | * R28 (0x1C) - Notch Filter 2 | ||
521 | */ | ||
522 | #define WM8983_NFU 0x0100 /* NFU */ | ||
523 | #define WM8983_NFU_MASK 0x0100 /* NFU */ | ||
524 | #define WM8983_NFU_SHIFT 8 /* NFU */ | ||
525 | #define WM8983_NFU_WIDTH 1 /* NFU */ | ||
526 | #define WM8983_NFA0_6_0_MASK 0x007F /* NFA0(6:0) - [6:0] */ | ||
527 | #define WM8983_NFA0_6_0_SHIFT 0 /* NFA0(6:0) - [6:0] */ | ||
528 | #define WM8983_NFA0_6_0_WIDTH 7 /* NFA0(6:0) - [6:0] */ | ||
529 | |||
530 | /* | ||
531 | * R29 (0x1D) - Notch Filter 3 | ||
532 | */ | ||
533 | #define WM8983_NFU 0x0100 /* NFU */ | ||
534 | #define WM8983_NFU_MASK 0x0100 /* NFU */ | ||
535 | #define WM8983_NFU_SHIFT 8 /* NFU */ | ||
536 | #define WM8983_NFU_WIDTH 1 /* NFU */ | ||
537 | #define WM8983_NFA1_13_7_MASK 0x007F /* NFA1(13:7) - [6:0] */ | ||
538 | #define WM8983_NFA1_13_7_SHIFT 0 /* NFA1(13:7) - [6:0] */ | ||
539 | #define WM8983_NFA1_13_7_WIDTH 7 /* NFA1(13:7) - [6:0] */ | ||
540 | |||
541 | /* | ||
542 | * R30 (0x1E) - Notch Filter 4 | ||
543 | */ | ||
544 | #define WM8983_NFU 0x0100 /* NFU */ | ||
545 | #define WM8983_NFU_MASK 0x0100 /* NFU */ | ||
546 | #define WM8983_NFU_SHIFT 8 /* NFU */ | ||
547 | #define WM8983_NFU_WIDTH 1 /* NFU */ | ||
548 | #define WM8983_NFA1_6_0_MASK 0x007F /* NFA1(6:0) - [6:0] */ | ||
549 | #define WM8983_NFA1_6_0_SHIFT 0 /* NFA1(6:0) - [6:0] */ | ||
550 | #define WM8983_NFA1_6_0_WIDTH 7 /* NFA1(6:0) - [6:0] */ | ||
551 | |||
552 | /* | ||
553 | * R32 (0x20) - ALC control 1 | ||
554 | */ | ||
555 | #define WM8983_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */ | ||
556 | #define WM8983_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */ | ||
557 | #define WM8983_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */ | ||
558 | #define WM8983_ALCMAX_MASK 0x0038 /* ALCMAX - [5:3] */ | ||
559 | #define WM8983_ALCMAX_SHIFT 3 /* ALCMAX - [5:3] */ | ||
560 | #define WM8983_ALCMAX_WIDTH 3 /* ALCMAX - [5:3] */ | ||
561 | #define WM8983_ALCMIN_MASK 0x0007 /* ALCMIN - [2:0] */ | ||
562 | #define WM8983_ALCMIN_SHIFT 0 /* ALCMIN - [2:0] */ | ||
563 | #define WM8983_ALCMIN_WIDTH 3 /* ALCMIN - [2:0] */ | ||
564 | |||
565 | /* | ||
566 | * R33 (0x21) - ALC control 2 | ||
567 | */ | ||
568 | #define WM8983_ALCHLD_MASK 0x00F0 /* ALCHLD - [7:4] */ | ||
569 | #define WM8983_ALCHLD_SHIFT 4 /* ALCHLD - [7:4] */ | ||
570 | #define WM8983_ALCHLD_WIDTH 4 /* ALCHLD - [7:4] */ | ||
571 | #define WM8983_ALCLVL_MASK 0x000F /* ALCLVL - [3:0] */ | ||
572 | #define WM8983_ALCLVL_SHIFT 0 /* ALCLVL - [3:0] */ | ||
573 | #define WM8983_ALCLVL_WIDTH 4 /* ALCLVL - [3:0] */ | ||
574 | |||
575 | /* | ||
576 | * R34 (0x22) - ALC control 3 | ||
577 | */ | ||
578 | #define WM8983_ALCMODE 0x0100 /* ALCMODE */ | ||
579 | #define WM8983_ALCMODE_MASK 0x0100 /* ALCMODE */ | ||
580 | #define WM8983_ALCMODE_SHIFT 8 /* ALCMODE */ | ||
581 | #define WM8983_ALCMODE_WIDTH 1 /* ALCMODE */ | ||
582 | #define WM8983_ALCDCY_MASK 0x00F0 /* ALCDCY - [7:4] */ | ||
583 | #define WM8983_ALCDCY_SHIFT 4 /* ALCDCY - [7:4] */ | ||
584 | #define WM8983_ALCDCY_WIDTH 4 /* ALCDCY - [7:4] */ | ||
585 | #define WM8983_ALCATK_MASK 0x000F /* ALCATK - [3:0] */ | ||
586 | #define WM8983_ALCATK_SHIFT 0 /* ALCATK - [3:0] */ | ||
587 | #define WM8983_ALCATK_WIDTH 4 /* ALCATK - [3:0] */ | ||
588 | |||
589 | /* | ||
590 | * R35 (0x23) - Noise Gate | ||
591 | */ | ||
592 | #define WM8983_NGEN 0x0008 /* NGEN */ | ||
593 | #define WM8983_NGEN_MASK 0x0008 /* NGEN */ | ||
594 | #define WM8983_NGEN_SHIFT 3 /* NGEN */ | ||
595 | #define WM8983_NGEN_WIDTH 1 /* NGEN */ | ||
596 | #define WM8983_NGTH_MASK 0x0007 /* NGTH - [2:0] */ | ||
597 | #define WM8983_NGTH_SHIFT 0 /* NGTH - [2:0] */ | ||
598 | #define WM8983_NGTH_WIDTH 3 /* NGTH - [2:0] */ | ||
599 | |||
600 | /* | ||
601 | * R36 (0x24) - PLL N | ||
602 | */ | ||
603 | #define WM8983_PLL_PRESCALE 0x0010 /* PLL_PRESCALE */ | ||
604 | #define WM8983_PLL_PRESCALE_MASK 0x0010 /* PLL_PRESCALE */ | ||
605 | #define WM8983_PLL_PRESCALE_SHIFT 4 /* PLL_PRESCALE */ | ||
606 | #define WM8983_PLL_PRESCALE_WIDTH 1 /* PLL_PRESCALE */ | ||
607 | #define WM8983_PLLN_MASK 0x000F /* PLLN - [3:0] */ | ||
608 | #define WM8983_PLLN_SHIFT 0 /* PLLN - [3:0] */ | ||
609 | #define WM8983_PLLN_WIDTH 4 /* PLLN - [3:0] */ | ||
610 | |||
611 | /* | ||
612 | * R37 (0x25) - PLL K 1 | ||
613 | */ | ||
614 | #define WM8983_PLLK_23_18_MASK 0x003F /* PLLK(23:18) - [5:0] */ | ||
615 | #define WM8983_PLLK_23_18_SHIFT 0 /* PLLK(23:18) - [5:0] */ | ||
616 | #define WM8983_PLLK_23_18_WIDTH 6 /* PLLK(23:18) - [5:0] */ | ||
617 | |||
618 | /* | ||
619 | * R38 (0x26) - PLL K 2 | ||
620 | */ | ||
621 | #define WM8983_PLLK_17_9_MASK 0x01FF /* PLLK(17:9) - [8:0] */ | ||
622 | #define WM8983_PLLK_17_9_SHIFT 0 /* PLLK(17:9) - [8:0] */ | ||
623 | #define WM8983_PLLK_17_9_WIDTH 9 /* PLLK(17:9) - [8:0] */ | ||
624 | |||
625 | /* | ||
626 | * R39 (0x27) - PLL K 3 | ||
627 | */ | ||
628 | #define WM8983_PLLK_8_0_MASK 0x01FF /* PLLK(8:0) - [8:0] */ | ||
629 | #define WM8983_PLLK_8_0_SHIFT 0 /* PLLK(8:0) - [8:0] */ | ||
630 | #define WM8983_PLLK_8_0_WIDTH 9 /* PLLK(8:0) - [8:0] */ | ||
631 | |||
632 | /* | ||
633 | * R41 (0x29) - 3D control | ||
634 | */ | ||
635 | #define WM8983_DEPTH3D_MASK 0x000F /* DEPTH3D - [3:0] */ | ||
636 | #define WM8983_DEPTH3D_SHIFT 0 /* DEPTH3D - [3:0] */ | ||
637 | #define WM8983_DEPTH3D_WIDTH 4 /* DEPTH3D - [3:0] */ | ||
638 | |||
639 | /* | ||
640 | * R42 (0x2A) - OUT4 to ADC | ||
641 | */ | ||
642 | #define WM8983_OUT4_2ADCVOL_MASK 0x01C0 /* OUT4_2ADCVOL - [8:6] */ | ||
643 | #define WM8983_OUT4_2ADCVOL_SHIFT 6 /* OUT4_2ADCVOL - [8:6] */ | ||
644 | #define WM8983_OUT4_2ADCVOL_WIDTH 3 /* OUT4_2ADCVOL - [8:6] */ | ||
645 | #define WM8983_OUT4_2LNR 0x0020 /* OUT4_2LNR */ | ||
646 | #define WM8983_OUT4_2LNR_MASK 0x0020 /* OUT4_2LNR */ | ||
647 | #define WM8983_OUT4_2LNR_SHIFT 5 /* OUT4_2LNR */ | ||
648 | #define WM8983_OUT4_2LNR_WIDTH 1 /* OUT4_2LNR */ | ||
649 | #define WM8983_POBCTRL 0x0004 /* POBCTRL */ | ||
650 | #define WM8983_POBCTRL_MASK 0x0004 /* POBCTRL */ | ||
651 | #define WM8983_POBCTRL_SHIFT 2 /* POBCTRL */ | ||
652 | #define WM8983_POBCTRL_WIDTH 1 /* POBCTRL */ | ||
653 | #define WM8983_DELEN 0x0002 /* DELEN */ | ||
654 | #define WM8983_DELEN_MASK 0x0002 /* DELEN */ | ||
655 | #define WM8983_DELEN_SHIFT 1 /* DELEN */ | ||
656 | #define WM8983_DELEN_WIDTH 1 /* DELEN */ | ||
657 | #define WM8983_OUT1DEL 0x0001 /* OUT1DEL */ | ||
658 | #define WM8983_OUT1DEL_MASK 0x0001 /* OUT1DEL */ | ||
659 | #define WM8983_OUT1DEL_SHIFT 0 /* OUT1DEL */ | ||
660 | #define WM8983_OUT1DEL_WIDTH 1 /* OUT1DEL */ | ||
661 | |||
662 | /* | ||
663 | * R43 (0x2B) - Beep control | ||
664 | */ | ||
665 | #define WM8983_BYPL2RMIX 0x0100 /* BYPL2RMIX */ | ||
666 | #define WM8983_BYPL2RMIX_MASK 0x0100 /* BYPL2RMIX */ | ||
667 | #define WM8983_BYPL2RMIX_SHIFT 8 /* BYPL2RMIX */ | ||
668 | #define WM8983_BYPL2RMIX_WIDTH 1 /* BYPL2RMIX */ | ||
669 | #define WM8983_BYPR2LMIX 0x0080 /* BYPR2LMIX */ | ||
670 | #define WM8983_BYPR2LMIX_MASK 0x0080 /* BYPR2LMIX */ | ||
671 | #define WM8983_BYPR2LMIX_SHIFT 7 /* BYPR2LMIX */ | ||
672 | #define WM8983_BYPR2LMIX_WIDTH 1 /* BYPR2LMIX */ | ||
673 | #define WM8983_MUTERPGA2INV 0x0020 /* MUTERPGA2INV */ | ||
674 | #define WM8983_MUTERPGA2INV_MASK 0x0020 /* MUTERPGA2INV */ | ||
675 | #define WM8983_MUTERPGA2INV_SHIFT 5 /* MUTERPGA2INV */ | ||
676 | #define WM8983_MUTERPGA2INV_WIDTH 1 /* MUTERPGA2INV */ | ||
677 | #define WM8983_INVROUT2 0x0010 /* INVROUT2 */ | ||
678 | #define WM8983_INVROUT2_MASK 0x0010 /* INVROUT2 */ | ||
679 | #define WM8983_INVROUT2_SHIFT 4 /* INVROUT2 */ | ||
680 | #define WM8983_INVROUT2_WIDTH 1 /* INVROUT2 */ | ||
681 | #define WM8983_BEEPVOL_MASK 0x000E /* BEEPVOL - [3:1] */ | ||
682 | #define WM8983_BEEPVOL_SHIFT 1 /* BEEPVOL - [3:1] */ | ||
683 | #define WM8983_BEEPVOL_WIDTH 3 /* BEEPVOL - [3:1] */ | ||
684 | #define WM8983_BEEPEN 0x0001 /* BEEPEN */ | ||
685 | #define WM8983_BEEPEN_MASK 0x0001 /* BEEPEN */ | ||
686 | #define WM8983_BEEPEN_SHIFT 0 /* BEEPEN */ | ||
687 | #define WM8983_BEEPEN_WIDTH 1 /* BEEPEN */ | ||
688 | |||
689 | /* | ||
690 | * R44 (0x2C) - Input ctrl | ||
691 | */ | ||
692 | #define WM8983_MBVSEL 0x0100 /* MBVSEL */ | ||
693 | #define WM8983_MBVSEL_MASK 0x0100 /* MBVSEL */ | ||
694 | #define WM8983_MBVSEL_SHIFT 8 /* MBVSEL */ | ||
695 | #define WM8983_MBVSEL_WIDTH 1 /* MBVSEL */ | ||
696 | #define WM8983_R2_2INPPGA 0x0040 /* R2_2INPPGA */ | ||
697 | #define WM8983_R2_2INPPGA_MASK 0x0040 /* R2_2INPPGA */ | ||
698 | #define WM8983_R2_2INPPGA_SHIFT 6 /* R2_2INPPGA */ | ||
699 | #define WM8983_R2_2INPPGA_WIDTH 1 /* R2_2INPPGA */ | ||
700 | #define WM8983_RIN2INPPGA 0x0020 /* RIN2INPPGA */ | ||
701 | #define WM8983_RIN2INPPGA_MASK 0x0020 /* RIN2INPPGA */ | ||
702 | #define WM8983_RIN2INPPGA_SHIFT 5 /* RIN2INPPGA */ | ||
703 | #define WM8983_RIN2INPPGA_WIDTH 1 /* RIN2INPPGA */ | ||
704 | #define WM8983_RIP2INPPGA 0x0010 /* RIP2INPPGA */ | ||
705 | #define WM8983_RIP2INPPGA_MASK 0x0010 /* RIP2INPPGA */ | ||
706 | #define WM8983_RIP2INPPGA_SHIFT 4 /* RIP2INPPGA */ | ||
707 | #define WM8983_RIP2INPPGA_WIDTH 1 /* RIP2INPPGA */ | ||
708 | #define WM8983_L2_2INPPGA 0x0004 /* L2_2INPPGA */ | ||
709 | #define WM8983_L2_2INPPGA_MASK 0x0004 /* L2_2INPPGA */ | ||
710 | #define WM8983_L2_2INPPGA_SHIFT 2 /* L2_2INPPGA */ | ||
711 | #define WM8983_L2_2INPPGA_WIDTH 1 /* L2_2INPPGA */ | ||
712 | #define WM8983_LIN2INPPGA 0x0002 /* LIN2INPPGA */ | ||
713 | #define WM8983_LIN2INPPGA_MASK 0x0002 /* LIN2INPPGA */ | ||
714 | #define WM8983_LIN2INPPGA_SHIFT 1 /* LIN2INPPGA */ | ||
715 | #define WM8983_LIN2INPPGA_WIDTH 1 /* LIN2INPPGA */ | ||
716 | #define WM8983_LIP2INPPGA 0x0001 /* LIP2INPPGA */ | ||
717 | #define WM8983_LIP2INPPGA_MASK 0x0001 /* LIP2INPPGA */ | ||
718 | #define WM8983_LIP2INPPGA_SHIFT 0 /* LIP2INPPGA */ | ||
719 | #define WM8983_LIP2INPPGA_WIDTH 1 /* LIP2INPPGA */ | ||
720 | |||
721 | /* | ||
722 | * R45 (0x2D) - Left INP PGA gain ctrl | ||
723 | */ | ||
724 | #define WM8983_INPGAVU 0x0100 /* INPGAVU */ | ||
725 | #define WM8983_INPGAVU_MASK 0x0100 /* INPGAVU */ | ||
726 | #define WM8983_INPGAVU_SHIFT 8 /* INPGAVU */ | ||
727 | #define WM8983_INPGAVU_WIDTH 1 /* INPGAVU */ | ||
728 | #define WM8983_INPPGAZCL 0x0080 /* INPPGAZCL */ | ||
729 | #define WM8983_INPPGAZCL_MASK 0x0080 /* INPPGAZCL */ | ||
730 | #define WM8983_INPPGAZCL_SHIFT 7 /* INPPGAZCL */ | ||
731 | #define WM8983_INPPGAZCL_WIDTH 1 /* INPPGAZCL */ | ||
732 | #define WM8983_INPPGAMUTEL 0x0040 /* INPPGAMUTEL */ | ||
733 | #define WM8983_INPPGAMUTEL_MASK 0x0040 /* INPPGAMUTEL */ | ||
734 | #define WM8983_INPPGAMUTEL_SHIFT 6 /* INPPGAMUTEL */ | ||
735 | #define WM8983_INPPGAMUTEL_WIDTH 1 /* INPPGAMUTEL */ | ||
736 | #define WM8983_INPPGAVOLL_MASK 0x003F /* INPPGAVOLL - [5:0] */ | ||
737 | #define WM8983_INPPGAVOLL_SHIFT 0 /* INPPGAVOLL - [5:0] */ | ||
738 | #define WM8983_INPPGAVOLL_WIDTH 6 /* INPPGAVOLL - [5:0] */ | ||
739 | |||
740 | /* | ||
741 | * R46 (0x2E) - Right INP PGA gain ctrl | ||
742 | */ | ||
743 | #define WM8983_INPGAVU 0x0100 /* INPGAVU */ | ||
744 | #define WM8983_INPGAVU_MASK 0x0100 /* INPGAVU */ | ||
745 | #define WM8983_INPGAVU_SHIFT 8 /* INPGAVU */ | ||
746 | #define WM8983_INPGAVU_WIDTH 1 /* INPGAVU */ | ||
747 | #define WM8983_INPPGAZCR 0x0080 /* INPPGAZCR */ | ||
748 | #define WM8983_INPPGAZCR_MASK 0x0080 /* INPPGAZCR */ | ||
749 | #define WM8983_INPPGAZCR_SHIFT 7 /* INPPGAZCR */ | ||
750 | #define WM8983_INPPGAZCR_WIDTH 1 /* INPPGAZCR */ | ||
751 | #define WM8983_INPPGAMUTER 0x0040 /* INPPGAMUTER */ | ||
752 | #define WM8983_INPPGAMUTER_MASK 0x0040 /* INPPGAMUTER */ | ||
753 | #define WM8983_INPPGAMUTER_SHIFT 6 /* INPPGAMUTER */ | ||
754 | #define WM8983_INPPGAMUTER_WIDTH 1 /* INPPGAMUTER */ | ||
755 | #define WM8983_INPPGAVOLR_MASK 0x003F /* INPPGAVOLR - [5:0] */ | ||
756 | #define WM8983_INPPGAVOLR_SHIFT 0 /* INPPGAVOLR - [5:0] */ | ||
757 | #define WM8983_INPPGAVOLR_WIDTH 6 /* INPPGAVOLR - [5:0] */ | ||
758 | |||
759 | /* | ||
760 | * R47 (0x2F) - Left ADC BOOST ctrl | ||
761 | */ | ||
762 | #define WM8983_PGABOOSTL 0x0100 /* PGABOOSTL */ | ||
763 | #define WM8983_PGABOOSTL_MASK 0x0100 /* PGABOOSTL */ | ||
764 | #define WM8983_PGABOOSTL_SHIFT 8 /* PGABOOSTL */ | ||
765 | #define WM8983_PGABOOSTL_WIDTH 1 /* PGABOOSTL */ | ||
766 | #define WM8983_L2_2BOOSTVOL_MASK 0x0070 /* L2_2BOOSTVOL - [6:4] */ | ||
767 | #define WM8983_L2_2BOOSTVOL_SHIFT 4 /* L2_2BOOSTVOL - [6:4] */ | ||
768 | #define WM8983_L2_2BOOSTVOL_WIDTH 3 /* L2_2BOOSTVOL - [6:4] */ | ||
769 | #define WM8983_AUXL2BOOSTVOL_MASK 0x0007 /* AUXL2BOOSTVOL - [2:0] */ | ||
770 | #define WM8983_AUXL2BOOSTVOL_SHIFT 0 /* AUXL2BOOSTVOL - [2:0] */ | ||
771 | #define WM8983_AUXL2BOOSTVOL_WIDTH 3 /* AUXL2BOOSTVOL - [2:0] */ | ||
772 | |||
773 | /* | ||
774 | * R48 (0x30) - Right ADC BOOST ctrl | ||
775 | */ | ||
776 | #define WM8983_PGABOOSTR 0x0100 /* PGABOOSTR */ | ||
777 | #define WM8983_PGABOOSTR_MASK 0x0100 /* PGABOOSTR */ | ||
778 | #define WM8983_PGABOOSTR_SHIFT 8 /* PGABOOSTR */ | ||
779 | #define WM8983_PGABOOSTR_WIDTH 1 /* PGABOOSTR */ | ||
780 | #define WM8983_R2_2BOOSTVOL_MASK 0x0070 /* R2_2BOOSTVOL - [6:4] */ | ||
781 | #define WM8983_R2_2BOOSTVOL_SHIFT 4 /* R2_2BOOSTVOL - [6:4] */ | ||
782 | #define WM8983_R2_2BOOSTVOL_WIDTH 3 /* R2_2BOOSTVOL - [6:4] */ | ||
783 | #define WM8983_AUXR2BOOSTVOL_MASK 0x0007 /* AUXR2BOOSTVOL - [2:0] */ | ||
784 | #define WM8983_AUXR2BOOSTVOL_SHIFT 0 /* AUXR2BOOSTVOL - [2:0] */ | ||
785 | #define WM8983_AUXR2BOOSTVOL_WIDTH 3 /* AUXR2BOOSTVOL - [2:0] */ | ||
786 | |||
787 | /* | ||
788 | * R49 (0x31) - Output ctrl | ||
789 | */ | ||
790 | #define WM8983_DACL2RMIX 0x0040 /* DACL2RMIX */ | ||
791 | #define WM8983_DACL2RMIX_MASK 0x0040 /* DACL2RMIX */ | ||
792 | #define WM8983_DACL2RMIX_SHIFT 6 /* DACL2RMIX */ | ||
793 | #define WM8983_DACL2RMIX_WIDTH 1 /* DACL2RMIX */ | ||
794 | #define WM8983_DACR2LMIX 0x0020 /* DACR2LMIX */ | ||
795 | #define WM8983_DACR2LMIX_MASK 0x0020 /* DACR2LMIX */ | ||
796 | #define WM8983_DACR2LMIX_SHIFT 5 /* DACR2LMIX */ | ||
797 | #define WM8983_DACR2LMIX_WIDTH 1 /* DACR2LMIX */ | ||
798 | #define WM8983_OUT4BOOST 0x0010 /* OUT4BOOST */ | ||
799 | #define WM8983_OUT4BOOST_MASK 0x0010 /* OUT4BOOST */ | ||
800 | #define WM8983_OUT4BOOST_SHIFT 4 /* OUT4BOOST */ | ||
801 | #define WM8983_OUT4BOOST_WIDTH 1 /* OUT4BOOST */ | ||
802 | #define WM8983_OUT3BOOST 0x0008 /* OUT3BOOST */ | ||
803 | #define WM8983_OUT3BOOST_MASK 0x0008 /* OUT3BOOST */ | ||
804 | #define WM8983_OUT3BOOST_SHIFT 3 /* OUT3BOOST */ | ||
805 | #define WM8983_OUT3BOOST_WIDTH 1 /* OUT3BOOST */ | ||
806 | #define WM8983_SPKBOOST 0x0004 /* SPKBOOST */ | ||
807 | #define WM8983_SPKBOOST_MASK 0x0004 /* SPKBOOST */ | ||
808 | #define WM8983_SPKBOOST_SHIFT 2 /* SPKBOOST */ | ||
809 | #define WM8983_SPKBOOST_WIDTH 1 /* SPKBOOST */ | ||
810 | #define WM8983_TSDEN 0x0002 /* TSDEN */ | ||
811 | #define WM8983_TSDEN_MASK 0x0002 /* TSDEN */ | ||
812 | #define WM8983_TSDEN_SHIFT 1 /* TSDEN */ | ||
813 | #define WM8983_TSDEN_WIDTH 1 /* TSDEN */ | ||
814 | #define WM8983_VROI 0x0001 /* VROI */ | ||
815 | #define WM8983_VROI_MASK 0x0001 /* VROI */ | ||
816 | #define WM8983_VROI_SHIFT 0 /* VROI */ | ||
817 | #define WM8983_VROI_WIDTH 1 /* VROI */ | ||
818 | |||
819 | /* | ||
820 | * R50 (0x32) - Left mixer ctrl | ||
821 | */ | ||
822 | #define WM8983_AUXLMIXVOL_MASK 0x01C0 /* AUXLMIXVOL - [8:6] */ | ||
823 | #define WM8983_AUXLMIXVOL_SHIFT 6 /* AUXLMIXVOL - [8:6] */ | ||
824 | #define WM8983_AUXLMIXVOL_WIDTH 3 /* AUXLMIXVOL - [8:6] */ | ||
825 | #define WM8983_AUXL2LMIX 0x0020 /* AUXL2LMIX */ | ||
826 | #define WM8983_AUXL2LMIX_MASK 0x0020 /* AUXL2LMIX */ | ||
827 | #define WM8983_AUXL2LMIX_SHIFT 5 /* AUXL2LMIX */ | ||
828 | #define WM8983_AUXL2LMIX_WIDTH 1 /* AUXL2LMIX */ | ||
829 | #define WM8983_BYPLMIXVOL_MASK 0x001C /* BYPLMIXVOL - [4:2] */ | ||
830 | #define WM8983_BYPLMIXVOL_SHIFT 2 /* BYPLMIXVOL - [4:2] */ | ||
831 | #define WM8983_BYPLMIXVOL_WIDTH 3 /* BYPLMIXVOL - [4:2] */ | ||
832 | #define WM8983_BYPL2LMIX 0x0002 /* BYPL2LMIX */ | ||
833 | #define WM8983_BYPL2LMIX_MASK 0x0002 /* BYPL2LMIX */ | ||
834 | #define WM8983_BYPL2LMIX_SHIFT 1 /* BYPL2LMIX */ | ||
835 | #define WM8983_BYPL2LMIX_WIDTH 1 /* BYPL2LMIX */ | ||
836 | #define WM8983_DACL2LMIX 0x0001 /* DACL2LMIX */ | ||
837 | #define WM8983_DACL2LMIX_MASK 0x0001 /* DACL2LMIX */ | ||
838 | #define WM8983_DACL2LMIX_SHIFT 0 /* DACL2LMIX */ | ||
839 | #define WM8983_DACL2LMIX_WIDTH 1 /* DACL2LMIX */ | ||
840 | |||
841 | /* | ||
842 | * R51 (0x33) - Right mixer ctrl | ||
843 | */ | ||
844 | #define WM8983_AUXRMIXVOL_MASK 0x01C0 /* AUXRMIXVOL - [8:6] */ | ||
845 | #define WM8983_AUXRMIXVOL_SHIFT 6 /* AUXRMIXVOL - [8:6] */ | ||
846 | #define WM8983_AUXRMIXVOL_WIDTH 3 /* AUXRMIXVOL - [8:6] */ | ||
847 | #define WM8983_AUXR2RMIX 0x0020 /* AUXR2RMIX */ | ||
848 | #define WM8983_AUXR2RMIX_MASK 0x0020 /* AUXR2RMIX */ | ||
849 | #define WM8983_AUXR2RMIX_SHIFT 5 /* AUXR2RMIX */ | ||
850 | #define WM8983_AUXR2RMIX_WIDTH 1 /* AUXR2RMIX */ | ||
851 | #define WM8983_BYPRMIXVOL_MASK 0x001C /* BYPRMIXVOL - [4:2] */ | ||
852 | #define WM8983_BYPRMIXVOL_SHIFT 2 /* BYPRMIXVOL - [4:2] */ | ||
853 | #define WM8983_BYPRMIXVOL_WIDTH 3 /* BYPRMIXVOL - [4:2] */ | ||
854 | #define WM8983_BYPR2RMIX 0x0002 /* BYPR2RMIX */ | ||
855 | #define WM8983_BYPR2RMIX_MASK 0x0002 /* BYPR2RMIX */ | ||
856 | #define WM8983_BYPR2RMIX_SHIFT 1 /* BYPR2RMIX */ | ||
857 | #define WM8983_BYPR2RMIX_WIDTH 1 /* BYPR2RMIX */ | ||
858 | #define WM8983_DACR2RMIX 0x0001 /* DACR2RMIX */ | ||
859 | #define WM8983_DACR2RMIX_MASK 0x0001 /* DACR2RMIX */ | ||
860 | #define WM8983_DACR2RMIX_SHIFT 0 /* DACR2RMIX */ | ||
861 | #define WM8983_DACR2RMIX_WIDTH 1 /* DACR2RMIX */ | ||
862 | |||
863 | /* | ||
864 | * R52 (0x34) - LOUT1 (HP) volume ctrl | ||
865 | */ | ||
866 | #define WM8983_OUT1VU 0x0100 /* OUT1VU */ | ||
867 | #define WM8983_OUT1VU_MASK 0x0100 /* OUT1VU */ | ||
868 | #define WM8983_OUT1VU_SHIFT 8 /* OUT1VU */ | ||
869 | #define WM8983_OUT1VU_WIDTH 1 /* OUT1VU */ | ||
870 | #define WM8983_LOUT1ZC 0x0080 /* LOUT1ZC */ | ||
871 | #define WM8983_LOUT1ZC_MASK 0x0080 /* LOUT1ZC */ | ||
872 | #define WM8983_LOUT1ZC_SHIFT 7 /* LOUT1ZC */ | ||
873 | #define WM8983_LOUT1ZC_WIDTH 1 /* LOUT1ZC */ | ||
874 | #define WM8983_LOUT1MUTE 0x0040 /* LOUT1MUTE */ | ||
875 | #define WM8983_LOUT1MUTE_MASK 0x0040 /* LOUT1MUTE */ | ||
876 | #define WM8983_LOUT1MUTE_SHIFT 6 /* LOUT1MUTE */ | ||
877 | #define WM8983_LOUT1MUTE_WIDTH 1 /* LOUT1MUTE */ | ||
878 | #define WM8983_LOUT1VOL_MASK 0x003F /* LOUT1VOL - [5:0] */ | ||
879 | #define WM8983_LOUT1VOL_SHIFT 0 /* LOUT1VOL - [5:0] */ | ||
880 | #define WM8983_LOUT1VOL_WIDTH 6 /* LOUT1VOL - [5:0] */ | ||
881 | |||
882 | /* | ||
883 | * R53 (0x35) - ROUT1 (HP) volume ctrl | ||
884 | */ | ||
885 | #define WM8983_OUT1VU 0x0100 /* OUT1VU */ | ||
886 | #define WM8983_OUT1VU_MASK 0x0100 /* OUT1VU */ | ||
887 | #define WM8983_OUT1VU_SHIFT 8 /* OUT1VU */ | ||
888 | #define WM8983_OUT1VU_WIDTH 1 /* OUT1VU */ | ||
889 | #define WM8983_ROUT1ZC 0x0080 /* ROUT1ZC */ | ||
890 | #define WM8983_ROUT1ZC_MASK 0x0080 /* ROUT1ZC */ | ||
891 | #define WM8983_ROUT1ZC_SHIFT 7 /* ROUT1ZC */ | ||
892 | #define WM8983_ROUT1ZC_WIDTH 1 /* ROUT1ZC */ | ||
893 | #define WM8983_ROUT1MUTE 0x0040 /* ROUT1MUTE */ | ||
894 | #define WM8983_ROUT1MUTE_MASK 0x0040 /* ROUT1MUTE */ | ||
895 | #define WM8983_ROUT1MUTE_SHIFT 6 /* ROUT1MUTE */ | ||
896 | #define WM8983_ROUT1MUTE_WIDTH 1 /* ROUT1MUTE */ | ||
897 | #define WM8983_ROUT1VOL_MASK 0x003F /* ROUT1VOL - [5:0] */ | ||
898 | #define WM8983_ROUT1VOL_SHIFT 0 /* ROUT1VOL - [5:0] */ | ||
899 | #define WM8983_ROUT1VOL_WIDTH 6 /* ROUT1VOL - [5:0] */ | ||
900 | |||
901 | /* | ||
902 | * R54 (0x36) - LOUT2 (SPK) volume ctrl | ||
903 | */ | ||
904 | #define WM8983_OUT2VU 0x0100 /* OUT2VU */ | ||
905 | #define WM8983_OUT2VU_MASK 0x0100 /* OUT2VU */ | ||
906 | #define WM8983_OUT2VU_SHIFT 8 /* OUT2VU */ | ||
907 | #define WM8983_OUT2VU_WIDTH 1 /* OUT2VU */ | ||
908 | #define WM8983_LOUT2ZC 0x0080 /* LOUT2ZC */ | ||
909 | #define WM8983_LOUT2ZC_MASK 0x0080 /* LOUT2ZC */ | ||
910 | #define WM8983_LOUT2ZC_SHIFT 7 /* LOUT2ZC */ | ||
911 | #define WM8983_LOUT2ZC_WIDTH 1 /* LOUT2ZC */ | ||
912 | #define WM8983_LOUT2MUTE 0x0040 /* LOUT2MUTE */ | ||
913 | #define WM8983_LOUT2MUTE_MASK 0x0040 /* LOUT2MUTE */ | ||
914 | #define WM8983_LOUT2MUTE_SHIFT 6 /* LOUT2MUTE */ | ||
915 | #define WM8983_LOUT2MUTE_WIDTH 1 /* LOUT2MUTE */ | ||
916 | #define WM8983_LOUT2VOL_MASK 0x003F /* LOUT2VOL - [5:0] */ | ||
917 | #define WM8983_LOUT2VOL_SHIFT 0 /* LOUT2VOL - [5:0] */ | ||
918 | #define WM8983_LOUT2VOL_WIDTH 6 /* LOUT2VOL - [5:0] */ | ||
919 | |||
920 | /* | ||
921 | * R55 (0x37) - ROUT2 (SPK) volume ctrl | ||
922 | */ | ||
923 | #define WM8983_OUT2VU 0x0100 /* OUT2VU */ | ||
924 | #define WM8983_OUT2VU_MASK 0x0100 /* OUT2VU */ | ||
925 | #define WM8983_OUT2VU_SHIFT 8 /* OUT2VU */ | ||
926 | #define WM8983_OUT2VU_WIDTH 1 /* OUT2VU */ | ||
927 | #define WM8983_ROUT2ZC 0x0080 /* ROUT2ZC */ | ||
928 | #define WM8983_ROUT2ZC_MASK 0x0080 /* ROUT2ZC */ | ||
929 | #define WM8983_ROUT2ZC_SHIFT 7 /* ROUT2ZC */ | ||
930 | #define WM8983_ROUT2ZC_WIDTH 1 /* ROUT2ZC */ | ||
931 | #define WM8983_ROUT2MUTE 0x0040 /* ROUT2MUTE */ | ||
932 | #define WM8983_ROUT2MUTE_MASK 0x0040 /* ROUT2MUTE */ | ||
933 | #define WM8983_ROUT2MUTE_SHIFT 6 /* ROUT2MUTE */ | ||
934 | #define WM8983_ROUT2MUTE_WIDTH 1 /* ROUT2MUTE */ | ||
935 | #define WM8983_ROUT2VOL_MASK 0x003F /* ROUT2VOL - [5:0] */ | ||
936 | #define WM8983_ROUT2VOL_SHIFT 0 /* ROUT2VOL - [5:0] */ | ||
937 | #define WM8983_ROUT2VOL_WIDTH 6 /* ROUT2VOL - [5:0] */ | ||
938 | |||
939 | /* | ||
940 | * R56 (0x38) - OUT3 mixer ctrl | ||
941 | */ | ||
942 | #define WM8983_OUT3MUTE 0x0040 /* OUT3MUTE */ | ||
943 | #define WM8983_OUT3MUTE_MASK 0x0040 /* OUT3MUTE */ | ||
944 | #define WM8983_OUT3MUTE_SHIFT 6 /* OUT3MUTE */ | ||
945 | #define WM8983_OUT3MUTE_WIDTH 1 /* OUT3MUTE */ | ||
946 | #define WM8983_OUT4_2OUT3 0x0008 /* OUT4_2OUT3 */ | ||
947 | #define WM8983_OUT4_2OUT3_MASK 0x0008 /* OUT4_2OUT3 */ | ||
948 | #define WM8983_OUT4_2OUT3_SHIFT 3 /* OUT4_2OUT3 */ | ||
949 | #define WM8983_OUT4_2OUT3_WIDTH 1 /* OUT4_2OUT3 */ | ||
950 | #define WM8983_BYPL2OUT3 0x0004 /* BYPL2OUT3 */ | ||
951 | #define WM8983_BYPL2OUT3_MASK 0x0004 /* BYPL2OUT3 */ | ||
952 | #define WM8983_BYPL2OUT3_SHIFT 2 /* BYPL2OUT3 */ | ||
953 | #define WM8983_BYPL2OUT3_WIDTH 1 /* BYPL2OUT3 */ | ||
954 | #define WM8983_LMIX2OUT3 0x0002 /* LMIX2OUT3 */ | ||
955 | #define WM8983_LMIX2OUT3_MASK 0x0002 /* LMIX2OUT3 */ | ||
956 | #define WM8983_LMIX2OUT3_SHIFT 1 /* LMIX2OUT3 */ | ||
957 | #define WM8983_LMIX2OUT3_WIDTH 1 /* LMIX2OUT3 */ | ||
958 | #define WM8983_LDAC2OUT3 0x0001 /* LDAC2OUT3 */ | ||
959 | #define WM8983_LDAC2OUT3_MASK 0x0001 /* LDAC2OUT3 */ | ||
960 | #define WM8983_LDAC2OUT3_SHIFT 0 /* LDAC2OUT3 */ | ||
961 | #define WM8983_LDAC2OUT3_WIDTH 1 /* LDAC2OUT3 */ | ||
962 | |||
963 | /* | ||
964 | * R57 (0x39) - OUT4 (MONO) mix ctrl | ||
965 | */ | ||
966 | #define WM8983_OUT3_2OUT4 0x0080 /* OUT3_2OUT4 */ | ||
967 | #define WM8983_OUT3_2OUT4_MASK 0x0080 /* OUT3_2OUT4 */ | ||
968 | #define WM8983_OUT3_2OUT4_SHIFT 7 /* OUT3_2OUT4 */ | ||
969 | #define WM8983_OUT3_2OUT4_WIDTH 1 /* OUT3_2OUT4 */ | ||
970 | #define WM8983_OUT4MUTE 0x0040 /* OUT4MUTE */ | ||
971 | #define WM8983_OUT4MUTE_MASK 0x0040 /* OUT4MUTE */ | ||
972 | #define WM8983_OUT4MUTE_SHIFT 6 /* OUT4MUTE */ | ||
973 | #define WM8983_OUT4MUTE_WIDTH 1 /* OUT4MUTE */ | ||
974 | #define WM8983_OUT4ATTN 0x0020 /* OUT4ATTN */ | ||
975 | #define WM8983_OUT4ATTN_MASK 0x0020 /* OUT4ATTN */ | ||
976 | #define WM8983_OUT4ATTN_SHIFT 5 /* OUT4ATTN */ | ||
977 | #define WM8983_OUT4ATTN_WIDTH 1 /* OUT4ATTN */ | ||
978 | #define WM8983_LMIX2OUT4 0x0010 /* LMIX2OUT4 */ | ||
979 | #define WM8983_LMIX2OUT4_MASK 0x0010 /* LMIX2OUT4 */ | ||
980 | #define WM8983_LMIX2OUT4_SHIFT 4 /* LMIX2OUT4 */ | ||
981 | #define WM8983_LMIX2OUT4_WIDTH 1 /* LMIX2OUT4 */ | ||
982 | #define WM8983_LDAC2OUT4 0x0008 /* LDAC2OUT4 */ | ||
983 | #define WM8983_LDAC2OUT4_MASK 0x0008 /* LDAC2OUT4 */ | ||
984 | #define WM8983_LDAC2OUT4_SHIFT 3 /* LDAC2OUT4 */ | ||
985 | #define WM8983_LDAC2OUT4_WIDTH 1 /* LDAC2OUT4 */ | ||
986 | #define WM8983_BYPR2OUT4 0x0004 /* BYPR2OUT4 */ | ||
987 | #define WM8983_BYPR2OUT4_MASK 0x0004 /* BYPR2OUT4 */ | ||
988 | #define WM8983_BYPR2OUT4_SHIFT 2 /* BYPR2OUT4 */ | ||
989 | #define WM8983_BYPR2OUT4_WIDTH 1 /* BYPR2OUT4 */ | ||
990 | #define WM8983_RMIX2OUT4 0x0002 /* RMIX2OUT4 */ | ||
991 | #define WM8983_RMIX2OUT4_MASK 0x0002 /* RMIX2OUT4 */ | ||
992 | #define WM8983_RMIX2OUT4_SHIFT 1 /* RMIX2OUT4 */ | ||
993 | #define WM8983_RMIX2OUT4_WIDTH 1 /* RMIX2OUT4 */ | ||
994 | #define WM8983_RDAC2OUT4 0x0001 /* RDAC2OUT4 */ | ||
995 | #define WM8983_RDAC2OUT4_MASK 0x0001 /* RDAC2OUT4 */ | ||
996 | #define WM8983_RDAC2OUT4_SHIFT 0 /* RDAC2OUT4 */ | ||
997 | #define WM8983_RDAC2OUT4_WIDTH 1 /* RDAC2OUT4 */ | ||
998 | |||
999 | /* | ||
1000 | * R61 (0x3D) - BIAS CTRL | ||
1001 | */ | ||
1002 | #define WM8983_BIASCUT 0x0100 /* BIASCUT */ | ||
1003 | #define WM8983_BIASCUT_MASK 0x0100 /* BIASCUT */ | ||
1004 | #define WM8983_BIASCUT_SHIFT 8 /* BIASCUT */ | ||
1005 | #define WM8983_BIASCUT_WIDTH 1 /* BIASCUT */ | ||
1006 | #define WM8983_HALFIPBIAS 0x0080 /* HALFIPBIAS */ | ||
1007 | #define WM8983_HALFIPBIAS_MASK 0x0080 /* HALFIPBIAS */ | ||
1008 | #define WM8983_HALFIPBIAS_SHIFT 7 /* HALFIPBIAS */ | ||
1009 | #define WM8983_HALFIPBIAS_WIDTH 1 /* HALFIPBIAS */ | ||
1010 | #define WM8983_VBBIASTST_MASK 0x0060 /* VBBIASTST - [6:5] */ | ||
1011 | #define WM8983_VBBIASTST_SHIFT 5 /* VBBIASTST - [6:5] */ | ||
1012 | #define WM8983_VBBIASTST_WIDTH 2 /* VBBIASTST - [6:5] */ | ||
1013 | #define WM8983_BUFBIAS_MASK 0x0018 /* BUFBIAS - [4:3] */ | ||
1014 | #define WM8983_BUFBIAS_SHIFT 3 /* BUFBIAS - [4:3] */ | ||
1015 | #define WM8983_BUFBIAS_WIDTH 2 /* BUFBIAS - [4:3] */ | ||
1016 | #define WM8983_ADCBIAS_MASK 0x0006 /* ADCBIAS - [2:1] */ | ||
1017 | #define WM8983_ADCBIAS_SHIFT 1 /* ADCBIAS - [2:1] */ | ||
1018 | #define WM8983_ADCBIAS_WIDTH 2 /* ADCBIAS - [2:1] */ | ||
1019 | #define WM8983_HALFOPBIAS 0x0001 /* HALFOPBIAS */ | ||
1020 | #define WM8983_HALFOPBIAS_MASK 0x0001 /* HALFOPBIAS */ | ||
1021 | #define WM8983_HALFOPBIAS_SHIFT 0 /* HALFOPBIAS */ | ||
1022 | #define WM8983_HALFOPBIAS_WIDTH 1 /* HALFOPBIAS */ | ||
1023 | |||
1024 | enum clk_src { | ||
1025 | WM8983_CLKSRC_MCLK, | ||
1026 | WM8983_CLKSRC_PLL | ||
1027 | }; | ||
1028 | |||
1029 | #endif /* _WM8983_H */ | ||
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 9e5ff789b805..6e85b8869af7 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -876,7 +876,7 @@ SND_SOC_DAPM_MIXER("SPKL", WM8993_POWER_MANAGEMENT_3, 8, 0, | |||
876 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), | 876 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), |
877 | SND_SOC_DAPM_MIXER("SPKR", WM8993_POWER_MANAGEMENT_3, 9, 0, | 877 | SND_SOC_DAPM_MIXER("SPKR", WM8993_POWER_MANAGEMENT_3, 9, 0, |
878 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), | 878 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), |
879 | 879 | SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), | |
880 | }; | 880 | }; |
881 | 881 | ||
882 | static const struct snd_soc_dapm_route routes[] = { | 882 | static const struct snd_soc_dapm_route routes[] = { |
@@ -1434,6 +1434,7 @@ static int wm8993_probe(struct snd_soc_codec *codec) | |||
1434 | 1434 | ||
1435 | wm8993->hubs_data.hp_startup_mode = 1; | 1435 | wm8993->hubs_data.hp_startup_mode = 1; |
1436 | wm8993->hubs_data.dcs_codes = -2; | 1436 | wm8993->hubs_data.dcs_codes = -2; |
1437 | wm8993->hubs_data.series_startup = 1; | ||
1437 | 1438 | ||
1438 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 1439 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
1439 | if (ret != 0) { | 1440 | if (ret != 0) { |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index c2fc0356c2a4..09e680ae88b2 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -195,10 +195,6 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif) | |||
195 | aif + 1, rate); | 195 | aif + 1, rate); |
196 | } | 196 | } |
197 | 197 | ||
198 | if (rate && rate < 3000000) | ||
199 | dev_warn(codec->dev, "AIF%dCLK is %dHz, should be >=3MHz for optimal performance\n", | ||
200 | aif + 1, rate); | ||
201 | |||
202 | wm8994->aifclk[aif] = rate; | 198 | wm8994->aifclk[aif] = rate; |
203 | 199 | ||
204 | snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1 + offset, | 200 | snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1 + offset, |
@@ -1146,13 +1142,33 @@ SND_SOC_DAPM_PGA_E("Late DAC2L Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, | |||
1146 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | 1142 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), |
1147 | SND_SOC_DAPM_PGA_E("Late DAC2R Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, | 1143 | SND_SOC_DAPM_PGA_E("Late DAC2R Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, |
1148 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | 1144 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), |
1145 | SND_SOC_DAPM_PGA_E("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0, | ||
1146 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | ||
1147 | |||
1148 | SND_SOC_DAPM_MIXER_E("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, | ||
1149 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer), | ||
1150 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | ||
1151 | SND_SOC_DAPM_MIXER_E("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0, | ||
1152 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer), | ||
1153 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | ||
1154 | SND_SOC_DAPM_MUX_E("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux, | ||
1155 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | ||
1156 | SND_SOC_DAPM_MUX_E("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux, | ||
1157 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | ||
1149 | 1158 | ||
1150 | SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev) | 1159 | SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev) |
1151 | }; | 1160 | }; |
1152 | 1161 | ||
1153 | static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = { | 1162 | static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = { |
1154 | SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0), | 1163 | SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0), |
1155 | SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0) | 1164 | SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0), |
1165 | SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1166 | SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, | ||
1167 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), | ||
1168 | SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0, | ||
1169 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), | ||
1170 | SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), | ||
1171 | SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), | ||
1156 | }; | 1172 | }; |
1157 | 1173 | ||
1158 | static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = { | 1174 | static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = { |
@@ -1190,7 +1206,6 @@ SND_SOC_DAPM_INPUT("DMIC1DAT"), | |||
1190 | SND_SOC_DAPM_INPUT("DMIC2DAT"), | 1206 | SND_SOC_DAPM_INPUT("DMIC2DAT"), |
1191 | SND_SOC_DAPM_INPUT("Clock"), | 1207 | SND_SOC_DAPM_INPUT("Clock"), |
1192 | 1208 | ||
1193 | SND_SOC_DAPM_MICBIAS("MICBIAS", WM8994_MICBIAS, 2, 0), | ||
1194 | SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev, | 1209 | SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev, |
1195 | SND_SOC_DAPM_PRE_PMU), | 1210 | SND_SOC_DAPM_PRE_PMU), |
1196 | 1211 | ||
@@ -1283,14 +1298,6 @@ SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8994_POWER_MANAGEMENT_4, 2, 0), | |||
1283 | SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), | 1298 | SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), |
1284 | SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), | 1299 | SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), |
1285 | 1300 | ||
1286 | SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), | ||
1287 | SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), | ||
1288 | |||
1289 | SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, | ||
1290 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), | ||
1291 | SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0, | ||
1292 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), | ||
1293 | |||
1294 | SND_SOC_DAPM_POST("Debug log", post_ev), | 1301 | SND_SOC_DAPM_POST("Debug log", post_ev), |
1295 | }; | 1302 | }; |
1296 | 1303 | ||
@@ -1509,8 +1516,10 @@ static const struct snd_soc_dapm_route wm8994_revd_intercon[] = { | |||
1509 | { "AIF2DACDAT", NULL, "AIF1DACDAT" }, | 1516 | { "AIF2DACDAT", NULL, "AIF1DACDAT" }, |
1510 | { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, | 1517 | { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, |
1511 | { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, | 1518 | { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, |
1512 | { "MICBIAS", NULL, "CLK_SYS" }, | 1519 | { "MICBIAS1", NULL, "CLK_SYS" }, |
1513 | { "MICBIAS", NULL, "MICBIAS Supply" }, | 1520 | { "MICBIAS1", NULL, "MICBIAS Supply" }, |
1521 | { "MICBIAS2", NULL, "CLK_SYS" }, | ||
1522 | { "MICBIAS2", NULL, "MICBIAS Supply" }, | ||
1514 | }; | 1523 | }; |
1515 | 1524 | ||
1516 | static const struct snd_soc_dapm_route wm8994_intercon[] = { | 1525 | static const struct snd_soc_dapm_route wm8994_intercon[] = { |
@@ -1623,6 +1632,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1623 | int reg_offset, ret; | 1632 | int reg_offset, ret; |
1624 | struct fll_div fll; | 1633 | struct fll_div fll; |
1625 | u16 reg, aif1, aif2; | 1634 | u16 reg, aif1, aif2; |
1635 | unsigned long timeout; | ||
1626 | 1636 | ||
1627 | aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) | 1637 | aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) |
1628 | & WM8994_AIF1CLK_ENA; | 1638 | & WM8994_AIF1CLK_ENA; |
@@ -1704,6 +1714,9 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1704 | (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | | 1714 | (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | |
1705 | (src - 1)); | 1715 | (src - 1)); |
1706 | 1716 | ||
1717 | /* Clear any pending completion from a previous failure */ | ||
1718 | try_wait_for_completion(&wm8994->fll_locked[id]); | ||
1719 | |||
1707 | /* Enable (with fractional mode if required) */ | 1720 | /* Enable (with fractional mode if required) */ |
1708 | if (freq_out) { | 1721 | if (freq_out) { |
1709 | if (fll.k) | 1722 | if (fll.k) |
@@ -1714,7 +1727,15 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1714 | WM8994_FLL1_ENA | WM8994_FLL1_FRAC, | 1727 | WM8994_FLL1_ENA | WM8994_FLL1_FRAC, |
1715 | reg); | 1728 | reg); |
1716 | 1729 | ||
1717 | msleep(5); | 1730 | if (wm8994->fll_locked_irq) { |
1731 | timeout = wait_for_completion_timeout(&wm8994->fll_locked[id], | ||
1732 | msecs_to_jiffies(10)); | ||
1733 | if (timeout == 0) | ||
1734 | dev_warn(codec->dev, | ||
1735 | "Timed out waiting for FLL lock\n"); | ||
1736 | } else { | ||
1737 | msleep(5); | ||
1738 | } | ||
1718 | } | 1739 | } |
1719 | 1740 | ||
1720 | wm8994->fll[id].in = freq_in; | 1741 | wm8994->fll[id].in = freq_in; |
@@ -1732,6 +1753,14 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1732 | return 0; | 1753 | return 0; |
1733 | } | 1754 | } |
1734 | 1755 | ||
1756 | static irqreturn_t wm8994_fll_locked_irq(int irq, void *data) | ||
1757 | { | ||
1758 | struct completion *completion = data; | ||
1759 | |||
1760 | complete(completion); | ||
1761 | |||
1762 | return IRQ_HANDLED; | ||
1763 | } | ||
1735 | 1764 | ||
1736 | static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; | 1765 | static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; |
1737 | 1766 | ||
@@ -2271,6 +2300,33 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream, | |||
2271 | return snd_soc_update_bits(codec, aif1_reg, WM8994_AIF1_WL_MASK, aif1); | 2300 | return snd_soc_update_bits(codec, aif1_reg, WM8994_AIF1_WL_MASK, aif1); |
2272 | } | 2301 | } |
2273 | 2302 | ||
2303 | static void wm8994_aif_shutdown(struct snd_pcm_substream *substream, | ||
2304 | struct snd_soc_dai *dai) | ||
2305 | { | ||
2306 | struct snd_soc_codec *codec = dai->codec; | ||
2307 | int rate_reg = 0; | ||
2308 | |||
2309 | switch (dai->id) { | ||
2310 | case 1: | ||
2311 | rate_reg = WM8994_AIF1_RATE; | ||
2312 | break; | ||
2313 | case 2: | ||
2314 | rate_reg = WM8994_AIF1_RATE; | ||
2315 | break; | ||
2316 | default: | ||
2317 | break; | ||
2318 | } | ||
2319 | |||
2320 | /* If the DAI is idle then configure the divider tree for the | ||
2321 | * lowest output rate to save a little power if the clock is | ||
2322 | * still active (eg, because it is system clock). | ||
2323 | */ | ||
2324 | if (rate_reg && !dai->playback_active && !dai->capture_active) | ||
2325 | snd_soc_update_bits(codec, rate_reg, | ||
2326 | WM8994_AIF1_SR_MASK | | ||
2327 | WM8994_AIF1CLK_RATE_MASK, 0x9); | ||
2328 | } | ||
2329 | |||
2274 | static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute) | 2330 | static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute) |
2275 | { | 2331 | { |
2276 | struct snd_soc_codec *codec = codec_dai->codec; | 2332 | struct snd_soc_codec *codec = codec_dai->codec; |
@@ -2337,6 +2393,7 @@ static struct snd_soc_dai_ops wm8994_aif1_dai_ops = { | |||
2337 | .set_sysclk = wm8994_set_dai_sysclk, | 2393 | .set_sysclk = wm8994_set_dai_sysclk, |
2338 | .set_fmt = wm8994_set_dai_fmt, | 2394 | .set_fmt = wm8994_set_dai_fmt, |
2339 | .hw_params = wm8994_hw_params, | 2395 | .hw_params = wm8994_hw_params, |
2396 | .shutdown = wm8994_aif_shutdown, | ||
2340 | .digital_mute = wm8994_aif_mute, | 2397 | .digital_mute = wm8994_aif_mute, |
2341 | .set_pll = wm8994_set_fll, | 2398 | .set_pll = wm8994_set_fll, |
2342 | .set_tristate = wm8994_set_tristate, | 2399 | .set_tristate = wm8994_set_tristate, |
@@ -2346,6 +2403,7 @@ static struct snd_soc_dai_ops wm8994_aif2_dai_ops = { | |||
2346 | .set_sysclk = wm8994_set_dai_sysclk, | 2403 | .set_sysclk = wm8994_set_dai_sysclk, |
2347 | .set_fmt = wm8994_set_dai_fmt, | 2404 | .set_fmt = wm8994_set_dai_fmt, |
2348 | .hw_params = wm8994_hw_params, | 2405 | .hw_params = wm8994_hw_params, |
2406 | .shutdown = wm8994_aif_shutdown, | ||
2349 | .digital_mute = wm8994_aif_mute, | 2407 | .digital_mute = wm8994_aif_mute, |
2350 | .set_pll = wm8994_set_fll, | 2408 | .set_pll = wm8994_set_fll, |
2351 | .set_tristate = wm8994_set_tristate, | 2409 | .set_tristate = wm8994_set_tristate, |
@@ -2763,7 +2821,7 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
2763 | report = SND_JACK_MICROPHONE; | 2821 | report = SND_JACK_MICROPHONE; |
2764 | 2822 | ||
2765 | /* Everything else is buttons; just assign slots */ | 2823 | /* Everything else is buttons; just assign slots */ |
2766 | if (status & 0x1c0) | 2824 | if (status & 0x1c) |
2767 | report |= SND_JACK_BTN_0; | 2825 | report |= SND_JACK_BTN_0; |
2768 | 2826 | ||
2769 | done: | 2827 | done: |
@@ -2849,6 +2907,15 @@ out: | |||
2849 | return IRQ_HANDLED; | 2907 | return IRQ_HANDLED; |
2850 | } | 2908 | } |
2851 | 2909 | ||
2910 | static irqreturn_t wm8994_fifo_error(int irq, void *data) | ||
2911 | { | ||
2912 | struct snd_soc_codec *codec = data; | ||
2913 | |||
2914 | dev_err(codec->dev, "FIFO error\n"); | ||
2915 | |||
2916 | return IRQ_HANDLED; | ||
2917 | } | ||
2918 | |||
2852 | static int wm8994_codec_probe(struct snd_soc_codec *codec) | 2919 | static int wm8994_codec_probe(struct snd_soc_codec *codec) |
2853 | { | 2920 | { |
2854 | struct wm8994 *control; | 2921 | struct wm8994 *control; |
@@ -2867,6 +2934,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2867 | wm8994->pdata = dev_get_platdata(codec->dev->parent); | 2934 | wm8994->pdata = dev_get_platdata(codec->dev->parent); |
2868 | wm8994->codec = codec; | 2935 | wm8994->codec = codec; |
2869 | 2936 | ||
2937 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | ||
2938 | init_completion(&wm8994->fll_locked[i]); | ||
2939 | |||
2870 | if (wm8994->pdata && wm8994->pdata->micdet_irq) | 2940 | if (wm8994->pdata && wm8994->pdata->micdet_irq) |
2871 | wm8994->micdet_irq = wm8994->pdata->micdet_irq; | 2941 | wm8994->micdet_irq = wm8994->pdata->micdet_irq; |
2872 | else if (wm8994->pdata && wm8994->pdata->irq_base) | 2942 | else if (wm8994->pdata && wm8994->pdata->irq_base) |
@@ -2905,6 +2975,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2905 | wm8994->hubs.dcs_codes = -5; | 2975 | wm8994->hubs.dcs_codes = -5; |
2906 | wm8994->hubs.hp_startup_mode = 1; | 2976 | wm8994->hubs.hp_startup_mode = 1; |
2907 | wm8994->hubs.dcs_readback_mode = 1; | 2977 | wm8994->hubs.dcs_readback_mode = 1; |
2978 | wm8994->hubs.series_startup = 1; | ||
2908 | break; | 2979 | break; |
2909 | default: | 2980 | default: |
2910 | wm8994->hubs.dcs_readback_mode = 1; | 2981 | wm8994->hubs.dcs_readback_mode = 1; |
@@ -2919,6 +2990,15 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2919 | break; | 2990 | break; |
2920 | } | 2991 | } |
2921 | 2992 | ||
2993 | wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, | ||
2994 | wm8994_fifo_error, "FIFO error", codec); | ||
2995 | |||
2996 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE, | ||
2997 | wm_hubs_dcs_done, "DC servo done", | ||
2998 | &wm8994->hubs); | ||
2999 | if (ret == 0) | ||
3000 | wm8994->hubs.dcs_done_irq = true; | ||
3001 | |||
2922 | switch (control->type) { | 3002 | switch (control->type) { |
2923 | case WM8994: | 3003 | case WM8994: |
2924 | if (wm8994->micdet_irq) { | 3004 | if (wm8994->micdet_irq) { |
@@ -2975,6 +3055,16 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2975 | } | 3055 | } |
2976 | } | 3056 | } |
2977 | 3057 | ||
3058 | wm8994->fll_locked_irq = true; | ||
3059 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) { | ||
3060 | ret = wm8994_request_irq(codec->control_data, | ||
3061 | WM8994_IRQ_FLL1_LOCK + i, | ||
3062 | wm8994_fll_locked_irq, "FLL lock", | ||
3063 | &wm8994->fll_locked[i]); | ||
3064 | if (ret != 0) | ||
3065 | wm8994->fll_locked_irq = false; | ||
3066 | } | ||
3067 | |||
2978 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be | 3068 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be |
2979 | * configured on init - if a system wants to do this dynamically | 3069 | * configured on init - if a system wants to do this dynamically |
2980 | * at runtime we can deal with that then. | 3070 | * at runtime we can deal with that then. |
@@ -3050,10 +3140,18 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3050 | 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT, | 3140 | 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT, |
3051 | 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT); | 3141 | 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT); |
3052 | 3142 | ||
3053 | /* Unconditionally enable AIF1 ADC TDM mode; it only affects | 3143 | /* Unconditionally enable AIF1 ADC TDM mode on chips which can |
3054 | * behaviour on idle TDM clock cycles. */ | 3144 | * use this; it only affects behaviour on idle TDM clock |
3055 | snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1, | 3145 | * cycles. */ |
3056 | WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM); | 3146 | switch (control->type) { |
3147 | case WM8994: | ||
3148 | case WM8958: | ||
3149 | snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1, | ||
3150 | WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM); | ||
3151 | break; | ||
3152 | default: | ||
3153 | break; | ||
3154 | } | ||
3057 | 3155 | ||
3058 | wm8994_update_class_w(codec); | 3156 | wm8994_update_class_w(codec); |
3059 | 3157 | ||
@@ -3152,6 +3250,12 @@ err_irq: | |||
3152 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); | 3250 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); |
3153 | if (wm8994->micdet_irq) | 3251 | if (wm8994->micdet_irq) |
3154 | free_irq(wm8994->micdet_irq, wm8994); | 3252 | free_irq(wm8994->micdet_irq, wm8994); |
3253 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | ||
3254 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i, | ||
3255 | &wm8994->fll_locked[i]); | ||
3256 | wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, | ||
3257 | &wm8994->hubs); | ||
3258 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); | ||
3155 | err: | 3259 | err: |
3156 | kfree(wm8994); | 3260 | kfree(wm8994); |
3157 | return ret; | 3261 | return ret; |
@@ -3161,11 +3265,20 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) | |||
3161 | { | 3265 | { |
3162 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3266 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3163 | struct wm8994 *control = codec->control_data; | 3267 | struct wm8994 *control = codec->control_data; |
3268 | int i; | ||
3164 | 3269 | ||
3165 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); | 3270 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); |
3166 | 3271 | ||
3167 | pm_runtime_disable(codec->dev); | 3272 | pm_runtime_disable(codec->dev); |
3168 | 3273 | ||
3274 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | ||
3275 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i, | ||
3276 | &wm8994->fll_locked[i]); | ||
3277 | |||
3278 | wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, | ||
3279 | &wm8994->hubs); | ||
3280 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); | ||
3281 | |||
3169 | switch (control->type) { | 3282 | switch (control->type) { |
3170 | case WM8994: | 3283 | case WM8994: |
3171 | if (wm8994->micdet_irq) | 3284 | if (wm8994->micdet_irq) |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 0a1db04b73bd..1ab2266039f7 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <sound/soc.h> | 12 | #include <sound/soc.h> |
13 | #include <linux/firmware.h> | 13 | #include <linux/firmware.h> |
14 | #include <linux/completion.h> | ||
14 | 15 | ||
15 | #include "wm_hubs.h" | 16 | #include "wm_hubs.h" |
16 | 17 | ||
@@ -79,6 +80,8 @@ struct wm8994_priv { | |||
79 | int mclk[2]; | 80 | int mclk[2]; |
80 | int aifclk[2]; | 81 | int aifclk[2]; |
81 | struct wm8994_fll_config fll[2], fll_suspend[2]; | 82 | struct wm8994_fll_config fll[2], fll_suspend[2]; |
83 | struct completion fll_locked[2]; | ||
84 | bool fll_locked_irq; | ||
82 | 85 | ||
83 | int dac_rates[2]; | 86 | int dac_rates[2]; |
84 | int lrclk_shared[2]; | 87 | int lrclk_shared[2]; |
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 91c6b39de50c..a4691321f9b3 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -727,7 +727,7 @@ SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0, | |||
727 | SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0), | 727 | SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0), |
728 | 728 | ||
729 | SND_SOC_DAPM_PGA("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0), | 729 | SND_SOC_DAPM_PGA("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0), |
730 | SND_SOC_DAPM_PGA("Speaker", WM9081_POWER_MANAGEMENT, 1, 0, NULL, 0), | 730 | SND_SOC_DAPM_OUT_DRV("Speaker", WM9081_POWER_MANAGEMENT, 1, 0, NULL, 0), |
731 | 731 | ||
732 | SND_SOC_DAPM_OUTPUT("LINEOUT"), | 732 | SND_SOC_DAPM_OUTPUT("LINEOUT"), |
733 | SND_SOC_DAPM_OUTPUT("SPKN"), | 733 | SND_SOC_DAPM_OUTPUT("SPKN"), |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 9e370d14ad88..4cc2d567f22f 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -63,8 +63,10 @@ static const struct soc_enum speaker_mode = | |||
63 | 63 | ||
64 | static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) | 64 | static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) |
65 | { | 65 | { |
66 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | ||
66 | unsigned int reg; | 67 | unsigned int reg; |
67 | int count = 0; | 68 | int count = 0; |
69 | int timeout; | ||
68 | unsigned int val; | 70 | unsigned int val; |
69 | 71 | ||
70 | val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1; | 72 | val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1; |
@@ -74,18 +76,39 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) | |||
74 | 76 | ||
75 | dev_dbg(codec->dev, "Waiting for DC servo...\n"); | 77 | dev_dbg(codec->dev, "Waiting for DC servo...\n"); |
76 | 78 | ||
79 | if (hubs->dcs_done_irq) | ||
80 | timeout = 4; | ||
81 | else | ||
82 | timeout = 400; | ||
83 | |||
77 | do { | 84 | do { |
78 | count++; | 85 | count++; |
79 | msleep(1); | 86 | |
87 | if (hubs->dcs_done_irq) | ||
88 | wait_for_completion_timeout(&hubs->dcs_done, | ||
89 | msecs_to_jiffies(250)); | ||
90 | else | ||
91 | msleep(1); | ||
92 | |||
80 | reg = snd_soc_read(codec, WM8993_DC_SERVO_0); | 93 | reg = snd_soc_read(codec, WM8993_DC_SERVO_0); |
81 | dev_dbg(codec->dev, "DC servo: %x\n", reg); | 94 | dev_dbg(codec->dev, "DC servo: %x\n", reg); |
82 | } while (reg & op && count < 400); | 95 | } while (reg & op && count < timeout); |
83 | 96 | ||
84 | if (reg & op) | 97 | if (reg & op) |
85 | dev_err(codec->dev, "Timed out waiting for DC Servo %x\n", | 98 | dev_err(codec->dev, "Timed out waiting for DC Servo %x\n", |
86 | op); | 99 | op); |
87 | } | 100 | } |
88 | 101 | ||
102 | irqreturn_t wm_hubs_dcs_done(int irq, void *data) | ||
103 | { | ||
104 | struct wm_hubs_data *hubs = data; | ||
105 | |||
106 | complete(&hubs->dcs_done); | ||
107 | |||
108 | return IRQ_HANDLED; | ||
109 | } | ||
110 | EXPORT_SYMBOL_GPL(wm_hubs_dcs_done); | ||
111 | |||
89 | /* | 112 | /* |
90 | * Startup calibration of the DC servo | 113 | * Startup calibration of the DC servo |
91 | */ | 114 | */ |
@@ -107,8 +130,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
107 | return; | 130 | return; |
108 | } | 131 | } |
109 | 132 | ||
110 | /* Devices not using a DCS code correction have startup mode */ | 133 | if (hubs->series_startup) { |
111 | if (hubs->dcs_codes) { | ||
112 | /* Set for 32 series updates */ | 134 | /* Set for 32 series updates */ |
113 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, | 135 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, |
114 | WM8993_DCS_SERIES_NO_01_MASK, | 136 | WM8993_DCS_SERIES_NO_01_MASK, |
@@ -134,9 +156,9 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
134 | break; | 156 | break; |
135 | case 1: | 157 | case 1: |
136 | reg = snd_soc_read(codec, WM8993_DC_SERVO_3); | 158 | reg = snd_soc_read(codec, WM8993_DC_SERVO_3); |
137 | reg_l = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) | 159 | reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) |
138 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; | 160 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
139 | reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; | 161 | reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; |
140 | break; | 162 | break; |
141 | default: | 163 | default: |
142 | WARN(1, "Unknown DCS readback method\n"); | 164 | WARN(1, "Unknown DCS readback method\n"); |
@@ -150,13 +172,13 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
150 | dev_dbg(codec->dev, "Applying %d code DC servo correction\n", | 172 | dev_dbg(codec->dev, "Applying %d code DC servo correction\n", |
151 | hubs->dcs_codes); | 173 | hubs->dcs_codes); |
152 | 174 | ||
153 | /* HPOUT1L */ | 175 | /* HPOUT1R */ |
154 | offset = reg_l; | 176 | offset = reg_r; |
155 | offset += hubs->dcs_codes; | 177 | offset += hubs->dcs_codes; |
156 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; | 178 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
157 | 179 | ||
158 | /* HPOUT1R */ | 180 | /* HPOUT1L */ |
159 | offset = reg_r; | 181 | offset = reg_l; |
160 | offset += hubs->dcs_codes; | 182 | offset += hubs->dcs_codes; |
161 | dcs_cfg |= (u8)offset; | 183 | dcs_cfg |= (u8)offset; |
162 | 184 | ||
@@ -168,8 +190,8 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
168 | WM8993_DCS_TRIG_DAC_WR_0 | | 190 | WM8993_DCS_TRIG_DAC_WR_0 | |
169 | WM8993_DCS_TRIG_DAC_WR_1); | 191 | WM8993_DCS_TRIG_DAC_WR_1); |
170 | } else { | 192 | } else { |
171 | dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT; | 193 | dcs_cfg = reg_r << WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
172 | dcs_cfg |= reg_r; | 194 | dcs_cfg |= reg_l; |
173 | } | 195 | } |
174 | 196 | ||
175 | /* Save the callibrated offset if we're in class W mode and | 197 | /* Save the callibrated offset if we're in class W mode and |
@@ -195,7 +217,7 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, | |||
195 | 217 | ||
196 | /* If we're applying an offset correction then updating the | 218 | /* If we're applying an offset correction then updating the |
197 | * callibration would be likely to introduce further offsets. */ | 219 | * callibration would be likely to introduce further offsets. */ |
198 | if (hubs->dcs_codes) | 220 | if (hubs->dcs_codes || hubs->no_series_update) |
199 | return ret; | 221 | return ret; |
200 | 222 | ||
201 | /* Only need to do this if the outputs are active */ | 223 | /* Only need to do this if the outputs are active */ |
@@ -599,9 +621,6 @@ SND_SOC_DAPM_MIXER("IN2L PGA", WM8993_POWER_MANAGEMENT_2, 7, 0, | |||
599 | SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0, | 621 | SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0, |
600 | in2r_pga, ARRAY_SIZE(in2r_pga)), | 622 | in2r_pga, ARRAY_SIZE(in2r_pga)), |
601 | 623 | ||
602 | /* Dummy widgets to represent differential paths */ | ||
603 | SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
604 | |||
605 | SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0, | 624 | SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0, |
606 | mixinl, ARRAY_SIZE(mixinl)), | 625 | mixinl, ARRAY_SIZE(mixinl)), |
607 | SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0, | 626 | SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0, |
@@ -867,8 +886,11 @@ EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_controls); | |||
867 | int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, | 886 | int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, |
868 | int lineout1_diff, int lineout2_diff) | 887 | int lineout1_diff, int lineout2_diff) |
869 | { | 888 | { |
889 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | ||
870 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 890 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
871 | 891 | ||
892 | init_completion(&hubs->dcs_done); | ||
893 | |||
872 | snd_soc_dapm_add_routes(dapm, analogue_routes, | 894 | snd_soc_dapm_add_routes(dapm, analogue_routes, |
873 | ARRAY_SIZE(analogue_routes)); | 895 | ARRAY_SIZE(analogue_routes)); |
874 | 896 | ||
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index f8a5e976b5e6..676b1252ab91 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h | |||
@@ -14,6 +14,9 @@ | |||
14 | #ifndef _WM_HUBS_H | 14 | #ifndef _WM_HUBS_H |
15 | #define _WM_HUBS_H | 15 | #define _WM_HUBS_H |
16 | 16 | ||
17 | #include <linux/completion.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | |||
17 | struct snd_soc_codec; | 20 | struct snd_soc_codec; |
18 | 21 | ||
19 | extern const unsigned int wm_hubs_spkmix_tlv[]; | 22 | extern const unsigned int wm_hubs_spkmix_tlv[]; |
@@ -23,9 +26,14 @@ struct wm_hubs_data { | |||
23 | int dcs_codes; | 26 | int dcs_codes; |
24 | int dcs_readback_mode; | 27 | int dcs_readback_mode; |
25 | int hp_startup_mode; | 28 | int hp_startup_mode; |
29 | int series_startup; | ||
30 | int no_series_update; | ||
26 | 31 | ||
27 | bool class_w; | 32 | bool class_w; |
28 | u16 class_w_dcs; | 33 | u16 class_w_dcs; |
34 | |||
35 | bool dcs_done_irq; | ||
36 | struct completion dcs_done; | ||
29 | }; | 37 | }; |
30 | 38 | ||
31 | extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); | 39 | extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); |
@@ -36,4 +44,6 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *, | |||
36 | int jd_scthr, int jd_thr, | 44 | int jd_scthr, int jd_thr, |
37 | int micbias1_lvl, int micbias2_lvl); | 45 | int micbias1_lvl, int micbias2_lvl); |
38 | 46 | ||
47 | extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); | ||
48 | |||
39 | #endif | 49 | #endif |